编译原理实验报告
实验名称:分析调试语义分析程序 实验类型:验证型 指导教师: 专业班级: 姓 名: 学 号: 实验地点:
实验成绩:
日期: 2016 年 6 月 3 日
实验三 分析调试语义分析程序
一、实验目的
通过分析调试TEST语言的语义分析和中间代码生成程序,加深对语法制导翻译思想的理解,掌握将语法分析所识别的语法范畴变换为中间代码的语义翻译方法。
二、实验知识
1.语法制导基本思想
语法制导就是对文法中的每个产生式都附加一个语义动作或语义子程序,且在语法分析过程中,每当需要使用一个产生式进行推导或归约时,语法分析程序除执行相应的语法分析动作外,还要执行相应的语义动作或调用相应的语义子程序。
基本思想是,根据翻译的需要设置文法符号的属性,以描述语法结构的语义。例如,一个变量的属性有类型,层次,存储地址等。表达式的属性有类型,值等。属性值的计算和产生式相联系。随着语法分析的进行,执行属性值的计算,完成语义分析和翻译的任务。
2.翻译方案设计
1)设计原理:在实验二的基础上为文法符号引进一组属性及相应求值规则和动作,得到属性翻译文法,并引进一个符号表(包括变量名,变量数据是否有效,变量地址,变量的具体数据,数据类型等),在进行语法分析的同时,结合符号表完成语义分析与检测,同时根据属性翻译文法的属性及相关动作得到中间代码(抽象机式汇编指令),最后通过模拟的抽象机运行出结果。
2)设计方法:(@为动作标志,↓为继承属性,↑为综合属性) 结合课本语法制导相关内容对文法增加属性和动作如下:
以下列出有修改的属性翻译文法: ①
其中动作符号的含义如下
@name-def↓n,t:插入符号表;
②
其中动作符号的含义如下
@BRF↑label1 :输出 BRF label1; @BR↑label2:输出 BR label2; @SETlabel↓label1:设置标号label1; @SETlabel↓label2:设置标号label2;
③
其中动作符号的含义如下
@SETlabel↑label1:设置标号label1; @BRF↑label2 :输出 BRF label2; @BR↓label1:输出 BR label1;
@SETlabel↓label2:设置标号label2;
④
其中动作符号的含义如下
@SETlabel↓label1:设置标号label1;
@BRF↑label2 :输出 BRF label2; @BR↑label3:输出 BR label3;
@SETlabel↓label4:设置标号label4; @BR↑label1:输出 BR label1;
@SETlabel↓label3:设置标号label3; @BR↑label4:输出 BR label4;
@SETlabel↓label2:设置标号label2; ⑤
其中动作符号的含义如下 @ OUT:输出 OUT
⑥
其中动作符号的含义如下
@LOOK↓n↑d:查符号表n,给出变量地址d; 没有,变量没定义; @IN:输出IN;
@STO↓d:输出指令代码STO d; @POP:将栈顶元素出栈
⑦
|
其中动作符号的含义如下
@LOOK↓n↑d:查符号表n,给出变量地址d; 没有,变量没定义; @ASSIGN:记住当前文件位置; @STO↓d:输出指令代码STO d; ⑧
|< additive_expr >>
其中动作符号的含义如下
@GT:次栈顶与栈顶作大于比较; @LES:次栈顶与栈顶作小于比较; @GE:次栈顶与栈顶作大于等于比较; @LE:次栈顶与栈顶作小于等于比较;
@EQ:次栈顶与栈顶作等于比较;
@NOTEQ:次栈顶与栈顶作不等于比较;
B→+
⑨
C→*
⑩
? < factor >→(< expression >)| ID↑n@LOOK↓n↑d@LOAD↓d |NUM↑
i@LOADI↓i
其中动作符号的含义如下
@LOOK↓n↑d:查符号表n,给出变量地址d; 没有,变量没定义; @LOAD↓d:将地址d的变量入栈; @LOADI↓i:将常量i入栈;
3)设计结果:
1)
2)
3)
5)
|
6)
7)
8)
9)
10)
13)
14)
15)
17)
18) < term >→
19)
20) < factor >→(< expression >)| ID↑n@LOOK↓n↑d@LOAD↓d |NUM↑i@LOADI↓i 三、实验过程
首先,理解书上的代码和观看相关的知识的PPT,深入理解属性反应文法的作用,据此在我之前实验写好的语法分析基础上进行修改,写出语义分析代码。在语义分析里增加“不可引用未赋初值变量”的规则,在init()、showVarTable()、checkInitValue()中增加了相关操作。
然后,结合栈式抽象机及其汇编指令相关命令的操作含义,模拟写出TEST语言的抽象机模型用以运行文法生成的中间代码。
最后,写出执行中间代码的虚拟机程序。最后,编写TEST语言程序进行代码实例
测试,调试观察运行过程及结果,并调试修改程序BUG。
代码完成后,测试、完善。
//定义符号表结构,添加未赋初值记录 struct{
char name[8];
//在插入符号表动作@name-def↓n, t的程序中给notInit赋值为0, vartable[vartablep].notInit =0;
//在该函数给中判断notInit的值是否为0和查询表中是否有变量名,若查询表中有该变量名,且notInit为0时,将该变量的notInit赋值为1,表示已经判断已经赋值
void init(char *name)
//在该函数中首先判定变量是否声明,再判定notInit的值是否为0,若变量是声明了且notInit为0时,则判定变量未赋初值。
void checkInitValue(char *name)
int address;
int notInit;//未赋初值
}vartable[maxvartablep];//改符号表最多容纳maxvartablep个记录