实验四 用Yacc实现的语法分析器
- 格式:doc
- 大小:95.00 KB
- 文档页数:5
实验4 用Yacc工具构造语法分析器
一、实验目的
掌握移进-归约技术语法分析技术,利用语法分析器生成工具Yacc/Bison实
现语法分析器的构造。
二、实验内容
利用语法分析器生成工具Yacc/Bison编写一个语法分析程序,与词法分析器
结合,能够根据语言的上下文无关文法,识别输入的单词序列是否文法的句子。
三、实验要求
1.个人完成,提交实验报告。
2.实验报告中给出采用测试源代码片断,及其对应的最右推导过程(形式可以
自行考虑,如依次给出推导使用的产生式)。
例如,程序片断
四、实验步骤
1、根据文法编写.y文件:
%{
#include
#include
#define YYSIYPE double
void yyerror(char *s)
{
printf("%s\n",s);
}
%}
%token NUM
%token BASIC IF ELSE DO BREAK REAL TRUE FALSE ID LE INDEX
%token WHILE AND OR EQ NE GE
%left '+''-'
%left '*''/'
%right UMINUS
%%
program : block {printf("program->block\n");}
;
block : '{'decls stmts'}' {printf("block->decls stmts\n");}
;
decls : decls decl {printf("decls->decls decl\n");}
| {printf("\decls->E\n");}
;
decl : type ID ';' {printf("decl->type id\n");}
;
type : type '[' NUM ']' {printf("type->type [num]\n");}
| BASIC {printf("type->basic\n");}
;
stmts : stmts stmt {printf("stmts->stmts stmt\n");}
| {printf("stmts->E\n");}
;
stmt : loc '=' bool ';' {printf("stmt->loc=bool\n");}
|IF '(' bool ')' stmt {printf("stmt->if(bool) stmt\n");}
|IF '(' bool ')' stmt ELSE stmt {printf("stmt->if(bool) stmt else stmt\n");}
|WHILE '(' bool')' stmt {printf("stmt->while(bool) stmt\n");}
|DO stmt WHILE '(' bool ')' ';' {printf("stmt->->do stmt while(bool)\n");}
|BREAK ';' {printf("stmt->break\n");}
| block {printf("stmt->block\n");}
;
loc : loc '[' bool ']' {printf("loc->loc[bool]\n");}
|ID {printf("loc->id\n");}
;
bool : bool OR join {printf("bool->bool||join\n");}
| join {printf("bool->join\n");}
;
join : join AND equality {printf("join->join && equality\n");}
| equality {printf("join->equality\n");}
;
equality : equality EQ rel {printf("equality->equality==rel\n");}
| equality NE rel {printf("equality->equality!=rel\n");}
| rel {printf("equality->rel\n");}
;
rel : expr '<' expr {printf("rel->expr
| expr '>' expr {printf("rel->expr>expr\n");}
| expr GE expr {printf("rel->expr>=expr\n");}
| expr {printf("rel->expr\n");}
;
expr : expr '+' term {printf("expr->expt+term\n");}
| expr '-' term {printf("expr->expr-term\n");}
| term {printf("expr->term\n");}
;
term : term '*' unary {printf("term->term*unary\n");}
| term '/' unary {printf("term->term/unary\n");}
| unary {printf("term->unary\n");}
;
unary : '!' unary {printf("unary->!unary\n");}
| '-' unary {printf("unary->-unary\n");}
| factor {printf("unary->factor\n");}
;
factor: '(' bool ')' {printf("factor->(bool)\n");}
| loc {printf("factor->loc\n");}
| NUM {printf("factor->num\n");}
| REAL {printf("factor->real\n");}
| TRUE {printf("factor->true\n");}
| FALSE {printf("factor->false\n");}
;
%%
2、在.y文件中添加main()函数,以及一些外部函数的声明:
#include "lex.yy.c"
int yyparse();
extern void BeginCompileOneFile( const char * filename );
extern void EndCompileOneFile(void);
void main()
{
char filename[200];
printf("请输入源程序文件名:");
scanf("%s:",filename);
BeginCompileOneFile( filename );
yyparse();
EndCompileOneFile();
}
3、修改实验三的.l文件,删除main()函数:
4、用flex.exe编译.l文件,生成lex.yy.c
5、用bison.exe编译.y文件,生成my.tab.c
6、在VC下建立工程,添加lex.yy.c和my.tab.c文件
7、以文件读入方式进行测试,测试例子为:
{
i = 2;
while (i <=100)
{
sum = sum + i;
i = i + 2;
}
}
五、实验结果
六、心得体会
其实这个实验并不难,不过很容易出错。在按照文法产生式编写.y文件时,
只要不注意写错,那或者在编译的无法生成.c文件,或者生成.c文件后在项目编
译时生成一大堆的错误。在理论课上学习了yacc进行语法分析的原理,这次通过
实验观察yacc的移入规约情况可以说是对课本知识的复习,收获很多。