实验四 用YACC实现的语法分析器
- 格式:pdf
- 大小:192.63 KB
- 文档页数:5
语法分析程序自动产生器yacc的使用方法2.l yacc概述形式语言都有严格定义的语法结构,我们对它们进行处理时首先要分析其语法结构。
yace 是一个语法分析程序的自动产生器,严格地说Lex也是一个形式语言的语法分析程序的自动产生器。
不过Lex所能处理的语言仅限于正规语言,而高级语言的词法结构恰好可用正规式表示,因此Lex只是一个词法分析程序的产生器。
yace可以处理能用LALR(1)文法表示的上下文无关语言。
而且我们将会看到yace具有一定的解决语法的二义性的功能。
yacc的用途很广,但主要用于程序设计语言的编译程序的自动构造上。
例如可移植的C 语言的编译程序就是用yacc来写的。
还有许多数据库查询语言是用yacc实现的。
因此,yacc 又叫做“编译程序的编译程序("A Compiler ComPiler")。
yacc的工作示意图如下;图2.1 yacc示意图在图2.1中,“yacc源程序”是用户用yacc提供的一种类似BNF的语言写的要处理的语言的语法描述。
yacc会自动地将这个源程序转换成用LR方法进行语法分析的语法分析程序yyparse,同Lex一样,yacc的宿主语言也是C,因此yyParse是一个C语言的程序,用户在主程序中通过调用yyparse进行语法分析。
语法分析必须建立在词法分析的基础之上,所以生成的语法分析程序还需要有一个词法分析程序与它配合工作。
yyparse要求这个词法分析程序的名字为yylex。
用户写yylex时可以借助于Lex。
因为Lex产生的词法分析程序的名字正好是yylex,所以Lex与yacc配合使用是很方便的,这将在2.5的2.5.3中详细介绍,请注意词法分析程序也是可以包含在yacc 源程序中的。
在yacc源程序中除了语法规则外,还要包括当这些语法规则被识别出来时,即用它们进行归约时要完成的语义动作,语义动作是用C语言写的程序段。
语法分析的输出可能是一棵语法树,或生成的目标代码,或者就是关于输入串是否符合语法的信息。
实验四借助Flex/Bison进行语法分析一.说明:利用附录提供的C语言文法的相关参考资料,利用Yacc/Bison编写一个C语言分析器。
二.具体内容:利用语法分析器生成工具Bison编写一个语法分析程序,与词法分析器结合,能够根据语言的上下文无关文法,识别输入的单词序列是否文法的句子。
三.实验要求:实验资料如下:3.1 阅读Flex源文件input.lex、Bison源文件cgrammar-new.y。
3.2 实现C 语言的语法分析功能,最后上机调试。
3.3 生成语法分析程序2_2.exe,以给定的测试文件作为输入,输出运行结果到输出文件中。
四.实验过程:(1)执行以下命令,生成lex.yy.c、cgrammar-new.tab.h、cgrammar-new.tab.c。
(2)cgrammar-new.y有移近规约冲突。
执行命令bison -d cgrammar-new.y 后,Bison提示移近规约冲突“cgrammar-new.y: conflicts: 1 shift/reduce”。
以Bison的"-v"选项生成状态机描述文件cgrammar-new.output,即执行bison -d cgrammar-new.y。
cgrammar-new.output文件内容如下:修改以下两处:2.1 在yacc的头部加入%nonassoc LOWER_THAN_ELSE%nonassoc ELSE2.2 在355行加入%prec LOWER_THAN_ELSE(3)编译使用cl.exe或gcc编译器,编译lex.yy.c cgrammar-new.tab.c main.c parser.c。
使用cl.exe编译后,得到以下错误提示:修改lex.yy.c,使其能顺利编译。
3.1 将lex.yy.c中的#ifdef __cplusplusstatic int yyinput()#elsestatic int input()#endif改为static int yyinput()2.2 将lex.yy.c中的#ifdef __cplusplusreturn yyinput();#elsereturn input();#endif改为return yyinput();(3)生成可执行文件2_2.exe,并分析源文件test.c。
使用Yacc生成语法分析程序1、创建空工程File菜单下选择New:弹出下面对话框:选择Win32 Console Application,同时在Project Name下输入工程名字:ParserByYacc点击Ok按钮,弹出下面对话框:不做任何选择,按照默认“An empty project”,直接点击Finish按钮,弹出下面对话框:直接点击OK按钮,工程创建完毕。
2、使用Yacc生成语法分析程序点击“开始”,在“开始”菜单中选择“运行”,如下图所示在弹出的对话框中敲入cmd,启动DOS窗口使用DOS命令切换到E:\ ParserByYacc将yacc.exe文件拷贝到ParserByYacc工程下:将编写好的TINY.Y文件拷贝到ParserByYacc工程下:运行yacc生成y.tab.c和y.tab.h文件:3、添加文件首先在windows环境下,把设计好的文件GLOBALS.H、MAIN.C、SCAN.C、SCAN.H、PARSE.H、UTIL.C 和UTIL.H拷贝到ParserByYacc工程下:如图所示,选中Project菜单,选择下面Add To Project子菜单下面的Files子菜单:点击后弹出对话框:选中的刚拷贝进来的文件和Yacc生成的文件,点击OK按钮:在左侧的工程文件列表中,可以清楚地看到这些文件:4、生成可执行文件编译生成可执行文件ParserByYacc.exe在本工程的debug目录下:为了验证本语法分析程序的运行结果,把样本程序SAMPLE.TNY拷贝到可执行程序所在的目录下:5、验证运行结果Windows环境下点击“开始”,选中其中的“运行(R)”弹出下面对话框,输入cmd命令:输入上图所示的类似命令,进入可执行程序所在目录。
在当前目录下输入命令:ParserByYacc sample.tny,然后回车,则得到相应的运行结果:。
实验2.4 学习YACC并构造简单语法分析程序一、实验目的1. 学习使用辅助软件YACC2. 理解语法分析程序的构造原理二、实验内容构造一个PL/0程序的命令行简易版本程序,要求具有变量和常量定义语句Var和Const,具有基本输入输出语句Read 和Write,包含基本的算术运算+ 、-、*、/ 和( ) 运算,语句以分号(;)结束,整个程序以END结束。
1. 学习YACC语法的使用具体内容可参考课本附录2. 使用LEX构造词法分析程序yylex.c示例代码:\+ {return '+';}\* {return '*';}":=" {return BECOMES;}\, {return ',';}\; {return ';';}V AR|var {return V AR;}[a-zA-Z][a-zA-Z0-9]* {strcpy(yylval.str,yytext);return IDENT;}3. 使用YACC构造语法分析程序构造符合YACC语法的程序PL0.YACPL0.YAC示例代码:%union {char str[MAXSTRLEN];int num;}%token V AR CONST READ WRITE EXIT BECOMES%token <num> NUMBER%token <str> IDENT%type <num> number%type <str> ident%type <num> expression%left '+' '-'%left '*' '/'%left UMINUS%%begins : /*empty*/| begins program;program : var_state ';'| const_state ';'| statement ';'| error ';'{};var_state : VAR var_list{};var_list : a_var_list| var_list ',' a_var_list{};a_var_list : ident{ i=position($1);if (i) printf("Error: variable (%s) already defines \n",$1);else { if (tx==MAXTABLESIZE)printf("Error: table full(only%d numbers) ,varible define error \n",MAXTABLESIZE);else {strcpy(table[tx].name,$1);table[tx].kind=V ARLABEL;printf("variable (%d):%s successfullt defined.\n",tx,$1);tx++;}}};statement : write_state| read_state| value_state| exit_state ';'write_state: WRITE '(' write_list ')'{ if (debug) printf("(write_statement finished)\n");};write_list : a_write| write_list ',' a_write;a_write : expression{ printf("%d\n",$1);}%%#include "lexyy.c"int yyparse();main(){return yyparse();}4. 生成目标代码并运行1) 生成C语言源程序在DOS 命令提示符下运行Y ACC.exeYACC pl0.yac产生C语言代码pl0.C2)进入TC集成环境将.C文件编译产生可执行文件.EXETC pl0.C3)在DOS 命令提示符下执行生成的pl0.exe输入程序示例如下:Const a =3 ;Var b,c ;Read(b);c := a + b ;Write(c) ;END.三、实验报告按照语法分析的原理,给出借助Y ACC自动生成语法分析器的过程描述,和生成的语法分析程序是如何运作的。
编译原理课内实验报告学生姓名石磊专业/班级计算机26学号2120505140所在学院电信学院提交日期2014-12-2一:实验目的:1.强化对系统软件综合工程实现能力的训练;2.加强对语法分析原理、方法和基本实现技术的理解;二:实验内容1.用C语言或者其他的高级语言作为宿主语言完成C0语言的词法分析器的设计和实现。
2.针对if语句的文法编写一个递归下降分析程序,输出结果为抽象语法树。
注意,if语句文法中的表达式E采用四则运算表达式的文法;抽象语法树的格式自行设计,如果需要降低难度的话,也可用具体语法树而不用抽象语法树作为输出。
三:实验功能描述语言的语法分析器的源程序并调试通过。
其中语法分析程序既可1.编写C以自己手动去完成,也可以利用YACC自动生成。
2. 通过测试程序的验收;四:功能描述:该语法分析器用yacc生成,针对if语句的文法编写的向下递归程序,输出结果为语法树,实现了实验目标,达到了实验要求。
五:实验程序代码%{#include <string.h>#include <stdlib.h>#include "yystype.h"#include "y.tab.h"#include "treedisp.h"int yycount = 0;extern YYSTYPE yylval;#define NSYMS 20struct symtab {char *name;double value;} symtab[NSYMS];struct symtab *symlook(char *s);#define NRSVS 10struct rsvtab {char *name;int id;} rsvtab[NRSVS] = {{"if", IF},{"else", ELSE},{"while", WHILE},{"for", FOR},{"other", OTHER},{"var", VAR}};int rsvlook(char *s);%}digit [0-9]integer {digit}+eq "=="pl "+"mi "-"mu "*"di "/"sc ";"as "="identifier [a-zA-Z][a-zA-Z0-9_]*delim [ \n\t]ws {delim}+other "other"%%{integer} {//yylval = atoi(yytext);rec_token("INTEGER");return INTEGER;}{identifier} {if (rsvlook(yytext) != 0) {rec_token("RESERVED");return rsvlook(yytext);}rec_token("SYMBOL");return SYMBOL;{eq} { rec_token("OPR"); return EQ; } {pl} { rec_token("OPR"); return PL; } {mi} { rec_token("OPR"); return MI; } {mu} { rec_token("OPR"); return MU; } {di} { rec_token("OPR"); return DI; } {as} { rec_token("OPR"); return ASSIGN; } {sc} { rec_token("SC"); return SC; }\( { rec_token("LB"); return LB; }\) { rec_token("RB"); return RB; }{ws} ;. {printf("error: %s\n", yytext);yyerror("Illigal input.");}%%char *buffer[20];void rec_token(char *s) {yylval.token_id = ++yycount;yylval.text = strdup(yytext);sprintf(buffer, "%s(%s)", s, yytext);name_node(yycount, buffer);}int rsvlook(char *s) {struct rsvtab *sp;for (sp = rsvtab; sp < &rsvtab[NRSVS]; ++sp) { if (sp->name && !strcmp(sp->name, s))return sp->id;}return 0;}struct symtab *symlook(char *s) {struct symtab *sp;for (sp = symtab; sp < &symtab[NSYMS]; ++sp) { if (sp->name && !strcmp(sp->name, s))return sp;if (!sp->name) {sp->name = strdup(s);return sp;}}yyerror("Too many symbols.");exit(1);}测试代码:if (1+1)if (2*3+5)if (3*4+9)if (5*3+2)other;elseother;elseother;elseother;elseb=2*3+5;测试结果:stseq├── statement│└── mifst│├── RESERVED(if)│├── LB(()│├── exp││└── term││└── factor││└── INTEGER(1)│├── RB())│├── mifst││├── RESERVED(if)││├── LB(()││├── exp│││├── term││││├── term│││││└── factor│││││└── INTEGER(2) ││││├── OPR(*)││││└── factor││││└── INTEGER(3)│││├── OPR(+)│││└── exp│││└── term│││└── factor│││└── INTEGER(5) ││├── RB())││├── mifst│││├── RESERVED(if)│││├── LB(()│││├── exp││││├── term│││││├── term││││││└── factor││││││└── INTEGER(3)│││││├── OPR(*)│││││└── factor│││││└── INTEGER(4)││││├── OPR(+)││││└── exp││││└── term││││└── factor││││└── INTEGER(9)│││├── RB())│││├── mifst││││├── RESERVED(if)││││├── LB(()││││├── exp│││││├── term││││││├── term│││││││└── factor│││││││└── INTEGER(5) ││││││├── OPR(*)││││││└── factor││││││└── INTEGER(3)│││││├── OPR(+)│││││└── exp│││││└── term│││││└── factor│││││└── INTEGER(2) ││││├── RB())││││├── statement│││││├── RESERVED(other)│││││└── SC(;)││││├── RESERVED(else)││││└── statement││││├── RESERVED(other)││││└── SC(;)│││├── RESERVED(else)│││└── statement│││├── RESERVED(other)│││└── SC(;)││├── RESERVED(else)││└── statement││├── RESERVED(other)││└── SC(;)│├── RESERVED(else)│└── mifst│├── SYMBOL(b)│├── OPR(=)│├── exp││├── term│││├── term││││└── factor││││└── INTEGER(2)│││├── OPR(*)│││└── factor│││└── INTEGER(3)││├── OPR(+)││└── exp││└── term││└── factor││└── INTEGER(5)│└── SC(;)└── stseq└── (empty)六:实验心得在本次实验中,我耗费了大量时间来设计分析设计。
⽤Yacc实现语法分析器-4-编译原理⽤Yacc实现语法分析器⼀、实验⽬的掌握语法分析器的构造原理,掌握Yacc的编程⽅法。
⼆、实验内容⽤Yacc编写⼀个语法分析程序,使之与词法分析器结合,能够根据语⾔的上下⽂⽆关⽂法,识别输⼊的单词序列是否⽂法的句⼦。
program→blockblock→ { stmts }stmts→ stmt stmts | estmt→ id= expr ;| if ( bool ) stmt| if ( bool) stmt else stmt| while (bool) stmt| do stmt while (bool ) ;| break ;| blockbool →expr < expr| expr <= expr| expr > expr| expr >= expr| exprexpr→expr + term| expr - term| termterm→term * factor| term / factor| factorfactor→ ( expr ) | id| num 三、实验步骤及结果实验环境:unix实验结果:按归约的先后顺序显⽰每次归约时所使⽤的产⽣式。
部分代码:⽤于产⽣flex输⼊的代码View CodeTest.l:[a-zA-Z_][a-zA-Z_0-9]* {return ID;}[0-9]+\.[0-9]+ {return REAL;}[0-9]+ {return NUM;}"||" {return OR;}"&&" {return AND;}"|" {return'|';}"&" {return'&';}"<=" {return LE;}"<" { return'<';}">=" {return GE;}">" {return'>';}"!=" {return NE;}"=" { return'=';}"==" {return EQ;}"\+" {return'+';}"\-" {return'-';}"\*" {return'*';}"\/" {return'/';}"(" {return'(';}")" {return')';}";" {return';';}"{" {return'{';}"}" {return'}';}"[" {return'['; }"]" {return']';}Test.y:rel : expr '<' expr { printf("rel-->expr<expr\n"); }| expr LE expr { printf("rel-->expr<=expr\n"); }| expr GE expr { printf("rel-->expr>=expr\n"); }| expr '>' expr { printf("rel-->expr>expr\n"); }| expr { printf("rel-->expr\n"); };expr : expr '+' term { printf("expr-->expr+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 %prec UMINUS{ 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"); }Flex⽣成代码:View CodeTest.l:[a-zA-Z_][a-zA-Z_0-9]* {return ID;}[0-9]+\.[0-9]+ {return REAL;}[0-9]+ {return NUM;}"||" {return OR;}"&&" {return AND;}"|" {return'|';}"&" {return'&';}"<=" {return LE;}"<" { return'<';}">=" {return GE;}">" {return'>';}"!=" {return NE;}"=" { return'=';}"==" {return EQ;}"\+" {return'+';}"\-" {return'-';}"\*" {return'*';}"\/" {return'/';}"(" {return'(';}")" {return')';}";" {return';';}"{" {return'{';}"}" {return'}';}"[" {return'['; }"]" {return']';}Test.y:rel : expr '<' expr { printf("rel-->expr<expr\n"); } | expr LE expr { printf("rel-->expr<=expr\n"); }| expr GE expr { printf("rel-->expr>=expr\n"); } | expr '>' expr { printf("rel-->expr>expr\n"); }| expr { printf("rel-->expr\n"); };expr : expr '+' term { printf("expr-->expr+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 %prec UMINUS{ 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"); }Yacc⽣成部分代码:View Code#line 1334 "y.tab.c"yyvsp -= yylen;yyssp -= yylen;YY_STACK_PRINT (yyss, yyssp);*++yyvsp = yyval;/* Now `shift' the result of the reduction. Determine what statethat goes to, based on the state we popped back to and the rulenumber reduced by. */yyn = yyr1[yyn];yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate];elseyystate = yydefgoto[yyn - YYNTOKENS];goto yynewstate;/*------------------------------------.| yyerrlab -- here on detecting error |`------------------------------------*/yyerrlab:/* If not already recovering from an error, report this error. */if (!yyerrstatus){++yynerrs;#if YYERROR_VERBOSEyyn = yypact[yystate];if (YYPACT_NINF < yyn && yyn < YYLAST){YYSIZE_T yysize = 0;int yytype = YYTRANSLATE (yychar);const char* yyprefix;char *yymsg;int yyx;/* Start YYX at -YYN if negative to avoid negative indexes inYYCHECK. */int yyxbegin = yyn < 0 ? -yyn : 0;/* Stay within bounds of both yycheck and yytname. */int yychecklim = YYLAST - yyn;int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;int yycount = 0;yyprefix = ", expecting ";for (yyx = yyxbegin; yyx < yyxend; ++yyx)if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR){yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);yycount += 1;if (yycount == 5){yysize = 0;break;}}yysize += (sizeof ("syntax error, unexpected ")+ yystrlen (yytname[yytype]));yymsg = (char *) YYSTACK_ALLOC (yysize);if (yymsg != 0){char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");yyp = yystpcpy (yyp, yytname[yytype]);if (yycount < 5){yyprefix = ", expecting ";for (yyx = yyxbegin; yyx < yyxend; ++yyx)if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR){yyp = yystpcpy (yyp, yyprefix);yyp = yystpcpy (yyp, yytname[yyx]);yyprefix = " or ";}}yyerror (yymsg);YYSTACK_FREE (yymsg);}elseyyerror ("syntax error; also virtual memory exhausted");}else例如,程序⽚断{i = 2;while (i <=100){sum = sum + i;i = i + 2;}}(注:原本是在windwos环境下编程,最后到unix环境下,发现速度快了,灵活性⾼了,同时⽅便了很多。
编译原理实践yacc(sql查询语句解析) 概述说明1. 引言1.1 概述本篇文章旨在介绍编译原理实践中使用Yacc工具对SQL查询语句进行解析的过程。
编译原理是计算机科学中的重要研究领域,主要涉及将高级语言转化为低级的机器语言,以便计算机能够理解和执行。
通过使用编译原理中的概念和技术,可以大大简化复杂语法的分析和解析过程,提高程序开发的效率。
1.2 文章结构本文共分为五个部分,每个部分都有其特定的内容和目标:- 引言:介绍本篇文章的背景和目的。
- 编译原理实践yacc:阐述编译原理及介绍Yacc工具在该领域中的应用。
- SQL查询语句解析过程:详细讲解SQL查询语句的基本结构、词法分析过程以及语法分析过程。
- Yacc工具的使用和配置:指导读者如何安装Yacc工具,并演示如何编写Yacc 源文件以及生成解析器代码并进行运行。
- 结论与展望:总结全文内容并提供未来可能的拓展方向。
1.3 目的本文目的在于通过对编译原理和Yacc工具在SQL查询语句解析中的应用进行介绍,帮助读者更好地理解编译原理的相关概念,并掌握使用Yacc工具进行语法分析和解析的方法。
通过实践演示和案例讲解,读者能够学会配置和使用Yacc 工具,并将其应用于自己感兴趣的领域。
以上为“1. 引言”部分内容的详细描述,请结合实际情况进行参考与调整。
2. 编译原理实践yacc2.1 什么是编译原理编译原理是计算机科学领域的一个重要分支,研究如何将高级程序语言转换为机器语言。
它涉及到编程语言的词法分析、语法分析和代码生成等多个方面。
通过编译原理,我们可以了解程序如何被解释和执行,从而能够更好地设计和优化程序。
2.2 Yacc介绍Yacc(Yet Another Compiler Compiler)是一款用于生成语法解析器的工具。
它是由AT&T贝尔实验室的Stephen C. Johnson在20世纪70年代开发的,并成为Unix操作系统环境下广泛使用的编译器工具之一。
实验4 用Yacc工具构造语法分析器一、实验目的掌握移进-归约技术语法分析技术,利用语法分析器生成工具Yacc/Bison实现语法分析器的构造。
二、实验内容利用语法分析器生成工具Yacc/Bison编写一个语法分析程序,与词法分析器结合,能够根据语言的上下文无关文法,识别输入的单词序列是否文法的句子。
三、实验要求1.个人完成,提交实验报告。
2.实验报告中给出采用测试源代码片断,及其对应的最右推导过程(形式可以自行考虑,如依次给出推导使用的产生式)。
例如,程序片断四、实验步骤1、根据文法编写.y文件:%{#include<ctype.h>#include<stdio.h>#define YYSIYPE doublevoid 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\n");}| expr LE expr {printf("rel->expr<=expr\n");}| 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.c5、用bison.exe编译.y文件,生成my.tab.c6、在VC下建立工程,添加lex.yy.c和my.tab.c文件7、以文件读入方式进行测试,测试例子为:{i = 2;while (i <=100){sum = sum + i;i = i + 2;}}五、实验结果六、心得体会其实这个实验并不难,不过很容易出错。