广工2014编译原理课程设计报告文档格式.doc
《广工2014编译原理课程设计报告文档格式.doc》由会员分享,可在线阅读,更多相关《广工2014编译原理课程设计报告文档格式.doc(15页珍藏版)》请在冰豆网上搜索。
“优”和“良”)
(1)增加类型:
①字符类型;
②实数类型。
(2)增加注释;
注释由/*和*/包含;
(3)扩充函数:
①有返回值和返回语句;
②有参数函数。
(4)增加一维数组类型(可增加指令)。
(5)其他典型语言设施。
二、实验环境与工具
1、源语言:
PL/0语言,PL/0语言是PASCAL语言的子集,它的编译程序是一个编译解析执行系统,后缀名为.PL0;
2、目标语言:
生成文件后缀为*.COD的目标代码
3、实现平台:
BorlandC++Builder6
4、运行平台:
Windows8.1
三、设计概述
1、结构设计说明
(1)PL/0编译系统的结构框架
出
错
处
理
函
数
表
格
管
PL/0源程序
目标代码生成程序程序
源语言:
源语言是基于C语言写的PL/0编译程序——PL0语言(可以看成Pascal语言的子集)
目标语言:
假想的栈式计算机计算语言,即类PCODE指令代码。
指令格式如下:
f
l
a
其中f代表功能码,l表示层次差,a的含意对不同的指令有所区别。
具体的指令功能表:
LIT0a
将常数值取到栈顶,a为常数值
LODla
将变量值取到栈顶,a为偏移量,l为层差
STOla
将栈顶内容送入某变量单元中,a为偏移量,l为层差
CALla
调用过程,a为过程地址,l为层差
INT0a
在运行栈中为被调用的过程开辟a个单元的数据区
JMP0a
无条件跳转至a地址
JPC0a
条件跳转,当栈顶布尔值非真则跳转至a地址,否则顺序执行
OPR00
过程调用结束后,返回调用点并退栈
OPR01
栈顶元素取反
OPR02
次栈顶与栈顶相加,退两个栈元素,结果值进栈
OPR03
次栈顶减去栈顶,退两个栈元素,结果值进栈
OPR04
次栈顶乘以栈顶,退两个栈元素,结果值进栈
OPR05
次栈顶除以栈顶,退两个栈元素,结果值进栈
OPR06
栈顶元素的奇偶判断,结果值在栈顶
OPR07
OPR08
次栈顶与栈顶是否相等,退两个栈元素,结果值进栈
OPR09
次栈顶与栈顶是否不等,退两个栈元素,结果值进栈
OPR010
次栈顶是否小于栈顶,退两个栈元素,结果值进栈
OPR011
次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈
OPR012
次栈顶是否大于栈顶,退两个栈元素,结果值进栈
OPR013
次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈
OPR014
栈顶值输出至屏幕
OPR015
屏幕输出换行
OPR016
从命令行读入一个输入置于栈顶
四、设计分析
(一)扩充赋值运算:
需要增加2个运算符*=和/=,用下面表格定义的SYM代替
运算符
*=
/=
SYM表示
TIMESBECOMES
SLASHBECOMES
*=和/=的语法描述图:
(二)扩充语句(Pascal的FOR语句)
因为在Pascal中的FOR语句描述为:
FOR<
STEP<
UNTIL<
DO<
所以增加FOR,STEP,UNTIL,DO
FOR语句语法描述图为:
五、程序设计
1)增加所需要的保留字和运算符,实现*=和/=,以及FOR语句,应该增加TIMESBECOMES,SLASHBECOMES,FOR,STEP,UNTIL,DO。
注:
因为要求课设和之前实验的内容合并在一起,所以保留了课程实验已经添加的保留字和运算符,之前的已经添加了的不再赘述。
具体实现的语句如下所示:
typedefenum{NUL,IDENT,NUMBER,PLUS,MINUS,TIMES,
SLASH,ODDSYM,EQL,NEQ,LSS,LEQ,GTR,GEQ,
LPAREN,RPAREN,COMMA,SEMICOLON,PERIOD,
BECOMES,BEGINSYM,ENDSYM,IFSYM,THENSYM,
WHILESYM,WRITESYM,READSYM,DOSYM,CALLSYM,
CONSTSYM,VARSYM,PROCSYM,PROGSYM,ELSESYM,
FORSYM,STEPSYM,UNTILSYM,RETURNSYM,
TIMESBECOMES,SLASHBECOMES,ANDSYM,ORSYM,NOTSYM
}SYMBOL;
这里需要考虑需要增加保留字的个数,以及如何命名,再将新增的保留字添加对应的保留字的集合中。
char*SYMOUT[]={"
NUL"
"
IDENT"
NUMBER"
PLUS"
MINUS"
TIMES"
"
SLASH"
ODDSYM"
EQL"
NEQ"
LSS"
LEQ"
GTR"
GEQ"
LPAREN"
RPAREN"
COMMA"
SEMICOLON"
PERIOD"
BECOMES"
BEGINSYM"
ENDSYM"
IFSYM"
THENSYM"
WHILESYM"
WRITESYM"
READSYM"
DOSYM"
CALLSYM"
CONSTSYM"
VARSYM"
PROCSYM"
PROGSYM"
"
ELSESYM"
"
FORSYM"
"
STEPSYM"
UNTILSYM"
RETURNSYM"
TIMESBECOMES"
"
SLASHBECOMES"
ANDSYM"
ORSYM"
NOTSYM"
};
2)将新增的保留字按照字母表升序的方式添加,运算符参照已有的运算符来进行添加,注意好符号与SYM的对应。
特别注意点:
此处一定要考虑到PLO编译器采用了折半查找算法来进行操作,如果新增的保留字没有按照既定的升序规则来插入,会造成在编译过程中,编译器无法识别某些保留字。
strcpy(KWORD[1],"
BEGIN"
);
strcpy(KWORD[2],"
CALL"
strcpy(KWORD[3],"
CONST"
strcpy(KWORD[4],"
DO"
strcpy(KWORD[5],"
ELSE"
strcpy(KWORD[6],"
END"
strcpy(KWORD[7],"
FOR"
strcpy(KWORD[8],"
IF"
strcpy(KWORD[9],"
ODD"
strcpy(KWORD[10],"
PROCEDURE"
strcpy(KWORD[11],"
PROGRAM"
strcpy(KWORD[12],"
READ"
strcpy(KWORD[13],"
RETURN"
strcpy(KWORD[14],"
STEP"
strcpy(KWORD[15],"
THEN"
strcpy(KWORD[16],"
UNTIL"
strcpy(KWORD[17],"
VAR"
strcpy(KWORD[18],"
WHILE"
strcpy(KWORD[19],"
WRITE"
WSYM[1]=BEGINSYM;
WSYM[2]=CALLSYM;
WSYM[3]=CONSTSYM;
WSYM[4]=DOSYM;
WSYM[5]=ELSESYM;
WSYM[6]=ENDSYM;
WSYM[7]=FORSYM;
WSYM[8]=IFSYM;
WSYM[9]=ODDSYM;
WSYM[10]=PROCSYM;
WSYM[11]=PROGSYM;
WSYM[12]=READSYM;
WSYM[13]=RETURNSYM;
WSYM[14]=STEPSYM;
WSYM[15]=THENSYM;
WSYM[16]=UNTILSYM;
WSYM[17]=VARSYM;
WSYM[18]=WHILESYM;
WSYM[19]=WRITESYM;
SSYM['
+'
]=PLUS;
SSYM['
-'
]=MINUS;
*'
]=TIMES;
SSYM['
/'
]=SLASH;
('
]=LPAREN;
SSYM['
)'
]=RPAREN;
='
]=EQL;
SSYM['
'
]=COMMA;
.'
]=PERIOD;
;
'
]=SEMICOLON;
&
]=ANDSYM;
|'
]=ORSYM;
!
]=NOTSYM;
3)特别需要注意的两点,这个是很容易被忽略的地方,就是在完成保留字和运算符的增加以后,一定要对PLO编译器对保留字个数已经单词总数定义进行相应的修改。
保留字总数
比如说在不添加任何保留字的情况下,PL0编译器的原保留字应该是14个,所以在Unit1.CPP中有定义constNORW=14;
/*#OFRESERVEDWORDS*/
而在实验中因为新增加保留字5个,故此处应改为:
constNORW=19;
单词总数
与保留字总数一样,我们增加完保留字和运算符以后,要修改单词总是,比如原单词总数是33,因为原编译器中并未定义一个常量来进行统一管理,所以需要对所有“i<
33”的地方进行修改。
因为实验中新增加单词10个,故应改为“i<
43”。
如下面代码所示举例:
S