编译原理实验报告
汕头大学 08 计算机科学与技术 编译原理实验报告
2
一.实验目的:
熟练掌握 PLO 语言编译程序的结构和功能;
二.实验要求:
扩充 PLO 语言的功能,增加 for 语句和 case 语句;已知 for 语句和 case 语句的语法如下:
<for 语句>::=for(赋值语句;关系表达式) do <语句>
<关系表达式>::=<表达式><关系运算符><表达式>
<case 语句>::=<case><标识符>:{<常量>:<语句>}endcase .
三. 实验环境与工具:
(1)计算机及操作系统:WindowsXP
(2)程序设计语言:C
(3)编译程序:PL/0
(4)实现工具(平台):VC++6.0
四.设计方案:
1. 概述:
源语言:pl0
目标语言:类 pcode 代码
实现工具(平台):VC++6.0
2. 结构设计说明:
PlO 所有子程序如下:
过程或函数名
简要功能说明
main
初始化编译环境,建立关键字表,调用分程序 Block 对源文件进行编译,
当编译正确时,自动调用解释执行程序,对目标代码进行解释执行。
error
出错处理,打印出错位置和错误性质编号。并在信息栏输出错误信息。
getch
过滤空格,读取一个字符
getsym
词法分析,读取一个单词
gen
生成目标代码(类 pcode 代码),并送入目标程序区。
test
测试当前单词是否是合法
block
分程序分析处理过程。
enter
登录过程说明对象包括变量、常量和过程名的属性信息到符号表。
汕头大学 08 计算机科学与技术 编译原理实验报告
3
position
查找标识符在符号表中的位置。
constdeclaration
常量定义处理,收集常量信息并登录到符号表。
vardeclaration
变量定义处理,收集变量信息并登录到符号表。
listcode
列出目标代码清单。
statement
语法分析,语句部分处理。
expression
表达式分析处理。
term
项分析处理过程。
factor
因子分析处理。
condition
条件处理。
interpret
对目标代码进行解析执行。
Base
通过静态链求数据区首地址。
3. 增加 for 语句:
(1)设计思想:
For 语句的语法分析:
<for 语句>::=for(赋值语句;关系表达式) do <语句>
设计思路:
主要分为两部分模块:一,for 和;之间的赋值语句处理;二,条件语句处理和最后的语句处
理。
首先获取赋值号左边的标识符,从符号表中找到它的信息,并确认这个标识符确为变量名。
然后通过调用表达式处理过程算得赋值号右部的表达式的值并生成相应的指令保证这个值放在运
行期的数据栈顶。最后通过前面查到的左部变量的位置信息,生成相应的 STO 指令,把栈顶值存入
指定的变量的空间,实现了赋值操作。返回函数值也是用赋值语句进行返回值的储存。
首先调用 condition 函数处理条件语句,并且把当前 condition 处理生成的判断条件操作代
码的的地址 cx 保存到 cx1。每个循环体中,在循环体结束前,设置跳回判断操作判断当前条件是否
跳出循环。都把本循环体结束的下一个位置保存到 cx2 生成跳转,并在循环结束时用 cx2 更新为目
前循环结束跳转地址。
难点分析:本模块,主要难点是处理循环体的跳转,解决方法参照上点。不过可以参照 if 语
句和 while 语句。
for
ident
:=
表达式
;
条件
do
语句
汕头大学 08 计算机科学与技术 编译原理实验报告
4
(2)扩充代码:
1)在头文件 pl0.h 中的符号 symbol 中增加所要求增加的符号,用加粗倾斜红色字体标出:
2)源代码:
if(sym==forsym) /* 准备按照 for 语句处理 */
{
getsymdo;
if(sym==ident) /* 按照赋值语句处理 */
{
i=postion(id,*ptx);
if(i==0)error(11); /* 变量未找到 */
else
{
if(table[i].kind!=variable)
{
error(12); /* for 语句格式错误或者赋值语句格式错误 */
i=0;
}
}
getsymdo;
if(sym==becomes)
{
getsymdo;
}
else error(13); /* 检测赋值符号 */
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
expressiondo(nxtlev,ptx,lev); /* 处理赋值符号右侧表达式 */
if(i!=0)
{
gendo(sto,lev-table[i].level,table[i].adr); /* expression 将执行一系列指令,但最终结
果将会保存在栈顶,执行 sto 命令完成赋值 */
}
}
else error(17);
cx1=cx; /* 保存判断条件操作的位置 */
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[dosym]=true; /* 后跟符号为 do */
conditiondo(nxtlev,ptx,lev); /* 调用条件处理 */
cx2=cx; /* 保存循环体的结束的下一个位置 */
gendo(jpc,0,0); /* 生成条件跳转,但跳出循环的地址未知 */
if(sym==dosym)
{
getsymdo;