这段时间一直在反思教育问题,把自己以前的书翻出来好好读,发现了许多不明白,未曾真懂得东西。

刚刚看完了词法分析和语法分析,越看越简单,不知道以前怎么会觉得它这么难。总之以前还是缺少实践。

下面来谈谈我在做lex和yacc遇到的一个例子。
   
lex与yacc(第二版)原书第一章有个实例源码是这样的。

ch1-05.l
   
%{
/*
 * We now build a lexical analyzer to be used by a higher-level parser.
 */

#include "ch1-05y.h" /* token codes from the parser */

#define LOOKUP 0 /* default - not a defined word type. */

int state;

%}

%%

/n { state = LOOKUP; }

/./n { state = LOOKUP;
  return 0; /* end of sentence */
 }

^verb { state = VERB; }
^adj { state = ADJECTIVE; }
^adv { state = ADVERB; }
^noun { state = NOUN; }
^prep { state = PREPOSITION; }
^pron { state = PRONOUN; }
^conj { state = CONJUNCTION; }

[a-zA-Z]+ {
      if(state != LOOKUP) {
       add_word(state, yytext);
      } else {
  switch(lookup_word(yytext)) {
  case VERB:
    return(VERB);
  case ADJECTIVE:
    return(ADJECTIVE);
  case ADVERB:
    return(ADVERB);
  case NOUN:
    return(NOUN);
  case PREPOSITION:
    return(PREPOSITION);
  case PRONOUN:
    return(PRONOUN);
  case CONJUNCTION:
    return(CONJUNCTION);
  default:
    printf("%s:  don't recognize/n", yytext);
    /* don't return, just ignore it */
  }
            }
          }

. ;

%%
/* define a linked list of words and types */
struct word {
 char *word_name;
 int word_type;
 struct word *next;
};

struct word *word_list; /* first element in word list */

extern void *malloc();

int
add_word(int type, char *word)
{
 struct word *wp;

if(lookup_word(word) != LOOKUP) {
  printf("!!! warning: word %s already defined /n", word);
  return 0;
 }
 
 /* word not there, allocate a new entry and link it on the list */

wp = (struct word *) malloc(sizeof(struct word));

wp->next = word_list;

/* have to copy the word itself as well */
 
 wp->word_name = (char *) malloc(strlen(word)+1);
 strcpy(wp->word_name, word);
 wp->word_type = type;
 word_list = wp;
 return 1; /* it worked */
}

int
lookup_word(char *word)
{
 struct word *wp = word_list;

/* search down the list looking for the word */
 for(; wp; wp = wp->next) {
  if(strcmp(wp->word_name, word) == 0)
   return wp->word_type;
 }

return LOOKUP; /* not found */
}

ch1-05.y

%{
/*
 * A lexer for the basic grammar to use for recognizing english sentences.
 */
#include <stdio.h>
%}

%token NOUN PRONOUN VERB ADVERB ADJECTIVE PREPOSITION CONJUNCTION

%%
sentence: subject VERB object { printf("Sentence is valid./n"); }
 ;

subject: NOUN
 | PRONOUN
 ;

object:  NOUN
 ;
%%

extern FILE *yyin;

main()
{
 while(!feof(yyin)) {
  yyparse();
 }
}

yyerror(s)
char *s;
{
    fprintf(stderr, "%s/n", s);
}

ch1-05.y是yacc程序,yyparse()例程表示开始语法分析,根据编译原理所学,yyparse会调用lex的yylex,
执行yylex后,符合词法规则,则执行相应动作返回给yyparse。

编译运行后(在flex和bison下,使用cygwin模拟环境)

flex ch1-05.l
mv lex.xx.c ch1-05.c
bison -d ch1-05.y
gcc -g -DYYDEBUG -c -o ch1-05l.o ch1-05l.c
gcc -g -DYYDEBUG -c -o ch1-05y.o ch1-05y.c
gcc -g -o ch1-05.pgm ch1-05l.o ch1-05y.o -lfl
其中lfl为flex库。

(1)第一次运行./ch1-05.pgm,报告segment fault。使用gdb调试,在while(!feof(yyin))处发生,通过
对ch1-05l.c和ch1-05y.c源代码的查看加上猜测,估计此事yyin还没有值,应该是在yyparse后才会有值。
于是ch1-05y.c的main代码改为

main()
{
 do {
  yyparse();
 }while(!feof(yyin))
  
}

(2) 第二次运行./ch1-05.pgm,输入如下:
verb is are am
noun i he pig
he is student
报告sentence is valid
再次输入
he is student
报告
syntax error

为什么呢?
想了一下,回过头看了下语法分析LALR和ch1-05.l分析的过程
发现yyparse调用后,经过了多次yylex的调用,已经把
he is student规约为sentence,但是由于缺少句号,一次yyparse调用并没有结束,再输入第二个he is student,即
栈内为sentence,输入为he is student,无法再规约,报告语法错误。

(3)第三次运行./ch1-05.pgm,输入如下:
verb is are am
noun i he pig
he is student
报告sentence is valid
再次输入
. 此处输入后yylex返回0,则本次yyparse调用结束。

he is student.

报告
sentence is valid.

上面就是基本的词法与语法分析的一个例子,应该对大家会有点启发。

编译原理——lex 与yacc实例剖析相关推荐

  1. 编译原理:利用yacc/bison进行语法分析

    YACC(Yet Another Compiler-Compiler)是一个LALR(1)分析器自动生成器,是贝尔实验室在UNIX上首次实现,与LEX有直接的接口.此外GNU(GNU is not U ...

  2. 编译原理拉链回填技术c语言,编译原理笔记1:概述编译相关的基本知识

    本系列为个人编译原理学习笔记,谬误之处恳请高人指点,感激不尽! 内容整理自西安电子科技大学 王小兵.张南.鱼滨老师的编译原理课程. 编译器的工作步骤 在开始说任何东西之前,我们先来大致看一下编译器是怎 ...

  3. 编写Lex和Yacc

    大学课程设计中,有一次是编写Lex(词法分析器的生成器)和Yacc(语法分析器的生成器),编写这类工具软件不是一件容易的事情.这篇文章记录了当时编程时候的主要思想,主要还是编译原理的思想. 准备 Le ...

  4. 编译原理 yacc lex 制作一个计算器

    这篇文档是我从别的地方摘抄的,留给自己以后回忆使用.(写的非常详细!) Flex工具的使用方法 Lex 是一种生成扫描器的工具. Lex是Unix环境下非常著名的工具,主要功能是生成一个扫描器(Sca ...

  5. 编译原理:用lex/flex做词法分析

    最近在自学<编译原理>,感觉对于我来说有点难度. 写这个的目的是为了做笔记,感谢https://blog.csdn.net/xiaowei_cqu/article/details/7760 ...

  6. 【编译原理】实验四:Yacc 分析程序生成器

    目录 实验四 Yacc 分析程序生成器 一.实验目的 二.预备知识 三.实验内容 巴科斯范式BNF 分析器的生成器Yacc sample.txt文件 ytab.c文件 ytab.h文件 y.outpu ...

  7. 编译原理实验四:验证Yacc的使用

    所有实验的源代码:点此下载 实验目的: 熟悉语法分析器生成工具Yacc的使用,并学会在cygwin下使用bison工具编译Yacc文法说明文件.学习如何使用lex和yacc合作进行语法分析. 实验内容 ...

  8. 编译原理-如何使用flex和yacc工具构造一个高级计算器

    Flex工具的使用方法 Lex 是一种生成扫描器的工具. Lex是Unix环境下非常著名的工具,主要功能是生成一个扫描器(Scanner)的C源码. 扫描器是一种识别文本中的词汇模式的程序. 这些词汇 ...

  9. 深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)

    原文:http://www.cnblogs.com/artech/archive/2007/05/21/753620.html Microsoft 的Visual Studio为我们在应用开发中提供的 ...

最新文章

  1. python游戏编程入门电子书-请问自学 Python 有必要买课程吗?
  2. java数据库初始化参数,oracle数据库初始化参数设置--Java免费学习网
  3. oracle精度说明符1~38_Oracle错误代码案例总结及解决方案
  4. 64位Ubuntu 12.04下搭建嵌入式Qt(4.8.6)、QtCreator、qvfb过程全记录
  5. openglpython3d重构_python+opengl显示三维模型小程序
  6. Shiro-从数据表中初始化资源和权限
  7. linux如何查看tomcat端口号,如何在Linux中修改tomcat端口号
  8. poj 2406 Power Strings(KMP)
  9. 腾讯云重装和还原操作系统
  10. V神发布ETH2.0信标链首个硬分叉提案HF1,引入更公平的节点惩罚机制
  11. 解读大内老A的《.NET Core框架本质》
  12. pandas去除重复列
  13. 数据库原理第四章测验(标黑的为答案)
  14. 软件系统的多维性能模型
  15. 17.2: Apps that require users to share personal information, such as email address and date of birth
  16. scrapy-selenium-谷歌浏览器爬取带有时效性cookies的网站
  17. HTML之form表单
  18. js一天、两天倒计时定时器实现方案
  19. 【模拟电路】波形产生与变换设计(555+运放)
  20. Windows下Scala+Spark+IDEA+Hadoop环境搭建

热门文章

  1. 二元一次方程的求解java语言
  2. dds:subscribe:DataReader
  3. JetBrains旗下软件通用激活方法
  4. The method of type serviceimpl must override a superclass method报错
  5. 抗体纯化策略——介质篇
  6. 【字符是json格式】 如何拿取里面的id?
  7. 2018年第九届蓝桥杯B组 国赛
  8. h5页面ios验证码无法自动回填到键盘问题
  9. C语言中的clock函数
  10. C#之CAD二次开发(14) Ribbon界面初探