编译原理——lex 与yacc实例剖析
这段时间一直在反思教育问题,把自己以前的书翻出来好好读,发现了许多不明白,未曾真懂得东西。
刚刚看完了词法分析和语法分析,越看越简单,不知道以前怎么会觉得它这么难。总之以前还是缺少实践。
下面来谈谈我在做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实例剖析相关推荐
- 编译原理:利用yacc/bison进行语法分析
YACC(Yet Another Compiler-Compiler)是一个LALR(1)分析器自动生成器,是贝尔实验室在UNIX上首次实现,与LEX有直接的接口.此外GNU(GNU is not U ...
- 编译原理拉链回填技术c语言,编译原理笔记1:概述编译相关的基本知识
本系列为个人编译原理学习笔记,谬误之处恳请高人指点,感激不尽! 内容整理自西安电子科技大学 王小兵.张南.鱼滨老师的编译原理课程. 编译器的工作步骤 在开始说任何东西之前,我们先来大致看一下编译器是怎 ...
- 编写Lex和Yacc
大学课程设计中,有一次是编写Lex(词法分析器的生成器)和Yacc(语法分析器的生成器),编写这类工具软件不是一件容易的事情.这篇文章记录了当时编程时候的主要思想,主要还是编译原理的思想. 准备 Le ...
- 编译原理 yacc lex 制作一个计算器
这篇文档是我从别的地方摘抄的,留给自己以后回忆使用.(写的非常详细!) Flex工具的使用方法 Lex 是一种生成扫描器的工具. Lex是Unix环境下非常著名的工具,主要功能是生成一个扫描器(Sca ...
- 编译原理:用lex/flex做词法分析
最近在自学<编译原理>,感觉对于我来说有点难度. 写这个的目的是为了做笔记,感谢https://blog.csdn.net/xiaowei_cqu/article/details/7760 ...
- 【编译原理】实验四:Yacc 分析程序生成器
目录 实验四 Yacc 分析程序生成器 一.实验目的 二.预备知识 三.实验内容 巴科斯范式BNF 分析器的生成器Yacc sample.txt文件 ytab.c文件 ytab.h文件 y.outpu ...
- 编译原理实验四:验证Yacc的使用
所有实验的源代码:点此下载 实验目的: 熟悉语法分析器生成工具Yacc的使用,并学会在cygwin下使用bison工具编译Yacc文法说明文件.学习如何使用lex和yacc合作进行语法分析. 实验内容 ...
- 编译原理-如何使用flex和yacc工具构造一个高级计算器
Flex工具的使用方法 Lex 是一种生成扫描器的工具. Lex是Unix环境下非常著名的工具,主要功能是生成一个扫描器(Scanner)的C源码. 扫描器是一种识别文本中的词汇模式的程序. 这些词汇 ...
- 深入剖析ASP.NET的编译原理之一:动态编译(Dynamical Compilation)
原文:http://www.cnblogs.com/artech/archive/2007/05/21/753620.html Microsoft 的Visual Studio为我们在应用开发中提供的 ...
最新文章
- python游戏编程入门电子书-请问自学 Python 有必要买课程吗?
- java数据库初始化参数,oracle数据库初始化参数设置--Java免费学习网
- oracle精度说明符1~38_Oracle错误代码案例总结及解决方案
- 64位Ubuntu 12.04下搭建嵌入式Qt(4.8.6)、QtCreator、qvfb过程全记录
- openglpython3d重构_python+opengl显示三维模型小程序
- Shiro-从数据表中初始化资源和权限
- linux如何查看tomcat端口号,如何在Linux中修改tomcat端口号
- poj 2406 Power Strings(KMP)
- 腾讯云重装和还原操作系统
- V神发布ETH2.0信标链首个硬分叉提案HF1,引入更公平的节点惩罚机制
- 解读大内老A的《.NET Core框架本质》
- pandas去除重复列
- 数据库原理第四章测验(标黑的为答案)
- 软件系统的多维性能模型
- 17.2: Apps that require users to share personal information, such as email address and date of birth
- scrapy-selenium-谷歌浏览器爬取带有时效性cookies的网站
- HTML之form表单
- js一天、两天倒计时定时器实现方案
- 【模拟电路】波形产生与变换设计(555+运放)
- Windows下Scala+Spark+IDEA+Hadoop环境搭建