华南理工大学
《编译原理》课程实验报告
实验题目: 实现TINY+编译器
源代码及报告书: (为了大家的学习着想,此处就不放github的地址了 可以在我的个人上传资源中找到这份文档)。
(此处图片未显示,可以在github中下载报告书观看。报告书即为如下内容)
构造一个将TINY+高级程序设计语言转换为TINY+虚拟机上的中间代码的编译器。
整个实验包括两个部分:实验一完成TINY+编译器的词法分析器部分;实验二完成TINY+编译器的语法分析器部分、语义分析器部分及中间代码生成器部分。
Microsoft Visual Studio 2015
C++语言实现
分为实验一、二。学生在该实验中构造TINY+语言的词法分析程序。具体要求如下:
1 词法分析器的输入是源程序文件,输出是单词(token)流。
2 构造的词法分析器必须遵循最长子串原则,例如字符串‘:=’ 应该被识别为一个代表赋值符号的单词,而不是识别为两个单词‘:’和 ‘=’。
3 词法分析器识别出的单词应该被表示成二元组的形式(Kind, Value),其中Kind表示单词的种类,Value表示单词的实际值。要求用如下符号表示不同种类的单词:
l KEY 表示关键字;
l SYM 表示特殊符号;
l ID 表示标识符;
l NUM 表述数字常量
l STR 表示字符串常量
4 词法分析器的任务除了完成对单词的识别之外,还要检查程序中的词法错误,给出错误的信息以及错误在源程序中出现的位置(所在的行号)。词法错误的种类包括:
l Ø 非法符号,词法分析器可能识别到一个TINY+程序的字母表中不允许的符号,例如,词法分析器在一个源程序中识别到$,应报告一个词法错误,发现了一个非法符号;
l Ø 字符串类型的单词STRING,单引号不匹配。例如,源程序中出现' scanner,词法分析分析器应报告错误“字符串缺少右引号”;
l 注释的括号不匹配。例如源程序中出现{this is an example,词法分析器应报告错误“注释缺少右括号”。
词法分析实验过程:
Tiny关键字 |
if,then,else,end ,repeat,until,read,write |
Tiny+新增关键字 |
Or,and ,int,bool,char,while,do |
其中所有的关键字是程序设计语言保留使用的,并且用小写字母表示,用户自己定义的标识符不能和关键字重复。
Tiny符号 |
{ } ; := + - * / ( ) < = |
Tiny+新增符号 |
> <= >= , ' |
KEY |
关键字 |
SYM |
特殊符号 |
ID |
标识符 |
NUM |
数字常量 |
STR |
字符串常量 |
注释的括号不匹配。例如源程序中出现{this is an example,词法分析器应报告错误“注释缺少右括号”。
实验过程:
关键词 |
特殊符号 |
||
新增枚举定义 |
对应的关键词 |
新增枚举定义 |
对应特殊符号 |
OR |
or |
RT |
> |
AND |
and |
LTEQ |
<= |
INT |
Int |
RTEQ |
>= |
BOOL |
bool |
COMMA |
, |
CHAR |
char |
CO |
‘ |
WHILE |
while |
|
|
DO |
do |
|
|
测试一:
输入 |
输入右边所示文件,运行程序后,结果如下图: (下面两张图为同一输出结果) |
|
输出 |
|
测试二:
输入 |
输入右边所示文件,运行程序后,结果如下图: (下面两张图为同一输出结果) |
|
输出 |
|
测试三:(测试错误提示)
输入 |
输入右边所示文件,运行程序后,结果如下图: 其中有两处错误:
|
|
输出 |
|
学生在该实验中构造TINY+语言的语法分析器、语义分析器以及中间代码生成器,具体要求如下:
20 bool-exp -> bterm { or bterm } 21 bterm -> bfactor { and bfactor} 22 bfactor -> comparison-exp 23 comparison-exp -> arithmetic-exp comparison-op arithmetic-exp 24 comparison-op -> < | = | > | >= | <=
|
语句系列 |
|
语句间通过链表相连,除了第一条语句,其他语句均可通过前一个语句的->slibing查找到。 |
If语句 |
|
test位于If语句的child[0], then-part为child[1], else-part为child[2] |
Repeat |
|
Body位于repeat语句中的child[0], test位于chlid[1] |
Assign |
|
Expression 位于assign语句child[0] |
write |
|
Expression位于write的child[0] |
Op 逻辑运算 |
|
Left-operand 位于op语句的child[0], Right-opreand位于语句的child[1]; |
while |
|
Test位于while语句的child[0] Do-part位于child[1] |
Define 如: int A,B |
|
B位于A的slibing中, 其中A、B的子节点均未赋值(此处留给将来拓展用) |
测试一:
输入 |
输入右边所示文件,运行程序后,结果如下图: |
|
输出 |
|
1在main函数中将 NO_CODE 设置为TRUE,使程序进行语义分析过程。
2一个用TINY+语言编写的程序包括变量的声明和语句序列两个部分。变量声明部分可以为空,但一个TINY+程序至少要包含一条语句。
3构建语义分析器主要包括
当遇到定义的语法结点时候,将其变量新增到哈希表中,并存储其行号位置;
遇到含有变量的非定义语句的结点时,查找该变量位于哈希表中的位置,将该行号储存到哈希相应表项的next位置。
1. if语句结点中,if-test(child[0])的类型必定为boolean,
2. while语句结点中,while-test(child[0])的类型必定为boolean,
3. op算术运算结点中,child[0]、child[1]必须为integer类型
4. op逻辑运算结点中,child[0]、child[1]必须为boolean
5. 赋值运算结点中,child[0]、child[1]的类型必须一致
6. ……
测试一:
输入 |
输入右边所示文件,运行程序后,结果如下图:
|
|
输出 |
|
测试二:
输入 |
输入右边所示文件,运行程序后,结果如下图:
|
|
输出 |
|
测试三:(测试错误提示)
输入 |
输入右边所示文件,运行程序后,结果如下图: 代码中有三处错误:
|
|
输出 |
|
1 在main函数中将 NO_PARSE、NO_ANALYZE、NO_CODE 设置为FALSE,使程序进行中间代码生成过程。
2 构造TINY+的中间代码生成系,该中间代码生成器将TINY+程序翻译为三地址中间代码。
3在原tiny中间代码生成器的实现位于cgen.c和cgen.h中。其接口为codeGen(TreeNode* syntaxTree,char* codefile).
主要功能为:
注释以及指令均写在某指定.tm文件上,供TM程序调用并且运行。
如增加“>”的中间代码生成过程
此处中间代码生成比算术运算的中间代码复杂得多,根据TM程序的指令以及其操作原理,写出AND和OR中间生成代码功能:
此处通过Tiny+文法规则产生对于的三地址中间代码属性,完成while生成中间代码功能。
测试一:
输入 |
输入右边所示sample.tny文件到TINY+,运行程序后,获得example.tm文件。
将example.tm文件输入TM程序中,运行结果如图: 输入x=5,输出120(正确) 输入x=101,跳出if(正确) 输入x=4,输出24(正确) 输入x=-1,跳出if(正确) |
|
输出 |
Example.TM文件如下截图:
输入上述文件到TM程序中运行,结果如下:
|