Yacc库
每个实现都需要有用的例程库,在UNIX系统中,可以通过cc命令行尾端给出-ly标志(或通过其他系统下的等价物)来包含库。
库的内容在不同的实现之间是不同的,但总是包括main()和yyerror()
main()
yacc的所有版本都带有最小的主程序,该程序对于简短程序和测试有时是很有用的,它非常简单,如下所示:
main(argc,argv)
yyparse();
return 0;
}
和具有任何库例程一样,可以提供自己的main()。在几乎所有有用的应用软件中都可以提供main()用来接受命令参数和标志、打开文件和检查错误。
yyerror()
所有版本也都提供简单的错误报告例程,它也是非常简单:
yyerror(char *errmsg)
printf("%s\n",errmsg);
}
这有时能够满足要求,但是一个好的错误报告例程至少能报告行号和最近的标记(如果词法分析程序是用lex写的,那么会在yytext中),这将会对语法分析程序更有用。
YYABORT
YYABORT
在动作中使得语法分析例程yyparse()以一个非零值立即返回,显示失败。
当动作例程探测到错误非常严重以致于没有继续分析的点时是很有用的。
由于语法分析程序可以向前查看一个标记,所以在语法分析程序读到另一个标记前,包括YYABORT的规则动作尅不被归约。
YYACCEPT
YYACCEPT
在动作中使得语法分析例程yyparse()以一个零值立即返回,显示成功。
在词法分析程序不能告知输入数据何时结束而语法分析程序能告知的情况下是很有用的。
由于语法分析程序可以向前查看一个标记,所以在语法分析程序读到另一个标记前,包括YYACCEPT的规则动作尅不被归约。
YYBACKUP
宏YYBACKUP使得你可以移出当前记号并把它替换为另一个记号,该语法为:
sym: TOKEN {YYBACKUP(newtok,newval);}
它放弃已经被归约的符号sym,并且假装词法分析器刚刚读到记号newtok,其值为newval。如果此时存在一个向前查看的记号或者该规则在右部的符号超过一个的话,这个规则将通过调用yyerror()来宣告失败。
正确使用YYBACKUP非常困难,一般不用。
YYDEBUG
由于跟踪代码又大又慢,所以不能自动编译到目标程序中。为了包含跟踪代码,使用yacc命令行上的-t标志,或者要么在C编译程序命令行上,或者通过在定义段包含类似下面的句式,来定义C预处理程序符号YYDEBUG为非零值:
#define YYDEBUG 1
YYERROR
有时动作代码能探测到上下文相关的而语法分析程序本身却不能检测到的语法错误。如果代码检测到一个语法错误,就可以调用宏YYERROR,生成的效果与语法分析程序读到一个被语法禁止的标记时完全一样。一调用YYERROR,语法分析程序就访问yyerror(),进入错误恢复模式,寻找可以移进error标记的状态。
yyerror()
只要yacc语法分析程序探测到语法错误就调用yyerror()函数,将错误报告给用户。传递单个参数即描述这个错误的字符串,yacc库中的yyerror的默认版本仅仅是在标准输出文件中打印参数。
下面是返回更多信息的版本:
yyerror(const char *msg)
printf("%d: %s at '%s' \n",yylineno,msg,yytext);
yylineno是当前行号,yytext是包含当前标记的lex标记缓冲器。
yyparse()
yacc生成的语法分析程序的入口点是yyparse(),当程序调用yyparse()时,语法分析程序就试图分析输入流。如果分析成功,语法分析程序就返回一个零值,反之,则返回一个非零值。
每次调用该函数,语法分析程序就重新开始进行分析,而忘记上次返回的状态,这与lex扫描程序十分不同,它能够获得调用后的每一次状态。
Yacc库每个实现都需要有用的例程库,在UNIX系统中,可以通过cc命令行尾端给出-ly标志(或通过其他系统下的等价物)来包含库。库的内容在不同的实现之间是不同的,但总是包括main()和yyerror()main()yacc的所有版本都带有最小的主程序,该程序对于简短程序和测试有时是很有用的,它非常简单,如下所示:main(argc,argv){ yyparse
作者: 胡彦
本框架是一个
lex
/
yacc
完整的示例,用于
学习
lex
/
yacc
程序基本的搭建方法,在linux/cygwin下敲入make就可以编译和执行。
本例子虽小却演示了
lex
/
yacc
程序最常见和重要的特征:
*
lex
/
yacc
文件格式、程序结构。
* 如何在
lex
/
yacc
中使用C++和STL
库
,用extern "C"声明那些
lex
/
yacc
生成的、要链接的C函数,如yy
lex
(), yywrap(), yyerror()。
* 重定义YYSTYPE/yylval为复杂类型。
* 用%token方式声明
yacc
记号。
* 用%type方式声明非终结符的类型。
*
lex
里正则表达式的定义、识别方式。
*
lex
里用yylval向
yacc
返回属性值。
* 在
yacc
嵌入的C代码动作里,对记号属性($1, $2等)、和非终结符属性($$)的正确引用方法。
* 对yyin/yyout重赋值,以改变
yacc
默认的输入/输出目标。
* 如何开始解析(yyparse函数),结束或继续解析(yywrap函数)。
本例子功能是,对当前目录下的file.txt文件,解析出其中的标识符、数字、其它符号,显示在屏幕上。linux调试环境是Ubuntu 10.04。
总之,大部分框架已经搭好了,你只要稍加扩展就可以成为一个计算器之类的程序,用于《编译原理》的课程设计。
文件列表:
lex
.l:
lex
程序文件。
yacc
.y:
yacc
程序文件。
main.hpp: 共同使用的头文件。
Makefile: makefile文件。
file.txt: 给程序解析的文本文件。
使用方法:
1-把
lex
_
yacc
_example.rar解压到linux/cygwin下。
2-命令行进入
lex
_
yacc
_example目录。
3-敲入make,这时会自动执行以下操作:
(1) 自动调用f
lex
编译.l文件,生成
lex
.yy.c文件。
(2) 自动调用bison编译.y文件,生成
yacc
.tab.c和
yacc
.tab.h文件。
(3) 自动调用g++编译、链接出可执行文件main。
(4) 自动执行main,得到如下结果:。
bison -d
yacc
.y
g++ -c
lex
.yy.c
g++ -c
yacc
.tab.c
g++
lex
.yy.o
yacc
.tab.o -o main
id: abc
id: defghi
int: 123
int: 45678
op: !
op: @
op: #
op: $
AllId: abc defghi
参考资料:《
Lex
和
Yacc
从入门到精通(6)-解析C-C++包含文件》, http://blog.csdn.net/pandaxcl/article/details/1321552
其它文章和代码请留意我的blog: http://blog.csdn.net/huyansoft
2013-4-27
Error type A at line 3 : Mysterious characters '%'
Error type B at line 4: Missing ';'.
Error type B at line 6: Missin
最近在写f
lex
& bison程序,但是bison总是解析不正确,第一次运行yyparse()是正确的,但enter后再输入,总会报错ERROR: syntax error。改写yyerror函数为
yyerror(char *s)
extern int yylineno; // defined and maintained in
lex
extern char *yytext;...
自然语言中语言
学习
包含:单词和语法。
在编程语言中也包含单词和语法,分别有f
lex
和bison来实现。
所以f
lex
和bison的作用就是:用C语言来实现另外一种语言(SQL、python等)
f
lex
:
LEX
词法分析 (
lex
ical analysis)
单词提取:提取编程语言占用的各种保留字、操作符等等语言的元素
lex
把每个扫描出来的单词叫做token,token可以有很多类。对比自然语言中名词、形容词等,而汽车就是属于名词类型的一个具体token。在
文法分析用F
lex
(
Lex
):将数据分隔成一个个的标记token (标示符identifiers,关键字keywords,数字numbers, 中括号brackets, 大括号braces, 等等etc.)
语法分析用Bison(
Yacc
): 在分析标记的时候生成抽象语法树. Bison 将会做掉几乎所有的这些工作, 我们定义好我们的
本篇文章的代码基于原版文档的中的——source code for calculator代码
https://www.epaperpress.com/
lex
and
yacc
/index.html
我改造的程序,由四个部分组成,分别是calc3.l、calc3.y、calc3.h、calc3.c。
f
lex
*.l
bison -d *.y
g++ -o cal *.c -lfl
支持的操作
采用类C语言设计,支持任意定
YACC
(Yet AnotherCompile-Compiler)是语法分析器生成工具,它生成的是LALR分析器。
Yacc
于上世纪70年代产生,是美国贝尔实验室的产品,已经用于帮助实现了几百个编译器。
Yacc
是linux下的工具,本实验使用的编译工具是cygwin(cygwin在windows下模拟一个linux环境)下的bison,它与
Yacc
的使用方法基本相同,只有...
08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活。此系列是对四年专业课程
学习
的回顾,索引参见:http://blog.csdn.net/xiaowei_cqu/article/details/7747205
Yacc
全称 Yet Another Compiler Compiler
Yacc
是一个用来生成编译器的编译器(编译器代码生成器)。
yacc
生成的编译...
《
lex
与
yacc
第二版》是经典编译原理教材之一,它主要介绍了两个工具——
lex
和
yacc
的使用和实现原理。
其中,
lex
用于生成语法分析器,对输入的字符流进行识别和分析,将其转换为语法单元。它基于正则表达式进行匹配,配合动作函数可以实现一定的语义分析。
yacc
则是一种语法分析器生成器,可以将输入的文法转换为LR分析表,然后根据分析表进行语法分析,并生成语法树或目标代码。它基于LALR分析方法进行分析,具有高效、简单易用等特点。
在这本书中,作者对这两个工具进行了深入的讲解。在
lex
的部分中,介绍了正则表达式的语法、匹配原理和动作函数的使用方法,同时给出了一些实例演示其用法。在
yacc
部分中,作者先从基本语法入手,介绍了如何编写文法、标识符和运算符的处理、错误处理等方面的内容。然后,他讲解了LR分析和LALR分析的原理,以及使用
yacc
生成分析器的步骤和技巧。
此外,作者对使用这两个工具时遇到的一些常见问题进行了讲解,如如何处理复杂的语法、如何优化语法分析器等等。此外,《
lex
与
yacc
第二版》也介绍了一些相关的工具和技术,例如f
lex
和bison的使用、语法树的构建、代码生成等等。
总之,《
lex
与
yacc
第二版》是一本经典的编译原理教材,对于想要
学习
这方面知识的人来说,是一本非常值得一读的书籍。通过它的
学习
和理解,可以深入掌握关于语法分析的原理、方法和应用,从而为编译器和解释器的开发打下坚实的基础。