编译原理实验二报告.docx
- 文档编号:7913846
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:13
- 大小:312.34KB
编译原理实验二报告.docx
《编译原理实验二报告.docx》由会员分享,可在线阅读,更多相关《编译原理实验二报告.docx(13页珍藏版)》请在冰豆网上搜索。
编译原理实验二报告
编译原理实验报告
实验二基于YACC的TINY语法分析实验
一、实验目的
在这一阶段的实验中,同学们要完成tiny编译器的语法分析工作,即用bison工具生成一个语法分析程序,对词法分析输出的单词符号串(终结符串)进行自底向上的分析,并依次输出用来进行归约的语法规则。
二、Tiny语言的语法
参见教材。
请大家注意,文档中给出的BNF描述并不能直接被YACC识别,而是需要进行适当的改写。
请大家在做实验前,仔细研究一下教材中给出的例子。
三、软件工具及文档说明
实验环境为Windows操作系统,语法分析使用的主要工具是bison。
我们会提供给大家一些基本的数据结构、程序框架以及工具软件。
实验所用到的程序和工具主要包括两部分:
1.工具和程序框架(在StarterFiles路径下)
以下是主要文件的列表:
pp2.dsp/dswpp2工程文件不需要改动
main.c主程序不需要改动
scanner.h词法分析程序的头文件不需要改动
scanner.l词法分析程序需要改动
parser.h语法分析程序的头文件不需要改动
parser.l语法分析程序需要改动
utility.h一些工具函数不需要改动
test.frag测试文件不要改动
flex.exe工具不要改动
bison.exe/simple工具不要改动
debug.bat工具不要改动
程序的执行方法是:
(0)先根据完善parse.y(否则会编译出错)
(1)运行debug.bat(会生成parser_tab.h和parser_tab.c);
(2)用vc6.0打开pp2.dsw,编译链接生成pp2.exe;
(3)运行pp2[filename]。
其中filename是可选部分,如果没有filename,就默认是打开test.frag,否则就打开filename指定的文件。
这样设计,主要考虑在调试pp2程序时比较方便,但是测试程序时还是要对实例中给出的*.frag文件逐一进行测试。
另外,大家最好自己再编写一些合法和不合法的源文件,对程序进一步进行测试。
scanner.l是我们为大家提供的词法分析器,如果不对tiny语言本身作任何扩展,则不需要修改它,如果想对语言进行扩展,就要对它进行相应的修改。
大家也可以用自己在PP1实验中实现的词法分析器代替scanner.l,但是一定要保证你的词法分析器的输出和我们所提供的词法分析器的输出是一致的,否则会影响语法分析器的实现。
2.实例(在samples路径下)
*.fragTiny源程序
*.out正确的语法分析结果
四、实验难点和重点
1.bison工具的使用。
请大家仔细阅读教材5.5Yacc:
LAlR
(1)PARSINGGENERATOR和bison.info中的内容。
2.二义性和冲突的解决方法。
YACC在处理条件语句时会给出警告,但是按照YACC提供的两条消除二义性的规则可以正确处理,所以这个警告不算错。
但是其它的由于规则定义不完善引起的冲突是不允许出现的。
建议大家尽量通过调整规则来消除冲突。
在处理表达式时,可以借助%left、%right和%prec等子句消除二义性并规定优先级。
3.出错处理。
yacc缺省的出错处理是遇到错误时输出提示信息,然后停止分析。
这是基本要求。
(书上5.65.7分别介绍了一般的出错处理和TINY.C的出错处理)如果你希望做进一步的出错处理,我们将把它作为一种扩展。
例如,可以借助yacc提供的error终结符,在出错时跳过一部分符号后继续进行分析。
建议大家参考一下其它高级语言编译器的出错处理,然后再编程实现。
我们为大家提供的yyerror()函数能够在输出错误信息的同时,输出行号和第一个出错符号的列号,你可以修改这个函数以提供更全面的报错信息。
无论你实现的是何种出错处理,请都在readme.txt中给出说明。
4.在实验2阶段,对语义信息不作处理,虽然YACC提供了$开头的一系列伪变量可以进行一定的语义处理,但是目前先不考虑语义,例如,对表达式不需要赋值。
所有语法正确的源程序在实验2阶段都应当被正确识别,语义错误暂不考虑。
五、实验的扩展
1.对语言的扩展。
例如增加C语言中的“++”和“――”运算符,增加分支结构的switch语句等。
对语言的扩展需要你自己写语法规则,并要注意不与已有规则冲突,还要对词法分析程序进行相应的修改。
如果你实现了某种decaf语言的扩展,请在readme.txt文件中说明,并为我们提供相应的测试正例和反例。
2.语法规则的输出形式是必须有的,而且一定要与答案相符合。
如果你愿意输出其它形式的语法分析结果,例如语法树,请在readme.txt中说明,并将你的结果输出到单独的文件中,不要跟语法规则的输出混在一起,否则会影响对语法分析程序的检查。
3.对源程序的文本格式进行调整,增加可读性。
例如关键字,常量和变量分别以不同颜色输出。
对语句的格式进行调整,自动加入缩进等。
如果你实现了这方面的扩展,请在readme.txt文件中说明,并把调整后的decaf源程序输出到一个单独的文件中,而不要跟语法分析的输出混在一起,否则会影响对语法分析程序的检查。
4.对出错处理,我们不作太严格的要求,你完全可以采用YACC的缺省处理,即遇到错误就停止分析。
如果你愿意尝试更有挑战性的错误处理,请在readme.txt文件中说明,并为我们提供相应的测试正例和反例,我们将视为一种扩展。
六、实验要求
实验报告中的内容:
1)YACC输入文件的解析
2)上下文无关文法到LR
(1)文法的下推自动机的构造
3)LR
(1)下推自动机到相应分析表的构造。
4)针对我们提供的SAMPLE(上课时会提供)的测试结果。
在我们所提供的工具软件中,程序框架已经写好,同学们只要修改其中的部分文件就可以完成编码工作。
然后,请大家充分利用测试实例中提供的输入和输出文件对程序进行测试,自己确认通过后将所有的程序文件(包括你没有修改的文件)整理到一个目录下并编写相应的文档readme.txt,打包成Zip文件上传,zip文件名为“自己的学号.zip”,例如“101362.zip”。
1.想做扩展的同学,请提供两份程序,一份是基本程序,它的输出要与例子中给出的答案相符,另一份是扩展程序,它的输出可以与答案不同。
并请大家在文档中给出说明。
2.检查基本程序的主要标准是程序的输出与标准答案相符合的程度。
欢迎同学们对Decaf语言进行扩展,但是要单独提供一份扩展程序和相应的测试例子,同时在readme中给出说明,我们将查看你的扩展程序并做进一步的测试,如果扩展正确,可以考虑适当加分。
3.实验课主要以提问的方式检查各位同学对实验的理解及其完成情况。
4.本学期实验分共计20分。
评分分二部分上课提问的检查为一部分,其后的实验报告及其扩展情况为第二部分,同时参考实验一给出最终的实验评分。
5.请大家遵守诚信原则,如发现抄袭情况,则被抄袭者和抄袭者都没有成绩。
七、实验过程及结果
1、根据给定的文法完善parse.y,结果如下:
/*parser.y
*
*bison输入文件,用于产生parser
*
*pp2:
你的任务只是输出parser的规约动作,即只需要验证输入文件是否符合
*decaf语言的文法,并把规约动作输出。
*
*/
%{
/*
*同flex一样,第一个%{%}内部的程序将被直接copy到parser_tab.h/c中
*所以可以将要include的头文件和全局变量放到这儿。
*/
#include
#include
#include
#include
#include"scanner.h"
%}
/*
*在这儿,你可以定义tokens,types,precedence和associativity等。
*/
/*
*从program开始规约
*/
%startProgram
/*
*yylval
*------
*这儿定义全局变量yylval,你可以添加自己的非终结符。
*/
%union{/*bison可以从这个定义中产生yylval的定义*/
intintegerConstant;
intboolConstant;
constchar*stringConstant;
doubledoubleConstant;
charidentifier[128];
}
/*Tokens
*------
*这儿我们告诉bison所要用到的token类型。
*bison可以给这些类型定义唯一的数字并输出#define到parser_tab.h文件中。
*/
%tokenT_VoidT_BoolT_IntT_DoubleT_StringT_Class
%tokenT_LessEqualT_GreaterEqualT_EqualT_NotEqual
%tokenT_AndT_OrT_NullT_ExtendsT_This
%tokenT_WhileT_ForT_IfT_ElseT_ReturnT_Break
%tokenT_Identifier
%tokenT_StringConstantT_IntConstantT_DoubleConstantT_BoolConstant
%tokenT_NewT_NewArrayT_PrintT_ReadIntegerT_ReadLine
/*PrecedenceandAssociativity
*----------------------------
*定义算符优先级和结合性
*Note:
NOSPACEbetween%andnonassoc,left,right
*/
%%
/*
*在这儿写出你的规则和动作
*/
Program:
DeclList
{printf("Program->DeclList\n");@1}
;
DeclList:
DeclListDecl
{printf("DeclList->DeclListDecl\n");}
|/*empty*/
{printf("DeclList->\n");}
;
Decl:
VariableDecl{printf("Decl->VaruableDecl\n");}
|ClassDefn{printf("Decl->ClassDefn\n");}
|FunctionDefn{printf("Decl->FunctionDefn\n");}
|FunctionDecl{printf("Decl->FunctionDecl\n");}
;
VariableDecl:
Variable';'{printf("VariableDecl->Variable\n");}
;
Variable:
TypeT_Identifier{printf("Variable->Identifier\n");}
;
Type:
T_Int{printf("Type->Int\n");}
|T_Double{printf("Type->Double\n");}
|T_Bool{printf("Type->Bool\n");}
|T_String{printf("Type->String\n");}
|T_Void{printf("Type->Void\n");}
|T_ClassT_Identifier{printf("Type->Identifier\n");}
|Type'['']'{printf("Type->Type[]\n");}
;
FunctionDecl:
TypeT_Identifier'('Formals')'';'{printf("FunctionDecl->Identifier\n");}
;
Formals:
Variable'+'','{printf("Formals->Variable+,\n");}
|{printf("Formals->\n");}
;
FunctionDefn:
TypeT_Identifier'('Formals')'StmtBlock{printf("FunctionDefn->Identifier\n");}
;
ClassDefn:
T_ClassT_Identifier'<'T_ExtendsT_Identifier'>''{'Fieldlist'}'{printf("ClassIdentifier
;
Fieldlist:
FieldlistField{printf("Fieldlist->FieldlistField\n");}
|{printf("Fieldlist->\n");}
;
Field:
VariableDecl{printf("Field->VariableDecl\n");}
|FunctionDecl{printf("Field->FunctionDecl\n");}
|FunctionDefn{printf("Field->FunctionDefn\n");}
;
StmtBlock:
'{'Stmtlist'}'{printf("StmtBlock->:
{Stmtlist}\n");}
;
Stmtlist:
StmtlistStmt{printf("Stmtlist->StmtlistStmt\n");}
;
Stmt:
VariableDecl{printf("Stmt->VariableDecl\n");}
|SimpleStmt';'{printf("Stmt->SimpleStmt;\n");}
|IfStmt{printf("Stmt->IfStmt\n");}
|WhileStmt{printf("Stmt->WhileStmt\n");}
|ForStmt{printf("Stmt->ForStmt\n");}
|ReturnStmt';'{printf("Stmt->ReturnStmt;\n");}
|PrintStmt';'{printf("Stmt->PrintStmt;\n");}
|StmtBlock{printf("Stmt->StmtBlock\n");}
;
SimpleStmt:
LValue'='Expr{printf("SimpleStmt->LValue=Expr\n");}
|Expr{printf("SimpleStmt->Expr\n");}
|{printf("SimpleStmt->\n");}
;
LValue:
'<'Expr'.''>'T_Identifier{printf("LValue->:
|Expr'['Expr']'{printf("LValue->[Expr]\n");}
;
Call:
'<'Expr'.''>'T_Identifier'('Actuals')'{printf("Call->
;
Actuals:
Expr'+'','{printf("Actuals->Expr+,\n");}
|{printf("Actuals->\n");}
;
ForStmt:
T_For'('SimpleStmt';'BoolExpr';'SimpleStmt')'Stmt{printf("ForStmt->For(SimpleStmt;BoolExpr;SimpleStmt)Stmt\n");}
;
WhileStmt:
T_While'('BoolExpr')'Stmt{printf("WhileStmt->While(BoolExpr)Stmt\n");}
;
IfStmt:
T_If'('BoolExpr')'Stmt'<'T_ElseStmt'>'{printf("IfStmt->If(BoolExpr)Stmt
;
ReturnStmt:
T_Return{printf("ReturnStmt->Return\n");}
|T_ReturnExpr{printf("ReturnStmt->ReturnExpr\n");}
;
PrintStmt:
T_Print'('Expr'+'','')'{printf("PrintStmt->Print(Expr+,)\n");}
;
BoolExpr:
Expr{printf("BoolExpr->Expr\n");}
;
Expr:
Constant{printf("Expr->Constant\n");}
|LValue{printf("Expr->LValue\n");}
|T_This{printf("Expr->This\n");}
|Call{printf("Expr->Call\n");}
|'('Expr')'{printf("Expr->(Expr)\n");}
|Expr'+'Expr{printf("Expr->Expr+Expr\n");}
|Expr'-'Expr{printf("Expr->Expr-Expr\n");}
|Expr'*'Expr{printf("Expr->Expr*Expr\n");}
|Expr'/'Expr{printf("Expr->Expr/Expr\n");}
|Expr'%'Expr{printf("Expr->Expr%Expr\n");}
|'-'Expr{printf("Expr->-Expr\n");}
|Expr'<'Expr{printf("Expr->Expr |ExprT_LessEqualExpr{printf("Expr->LessEqualExpr\n");} |Expr'>'Expr{printf("Expr->Expr>Expr\n");} |ExprT_GreaterEqualExpr{printf("Expr->GreaterEqual\n");} |ExprT_EqualExpr{printf("Expr->EqualExpr\n");} |ExprT_NotEqualExpr{printf("Expr->NotEqualExpr\n");} |ExprT_AndExpr{printf("Expr->AndExpr\n");} |ExprT_OrExpr{printf("Expr->OrExpr\n");} |'! 'Expr{printf("Expr->! Expr\n");} |T_ReadInteger'('')'{printf("Expr->ExprReadInteger()\n");} |T_ReadLine'('')'{printf("Expr->ExprReadLine()\n");} |T_New'('T_Identifier')'{printf("Expr->New(Identifier)\n");} |T_NewArray'('Expr','Type')'{printf("Expr->NewArray(Expr,Type)\n");} ; Constant: T_IntConstant{printf("Constant->IntConstant\n");} |T_DoubleConstant{printf("Constant->DoubleConstant\n");} |T_BoolConstant{printf("Constant->BoolConstant\n");} |T_StringConstant{printf("Constant->StringConstant\n");} |T_Null{printf("Constant->Null\n");} ; %% /* *语法规则到此为止。 *以下是你自己定义的函数,这些函数将会直接被copy到parser_tab.c文件中, *如果你需要一些辅助的函数,可以写到这儿。 */ voidInityyparse(void) { } 2.运行debug.bat(会生成parser_tab.h和parser_tab.c): 3.用vs2010打开pp2.dsw 4.测试bad1.decaf(与bad1.out完全一致): 5.测试bad2.decaf(与bad2.out完全一致): 6.测试bad3.decaf(与bad3.out完全一致): 7.测试bad4.decaf(与bad4.out完全一致): 8.测试class.decaf(与class.out完全一致): 八、实验心得 这次实验过程中我掌握了Yacc语法规则及语法分析的的上机步骤。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 实验 报告