编译原理课程设计报告.doc
编译原理课程设计报告

《编译原理》课程设计报告一、课程设计目的通过课程设计进一步理解高级语言在计算机中的执行过程,了解现代编译器的运作机制,加深对编译原理中重点算法和编译技术的理解,提高自己自学和理解的能力。
学会如何利用已有软件JFLex、Java_cup对词法分析器及语法分析器的构造。
二、设计概述本tiger语言编译器的编译过程涉及到编译五个阶段中的二个,即词法分析器、语法分析器。
其中语法分析后还完成了语法树的打印的构造以及类型检查。
词法分析器由JFLex编译正则式生成,词法分析器编译产生式生成,语法分析器由CUP生成。
结果通过GUI界面呈现在使用者面前。
编译程序需要在单词级别上来分析和翻译源程序,所以首先要识别出单词,而词法分析部分的任务是:从左至右扫描源程序的字符串,按照词法规则(正则文法规则)识别出一个个正确的单词,并转换成该单词相应的二元式(种别码、属性值)交给语法分析使用。
因此,词法分析是编译的基础。
执行词法分析的程序称为词法分析器。
语法分析是编译程序的核心部分,其主要任务是确定语法结构,检查语法错误,报告错误的性质和位置,并进行适当的纠错工作。
三、设计过程(一)设计构思程序主要完成三大功能模块:词法分析器、语法分析器、GUI人机交互界面。
词法分析器由JFLex编译正则式生成,其中必须为外界提供一个获取记号流的接口,实验中定为java_cup.runtime.Symbol next_token。
语法分析器是建立在词法分析器上的,故必须包含词法分析器以便获得记号流,next_token为语法分析器提供TOKEN,语法分析器的对外接口是:java_cup.runtime.Symbol debug_parse(),同时返回语法树的根节点。
GUI 界面是提供人机交互的,它能够依次显示词法分析阶段分析得到的所有TOKEN 的信息,语法阶段生成的语法树,另外对于词法和语法阶段出现的错误在“错误提示”文本框中一一列举出来,提供用户改进代码的信息。
编译原理课程设计报告

课程设计报告( 2021--2022年度第一学期)名称:编译技术课程设计题目:算符优先分析法研究院系:班级:学号:学生姓名:指导教师:设计周数:一周成绩:日期:2021年12 月31日1 课程设计的目的和要求1.1 课程设计的目的本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。
设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。
1.2 课程设计的要求1. 文法使用产生式来定义;2. 分别给出每一个非终结符的FIRSTVT和LASTVT集。
3. 画出算符优先关系表;4. 判定给定的文法是否是算符优先文法;5. 给定符号串判定是否是文法中的句子,分析过程用分析表格的方式打印出来。
2 系统描述举例如下:本次实验使用Visual Studio 2019软件,利用只规定终结符之间的优先关系的自底向上移进-规约法实现对算符优先分析法的研究,输出非终结符的FIRSTVT和LASTVT集,算符优先关系表和对句子的分析表格,均在DOS窗口显示。
2.1 文法的描述G[S]: S->#E#;E->E+T|T;F-P!F|P;T->T*F|F;P->(E)|i2.2 属性文法的描述表2-1 条件语句及其语义规则3 概要设计3.1 概要设计(体现系统的设计思路和主要功能)主要步骤包括:用户自己输入文法,实质上是算数表达式的计算。
构建每个非终结符的FirstVT()和LastVT()集。
构建优先关系符号表。
构建词法分析的程序。
编写主函数,用户输入文法对语句利用算符优先文法进行判别。
算法的主体思想:用栈存储已经看到的输入符号,用优先关系指导移动归约语法分析器的动作,如果栈顶的终结符和下一个输入符之间的优先关系是<或=,则语法分析器移动,表示还没有发现句柄的右端,如果是>关系,就调用归约。
3.2 开发环境实验采用C++程序语言进行设计开发工具为Visual Studio 20194 详细设计4.1 系统的类图图4-1 文法类图4.2 主要算法的流程图图4-2 求非终结符的FIRSTVT 和LASTVT 集流程图求LASTVT 集的过程与此类似,但符号串的扫描顺序是从后开始若产生式右部第一个字符为非终结符 则直接将其加入first 集中else first[x].insert(str[0]);寻找该非终结符 的first 集 dfs(y);将该非终结符的first 集也加进去for (; it != first[y].end(); it++)first[x].insert(*it);if (isupper(str[0]))若产生式右部第一个字符为非终结符 string& left = VN_set[x].left;string&str = VN_set[x].right[i];产生产生式左部非终结符的FIRSTVT 集图4-3 构造算符优先关系表流程图图4-4 对输入串进行算符优先分析流程图4.3 数据分析与定义char relation[MAX][MAX]; //算符优先关系表vector<char> VT;vector<WF> VN_set; //类型为文法的数组VN_setmap<string, int> VN_dic; //map映射,一条产生式对应的第几条的序号set<char> first[MAX]; //FIRSTVT集set<char> last[MAX]; //LASTVT集4.4 系统界面设计用户输入文法个数和每条产生式的内容后,输出结果格式如下:分为:产生式、FIRSTVT集、;LASTVT集、算符优先关系表和分析过程图4-5 系统输出界面概况5 测试方法和测试结果5.1 测试用例1输入如程序5-1所示。
编译原理课程设计报告

实验要求✧基本内容1)增加单词:保留字ELSE,REPEAT,DOWHILE,RETURN运算符+=,-=,++,--2)修改单词:不等号# 改为<>3)增加条件语句的ELSE子句4)扩充赋值运算:+= 和-=5)扩充语句(Pascal的FOR语句):①FOR <变量>:=<表达式> TO <表达式> DO <语句>②FOR <变量>:=<表达式> DOWNTO <表达式> DO <语句>其中,语句①的循环变量的步长为2,语句②的循环变量的步长为-2。
✧选做内容1)增加运算:++ 和--。
2)增加类型:①字符类型;②实数类型。
3)扩充函数:①有返回值和返回语句;②有参数函数。
4)增加一维数组类型(可增加指令)。
5)其他典型语言设施。
设计方案1.概述:源、目标语言:编译程序编绎的源程序是PL0,程序产生的目标代码是一个假想栈式计算机的汇编语言.称为类PCODE指令代码 ,指令格式格式如下:F L A其中F代表功能码,L表示层次差,A表示位移量,不同指令其含义有所区别。
PL/0语言是Pascal语言的一个子集,这里分析的PL/0的编译程序包括了对PL/0语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。
PL/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。
词法分析和代码生成作为独立的子程序供语法分析程序调用。
语法分析的同时,提供了出错报告和出错恢复的功能。
在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。
实现工具(平台),运行平台:编译器实现工具和运行平台程序用C++语言编写,在C++ Builder平台下运行。
2.结构设计说明:PL/0的编译过程采用一趟扫描方式,以语法分析为核心,词法分析程序和代码生成程序都作为一个独立的过程,当语法分析需要读入单词时就调用词法分析程序,而当语法分析正确需生成相应的目标代码时,则调用代码生成程序。
编译原理课程设计报告

2011-2012学年第二学期《编译原理》课程设计报告学院:计算机科学与工程学院班级:学生姓名:学号:成绩:指导教师:时间:2012年5 月目录一、课程设计的目的 ---------------------------------------------------------------- - 1 -二、课堂实验及课程设计的内容 -------------------------------------------------- - 1 -2.1、课堂实验内容-------------------------------------------------------------- - 1 -2.2、课程设计内容-------------------------------------------------------------- - 1 -三、visual studio 2008 简介------------------------------------------------------- - 2 -四、问题分析及相关原理介绍 ----------------------------------------------------- - 3 -4.1、实验部分问题分析及相关原理介绍 ---------------------------------- - 3 -4.1.1、词法分析功能介绍及分析------------------------------------- - 3 -4.1.2、语法分析功能介绍及分析------------------------------------- - 3 -4.1.3、语义分析功能介绍及分析------------------------------------- - 4 -4.2、课程设计部分问题分析及相关原理介绍 ---------------------------- - 5 -4.2.1、编译程序介绍 ----------------------------------------------------- - 5 -4.2.2、对所写编译程序的源语言的描述(C语言) -------------- - 6 -4.2.3、各部分的功能介绍及分析 -------------------------------------- - 7 -4.3、关键算法:单词的识别-------------------------------------------------- - 8 -4.3.1、算法思想介绍 ----------------------------------------------------- - 8 -4.3.2、算法功能及分析 -------------------------------------------------- - 8 -五、设计思路及关键问题的解决方法 ------------------------------------------ - 10 -5.1、编译系统------------------------------------------------------------------ - 10 -5.1.1、设计思路 --------------------------------------------------------- - 10 -5.2、词法分析器总控算法--------------------------------------------------- - 12 -5.2.1、设计思路 --------------------------------------------------------- - 12 -5.2.2、关键问题及其解决方法 --------------------------------------- - 13 -六、结果及测试分析-------------------------------------------------------------- - 14 -6.1、软件运行环境及限制--------------------------------------------------- - 14 -6.2、测试数据说明------------------------------------------------------------ - 14 -6.3、运行结果及功能说明--------------------------------------------------- - 16 -6.4、测试及分析说明--------------------------------------------------------- - 16 -七、总结及心得体会 --------------------------------------------------------------- - 17 -7.1、设计过程------------------------------------------------------------------ - 17 -7.2、困难与收获 ------------------------------------------------------------- - 17 -八、参考文献 ------------------------------------------------------------------------ - 18 -一、课程设计的目的通过设计、编写和调试词法分析程序(又称扫描器),了解扫描器的组成结构,不同种类单词的识别方法,加深了对词法分析作用的理解。
编译原理课程设计报告

课程设计报告设计题目:一个简单文法的编译器的设计与实现班级:计算机1206班组长学号:2012XXX组长姓名:XXX指导教师:XXX设计时间:2014年12月设计分工组长学号及姓名:2012XXX XXX分工:1)读取源文件进行词法分析2)进行LL(1)分析生成分析表3)设计顶层自动机将源程序分段4)生成可执行的汇编程序组员1学号及姓名:2012XXX XXX分工:1)设计第二层自动机处理程序片段2)生成中间语言四元式3)源程序错误处理组员2学号及姓名:2012XXX XXX分工:1)设计第三层自动机处理复合表达式2)设计带动作的LL(1) 文法3)源程序错误处理摘要编译原理课程具有很强的理论性和实践性,是计算机专业的一门非常重要的专业基础课程,在系统软件中也是占有十分重要的地位。
本次课程设计我们是在Visual C++的平台上应用了词法分析、语法分析、语义分析、中间语言生成以及目标语言生成的知识设计了一个简单的编译器前端。
其中设计了一个简单的有限自动机来扫描源程序即进行语法分析,并生成了关键字表、标志符表、界符表、常数表和Token串;设计了一个LL(1)文法和一个带动作的文法来实现语法分析,并生成了Select集和LL(1)分析表;采用了四元式序列的设计来生成中间语言;通过汇编语言设计来生成目标语言。
最后为了使该编译器更加完善,我们设计了简单的的错误检查机制,能够对源程序进行比较全面的错误检查同时也能够指出错误出现的大致位置,增强了该编译器的健壮性。
关键字:编译器,前端,有限自动机,LL(1)文法,汇编语言,错误处理目录摘要 (3)1、概述 (5)2、课程设计任务及要求 (5)2.1设计任务 (5)2.2设计要求 (6)3、算法与数据结构 (6)3.1词法分析器的算法 (6)3.2 语法分析器的算法 (12)3.2.1 LL(1)文法设计算法 (12)3.2.2递归下降子程序设计算法 (19)3.3中间语言生成器算法 (20)3.4处理复合表达式算法 (24)3.5目标语言生成器算法 (30)3.6数据结构 (39)4、程序设计与实现 (39)4.1编译程序设计与实现 (39)4.2程序实验结果 (39)4.2.1待测源程序 (39)4.2.2词法分析结果 (40)4.2.3语法分析结果 (41)4.2.4中间语言生成结果 (42)4.2.5目标语言生成结果 (43)4.2.6程序错误处理结果 (44)5、参考文献 (44)1、概述本次课程设计的编译程序主要包括了词法分析器、语法分析器、中间代码生成器和目标代码生成器四部分,编译程序的输出结果包括了词法分析后的关键字表、界符表、标识符表和Token串,语法分析后的Select集和LL(1)分析表;中间代码生成器产生的四元式序列。
编译原理课程设计报告

《编译原理》课程设计报告姓名:熊齐超(1208060220)姓名:刘畅(1208060221)姓名:袁青伟(1208060222)姓名:张文(1208060223)班级:软件121班专业:软件工程指导教师:陈晓明时间:2015/6/14项目名称:算术表达式的语法及语义分析贵州大学计算机科学与信息学院目录一、课程设计目的 (3)二、课程设计题目描述和要求 (3)1、算术表达式的文法的描述: (3)2、课程设计的要求描述: (3)3、实现的功能描述: (4)4、分析器的使用描述 (4)三、课程设计实现描述 (4)1、实现平台 (4)2、课程设计的基本思路描述 (5)3、自顶向下与递归下降分析方法的基本原理描述 (5)4、程序运行的最后界面 (6)5、演示分析 (8)四、课程设计总结 (8)五、参考文献及小组分工 (9)六、核心代码 (10)一、课程设计目的通过设计、编制、调试一个算术表达式的语法及语义分析程序,加深对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。
加深对文法分析器的知识的掌握,掌握计算机语言的语法分析的过程。
以及掌握计算机语言的语法分析程序设计与文法应用的实现方法。
能够熟练运用一种分析方法,自上而下或自下而上的方法分析一个给定的文法,我使用的是自上而下的分析方法。
以及通过思考以及动手制作分析器的过程来锻炼自己的编程能力和逻辑思维能力,体会计算机编译器的奥妙之处。
二、课程设计题目描述和要求1、算术表达式的文法的描述:〈无符号整数〉∷=〈数字〉{〈数字〉}〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}〈表达式〉∷=〈项〉{〈加法运算符〉〈项〉}〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}〈因子〉∷=〈标志符〉|〈无符号整数〉〈加法运算符〉∷=+|-〈乘法运算符〉∷=*|/〈字母〉∷= a | b | … | z〈数字〉∷= 0 | 1 | … | 92、课程设计的要求描述:1)在递归下降法、LL(1)、算符优先分析法或者LR法中选择其中一种方法完成以上任务,中间代码选用四元式。
《编译原理》设计方案报告

《编译原理》课程设计报告设计题目:pl0编译器设计一、PL0程序的文法及,指令及属性翻译简化c语言文法定义(LL(1)文法)C程序::=void main(){函数体}函数体::=变量定义部分语句列变量定义部分::=变量定义变量定义部分| ɛ变量定义::=int 变量表变量表::=标识符|标识符,变量表语句列::=语句语句列| ɛ语句::=条件语句| 循环语句| 读语句| 写语句| 复合语句| 表达式语句| 空语句条件语句::=if(表达式)语句循环语句::=while(表达式)语句读语句::=read(变量表);写语句::=write(表达式表);复合语句::={语句列};表达式语句::=表达式;空语句::=;表达式定义(算符优先文法)表达式::=变量=表达式| 变量+=表达式| 变量-=表达式| 变量*=表达式| 变量/=表达式| 变量%=表达式| 表达式1表达式1::=表达式1 || 表达式2 | 表达式2表达式2::=表达式2&&表达式3 | 表达式3表达式3::=表达式3==表达式4 | 表达式3!=表达式4 | 表达式3>=表达式4 | 表达式3>表达式4 | 表达式3<=表达式4 | 表达式3<表达式4 | 表达式4表达式4::=表达式4+表达式5 | 表达式4-表达式5 | 表达式5表达式5::=表达式5*表达式6 | 表达式5/表达式6 |表达式5/表达式6 |表达式6表达式6::=!表达式7表达式7::=(表达式) | 变量| 常量PL0文法定义《程序》::=《分程序》.《分程序》::=《常量定义》;《常后分程序》|《常后分程序》《常后分程序》::=《变量定义》;《变后分程序》|《变后分程序》《变后分程序》::=《过程定义》;《变后分程序》|《语句》《常量定义》::=const 《常量定义表》《常量定义表》::=id = number | id = number,《常量定义表》《变量定义》::= var 《变量表》《变量表》::=id | id,《变量表》《过程定义》::=procedure id ;《分程序》《语句》::=《赋值语句》|《条件语句》|《循环语句》|《读语句》|《写语名》|《复合语句》| 《过程调用语句》|ε《赋值语句》::=id := 《表达式》《读语句》::=read(《变量表》)《写语句》::=write(《表达式表》)《表达式表》::=《表达式》| 《表达式》,《表达式表》《条件语句》::=if 《条件表达式》then 《语句》《循环语句》::=while 《条件表达式》do 《语句》《复合语句》::=begin 《语句列》end《过程调用语句》::=call id《参量表》::=《有参表》|ε《有参表》::=《表达式》,《有参表》|《表达式》《表达式》::=+《表达式1》|-《表达式1》|《表达式1》《表达式1》::=《表达式1》+《表达式2》|《表达式1》-《表达式2》|《表达式2》《表达式2》::=《表达式2》*《表达式3》|《表达式2》/《表达式3》| 《表达式2》mod 《表达式3》|《表达式3》《表达式3》::=id | number | (《表达式》)《条件表达式》::=《条件表达式》or 《条件表达式1》|《条件表达式1》《条件表达式1》::=《条件表达式1》and 《条件表达式2》| 《条件表达式2》《条件表达式2》::=not 《条件表达式3》|《条件表达式3》《条件表达式3》::=(《条件表达式》)|《关系表达式》《关系表达式》::=《表达式》>《表达式》《关系表达式》::=《表达式》>=《表达式》《关系表达式》::=《表达式》<《表达式》《关系表达式》::=《表达式》<=《表达式》《关系表达式》::=《表达式》=《表达式》《关系表达式》::=《表达式》#《表达式》PL0栈式机指令指令格式:指令码(f) 所在层数差(l),操作数(a)PL0栈式机指令:LIT:将常数a取到栈顶LOD:将位于(当前层-l)层处的变量a取到栈顶STO:将栈顶处值存储到指定位置,l,a同上CALL 调用当前-l层处的过程aINT:为调用过程在栈中开辟数据区,a为单元个数JMP:无条件转移指令,a目标地址JPC:条件转移指令,栈顶值的布尔值为非真时转移到a处,否则执行下面语句OPR:关系运算或算术运算PL0属性翻译MCONST(const:常量定义开始), V AR(var:变量定义开始), PROCEDURE(procedure:过程定义开始),CALL(call:过程调用语句),BEGIN(begon:复合语句开始),END(end:复合语句结束),IF(if:条件语句开始),THEN(then:条件结束),WHILE(while:循环语句开始), DO(do:循环条件结束), READ(read:读语句),WRITE(write:输出语句), ODD(odd:判奇运算),//分隔符、运算符号DOT(点:.),COMMA(逗号:,), SEMICOLON(分号:;), LPAREN(左括号:(), RPAREN(右括号:)), ASSIGNOP(赋值::=), PLUSOP(加法运算符号:+), MINUSOP(减法运算符:-), MULTOP(乘法运算符:*), DIVOP(除法运算符:/),GT(大于:>),GE(大于等于:>=),LT(小于:<),LE(小于等于:<=),EQ(等于:=),NE(不等:#),ENDF(输入结束符),//分析过程中需要的非终结符号SERVERKEY(保留字), FACTOR(因子),ROP(关系运算), CONSTANT(常量部份定义), V ARIABLE(变量部份定义), IDENT(自定义标识符), NUMBER(常数)二、符号表的结构,组织,填写及查找1、符号表结构const char *pName; //符号名称int kind; //符号类别,由上面单词分类确定int val; //符号表中的位置值int level; //符号的层数int parent; //符号的作用域int size; //过程长度char strBuff[MAXLENSTR]; //符号堆2、符号表的组织符号表的组织方式有:线性表、散列表、树结构等,其必须维持源程序中的作用域信息。
编译原理课程设计报告

编译原理课程设计报告软件学院05级时间:2007年7月25日一、词法分析1、实验目的编程实现词法分析程序,加深理解对词法分析原理。
2、实验要求a、识别出特殊符号(用顿号隔开),女口=、+、-、*、/、<、>、<=、>=、==、!=、;、:、,、{、}、卜卜(、)等b 识别出关键字,如if;the n;while;do;e nd;for 等c、识别其它标记ID和NUM,并通过以下正规式定义其他标记:ID -> letter (letter | digit)letter -> a | b ... | z | A |B ... | ZNUM -> digit digit*digit -> 0 | 1 ... | 93、算法思路:本程序每次判断均连续输入几个的词,不同的词之间用“空格”隔开,因为所输入的字符串中含有“空格”,故在输入的时候启用文本监视器,利用字符串解析器扫描所输入的字符串,以逗号,空格,分号分开,以java.util 包中的模式匹配生成文法和保留字对每个token进行分析,测试其匹配的模式,把它们区分开来4、程序流程图主程序流程图扫描程序流程图5.运行环境JDK6.0实验二:LL1语法判断、实验目要求:自定义一个文法集,输入文法产生式,计算文法的利用FIRST,FOLLOV和SELECT集合,SELECT集合构造预测分析表,接着用预测分析程序,栈和预测分析表对输入串进行分析,给出分析过程。
二、设计思想:设计算法实现:(1 )求FIRST集(用关系图法)(a)每个文法符号对应图中一个结点。
(b)如果文法中有产生式A、a X3 ,且a =>* £,则从对应A的结点到对应X的结点连一条箭弧。
(c)凡是从FIRST(A)的结点有路径可到达的终结符结点所标记的终结符都为FIRST(A的成员。
(d)判定£是否为某非终结符FIRST集的成员,若是则将加入该非终结符的FIRST集中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理课程设计报告Part A:源文件: *.plo 目标文件: *.COD 实现平台:C++ Builder6.0 运行平台:xindows xp sp21.设计说明PL/0语言是Pascal语言的一个子集,这里分析的PL/0的编译程序包括了对PL/0语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。
PL/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。
词法分析和代码生成作为独立的子程序供语法分析程序调用。
语法分析的同时,提供了出错报告和出错恢复的功能。
在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。
2.各功能模块描述词法分析子程序分析:词法分析子程序名为GETSYM,功能是从源程序中读出一个单词符号(TOTAKEN),把它的信息放入全局变量SYM、ID和NUM中,字符变量放入CH中,语法分析器需要单词时,直接从这三个变量中获得。
Getch过程通过反复调用Getch 子过程从源程序过获取字符,并把它们拼成单词。
GETCH过程中使用了行缓冲区技术以提高程序运行效率。
词法分析器的分析过程:调用GETSYM时,它通过GETCH过程从源程序中获得一个字符。
如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把SYM变量赋成相应的保留字类型值;如果没有查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过程的名字),把SYM 置为IDENT,把这个单词存入ID变量。
查保留字表时使用了二分法查找以提高效率。
如果Getch获得的字符是数字,则继续用Getch获取数字,并把它们拼成一个整数或实数,然后把SYM置为INTEGER或REAL,并把拼成的数值放入NUM变量。
如果识别出其它合法的符号(比如:赋值号、大于号、小于等于号等),则把SYM则成相应的类型。
如果遇到不合法的字符,把SYM置成NUL。
语法分析子程序分析:语法分析子程序采用了自顶向下的递归子程序法,语法分析同时也根据程序的语义生成相应三元代码,并提供了出错处理的机制。
语法分析主要由分程序分析过程(BLOCK)、参数变量分析过程(ParaDeclaration)、参数变量处理过程(ParaGetSub)、数组处理过程(ParaGetSub)、常量定义分析过程(ConstDeclaration)、变量定义分析过程(Vardeclaration)、语句分析过程(Statement)、表达式处理过程(Expression)、项处理过程(Term)、因子处理过程(Factor)和条件处理过程(Condition)构成。
这些过程在结构上构成一个嵌套的层次结构。
除此之外,还有出错报告过程(Error)、代码生成过程(Gen)、测试单词合法性及出错恢复过程(Test)、登录名字表过程(Enter)、查询名字表函数(Position)以及列出类PCODE代码过程(Listcode)作过语法分析的辅助过程。
由PL/0的语法图可知:一个完整的PL/0程序是由分程序和句号构成的。
因此,本编译程序在运行的时候,通过主程序中调用分程序处理过程block来分析分程序部分(分程序分析过程中还可能会递归调用block过程),然后,判断最后读入的符号是否为句号。
如果是句号且分程序分析中未出错,则是一个合法的PL/0程序,可以运行生成的代码,否则就说明源PL/0程序是不合法的,输出出错提示即可。
下面按各语法单元分析PL/0编译程序的运行机制。
分程序处理过程:语法分析开始后,首先调用分程序处理过程(Block)处理分程序。
过程入口参数置为:0层、符号表位置0、出错恢复单词集合为句号、声明符或语句开始符。
进入Block过程后,首先把局部数据段分配指针设为3,准备分配3个单元供运行期存放静态链SL、动态链DL 和返回地址RA。
然后用Tx0记录下当前符号表位置并产生一条Jmp指令,准备跳转到主程序的开始位置,由于当前还没有知到主程序究竟在何处开始,所以Jmp的目标暂时填为0,稍后再改。
同时在符号表的当前位置记录下这个Jmp指令在代码段中的位置。
在判断了嵌套层数没有超过规定的层数后,开始分析源程序。
首先判断是否遇到了常量声明,如果遇到则开始常量定义,把常量存入符号表。
接下去用同样的方法分析变量声明,变量定义过程中会用Dx变量记录下局部数据段分配的空间个数。
然后如果遇到Procedure保留字则进行过程声明和定义,声明的方法是把过程的名字和所在的层次记入符号表,过程定义的方法就是通过递归调用Block过程,因为每个过程都是一个分程序。
由于这是分程序中的分程序,因此调用Block时需把当前的层次号Lev加一传递给Block 过程。
分程序声明部分完成后,即将进入语句的处理,这时的代码分配指针CX的值正好指向语句的开始位置,这个位置正是前面的Jmp指令需要跳转到的位置。
于是通过前面记录下来的地址值,把这个Jmp指令的跳转位置改成当前cx 的位置。
并在符号表中记录下当前的代码段分配地址和局部数据段要分配的大小(DX 的值)。
生成一条INT指令,分配DX个空间,作为这个分程序段的第一条指令。
下面就调用语句处理过程Statement分析语句。
分析完成后,生成操作数为0的OPR指令,用于从分程序返回(对于0层的主程序来说,就是程序运行完成,退出)。
常量定义过程:通过循环,反复获得标识符和对应的值,存入符号表。
符号表中记录下标识符的名字和它对应的值。
变量定义过程:与常量定义类似,通过循环,反复获得标识符,存入符号表。
符号表中记录下标识符的名字、它所在的层及它在所在层中的偏移地址。
参变量定义过程:类似变量定义,将参变量,存入符号表中。
参变量处理过程:如果函数用参变量,依照形参的类型、个数,由实参进行赋值。
数组处理过程:计算数组括号内的偏移值,存入栈顶用于后面生成的STOARR和LODARR指令调用实际的数组中元素的地址。
语句处理过程:语句处理过程是一个嵌套子程序,通过调用表达式处理、项处理、因子处理等过程及递归调用自己来实现对语句的分析。
语句处理过程可以识别的语句包括赋值语句、read语句、write语句、++语句、--语句、+=语句、-=语句、if-else-then语句、while语句、For语句、repeat语句。
当遇到begin/end语句时,就递归调用自己来分析。
分析的同时生成相应的类PCODE指令。
赋值语句的处理:首先获取赋值号左边的标识符,从符号表中找到它的信息,并确认这个标识符确为变量名。
然后通过调用表达式处理过程算得赋值号右部的表达式的值并生成相应的指令保证这个值放在运行期的数据栈顶。
最后通过前面查到的左部变量的位置信息,生成相应的STO指令,把栈顶值存入指定的变量的空间,实现了赋值操作。
返回函数值也是用赋值语句进行返回值的储存。
对函数与过程调用的处理:首先判断读入的标识符属性为FUNCTION或PROCEDURE,从符号表中找到此标识符,获得其所在层次和偏移地址。
然后生成相应的cal指令。
至于调用子过程所需的保护现场等工作是由类PCODE解释程序在解释执行cal指令时自动完成的。
如果此标识符不在第0层而且是该层函数的函数名则作为返回值返回。
read语句的处理:确定read语句语法合理的前提下(否则报错),由变量的类型生成相应的指令:对于整型,第一条是16号操作的opr指令,实现从标准输入设备上读一个整数值,放在数据栈顶。
如果读入是实数就报错,第二条是sto指令,把栈顶的值存入read语句括号中的变量所在的单元。
对于实型,第一条是15号操作的opr指令,实现从标准输入设备上读一个实数值,放在数据栈顶。
第二条是sto 指令,把栈顶的值存入read语句括号中的变量所在的单元。
对于字符型,第一条是20号操作的opr指令,实现从标准输入设备上读一个字符值,第二条是sto指令,把栈顶的值存入read语句括号中的变量所在的单元。
write语句的处理:与read语句相似。
在语法正确的前提下,生成指令:通过循环调用表达式处理过程分析write语句括号中的每一个表达式,生成相应指令保证把表达式的值算出并放到数据栈顶并生成指令,输出表达式的值,如果是数字类型则生成14号操作的opr指令,如果是字符类型则生成19号操作的opr指令。
if-then-else语句的处理:按if语句的语法,首先调用逻辑表达式处理过程处理if语句的条件,把相应的真假值放到数据栈顶。
接下去记录下代码段分配位置(即下面生成的jpc指令的位置),然后生成条件转移jpc指令(遇0或遇假转移),转移地址未知暂时填0。
然后调用语句处理过程处理then语句后面的语句或语句块。
then后的语句处理完后,如果遇到else,就调用语句处理过程处理else语句后面的语句或语句块,这时当前代码段分配指针的位置就应该是上面的jpc指令的转移位置。
通过前面记录下的jpc指令的位置,把它的跳转位置改成当前的代码段指针位置,否则没遇到else,那么此时的当前代码段分配指针的位置也是上面jpc指令的转移位置,也是通过前面记录下的jpc位置指令的位置,把它的跳转到当前的代码段指针位置。
begin/end语句的处理:通过循环遍历begin/end语句块中的每一个语句,通过递归调用语句分析过程分析并生成相应代码。
while语句的处理:首先用cx1变量记下当前代码段分配位置,作为循环的开始位置。
然后处理while语句中的条件表达式生成相应代码把结果放在数据栈顶,再用cx2变量记下当前位置,生成条件转移指令,转移位置未知,填0。
通过递归调用语句分析过程分析do语句后的语句或语句块并生成相应代码。
最后生成一条无条件跳转指令jmp,跳转到cx1所指位置,并把cx2所指的条件跳转指令的跳转位置改成当前代码段分配位置。
Repeat语句的处理:首先用CX1变量记下当前代码段分配位置,作为循环的开始位置。
然后通过递归调用语句分析过程分析,直到遇到until保留字,如果未对应until则出错。
调用条件表达式处理过程生成相应代码把结果放在数据栈顶,再生成条件转移指令,转移位置为上面记录的CX1。
For语句的处理:按For语句的语法,首先对For后面的一个标识符进行初值的赋值过程(类似赋值语句处理),生成相应的代码。
之后遇到TO或DOWNTO保留字,如果未对应则出错。
用CX1变量记下当前代码段分配的位置,作为以后JMP循环的开始位置。
对上面识别的标识符变量进行存取,与TO或DOWNTO后面的表达式进行比较,生成比较指令(TO为13、DOWNTO为11),再用CX2变量记下当前代码段分配的位置,生成JPC指令,跳转地址未知,之后可用CX2记录下的位置进行回填。