实验四 用YACC实现的语法分析器
语法分析程序自动产生器yacc的使用方法
语法分析程序自动产生器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语言写的程序段。
语法分析的输出可能是一棵语法树,或生成的目标代码,或者就是关于输入串是否符合语法的信息。
实验四 借助FlexBison进行语法分析
实验四借助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。
编译原理实践11—语法分析程序的自动生成工具YACC
YACC源程序—语法规则部分
•语法规则部分是整个YACC源程序的主体,它是由一组 产生式及相应的语义动作组成。 •规则部分包括修改的BNF格式的文法规则,以及将在识 别出识别出相关的文法规则时被执行的C代码中的动作 (即根据LALR(1)分析算法,在归约中使用)。 •文法规则中使用的元符号惯例如下: 通常,竖线|被用作替换(也可以分别写出替换项),而 用来分隔文法规则的左右两边的箭头符号-〉在YACC中 用冒号表示,最后,必须用分号来结束每个文法规则。
•YACC和LEX有直接的接口,由于YACC与LEX 的特殊功能,这两个姐妹程序成为软件工程的重 要工具,被称为“黄金组合”。
•很多程序设计语言编译程序的设计都使用了 LEX和YACC,比如著名的GNU C语言编译器, PASCAL语言向C语言的转换工具p2c等,就是 用FLEX和BISON实现的
6-语义值类型定义 • 例:
% union{ int ival double dval INTERVAL vval; }
• 引用时候的方式
%token <ival> DREG VREG %token <dval> CONST %type <dval>dexp %type <vval>vexp
以%token开始的行定义的是终结符的类型 以%type开始的行定义是非终结符的类型
exp:exp’+’term{$$=$1+$3;}
含义是:当识别规则exp-〉exp+term时, 左边exp值为右边的exp的值与右边的term 的值之和,其中$$代表规则左部符号exp的 值,$1代表规则右部第一个符号exp的值、 $3表示规则右部第三个符号term的值。
语法分析器生成器YACC
E : num num
再分析3++5
5
分析器动作 移进 num,转向state 3 按(2)“E : num”归约,goto State 1 移进 +,转向State 4 移进error,转向 state 2 按(3)“E : error”归约,goto State 5, 按(1)“E : E‘+’E”归约,goto State 1 移进 +,转向State 4 移进 num,转向 State 3 按(2)“E : num”归约,goto State 5 按(1)“E : E‘+’E”归约,goto State 1 接受
2.2.3.2 YACC对语义的支持
分析器工作原理:
记号流 归约前栈顶 归约后栈顶 $3 E $2 + $1($$) E ... ... 驱动器 分析表 输出
语义栈对语法制导翻译提供直接支持。语义栈的 类型决定了文法符号的属性,语义栈类型表示能力的 强弱决定了YACC的能力。
<1> YACC默认的语义值类型 YACC语义栈与yylval同类型,并以终结符的yylval 值作为栈中的初值。因为yylval的默认类型为整型,所 以,当用户所需文法符号的语义类型是整型时,无需定 义它的类型。如在下述表达式的产生式中: E :E '+' E | E '*' E | num ; { $$=$1+$3;} { $$=$1*$3;}
2.2.1 YACC概述
利用YACC进行语法分析器设计的关键,也是如何编写 YACC源程序。 下边首先介绍YACC源程序的基本结构,然后着重讨论 YACC的产生式、YACC解决产生式冲突的方法、以及YACC对语 义的支持和对错误的处理等。
Yacc语法分析器设计步骤
使用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并构造简单语法分析程序
实验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实现语法分析器-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查询语句解析)_概述说明
编译原理实践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操作系统环境下广泛使用的编译器工具之一。
实验四 用Yacc实现的语法分析器
实验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;}}五、实验结果六、心得体会其实这个实验并不难,不过很容易出错。
4 语法分析上机
4 参考解决方案
mylexer.l主要源代码: digit [0-9] digits {digit}+ optional_fraction ("."{digits})? optional_exponent (E[+-]?{digits})? %% []+ ; //过滤空格 {digits}{optional_fraction}{optional_exponent} { return NUMBER; } "+" { return '+'; } "-" { return '-'; } "*" { return '*'; } "/" { return '/'; } "(" { return '('; } ")" { return ')'; } "\n" { return 0; //回车返回0,代表词法分析器读取完毕}
{ printf("识别加法!\n"); } { printf("识别减法!\n"); } { printf("识别乘法!\n"); } { printf("识别除法!\n"); } { printf("识别括号!\n"); } { printf("识别数字!\n"); }
//语法规则产生式 //语义动作
6
4 参考解决方案
执行结果:每次输入一个算术运算表达式,输出分析结果
注意:Yacc自动调用yylex()返回一个记号
语法分析器
实验二:语法分析器一、 实验目的:1.强化对系统软件综合工程实现能力的训练;2.采用各种设计方法实现语法分析程序;二、 实验内容:语言的语法分析程序的实用C语言或者其他的高级语言作为宿主语言完成C1现。
三、 实验要求:语言的语法分析器,生成语法分析树。
其中语法分析程序既可以1.实现C1自己手动去完成,也可以利用YACC自动生成。
程序的输入:C语言源程序或者词法分析阶段的输出文件程序的输出:存储了语法分析树信息的XML格式的文件2. 通过测试程序的验收;3.实验报告按照提供的模板填写:(1)功能描述:该程序具有什么功能?(2)程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;另外可以附加函数之间的调用关系图、程序总体执行流程图。
(3)实验总结:你在编程过程中花时多少?多少时间在纸上设计?多少时间上机输入和调试?多少时间在思考问题?遇到了哪些难题?你是怎么克服的?你对你的程序的评价?你的收获有哪些?四、 评判标准:1. 程序的正确性;2. 程序结构清晰,代码规范;3. 提交报告,报告阐述清楚。
五、 程序工作说明:(以C1语言为例)程序的输入是C语言源程序或者前一阶段词法分析器的输出文件。
程序的输出为包含了语法树相关信息的XML格式的文件程序输入/输出示例:如源程序为如下:1.void f1(int a,int b) {2. a = 1;3. b = a+b;4.}5.void main()6.{7. int a[100];8. int b;9. float c;10. a[b]=a;11. if(c<b){12. f1(a,b);13. }14.}那么词法分析输出文件:<?xml version="1.0"?><root><token line="1" type="VOID" string="void" /> <token line="1" type="ID" string="f1" /><token line="1" type="LPAREN" string="(" /> <token line="1" type="INT" string="int" /> <token line="1" type="ID" string="a" /><token line="1" type="COMMA" string="," /> <token line="1" type="INT" string="int" /> <token line="1" type="ID" string="b" /><token line="1" type="RPAREN" string=")" /> <token line="1" type="LBRACE" string="{" /> <token line="2" type="ID" string="a" /><token line="2" type="ASSIGN" string="=" /> <token line="2" type="NUMBER" string="1" /> <token line="2" type="SEMI" string=";" /> <token line="3" type="ID" string="b" /><token line="3" type="ASSIGN" string="=" /> <token line="3" type="ID" string="a" /><token line="3" type="ADD" string="+" /><token line="3" type="ID" string="b" /><token line="3" type="SEMI" string=";" /> <token line="4" type="RBRACE" string="}" /> <token line="5" type="VOID" string="void" /> <token line="5" type="ID" string="main" /> <token line="5" type="LPAREN" string="(" /> <token line="5" type="RPAREN" string=")" /> <token line="6" type="LBRACE" string="{" /> <token line="7" type="INT" string="int" />>>><token line="7" type="ID" string="a" />><token line="7" type="ASSIGN" string="=" />><token line="7" type="LSQUAR" string="[" /><token line="7" type="NUMBER" string="100" /><token line="7" type="RSQUAR" string="]" /><token line="7" type="SEMI" string=";" /><token line="8" type="INT" string="int" /><token line="8" type="ID" string="b" /><token line="8" type="SEMI" string=";" /><token line="9" type="FLOAT" string="float" /> <token line="9" type="ID" string="c" /><token line="9" type="SEMI" string=";" /><token line="10" type="ID" string="a" /><token line="10" type="LSQUAR" string="[" /><token line="10" type="ID" string="b" /><token line="10" type="RSQUAR" string="]" /><token line="10" type="ASSIGN" string="=" /><token line="10" type="ID" string="a" /><token line="10" type="SEMI" string=";" /><token line="11" type="IF" string="if" /><token line="11" type="LPAREN" string="(" /><token line="11" type="ID" string="c" /><token line="11" type="LT" string="<" /><token line="11" type="ID" string="b" /><token line="11" type="LBRACE" string="{" /><token line="12" type="ID" string="f1" /><token line="12" type="LPAREN" string="(" /><token line="12" type="ID" string="a" /><token line="12" type="COMMA" string="," /><token line="12" type="ID" string="b" /><token line="12" type="SEMI" string=";" /><token line="13" type="RBRACE" string="}" /><token line="14" type="RBRACE" string="}" /></root>语法分析器以此文件作为输入,产生以下输出文件:<?xml version="1.0" ?><file name="test.c">line="1"<Prog<DecListline="1"line="1"<Declline="1"<FunDecl/line="1"<TypeSpecstring="void"<ID line="1" string="f1" /><LPARTEN line="1" string="(" /><ID line="1" string="a" /><ID line="1" string="b" /><RPARTEN line="1" string=")" /><CompStmt line="1"><LBRACE line="2" string="{" /> <LoclDecls line="2" /> <StmtList line="2"> <Stmt line="2"> <ExprStmt line="2"> <Expr line="2"> <Var line="2"><ID line="2" string="a" /></Var > <ASMT line="2" string="=" /><Expr line="2"> <SimpExpr line="2"> <AddExpr line="2"> <Term line="2"> <Factor line="2"> <NUMBER line="2" string="1" /> </Factor > </Term > </AddExpr > </SimpExpr > </Expr ></Expr ><SEMI line="2" string=";" /></ExprStmt ></Stmt >...六、 参考书目:1. Kenneth C. Louden 著,冯博琴译《编译原理及实践》,机械工业出版社,2000年2. Andrew W.Appel 著,赵克佳等译《现代编译原理C 语言描述》人民邮电出版社,2006年3. 陈火旺,刘春林等,《程序设计语言编译原理》第三版,国防科大出版社,2001年。
语法分析器-YACC实验报告
|__Assign
|__VarId name:i
|__Expression type:+
|__VarId name:low
|__Number type:INT, value:1
|__While
|__Expression type:<
|__VarId nameACC文件格式
Lex文件分成三个部分,分别为definitions、rules以及auxiliary routines,中间用%%分割开。
Definitions包括要加入到生成的C程序的头部的代码,包括#include语句、#define语句及一些全局变量的定义。token也在Definitions部分定义,YACC规定,必须自己定义token,他将token定义为一系列从258开始的正整数,如在Definition部分加入了如下定义:%token NUMBER, 则在生成的C代码中:#define NUMBER 258。当然这个值也可以由用户定义。
3.如果产生式右边有多余一个的Symbol,则必须为$$建立结点,并将右面的Symbol作为他的儿子,如果有ID、NUM、type_specfier,和关键字,则不需建立结点,直接赋值给结点中的变量或忽略(结点类型自动说明)。
如:
iteration_stmt:WHILE LPARENTHESIS expression RPARENTHESIS statement
1.如果有NUM,则立刻用一个变量暂存,因为后面的识别会把TokenValue覆盖掉。
如:type_specifier id LBRACKET NUM { /*记录NUM*/ currentNum = atoi(tokenString); } RBRACKET SEMICOLON
C语言Yacc语法分析_v0.5
TDD技术总结与学习笔记C语言Yacc语法分析第0.5版Pizer.Fan目录目录 (2)文档目的与范畴 (4)术语与缩写 (4)1FLEX/YACC概述 (5)1.1F LEX概述 (11)1.2Y ACC概述 (11)1.2.1Yacc基本术语 (12)1.2.2Yacc语法分析树的设计 (12)2了解C语言语法 (13)3C语言语法分析树 (17)3.1申明 (17)3.1.1带修饰符的类型 (17)3.1.2申明名称 (20)3.1.3初始化值 (21)3.2函数定义 (21)3.3语句 (23)3.3.1跳转语句 (23)3.3.2标签语句 (24)3.3.3复合语句 (24)3.3.4选择语句 (24)3.3.5循环语句 (24)3.3.6表达式语句 (25)3.4表达式 (25)3.4.1基本表达式 (26)3.4.2后缀表达式 (27)3.4.3一元表达式 (27)3.4.4强制表达式 (28)3.4.5乘除表达式 (28)3.4.6加减表达式 (28)3.4.7移位表达式 (28)3.4.8关系表达式 (28)3.4.9等式表达式 (28)3.4.10位表达式 (28)3.4.11逻辑表达式 (29)3.4.12条件表达式 (29)3.4.13赋值表达式 (29)附件A-图索引 (30)附件B-参考 (30)文档目的与范畴以文档形式记录学习过程的心得,旨在促进同仁间技术交流,相互提高相关技术水平。
本文档主要分析了TD-SCDMA移动终端Packet-Switched业务的需求、系统分析以及概要设计等,这些的前提范畴:y TD-SCDMAy Packet-Switched术语与缩写术语全称以及解释1 远程调试技术在远程调试技术中,如何实现调试器与目标程序之间的调试命令?一般情况下,调试器与目标程序之间,可以通过“变量设置”、“注入消息”以及“函数调用”等实现。
调试器与目标程序是远程通信的,并不在同一进程中,如何实现两者之间的调试命令?下面是一个参考设计图:调试器图 1调试器之参考设计主要模块功能: z 调试器SHELL :图形模式:提供用户操作界面——譬如查看或者设置变量值,支持脚本的运行 文本模式:控制台模式下的调试器z 调试器核心:提供“目标”所有的类型信息以及“目标”中待调试的全局变量信息等,调试器核心以动态链接库形式存在,往上提供统一的接口,同时也便于支持脚本。
yacc用法
yacc用法Yacc(Yet Another Compiler-Compiler)是Unix操作系统中的一款语法分析器生成工具,用于生成编译器中的语法分析器(Parser)。
它可以通过输入一份文法来生成对应的语法分析器程序,并将其集成到对应的编译器中,用于识别和分析源代码中的语法结构。
Yacc的使用一般分为以下几步:1. 编写语法规则在使用Yacc生成语法分析器之前,需要先定义一组语法规则。
语法规则是定义程序语言的基础,它将源代码中的各种语法结构表示为一系列的规则。
例如,以下是一个简单的C语言语法规则:program: statements | /* empty*/ ; statements: statement | statements statement ;statement: ifstmt | whilestmt | assigstmt ;ifstmt: IF expr THEN statements | IF expr THEN statements ELSE statements ;whilestmt: WHILE expr DO statements ;assigstmt: ID '=' expr ;其中,各个非终结符(例如program、statements)表示一种语法结构,而终结符(例如IF、THEN、ID、=)表示源代码中的具体单词。
2. 编写语法分析器在定义好语法规则之后,可以使用Yacc生成对应的语法分析器。
首先,在命令行中输入以下命令:yacc -d parser.y其中,-d选项表示输出相应的头文件,并且在生成语法分析器时使用了名为parser.y的源文件。
执行完该命令后,将生成y.tab.c和y.tab.h两个文件,其中y.tab.c 就是生成的语法分析器源代码。
接下来,可以根据需要修改y.tab.c源代码,并将其集成到编译器中,以实现源代码的语法分析。
语法分析器实验报告
语法分析器实验报告实验报告:语法分析器的设计与实现摘要:语法分析器是编译器的一个重要组成部分,主要负责将词法分析器输出的词法单元序列进行分析和解释,并生成语法分析树。
本实验旨在设计与实现一个基于上下文无关文法的语法分析器,并通过实现一个简单的编程语言的解释器来验证其功能。
1.引言在计算机科学中,编译器是将高级程序语言转化为机器语言的一种工具。
编译器通常由词法分析器、语法分析器、语义分析器、中间代码生成器、优化器和目标代码生成器等多个模块组成。
其中,语法分析器负责将词法分析器生成的词法单元序列进行进一步的分析与解释,生成语法分析树,为后续的语义分析和中间代码生成提供基础。
2.设计与实现2.1上下文无关文法上下文无关文法(CFG)是指一类形式化的语法规则,其中所有的产生式规则都具有相同的左部非终结符,且右部由终结符和非终结符组成。
语法分析器的设计与实现需要依据给定的上下文无关文法来进行,在本实验中,我们设计了一个简单的CFG,用于描述一个名为"SimpleLang"的编程语言。
2.2预测分析法预测分析法是一种常用的自顶向下的语法分析方法,它利用一个预测分析表来决定下一步的推导选择。
预测分析表的构造依赖于给定的上下文无关文法,以及文法的FIRST集和FOLLOW集。
在本实验中,我们使用了LL(1)的预测分析法来实现语法分析器。
2.3语法分析器实现在实现语法分析器的过程中,我们首先需要根据给定的CFG构造文法的FIRST集和FOLLOW集,以及预测分析表。
接下来,我们将词法分析器输出的词法单元序列作为输入,通过不断地匹配输入符号与预测分析表中的预测符号,进行语法分析和推导。
最终,根据CFG和推导过程,构建语法分析树。
3.实验结果与分析通过实验发现,自顶向下的预测分析法在对简单的编程语言进行语法分析时具有较高的效率和准确性。
语法分析器能够正确地识别输入程序中的语法错误,并生成相应的错误提示信息。
语法和语义分析器试做报告
通过本实验加深了对语法分析器和语法制导翻译方法的理解,掌握了利用yacc工具编写语法分析程序。
开出注意事项
需要安装的软件:
1.linux操作系统;
院(系、部)验收组审查意见
院(系、部)负责人签字:
注:该表一式两份,一份院(系、部做报告
单位名称:计算机科学与技术系试做日期:2012年8月28日
新开实验项目名称
语法和语义分析器
学时数
4
面向专业
计算机科学与技术、计算机软件
试作教师签名
谢飞、朱强
一、实验目的
1.掌握Yacc的基本用法,并能够根据语言给出语法规则的定义,最后生成语言的解析器;
3.使用Yacc实现一个高级计算器程序。
二、实验内容
下面是计算器的功能:
1.运算符:+、-、*、/、unminus
优先级(从高到低):unminus
*、/
+、-
三、源程序清单或实验步骤
实验步骤:
1.编写lex和yacc源程序
vi calc.lex
vi calc.y
2.运行程序
四、实验结果
说明:此部分的内容和格式可根据每个实验项目的具体需要和要求,由各院(系、部)自行设计和确定相关栏目;其余部分应按此表格式统一。
3.6 语法分析器的自动生成解析
Yacc生成的语法分析器的工作原理:
Yacc生成的语法分析器由一个带栈的有穷 自动机组成。 此状态机只有四种动作:移进(shift)、规 约(reduce)、接受(accept)和错误(error)
输入符号串 总控程序 输出
状态与符号栈2018/10/10来自Action/Goto表
11
支持例程:
%% void main() { printf("Yacc Starting...\n"); yyparse(); } yylex(){ int c; /* while ( ( c = getchar ( ) ) == ' ' ); if ( ( c == '.' ) || (isdigit(c) ) ) { ungetc (c, stdin); scanf ( "%lf", &yylval); return NUMBER; } return c; */ /* 接受实数 */ 2018/10/10
12
支持例程(2):
c=getchar(); if (isdigit(c)){ yylval = c - '0'; return NUMBER; }; return c;
/* 接受1位整数 */
} yyerror(char *s) { fprintf(stderr,"...%s \n",s); } alloca() { }
编 译 原 理 Principle of Compiling
郭 一 晶
厦门大学嘉庚学院 2007 年 9 月
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
| {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");}
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;
三、实验要求
1.个人完成,提交实验报告。 2.实验报告中给出采用测试源代码片断,及其对应的最右推导过程(形式可以 自行考虑,如依次给出推导使用的产生式)。
例如,程序片断
四、实验步骤
1、根据文法编写.y文件:
%{ #include<ctype.h> #include<stdio.h> #define YYSIYPE double
|BREAK ';' {printf("stmt->break\n");}
| block {printf("stmt->block\n");}
;
loc
: loc '[' bool ']' {printf("loc->loc[bool]\n");}
|ID {printf("loc->id\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");}
;
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() {
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 %%
实验 4 用 Yacc 工具构造语法分析器
一、实验目的
掌握移进-归约技术语法分析技术,利用语法分析器生成工具 Yacc/Bison 实 现语法分析器的构造。
二、实验内容
利用语法分析器生成工具 Yacc/Bison 编写一个语法分析程序,与词法分析器 结合,能够根据语言的上下文无关文法,识别输入的单词序列是否文法的句子。
| 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");}
} }
五、实验结果
六、心得体会
其实这个实验并不难,不过很容易出错。在按照文法产生式编写.y文件时,
只要不注意写错,那或者在编译的无法生成.c文件,或者生成.c文件后在项目编 译时生成一大堆的错误。在理论课上学习了yacc进行语法分析的原理,这次通过 实验观察yacc的移入规约情况可以说是对课本知识的复习,收获很多。
|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");}
bool : bool OR join {printf("bool->bool||join\n");}
| join {printf("bool->join\n"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");}
;
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");}
program : block {printf("program->block\n");} ;
block : '{'decls stmts'}' {printf("block->decls stmts\n");}
;
decls : decls decl {printf("decls->decls decl\n");}