相关链接
编译原理:flex与bison–从0到1完成一个编译器(sample语言)〇
编译原理:flex与bison–从0到1完成一个编译器(sample语言)①
编译原理:flex与bison–从0到1完成一个编译器(sample语言)②
编译原理:flex与bison–从0到1完成一个编译器(sample语言)③
代码Github链接
文章目录
前言
本系列文章共三部分,记述了我完成编译器的过程,供后来的学弟学妹参考借鉴。(时隔三年,我终于想起更新第二三部分了。)
本项目是我的编译原理作业,文章是由实验报告整理而来的,重在阐述,如果没有学习编译原理的相关知识,还要结合一些教程来看。
本项目实现的编译器包括词法分析,语法分析,语义分析与中间代码生成,目标代码生成共四个阶段,能将sample语言翻译成可执行的汇编语言。使用flex与bison工具辅助,通过C语言实现。本人能力有限,项目有许多不足和值得改进的地方,也请读者多多指正。
一、 实验目的与要求
本次实验的任务是在词法分析、语法分析的基础上,对 Sample 语言书写的源代码进行语义 分析,并生成某种机器上的目标代码(汇编语言)或者中间代码(四元式)。实验依然要求使用词法分析工具 Flex 和语法分析工具 Bison 共同来完成。通过本次实验,加深对编译原理基础理论的理解,提高自身的动手实验能力。
本上机实习是结合前两次实验,进一步完成语义分析和中间代码生成与目标代码生成的综合练习。重点在语义分析和中间代码生成,要求能够将 Sample 源代码中的表达式、赋值语句和条件语句和循环语句翻译成四元式,并完成汇编代码的生成。
二、 实验原理与内容
中间代码是源程序的一种内部表示,不依赖目标机的结构,易于机械生成目标代码的中间表示。如果不生成中间代码而是直接生成机器语言或者汇编语言形式的目标代码,优点是编译时间短,缺点是目标代码执行效率和质量都比较低,移植性差。
语义分析与中间代码生成在编译器中的位置如下图所示。
该阶段输入是语法,输出是用中间代码表示的文本,和出错处理与定位。
本实验要实现对于Sample语言的中间代码生成,以四元式表示,并将四元式翻译成汇编语言。
样例一:对于表达式 A=B+C*(-D) 生成其四元式样例二:对于条件语句,生成其四元式
样例三:对于小程序输出其中间代码
样例四:复杂语句的翻译,比如条件语句中嵌套 do-while 循环语句等。
三、 实验步骤
3.1 语义分析和中间代码的生成
3.1.1符号表与四元式
本程序设计了VARLIST类和QUATERLIST类对应符号表与四元式。
对于每个在翻译过程中出现的符号(包括中间变量),本程序会记录其名称、类型和地址。Entry()方法定义了在符号表中找到变量并返回其地址。NewTemp()方法返回一个新的中间变量Ti的地址。FillType()方法是将某一地址之后的所有元素类型都设置为一指定类型。
对于每个生成的四元式,QUATERLIST记录其操作名称,两个运算量和结果单元的地址。根据地址可以在符号表中找到变量的名称和类型。若某一运算量为0则该运算量无效。四元式的地址从1开始,若执行到跳转到0的语句,则程序结束。GEN()方法能够制造一个四元式。
3.1.2赋值与表达式语句的翻译
赋值语句的翻译较为简单,其文法为:
<赋值语句> ::= <变量>:=<表达式>
若等式两边的类型相同,直接用GEN()制造一个赋值的四元式即可。若等式两边的类型不同,则需要进行类型转换。将等式右边的类型转换为等式左边的类型,再进行赋值。
如对于语句 a:=3.0 ,若a是整数,则需要将3.0转换成整数形式再赋值给a。
对于表达式语句,在实验二中有过阐述。文法保证了*和/的优先性。在本实验中,考虑了运算符两边类型不同的情况,对于运算符左右类型的不同情况,需要进行转化。转化方法如下表