Lex和Yacc使用学习笔记(二)
来源:互联网 发布:淘宝兔子20块 编辑:程序博客网 时间:2024/03/28 23:48
Yacc
yacc的文法由一个使用BNF文法(Backus-Naur form 的变量描述。文法规则最初由 John Backus 和 Peter Naur 发明,并且用于描述Algol60 语言。 BNF 能够用于表达上下文无关语言。现代程序语言中的大多数结构可以用BNF 文法来表达。例如,数值相乘和相加的文法是:
E > E + E
E > E * E
E > id
像 E (表达式)这样出现在左边的结构叫非终结符(nonterminal)。像 id(标识符)这样的结构叫终结符(terminal,由lex 返回的标记),它们只出现在右边。
yacc的输入文件格式与lex类似,给出一个例子,计算加减乘除的简单计算器,yacc和lex结合使用。
Lex的输入文件:
%{
/****************************************************************************
calclexer.l
ParserWizard generated Lex file.
Date:
****************************************************************************/
#include <stdlib.h>
void yyerror(char *);
#include "calcparser.h"
extern YYSTYPE yylval;
%}
/////////////////////////////////////////////////////////////////////////////
// declarations section
// place any declarations here
%%
/////////////////////////////////////////////////////////////////////////////
// rules section
// place your Lex rules here
[0-9]+ {
yylval = atoi(yytext);
return INTEGER;
}
[-+*//n] return *yytext;
[ /t] ; /* skip whitespace */
. yyerror("invalid character");
%%
/////////////////////////////////////////////////////////////////////////////
// programs section
int yywrap(void) {
return 1;
}
Yacc的输入文件:
%{
/****************************************************************************
calcparser.y
ParserWizard generated YACC file.
Date:
****************************************************************************/
#include "calclexer.h"
int yylex(void);
void yyerror(char *);
%}
/////////////////////////////////////////////////////////////////////////////
// declarations section
// attribute type
%include {
#ifndef YYSTYPE
#define YYSTYPE int
#endif
}
// place any declarations here
%token INTEGER
%left '+' '-'
%left '*' '/'
%%
/////////////////////////////////////////////////////////////////////////////
// rules section
// place your YACC rules here (there must be at least one)
program:
program expr '/n' { printf("%d/n", $2); }
|
;
expr:
INTEGER { $$ = $1; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
;
%%
/////////////////////////////////////////////////////////////////////////////
// programs section
void yyerror(char *s)
{
fprintf(stderr, "%s/n", s);
}
int main(void)
{
yyparse();
return 0;
}
需要注意以下几点:
l 在计算+-的时候,文法本身是有移近-规约冲突(shift-reduce conflict)的,例如
l yylval是在yacc的输出文件中定义的,在lex中使用时需要先用extern将其引入【extern YYSTYPE yylval;】
l yacc 在内部维护着两个堆栈;一个分析栈和一个内容栈。分析栈中保存着终结符和非终结符,并且代表当前剖析状态。内容栈是一个YYSTYPE 元素的数组,对于分析栈中的每一个元素都保存着一个对应的值。例如,当yylex 返回一个INTEGER 标记时,yacc 把这个标记移入分析栈。同时,相应的yylval 值将会被移入内容栈中。分析栈和内容栈的内容总是同步的,因此从栈中找到对应于一个标记的值是很容易实现的。
- Lex和Yacc使用学习笔记(二)
- Lex和Yacc使用学习笔记(一)
- LEX和YACC的使用二
- LEX AND YACC 使用(二)
- 《Lex 和 Yacc 》阅读笔记
- Lex和Yacc应用方法(二).再识Lex与Yacc
- Lex和Yacc应用方法(二).再识Lex与Yacc
- Lex和Yacc应用方法(二).再识Lex与Yacc
- yacc和lex学习概括
- 初步学习lex和yacc
- LEX和YACC的使用
- lex 和 yacc 学习笔记1
- 编译原理学习-Windows下Lex和yacc使用
- 如何使用Lex和Yacc工具(1)
- 使用 lex 和 yacc 编译代码
- 使用 yacc 和 lex 编写文本分析器
- LEX和YACC的使用一
- LEX和YACC的使用三
- 徐家骏:我在华为工作十年的感悟
- “Compiling... ,Error spawning cl.exe”错误
- 控制 TextBox 输入时若是英文自动转大写或转小写的方法
- 用 Firebug 动态调试和优化应用程序
- 网页常用Javascript
- Lex和Yacc使用学习笔记(二)
- 今天调休
- 进程与线程的讨论
- 获取web.xml中的context-param和init-param定义的值
- 双频段GSM/DCS移动电话射频指标分析
- 转: WebPart生命周期
- VB中播放声音文件
- 雷鸣:把设计当成一门艺术
- 将Java应用程序本地编译为EXE的几种方法(推荐使用JOVE和JET)