实验四 用YACC实现的语法分析器

合集下载

语法分析程序自动产生器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进行语法分析

实验四 借助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

编译原理实践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

语法分析器生成器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语法分析器设计步骤

使用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并构造简单语法分析程序

实验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;}}五、实验结果六、心得体会其实这个实验并不难,不过很容易出错。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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");}
相关文档
最新文档