语法分析器yacc实验报告
编译原理实验报告材料5
编译原理实验报告五年月日学号学号系年级2012级专业计算机科目编译原理题目验证Yacc的使用❖实验目的熟悉语法分析器生成工具Yacc的使用,并学会在cygwin下使用bison工具编译Yacc文法说明文件。
学习如何使用lex和yacc合作进行语法分析。
❖实验容根据给出的calculator例子(calculator0,calculator1,calculator2,calculator3)完成下面题目:用lex和yacc写一个计算布尔表达式真值的计算器。
❖实验要求输入为一个布尔表达式,以换行结束。
输出为这个布尔表达式的真值(true 或false)。
尝试二义文法和非二义文法两种不同的实现方式。
布尔表达式二义文法为:S –> S or S | S and S | not S | (S) | true | false,其中优先级or < and < not,or 和and 左结合,not 右结合。
非二义文法请参照表达式非二义文法自己写出来。
cygwin下用flex,bison和gcc工具将实验调试通过,并写出测试例测试正确性。
❖实验参考:calculator0-3这四个例子。
请认真阅读例子,发现错误及时提出。
❖代码编写或修改❖实验结果非二义:二义(版本1,未去掉对于运算结合性的定义):以上的容按照我们的计算顺序都是对的,一开始无法相通为什么二义与非二义的结果相同,后来明白了,于是有了下面的一个版本的结果。
二义(版本2,去掉了运算结合性的定义)这两项本来应该的结果与其相反,说明了二义文法如果不进行运算符优先性、结合性的定义,则会造成预料不到的结果。
❖实验心得1.要深刻理解二义与非二义文法的涵与区别,才能更好地完成这个实验;2.由于对yacc了解的不够好,导致用了一段时间才能看懂给的例子以及各部分的写法,这就告诉我们,不能够忽视老师对于这些工具的用法的讲解,每一部分都要学的认真仔细;3.一开始是写的非二义的文法,然后做出来后直接修改成二义的,没有去掉对于运算结合性的定义,导致了两者运行结果不管怎么尝试都没有差别,后来才考虑到这是因为我们定义了优先级与结合性,所以结果是一样的,于是特意为了尝试如果没有这些定义会如何,产生了二义版本2。
编译原理实践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的值。
实验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自动生成语法分析器的过程描述,和生成的语法分析程序是如何运作的。
大学编译原理实验报告
一、实验名称编译原理实验二、实验目的1. 理解编译原理的基本概念和原理。
2. 掌握文法分析、词法分析和语法分析的基本方法。
3. 学会使用编译工具,如Lex和Yacc,实现简单的编译器。
三、实验内容本次实验主要分为三个部分:1. 词法分析2. 语法分析3. 编译器构建四、实验步骤1. 词法分析- 使用Lex工具实现词法分析器。
- 定义输入文件格式,包括源代码和标记。
- 编写Lex规则,将源代码转换为标记序列。
- 使用Flex生成词法分析器程序。
2. 语法分析- 使用Yacc工具实现语法分析器。
- 定义语法规则,包括产生式和文法符号。
- 编写Yacc规则,将标记序列转换为语法分析树。
- 使用Bison生成语法分析器程序。
3. 编译器构建- 将词法分析器和语法分析器程序结合,构建简单的编译器。
- 实现编译器的中间代码生成功能。
- 实现编译器的目标代码生成功能。
五、实验结果1. 词法分析- 输入:`int a = 10;`- 输出:`TOKEN: int, TOKEN: a, TOKEN: =, TOKEN: 10, TOKEN: ;`2. 语法分析- 输入:`int a = 10;`- 输出:`Syntax Tree: Program -> Declaration -> Variable Declaration -> Identifier -> a, Token -> int, Token -> =, Token -> 10, Token -> ;`3. 编译器构建- 输入:`int a = 10;`- 输出:`Target Code: int a = 10;`六、实验心得1. 通过本次实验,我深入理解了编译原理的基本概念和原理,包括词法分析、语法分析和编译器构建。
2. 我学会了使用Lex和Yacc等编译工具,实现了简单的编译器。
3. 本次实验让我认识到编译原理在软件开发中的重要性,以及编译器在代码生成和优化方面的作用。
西安交大编译原理语法分析器实验报告
编译原理课内实验报告学生姓名石磊专业/班级计算机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)六:实验心得在本次实验中,我耗费了大量时间来设计分析设计。
语法分析器设计实验报告
语法分析器设计实验报告一、引言语法分析器是编译器中的重要组成部分,其主要功能是根据给定的文法规则,对输入的程序代码进行语法分析,判断其是否符合语法规范。
本实验旨在设计一个简单的语法分析器,通过实际实现一个基于LL(1)文法的语法分析器,深入了解语法分析的原理和实现方法。
二、实验目标本实验的目标是设计一个能够接受一个输入的程序代码并进行语法分析的程序。
具体而言,需要实现以下功能:1. 构建一个文法规则集合,用于描述程序代码的语法规范;2. 设计并实现一个LL(1)分析表,用于存储语法分析所需的预测分析表;3. 实现语法分析器,能够根据输入的程序代码,逐步地进行语法分析,并输出相应的结果。
三、实验环境本实验使用的是Java语言进行实现,操作系统环境为Windows 10。
使用的集成开发环境为Eclipse。
四、实验步骤1. 设计文法规则集合在语法分析器设计中,首先需要设计一个文法规则集合,用于描述需要分析的程序代码的语法规范。
文法规则集合的设计要符合LL(1)文法的要求,即每个非终结符的产生式至多有一个与输入符号串首符号相关的产生式。
2. 构建LL(1)分析表根据文法规则集合,构建一个LL(1)分析表,用于存储语法分析所需的预测分析表。
LL(1)分析表是一个二维表,其中行表示非终结符,列表示终结符。
表中的每个元素表示相应的产生式编号,用于指示语法分析器在分析过程中应该使用哪个产生式。
构建LL(1)分析表的方法包括:- 遍历文法规则集合,计算每个非终结符的FIRST集合和FOLLOW集合;- 根据计算得到的FIRST集合和FOLLOW集合,填充LL(1)分析表。
3. 实现语法分析器根据LL(1)分析表,实现一个语法分析器。
语法分析器的输入是一个程序代码,输出是语法分析器的分析结果。
实现语法分析器的主要过程包括:- 初始化分析栈,将文法规则的开始符号入栈;- 从输入的程序代码中读取下一个终结符;- 如果分析栈的栈顶是非终结符,根据LL(1)分析表中对应的产生式编号,将产生式右部的符号依次入栈;- 如果分析栈的栈顶是终结符,并且与输入的终结符相同,则将该终结符出栈,并继续读取下一个终结符;- 重复上述过程,直到分析栈为空或者无法继续推导。
用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实现的语法分析器
实验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;}}五、实验结果六、心得体会其实这个实验并不难,不过很容易出错。
实验二 语法和语义分析器
2、编写 calculator.lex 源程序
%{ #include <stdlib.h> #include "calculator.tab.h" void yyerror(char const *);
%} %% [a-z] {
yylval = *yytext - 'a'; return VARIABLE; }
3、编写 calculator.y 源程序
%{ #include<stdio.h> #include<math.h> #define wypi (0.017453292519943) void yyerror(char const *); int yylex(void); int sym[26];
%} %token INTEGER VARIABLE %left '+' '-' %left '*' '/' %left NEG %left '^' %left 'S' 'C' 'T' %left 'L'
%left '%'
%% program:
program statement '\n' | ; statement:
expr {printf("\t=%d\n", $1);} |VARIABLE '=' expr {sym[$1] = $3;} ; expr: INTEGER |VARIABLE{$$ = sym[$1];} |expr '+' expr {$$ = $1 + $3;} |expr '-' expr {$$ = $1 - $3;} |expr '*' expr {$$ = $1 * $3;} |expr '/' expr {$$ = $1 / $3;} |'-'expr %prec NEG {$$ = -$2;} |expr '^' expr {$$ = pow($1,$3);} |'S' expr {$$ = sin($2*(wypi));} |'C' expr {$$ = cos($2*(wypi));} |'T' expr {$$ = tan($2*(wypi));} |'L' expr {$$ = log10($2);} |expr '%' expr {$$ = $1%$3;} |'('expr')' {$$ = $2;} ; %% void yyerror(char const *msg) { fprintf(stderr, "%s\n",msg); } int main(void) { printf("a simple calculator.\n"); printf("+加、-减、*乘、/除\n"); printf("幂运算:a^b\n"); printf("S(sin)、C(cos)、T(tan)三角函数:\n"); printf("L 以 10 为底的对数运算:logA\n"); printf("求余运算%%:\n"); yyparse(); return 0; }
语法分析器
实验二:语法分析器一、 实验目的: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
编译原理lexyacc的联合使用实验报告(特选借鉴)
编译原理lexyacc的联合使用实验报告(特选借鉴)《编译原理》课程实验报告题目lex yacc 的联合使用专业班级学号姓名一. 实验题目lex yacc 的联合使用二. 实验日期三. 实验环境(操作系统,开发语言)操作系统是Windows开发语言是C语言四. 实验内容(实验要求)目的:熟悉lex和yacc的接口要求:(1)能对整数、实数进行带变量的四则运算(2)词法分析用lex实现(3)语法分析用yacc实现(4)交源代码和实验报告五. 实验步骤1.在实验二的基础上修改代码,并添加上以下的代码:double { return DOUBLE;}EOF { return 0;}{ID} { return ID;}2.在DOS环境下按照之前的步骤利用flex运行myleb.l,修改其中的错误之后,生成lex.yy.c文件。
3.参照书中第14章第7节和myparser-fifth.y文件中的代码,和老师说的思路修改myparser-sixth.y文件,按照实验要求修改代码。
4.在DOS环境下利用yacc运行myparser-sixth.y文件,会有出错提示,按照出错的地方指示,修改代码,使其最终能通过运行,生成y.tab.c文件。
(此步骤还未完成)5.打开c-free5.0,新建工程,在Source files文件夹中添加之前生成的lex.yy.c文件和y.tab.c文件,然后找到已给的calc.h文件,将其添加到新建工程中的Header files文件夹中,这时就能将三个文件组成一个类似于.exe文件类型的文件,最后运行。
6.运行并调试成功。
六. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)。
编译原理实验报告yacc的使用
1.1错误信息统计1.2正确运行及结果:2 yacc脚本%{#include <stdio.h>#include <ctype.h>%}%token NUMBER%%command: exp {printf("%d\n", $1);};/* print the result */exp :exp '+' term {$$ = $1 + $3;}|exp '-' term {$$ = $1 - $3;}|term {$$ = $1;};term :term '*' factor {$$ = $1 * $3;}|factor {$$ = $1;};factor :NUMBER{$$ = $1;}|'(' exp ')' {$$ = $2;}%%main(){return yyparse();}int yylex(void){int ch;ch = getchar();if(isdigit(ch)) {yylval = ch - '0'; return NUMBER;};/* 数字 */ if(ch == '\n') return 0;return ch;}void yyerror(char *s){fprintf(stderr, "%s\n", s); /* print error message */}3.Yacc脚本中,%token是定义的终结符还是非终结符? NUMBER又是属于什么性质的符号?%token是定义的是终结符,NUMBER属于宏定义常量,是由yacc内部决定的终结符编号常量。
4.指出上面的Yacc脚本中,其定义部分、规则部分和辅助程序(用户程序)部分各是什么?定义部分:%{#include <stdio.h>#include <ctype.h>%}%token NUMBER规则部分:%%command: exp {printf("%d\n", $1);};/* print the result */exp :exp '+' term {$$ = $1 + $3;}|exp '-' term {$$ = $1 - $3;}|term {$$ = $1;};term :term '*' factor {$$ = $1 * $3;}|factor {$$ = $1;};factor :NUMBER{$$ = $1;}|'(' exp ')' {$$ = $2;}%%辅助程序部分:main(){return yyparse();}int yylex(void){int ch;ch = getchar();if(isdigit(ch)) {yylval = ch - '0'; return NUMBER;};/* 数字 */ if(ch == '\n') return 0;return ch;}void yyerror(char *s){fprintf(stderr, "%s\n", s); /* print error message */}5.规则部分定义了几个非终结符成分,各是什么?其中,开始符是哪一个?如何从Yacc脚本中快速寻找开始符?规则定义了3个非终结符,分别是exp,term,factor;其中exp时开始符,寻找最初输入变量接收值的非终结符。
语法分析器实验报告
语法分析器实验报告实验报告:语法分析器的设计与实现摘要:语法分析器是编译器的一个重要组成部分,主要负责将词法分析器输出的词法单元序列进行分析和解释,并生成语法分析树。
本实验旨在设计与实现一个基于上下文无关文法的语法分析器,并通过实现一个简单的编程语言的解释器来验证其功能。
1.引言在计算机科学中,编译器是将高级程序语言转化为机器语言的一种工具。
编译器通常由词法分析器、语法分析器、语义分析器、中间代码生成器、优化器和目标代码生成器等多个模块组成。
其中,语法分析器负责将词法分析器生成的词法单元序列进行进一步的分析与解释,生成语法分析树,为后续的语义分析和中间代码生成提供基础。
2.设计与实现2.1上下文无关文法上下文无关文法(CFG)是指一类形式化的语法规则,其中所有的产生式规则都具有相同的左部非终结符,且右部由终结符和非终结符组成。
语法分析器的设计与实现需要依据给定的上下文无关文法来进行,在本实验中,我们设计了一个简单的CFG,用于描述一个名为"SimpleLang"的编程语言。
2.2预测分析法预测分析法是一种常用的自顶向下的语法分析方法,它利用一个预测分析表来决定下一步的推导选择。
预测分析表的构造依赖于给定的上下文无关文法,以及文法的FIRST集和FOLLOW集。
在本实验中,我们使用了LL(1)的预测分析法来实现语法分析器。
2.3语法分析器实现在实现语法分析器的过程中,我们首先需要根据给定的CFG构造文法的FIRST集和FOLLOW集,以及预测分析表。
接下来,我们将词法分析器输出的词法单元序列作为输入,通过不断地匹配输入符号与预测分析表中的预测符号,进行语法分析和推导。
最终,根据CFG和推导过程,构建语法分析树。
3.实验结果与分析通过实验发现,自顶向下的预测分析法在对简单的编程语言进行语法分析时具有较高的效率和准确性。
语法分析器能够正确地识别输入程序中的语法错误,并生成相应的错误提示信息。
语法分析器实验报告
杭州电子科技大学班级: 12052312 专业: 计算机科学与技术实验报告【实验名称】实验二语法分析一. 实验目的编写一个语法分析程序, 实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二. 实验内容利用编程语言实现语法分析程序, 并对简单语言进行语法分析。
2.1 待分析的简单语言的语法用扩充的BNF表示如下:⑴<程序>: : =begin<语句串>end⑵<语句串>: : =<语句>{;<语句>}⑶<语句>: : =<赋值语句>⑷<赋值语句>: : =ID: =<表达式>⑸<表达式>: : =<项>{+<项> | -<项>}⑹<项>: : =<因子>{*<因子> | /<因子>⑺<因子>: : =ID | NUM | (<表达式>)2.2 实验要求说明输入单词串, 以“#”结束, 如果是文法正确的句子, 则输出成功信息, 打印“success”, 否则输出“error”。
例如:输入begin a:=9; x:=2*3; b:=a+x end #输出success!输入x:=a+b*c end #输出error测试以上输入的分析, 并完成实验报告。
2.3 语法分析程序的算法思想(1)主程序示意图如图2-1所示。
图2-1 语法分析主程序示意图(2)递归下降分析程序示意图如图2-2所示。
(3)语句串分析过程示意图如图2-3所示。
图2-3 语句串分析示意图图2-2 递归下降分析程序示意图(4)statement 语句分析程序流程如图2-4.2-5.2-6.2-7所示。
图2-4 statement 语句分析函数示意图 图2-5 expression 表达式分析函数示意图图2-7 factor 分析过程示意图三.个人心得一、 通过该实验, 主要有以下几方面收获: 二、 对实验原理有更深的理解。
语法和语义分析器试做报告
通过本实验加深了对语法分析器和语法制导翻译方法的理解,掌握了利用yacc工具编写语法分析程序。
开出注意事项
需要安装的软件:
1.linux操作系统;
院(系、部)验收组审查意见
院(系、部)负责人签字:
注:该表一式两份,一份院(系、部做报告
单位名称:计算机科学与技术系试做日期:2012年8月28日
新开实验项目名称
语法和语义分析器
学时数
4
面向专业
计算机科学与技术、计算机软件
试作教师签名
谢飞、朱强
一、实验目的
1.掌握Yacc的基本用法,并能够根据语言给出语法规则的定义,最后生成语言的解析器;
3.使用Yacc实现一个高级计算器程序。
二、实验内容
下面是计算器的功能:
1.运算符:+、-、*、/、unminus
优先级(从高到低):unminus
*、/
+、-
三、源程序清单或实验步骤
实验步骤:
1.编写lex和yacc源程序
vi calc.lex
vi calc.y
2.运行程序
四、实验结果
说明:此部分的内容和格式可根据每个实验项目的具体需要和要求,由各院(系、部)自行设计和确定相关栏目;其余部分应按此表格式统一。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
|__Assign
|__VarId name:i
|__Expression type:+
|__VarId name:low
|__NumBiblioteka er type:INT, value:1
|__While
|__Expression type:<
|__VarId name:i
|__VarId name:high
t->sibling = $2;
$$ = $1;
}
else
$$ = $2;
}
|{$$ = NULL;}
;
YACC是由yylex()提供Token,因此需要编写getToken()函数,使用lex或手工实现均可,但需注意,其返回的Token值必须是YACC中定义的int,也就是说,不能在别处定义TokenType。
|__Comp
|__Return
|__VarId name:k
可见ParseTree中所需结点都被生成,并且ID、NUM、type_specifier都被记录在结点中。
小结
1.通过本实验,我熟悉了C-的语法规则,学习了ParseTree的构造方法。
2.学习了通过YACC构造语法分析器的方法,了解了YACC的三个部分:declarations、rules、auxiliary 的声明、实现以及如何与Scanner进行继承。事实上YACC与Scanner的联系之处便在于统一的token定义(定义为一系列int),以及一个获取函数yylex()。
Definitions中可以定义语法的结合性来消除二义性,包括两个符号%left表示左结合和%right表示右结合。
rules部分定义所有语法,以及语法识别出后执行的操作。
例如:
declaration:var_declaration{ $$ = $1; }
|fun_declaration{ $$ = $1; }
|__Number type:INT, value:10
|__FunDec name:minloc, return:INT
|__ArrParam name:a, type:INT
|__ValParam name:low, type:INT
|__ValParam name:high, type:INT
大学学院
实验 报 告
学号:姓名:专业:班级:第周
课程名称
编译原理课程设计
实验课时
实验项目
基于YACC的语法分析器
实验时间
实验目的
1.学习基于YACC的语法分析器的构造方法。
2.学习C-的语法结构。
实验环境
Parser Generator
VC++
实验内容(算法、程序、步骤和方法)
基于YACC构造词法分析器的方法
static Type yylex(void)
{ return getToken(); }
Type就是int,专门代表token值。
Auxiliary部分还可以定义YACC的出错处理函数,yyerror(char *s),其中s是YACC在遇到错误时产生的错误信息。
YACC的入口函数为:yyparse(),调用这个函数即开始语法分析过程。
;
%%表示产生式左边,$n表示产生式右边第n个字符的返回值,这条规则表示var_declaration或fun_declaration识别出后,将其赋值给declaration。
Auxiliary部分包括rules部分使用的一些辅助函数,同时,main函数也在其中定义。YACC中会自动调用yylex()获取token,默认yylex()返回int,代表识别出的token,如果文件结束返回0。因此一般会进行如下定义:
2数据结构
我们需要再YACC中构造Parse Tree,必须定义树结点,观察C-的语法,我们可以将语法分为三类:
Declaration : 包括函数与变量的声明。
Statement : 包括各种语句,如循环语句,选择语句等。
Expression : 包括各种表达式及各种变量、常量。
我们也将节点类型分为Dec、Stmt、Exp。节点类型定义如下:
5.如果有左递归,则统一用下面代码处理,注意,左递归的结点存储在sibling中而不是child中。
tatement_list:statement_list statement
{
TreeNode* t = $1;
if( t != NULL )
{
while(t->sibling != NULL)
t = t->sibling;
3.学习了Parse的打印方法,模仿Windows中的目录树,使用符号|和_,达到了不错的效果。
指导老师评 议
成绩评定: 指导教师签名:
在main函数中调用yyparse()即可进行编译。
数据记录
和计算
实验源程序如下:
/* a program to perform selection sort on a 10
element array. */
int x[10];
int minloc( int a[], int low, int high )
2.如果有ID,与NUM同理,用立刻一个字符串暂存。
3.如果产生式右边有多余一个的Symbol,则必须为$$建立结点,并将右面的Symbol作为他的儿子,如果有ID、NUM、type_specfier,和关键字,则不需建立结点,直接赋值给结点中的变量或忽略(结点类型自动说明)。
如:
iteration_stmt:WHILE LPARENTHESIS expression RPARENTHESIS statement
{
$$ = newStmtNode(WhileK);
$$ -> child[0] = $3;
$$ -> child[1] = $5;
}
4.如果右边仅有一个Symbol,如果为Token,则返回Token值,如果为Nonterminal,直接$$ = $1。
如:
statement:expression_stmt{ $$ = $1; }
|__Comp
|__Var name:i, type:INT
|__Var name:x, type:INT
|__Var name:k, type:INT
|__Assign
|__VarId name:k
|__VarId name:low
|__Assign
|__VarId name:x
|__ArrId name:low
{
int i; int x; int k;
k = low;
x = a[low];
i = low + 1;
while ( i < high )
{
if ( a[i] < x )
{
x = a[i];
k = i; }
}
return k;
}
结 论
(结 果)
生成的Parse Tree如下所示:
|__Arr name:x, type:INT
Definitions中同时还定义了YACC中的返回值类型,由于rules部分是由固定符号来代替一个Symbol的返回值,其默认类型为int,如果用户希望返回其他类型的值(如ParseTree树结点),则可以在Definition中定义Symbol的返回值。首先使用一个%union{…}包含所有需要的返回值类型,定义%type<t> {…}其中包含所有返回值为t的Symbol。
1YACC文件格式
Lex文件分成三个部分,分别为definitions、rules以及auxiliary routines,中间用%%分割开。
Definitions包括要加入到生成的C程序的头部的代码,包括#include语句、#define语句及一些全局变量的定义。token也在Definitions部分定义,YACC规定,必须自己定义token,他将token定义为一系列从258开始的正整数,如在Definition部分加入了如下定义:%token NUMBER, 则在生成的C代码中:#define NUMBER 258。当然这个值也可以由用户定义。
typedefstructtreeNode
{
果有NUM,则立刻用一个变量暂存,因为后面的识别会把TokenValue覆盖掉。
如:type_specifier id LBRACKET NUM { /*记录NUM*/ currentNum = atoi(tokenString); } RBRACKET SEMICOLON