编译原理课程设计报告

合集下载

编译原理课程设计报告

编译原理课程设计报告

《编译原理》课程设计报告一、课程设计目的通过课程设计进一步理解高级语言在计算机中的执行过程,了解现代编译器的运作机制,加深对编译原理中重点算法和编译技术的理解,提高自己自学和理解的能力。

学会如何利用已有软件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 的信息,语法阶段生成的语法树,另外对于词法和语法阶段出现的错误在“错误提示”文本框中一一列举出来,提供用户改进代码的信息。

编译原理课程设计报告

编译原理课程设计报告

实验要求✧基本内容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 -一、课程设计的目的通过设计、编写和调试词法分析程序(又称扫描器),了解扫描器的组成结构,不同种类单词的识别方法,加深了对词法分析作用的理解。

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

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

编译原理课程设计报告一、目的与要求目的:在分析理解一个教学型编译程序(如PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。

达到进一步了解程序编译过程的基本原理和基本实现方法的目的。

要求:对PL/0作以下修改扩充:基本内容(成绩范围:“中”、“及格”或“不及格”)(1)扩充赋值运算:+= 和-=(2)扩充语句REPEAT<语句序列>UNTIL <条件>其中,<条件>是循环条件,即条件不成立时,重复执行循环体的< 语句序列>;条件成立时,循环结束。

选做内容(成绩评定范围扩大到:“优”和“良”)(1)增加运算:++ 和--。

(2)增加类型:①字符类型;②实数类型。

(3)扩充函数:①有返回值和返回语句;②有参数函数。

(4)增加一维数组类型(可增加指令)。

(5)其他典型语言设施。

二、实验环境与工具(1)计算机及操作系统:PC机,WindowsXP(2)程序设计语言:C(3)教学型编译程序:PL/0三、设计方案(1)概述:源、目标语言,实现工具(平台),运行平台源语言: PL/0目标语言: 目标代码(生成的文件后缀为*.COD)实现平台: VC++ 6.0运行平台: WindowsXP(2)结构设计说明:各功能模块描述Error()出错处理,打印出错位置和错误编码GetCh()漏掉空格,读取一个字符GetSym()词法分析,读取一个单词GEN()目标代码生成过程,本过程用于把生成的目标代码写入目标代码数组,供后面的解释器解释执行TEST()测试当前单词是否合法过程testENTER()登陆符号表过程enterPOSITION() 在符号表中查找指定符号所在位置的函数position,如果找不到就返回0V ARDECLARATION()变量声明LISTCODE()列出目标代码清单;FACTOR()因子处理过程factorTERM()项处理过程term;EXPRESSION()表达式处理过程CONDITION()条件处理过程STATEMENT()语句处理过程BLOCK()语法分析过程BASE(): 通过静态链求出数据区基地址的函数,INTERPRET ():对目标代码解释运行过程(3)主要成分描述①符号表struct tablestruct{char name[al]; /* 名字*/enum object kind; /* 类型:const ,var ,procedure*/int val; /* 数值,仅const 使用*/int level; /* 所处层,仅const 不使用*/int adr; /* 地址,仅const 不使用*/Int size; /* 需要分配的数据区空间*/};struct tablestruct table[txmax]; /* 名字表*/②运行时存储组织和管理由于编译时目标程序运行的数据空间大小已经规定,所以存储组织属于静态存储。

编译原理课程设计 报告 论文

编译原理课程设计 报告 论文

目录1 前言 (1)2 报告主体 (1)2.1 设计目的: (1)2.2设计内容及要求: (1)2.2.1 设计符号表 (1)2.2.2 设计词法分析器 (1)2.2.3 语法分析与中间代码产生器 (2)2.2.4 优化器(选做) (2)2.2.5目标代码生成器(选做) (2)2.2.6 测试范例: (2)2.3 实现原理 (3)2.3.1 符号表的设计 (3)2.3.2 词法分析器的设计 (4)2.3.3 语法/语义分析 (5)2.4 算法实现流程图 (8)2.5 测试数据 (17)2.6结果输出及分析 (19)2.7 软件运行环境及限制 (28)2.8 心得体会 (29)2.9参考文献 (30)3 结论 (30)1 前言在网络世界中,我们往往对功能强大的程序叹为观止。

而这些强大程序的背后是编译这些程序的编译软件,是这些编译软件承托起了这些功能强大的运行程序。

我们有不少的同志致其自身于无尽的运行程序上。

而只有很少的人搞编译程序。

这就是为什么中国的可运行程序满天飞,而编译程序却很少。

本课程设计就是在这方面的探索,为你解读编译程序的奥秘。

课程设计题目选择9个题目中的一个,要求根据自己的兴趣和能力,选择一个对自己意义甚大的题目。

课程设计基本原理是在实践上,实现我们在课程上学习到的理论知识。

通过理论联系实践,更好的掌握课本上的理论知识。

2 报告主体2.1设计目的:本次课程设计是作一个集词法分析、语法分析、语义分析和中间代码生成于一体的编译器,它集中了《编译原理》里的几乎所有的思想。

不但加深了学生对编译方法的理解,而且能对学生的编程能力起到进一步提高的作用,培养学生的程序设计风格。

通过某种可视化编程语言的应用,具备初步的Windows环境下的编程思想。

2.2设计内容及要求:2.2.1 设计符号表确定符号表的组织方式,一般应包括名字栏和信息栏,其中名字栏作为关键字。

要考虑能够存储有关名字的信息,并可以高效地完成如下操作: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、符号表的组织符号表的组织方式有:线性表、散列表、树结构等,其必须维持源程序中的作用域信息。

编译原理课设报告ll0

编译原理课设报告ll0

编译原理课设报告ll0编译原理课设报告LL(0)。

一、引言。

编译原理是计算机科学与技术领域的重要课程之一,它研究如何将高级程序语言翻译成机器语言。

LL(0)是一种重要的语法分析方法,它是一种自顶向下的分析方法,通过构建语法树来实现对程序语言的分析和翻译。

本报告将介绍LL(0)语法分析的原理、算法以及课设的设计与实现。

二、LL(0)语法分析原理。

LL(0)语法分析是一种基于预测分析表的自顶向下语法分析方法。

它通过预测下一个输入符号,根据文法规则进行推导,最终构建出语法树。

LL(0)的意思是“左侧扫描、左推导、0个向前看符号”。

LL(0)语法分析的关键是构建预测分析表,该表包含了文法的非终结符和终结符的组合,以及对应的产生式。

通过分析输入串和预测分析表,可以确定下一个推导所使用的产生式,从而构建语法树。

三、LL(0)语法分析算法。

1. 构建First集和Follow集。

在LL(0)语法分析中,需要先构建每个非终结符的First集和Follow集。

First集表示该非终结符能够推导出的终结符集合,Follow集表示在该非终结符的右侧能够出现的终结符集合。

2. 构建预测分析表。

根据文法的产生式和First集、Follow集,构建预测分析表。

预测分析表的行表示文法的非终结符,列表示文法的终结符。

表中的每个格子填写对应的产生式。

3. 进行语法分析。

根据输入串和预测分析表,进行语法分析。

从左到右扫描输入串,根据当前输入符号和栈顶符号,在预测分析表中查找对应的产生式。

将产生式右侧的符号入栈,并将输入串向右移动一个位置。

重复这个过程,直到输入串为空或者出现错误。

四、课设设计与实现。

1. 文法设计。

根据课设要求,设计符合LL(0)语法分析方法的文法。

文法应该满足左递归消除、左因子消除等要求,以便于构建预测分析表。

2. 构建预测分析表。

根据设计的文法,构建预测分析表。

根据文法的非终结符和终结符,填写预测分析表中的产生式。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

武汉纺织大学编译原理课程设计实验报告学院:数学与计算机专业:计算机姓名:班级:学号:constdccl rtrfilri onVEM'decl OTIli-expression to ftnconditionintet'prct函数:)过程或曲数名功能简蔑说咽pio主程序error出错处理*打印出错位苫和错误编码gdsym词济分祈,煤取一t单詞秦理空格,读収「牛字苻生止目标优码.井送入目林序区test義试当前单诵符是否合法block务析程启噩理讨稈enterpnwfiion(画慰)查找标识符在名字丢中肿位置constdeclaratiDn常虽定克牲理TardeclaratiDn变虽主兗魁理listccxle列出目掃诧码詩单statemeiitespressiiMi盂这式处理tennfactorcrnidiiicn条件辿埋iiiteipret刖日标吒码购解释执厅程序通过静蠱穆求;L数据仅的宰地圳编译原理课设报告一、实验目的加强对编译程序的整体认识和了解,巩固《编译原理》课程所学知识。

通过本次课程设计掌握编译程序调试技巧和设计编译程序一般的原则,加深对词法分析、语法分析、语义分析等编译阶段及实用编译系统的认识。

使学生能将编译理论与实际应用结合起来,提高学生软件开发的能力。

二、实验内容1)仔细阅读PL/O编译程序文本(编译原理(第二版)张素琴吕映芝蒋维杜戴桂兰主编清华大学出版社),并上机调试通过。

2)对PL/0语言进行下列扩充(1)扩充一维整型数组。

扩充var数组:VAR <数组标识名>(<下界>:<上界>)〈下界〉和〈上界〉可用常量标识名。

(2)扩充条件语句的功能使其为:IF<条件>THEN齬句>[ELSE语句>](3)增加repeat重复语句:REPEAT<语句>{;<语句>}UNTIL<条件>可根据自己具体情况从中选择2个以上题目进行扩充。

三、实验原理PL/0语言可以看成PASCALS言的子集,它的编译程序是一个编译解释执行系统。

PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关。

PL/0的编译程序和目标程序的解释执行程序都是用PASCAL语言书写的,因此PL/0语言可在配备PASCAL语言的任何机器上实现。

其编译过程采用一趟扫描方式,以语法分析程序为核心,词法分析和代码生成程序都作为一个独立的过程,当语法分析需要读单词时就调用词法分析程序,而当语法分析正确需要生成相应的目标代码时,则调用代码生成程序。

用表格管理程序建立变量、常量和过程表示符的说明与引用之间的信息联系。

当源程序编译正确时,PL/0编译程序自动调用解释执行程序,对目标代码进行解释执行,并按用户程序的要求输入数据和输出运行结果。

编译原理errortest隔麺功能说阴孟:四、实验分析PL/O语言编译程序采用以语法分析为核心、一遍扫描的编译方法。

词法分析和代码生成作为独立的子程序供语法分析程序调用。

语法分析的同时,提供了出错报告和出错恢复的功能。

在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。

词法分析子程序分析:词法分析子程序名为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、、语句分析过程(Stateme nt )、表达式处理过程(Expressio n)、项处理过程(Term)、因子处理过程(Factor、和条件处理过程(Condition、构成。

这些过程在结构上构成一个嵌套的层次结构。

除此之外,还有出错报告过程(Error)、代码生成过程(Gen)、测试单词合法性及出错恢复过程(Test)、登录名字表过程(Enter、、查询名字表函数(Position)以及列出类PCODE 代码过程(Listcode、作过语法分析的辅助过程。

由PL/0的语法图可知:一个完整的PL/0程序是由分程序和句号构成的。

因此,本编译程序在运行的时候,通过主程序中调用分程序处理过程block来分析分程序部分(分程序分析过程中还可能会递归调用block过程),然后,判断最后读入的符号是否为句号。

如果是句号且分程序分析中未出错,则是一个合法的PL/0程序,可以运行生成的代码,否则就说明源PL/0程序是不合法的,输出出错提示即可。

if-then-else语句的处理:按if语句的语法,首先调用逻辑表达式处理过程处理if语句的条件,把相应的真假值放到数据栈顶。

接下去记录下代码段分配位置(即下面生成的jpc指令的位置),然后生成条件转移jpc指令(遇0或遇假转移),转移地址未知暂时填0。

然后调用语句处理过程处理then 语句后面的语句或语句块。

then后的语句处理完后,如果遇到else,就调用语句处理过程处理else语句后面的语句或语句块,这时当前代码段分配指针的位置就应该是上面的jpc指令的转移位置。

通过前面记录下的jpc指令的位置,把它的跳转位置改成当前的代码段指针位置,否则没遇到else,那么此时的当前代码段分配指针的位置也是上面jpc指令的转移位置,也是通过前面记录下的jpc位置指令的位置,把它的跳转到当前的代码段指针位k-i/ii■< !-|XVh luDotlWh kidraidJlRepeat 语句的处理:首先用CX1变量记下当前代码段分配位置,作为循环的开始位置。

然后通过递归调用语句 分析过程分析,直到遇到until 保留字,如果未对应 until 则出错。

调用条件表达式处理过程生成相应代码把结果放在数据栈顶,再生成条件转移指令,转移位置为上面记录的CX1。

tSkl宝 £ 丿 .2」实验代码;PLO.h 代码: #in elude <stdio.h> #in elude <set> #in elude <stri ng> #in elude <iostream> #in elude <iostream> #in elude <veetor> #ifndef WIRTH ZYC #define WIRTH ZYC using n amespaee std;〃 no. of reserved words 保留字的个数// le ngth of ide ntifier table 标示符表的长度(容量)// le ngth of ide ntifiers 标示符的最大长度// max. no. of digits in nu mbers 数字的最大长度 // maximum address 寻址空间 // maximum depth of block nest ing最大允许的块嵌套层数// size of code array 类PCODE 目标代码数组长度 (可容纳代 const int lineLength = 82; // 行缓冲区长度T 二)<Z>m五、 相关代码及运行结果 con st i nt norw = 16; con st i nt txmax = 100; const int al = 10; con st i nt nmax = 14; con st i nt amax = 2047;con st i nt levmax = 3; con st i nt exmax =typedef enum{NUL,IDENT,NUMBER,PLUS,MINUS,TIMES,SLASH,ODDSYM,EQL,NEQ,LSS,LEQ,GTR,GEQ,LPAREN,RPAREN,COMMA,SEMICOLON,PERIOD,BECOMES,BEGINSYM,ENDSYM,IFSYM,THENSYM,WHIL ESYM,WRITESYM,READSYM,DOSYM,CALLSYM,CONSTSYM,VARSYM,PROCSYM,ELSESYM,REPEATSY M,UNTILSYM} symbol; // symobl 类型标识了不同类型的词汇typedef char alfa[al+1]; // alfa 类型用于标识符typedef enum {CONSTANT,VARIABLE,PROCEDURE,ARRAY} obj0; // 三种标识符的类型typedef enum {LIT,OPR,LOD,STO,CAL,INT,JM,JPC} fct; // functionstypedef set<symbol> symset;struct instruction{fct f; // function codeint l; // level,cann't big than levmaxint a; // displacement address,cann't big than amax}; //类PCODE指令类型,包含三个字段:指令f、层差I和另一个操作数a/******************************************** Iit 0,a: Ioad constant a* opr 0,a: execute operation a* Iod I,a: Ioad variabIe I,a* sto I,a: store variabIe I,a* caI I,a: caII procedure a at IeveI I* int 0,a: increment t-register by a* jmp 0,a: jump to a* jpc 0,a: jump conditionaI to a *******************************************/typedef struct{aIfa name;obj0 kind;union {struct{int IeveI,adr,size;}inOther; int vaI;}other;} TabIe;cIass PL0{protected:bool listswitch,sourceEnd; char ch; symbol sym; II last character read II last symbol read II last identifier read II last number readalfa int id; num;int cc; II character count int ll;II line lengthint kk,err;int cx;II code allocation index int codeNo;II code line no.// error string// code line// error array// 词法分析器中用于临时存放正在分析的词// destination code array // 保留字表// 保留字表中每一个保留字对应的 symbol // 一些符号对应的 symbol 类型表II 类PCODE 指令助记符表symset declbegsys,statbegsys,facbegsys; // 声明开始、表达式开始和项开始符号集个字符static string errStr[]; char line[lineLength];vector<string> errorString; alfa a;instruction code[cxmax+1]; alfa word[norw+1];symbol wsym[norw+1]; 类型 symbol ssym[100]; char mnemonic[8][6];合Table table[txmax+1]; FILE* fin,*fout; public:PL0(char* source,char*destination); ~PL0(){fclose(fin),fclose(fout);}void error(int n);位置和出错代码void getsym();个单词void getch();II 符号表II 构造函数 II 析构函数II 出错处理, 打印出错II 词法分析,读取一 II 漏掉空格, 读取一void gen(fct x,int y,int z); II 生成目标代码,并送入目标void test(symset s1,symset s2,int n);合法void block(int lev,int tx,symset fsys); //分程序分析处理过程void enter(obj0 k,int &tx,int &dx,int lev); //登入名字表int position(alfa id,int tx);// 查找标示符在名字表中的位置void constdeclaration(int&tx,int&dx,int lev); // 常量定义处理void vardeclaration(int&tx,int&dx,int lev);//变量说明处理void listcode(int cx0);// 列出目标代码清单void statement(symset fsys,int tx,int lev); //语句部分处理void expression(symset fsys,int tx,int lev); // 表达式处理void term(symset fsys,int tx,int lev); // 项处理void factor(symset fsys,int tx,int lev);//因子处理void condition(symset fsys,int tx,int lev);// 条件处理void arraydeclaration(int& tx,int& dx,int lev);// 数组说明处理void interpret();// 对目标代码的解释执行程序int base(int l,int b,int s[]);// 通过静态链求出数据区的基地址void SaveCode();// 保存代码};#endifPL0.cpp 代码: #include "pl0.h" // 错误字符串数组string PL0::errStr[]={" ","error 0001: 常数说明中“ =”写成“: =” ", "error 0002: 常数说明中的“ =”后应为数字 ","error 0003: 常数说明中的标识符后应是“ =” ", "error 0004: const,var,procedure 后应为标识符 ", "error 0005: 漏掉了‘ ,'或‘ ;' ","error 0006: 过程说明后的符号不正确(应是语句开始符或过程开始符) "error 0007: 应是语句开始符 ","error 0008: 过程体内语句部分的后跟符不正确 ", "error 0009: 程序皆为丢了句号‘ .' ", "error 0010: 语句之间漏了‘ ;' ", "error 0011: 标识符没说明 ","error 0012: 赋值语句中,赋值号左部标识符属性应是变量 ", "error 0013: 赋值语句左部标识符应是赋值号 :=",程序区// 测试当前单词符号是否"error 0014: call 后应为标识符","error 0015: call 后标识符属性应为过程","error 0016: 条件语句中丢了then","error 0017: 丢了end 或;","error 0018: while 型循环语句中丢了do","error 0019: 语句后的标识符不正确","error 0020: 应为关系运算符","error 0021: 表达式内标识符属性不能是过程","error 0022: 表达式中漏掉了右括号‘ )' ","error 0023: 因子后的非法符号","error 0024: 表达式开始符不能是此符号","error 0025: 文件在不该结束的地方结束了","error 0026: 结束符出现在不该结束的地方","error 0027: ","error 0028: ","error 0029: ","error 0030: " "error 0031: 数越界","error 0032: read 语句括号中标识符不是变量","error 0033: else 附近错误" ,"error 0034: repeat 附近错误"};// PL0 构造函数PL0::PL0(char* source,char*destination) {listswitch=true,sourceEnd=false;strcpy(word[1],"begin"); strcpy(word[2],"call");// 初始化存储保留字strcpy(word[3],"const"); strcpy(word[4],"do"); strcpy(word[5],"else"); strcpy(word[6],"end");strcpy(word[7],"if"); strcpy(word[8],"odd"); strcpy(word[9],"procedure");strcpy(word[10],"read"); strcpy(word[11],"repeat"); strcpy(word[12],"then");strcpy(word[13],"until"); strcpy(word[14],"var"); strcpy(word[15],"while");strcpy(word[16],"write");wsym[1]= BEGINSYM; wsym[2]= CALLSYM;// 初始化保留字表中每一个保留字对应的symbol 类型wsym[3]= CONSTSYM; wsym[4]= DOSYM;wsym[5]= ELSESYM; wsym[6]= ENDSYM;wsym[7]= IFSYM; wsym[8]= ODDSYM;wsym[9]= PROCSYM; wsym[10]= READSYM;wsym[11]= REPEATSYM; wsym[12]=THENSYM;wsym[13]= UNTILSYM; wsym[14]= VARSYM; wsym[15]= WHILESYM; wsym[16]=WRITESYM;memset(code,0,sizeof(code)); memset(ssym,0,100*sizeof(symbol));memset(table,0,sizeof(table));memset(line,0,sizeof(line));ssym['+']= PLUS; // 初始化一些符号对应的symbol 类型表ssym['-']= MINUS;ssym['*']= TIMES;ssym['/']= SLASH;ssym['(']= LPAREN;ssym[')']= RPAREN;ssym['=']= EQL;ssym[',']= COMMA;ssym['.']= PERIOD;ssym['#']= NEQ;ssym['<']= LSS;ssym['>']= GTR;ssym[';']= SEMICOLON;strcpy(mnemonic[LIT]," lit"); // 初始化类PCODE指令助记符表strcpy(mnemonic[OPR]," opr "); strcpy(mnemonic[LOD]," lod "); strcpy(mnemonic[STO]," sto"); strcpy(mnemonic[CAL]," cal "); strcpy(mnemonic[INT]," int ");strcpy(mnemonic[JMP]," jmp "); strcpy(mnemonic[JPC]," jpc ");declbegsys.insert(CONSTSYM),declbegsys.insert(VARSYM),declbegsys.insert(PROCSYM); // 初始化声明开始符号集合statbegsys.insert(BEGINSYM),statbegsys.insert(CALLSYM),statbegsys.insert(IFSYM),statb egsys.insert(WHILESYM); // 初始化表达式开始符号集合facbegsys.insert(IDENT),facbegsys.insert(NUMBER),facbegsys.insert(LPAREN); // 初始化项开始符号集合err= 0;cc= 0;cx= 0;置生成新的代码ll= 0;ch= ' ';kk= al;codeNo=0;fin=fopen(source,"r");fout=fopen(destination,"w");}// 行缓冲区指针// 代码分配指针,代码生成模块总在// 行缓冲区长度// last character read// 引入此变量是出于程序性能考虑// code line no.// 出错处理,打印出错位置和出错代码void PL0::error(int n){char s[10];sprintf(s," 第%d 行:",codeNo); errorString.push_back(s+errStr[n]); err=err+1;//error count}//error end// 词法分析,读取一个单词void PL0::getsym(){if(sourceEnd)return;int i,j,k;while (ch ==' '||ch==9)getch(); // cls space and tab if(isalpha(ch)) // id or reserved word {k=0;memset(a,0,al+1);// 检测一个单词长度do{if (k < al){a[k]= ch; k= k+1;cx 所指位}getch();if(sourceEnd)return; }while(isalpha(ch)||isdigit(ch)); if(k >= kk) kk = k;else{do{a[kk]= ' ';kk= kk-1;}while(kk > k);}strcpy(id,a);i= 1;j= norw;// 判断是否是关键字(二分搜索) do{k= (i+j) / 2;if(strcmp(id, word[k])<=0) j= k-1;if(strcmp(id,word[k])>=0)i= k+1;}while(i<=j);if(i-1 > j)sym= wsym[k];elsesym= IDENT;}else if(isdigit(ch)) // number{k= 0;num= 0;sym= NUMBER;do{num= 10 * num + ch - '0';k= k+1;getch();}while(isdigit(ch));if(k > nmax)error(30);}else if (ch == ':'){getch();if( ch == '='){sym= BECOMES;getch();}elsesym= NUL;}else if(ch == '<') // extra stuff added to support <={getch();if (ch== '='){sym= LEQ;getch();}elsesym= LSS;}else if (ch == '>'){getch();if( ch == '='){sym= GEQ;getch();}elsesym= GTR;}else // end of extra stuff{sym= ssym[ch]; // 其它符号的赋值getch();}}// 漏掉空格,读取一个字符void PL0::getch(){if(cc == ll){if(feof(fin)){}if(sym!=PERIOD)error(25); sourceEnd=true; return; }cc= 0; fgets(line,lineLength,fin); codeNo++; ll=strlen(line);if(line[ll-1]==10) ll--;}ch= line[cc];cc= cc+1;}// 生成目标代码,并送入目标程序区void PL0::gen(fct x,int y,int z){if (cx > cxmax){cout<<"Program too long\n";return;}code[cx].f= x;code[cx].l= y;code[cx].a= z;cx= cx+1;}//gen end// 测试当前单词符号是否合法void PL0::test(symset s1,symset s2,int n){if(sourceEnd) return;if (s1.find(sym)==s1.end()){error(n);symset::iterator it;for(it=s2.begin();it!=s2.end();it++) s1.insert(*it);//s1=s1+s2 while(s1.find(sym)==s1.end()) getsym();}//test end// 分程序分析处理过程void PL0::block(int lev,int tx,symset fsys){ if(sourceEnd) return;int dx; // data allocation index int tx0; // initial table index int cx0; // initial code index dx= 3; // 变量的个数tx0= tx; // 表指针table[tx].other.inOther.adr= cx; gen(JMP,0,0);if( lev>levmax) error(32);do{if( sym == CONSTSYM) // 处理常量声明{getsym(); do{constdeclaration(tx,dx,lev); while (sym == COMMA) {getsym(); constdeclaration(tx,dx,lev);}if (sym ==SEMICOLON)getsym();else error(5);}while(sym==IDENT);}if( sym == VARSYM) // 处理变量声明{getsym(); do{vardeclaration(tx,dx,lev); while( sym == COMMA){ getsym();vardeclaration(tx,dx,lev);}if( sym ==SEMICOLON)getsym();elseerror(5);}while(sym==IDENT);}while( sym ==PROCSYM) // 处理过程的声明{getsym();if (sym ==IDENT){ enter(PROCEDURE,tx,dx,lev); getsym();}elseerror(4);if( sym ==SEMICOLON)getsym();elseerror(5);symset tmp = fsys;tmp.insert(SEMICOLON);block(lev+1,tx,tmp);if (sym == SEMICOLON){ getsym(); symset tmp = statbegsys; for(int i=IDENT;i<=PROCSYM;i++) tmp.insert((symbol)i);test(tmp,fsys,6);}elseerror(5);}symset tmp=statbegsys;tmp.insert(IDENT); test(tmp,declbegsys,7);}while(declbegsys.find(sym)!=declbegsys.end());code[table[tx0].other.inOther.adr].a= cx; table[tx0].other.inOther.adr= cx; // start adr of code table[tx0].other.inOther.size=dx;cx0= cx;gen(INT,0,dx);symset tmp=statbegsys;for(int i=SEMICOLON;i <= ENDSYM;i++)tmp.insert((symbol)i);statement(tmp,tx,lev);gen(OPR,0,0); // returnsymset s2;test(fsys,s2,8);listcode(cx0);}// block end// 登入名字表void PL0::enter(obj0 k,int &tx,int &dx,int lev){tx= tx+1;strcpy(table[tx].name,id);table[tx].kind=k;switch(k){case CONSTANT:if(num>amax){error(31);num=0;}table[tx].other.val=num;break;case VARIABLE: table[tx].other.inOther.level=lev; table[tx].other.inOther.adr=dx; dx++;break;case PROCEDURE: table[tx].other.inOther.level=lev; break;case ARRAY:table[tx].other.inOther.size = lev;break;}}//enter end// 查找标示符在名字表中的位置int PL0::position(alfa id,int tx)//find identifier id in table { int i; strcpy(table[0].name, id);i= tx;while (strcmp(table[i].name,id)!=0)i--;return i;}//position end// 常量定义处理void PL0::constdeclaration(int&tx,int&dx,int lev){if(sym == IDENT){getsym();if(sym>=EQL&&sym<=BECOMES){if( sym ==BECOMES)error(1);getsym();if( sym == NUMBER){enter(CONSTANT,tx,dx,lev); getsym();}elseerror(2);}elseerror(3);}elseerror(4);}// constdeclaration end// 变量说明处理void PL0::vardeclaration(int&tx,int&dx,int lev){if( sym == IDENT){enter(VARIABLE,tx,dx,lev);getsym();}elseerror(4);}//vardeclaration end// 数组说明处理void PL0::arraydeclaration(int&tx,int&dx,int lev){int upscript=0,downscript=0; getsym();if(sym == NUMBER || sym == CONSTSYM){if(num == 0){ upscript = num; getsym();}else error(32);} if(sym == COMMA) getsym();elseerror(32);if(sym == NUMBER || sym == CONSTSYM){downscript = num; getsym();} if(sym != RPAREN)error(32);else{ enter(ARRAY,tx,dx,downscript+1); getsym();}}// 列出目标代码清单void PL0::listcode(int cx0)//list code generated for this block {int i; if(listswitch)for (i= cx0;i<cx;i++) cout<<" "<<i<<" "<<mnemonic[code[i].f] <<" "<<code[i].l<<""<<code[i].a<<endl;}// listcode end// 语句部分处理void PL0::statement(symset fsys,int tx,int lev){ if(sourceEnd) return;int i,cx1,cx2;if(sym ==IDENT){i= position(id,tx);if (i == 0)error(11);else if (table[i].kind!=VARIABLE){error(12);i= 0;}getsym();if(sym ==BECOMES)getsym();elseerror(13);expression(fsys,tx,lev);if(sym != SEMICOLON)error(10);if( i!= 0)gen(STO,lev-table[i].other.inOther.level,table[i].other.inOther.adr); }else if( sym == READSYM){getsym();if( sym!=LPAREN)error(34);elsedo{getsym();if (sym==IDENT)i=position(id,tx);elsei=0;if( i==0 )error(35);else{gen(OPR,0,16); gen(STO,lev-table[i].other.inOther.level,table[i].other.inOther.adr);}getsym();}while(sym == COMMA);if (sym != RPAREN){error(33);while (fsys.find(sym)!=fsys.end()) getsym();}elsegetsym();}else if( sym == WRITESYM ){getsym();if (sym==LPAREN){do{getsym();symset tmp=fsys;for(int t=RPAREN;t<=COMMA;t++)tmp.insert((symbol)t);expression(tmp,tx,lev);gen(OPR,0,14);}while(sym==COMMA);if (sym!=RPAREN)error(33);elsegetsym();}gen(OPR,0,15);}else if( sym ==CALLSYM){getsym();if( sym!=IDENT)error(14);else{i= position(id,tx);if (i == 0)error(11);else if (table[i].kind = PROCEDURE)gen(CAL,lev-table[i].other.inOther.level,table[i].other.inOther.adr);else error(15);getsym();}}else if( sym ==IFSYM){getsym();symset tmp=fsys;for(int i = THENSYM;i<= DOSYM;i++)tmp.insert((symbol)i); condition(tmp,tx,lev); if( sym == THENSYM)getsym();elseerror(16); cx1= cx; gen(JPC,0,0); tmp.insert(ELSESYM); statement(tmp,tx,lev);getsym(); code[cx1].a= cx;if(sym == ELSESYM){getsym();cx2=cx; gen(JMP,0,0); code[cx1].a=cx; statement(fsys,tx,lev); code[cx2].a=cx;}}else if( sym ==BEGINSYM){getsym();symset tmp=fsys;for(int i=SEMICOLON;i<=ENDSYM;i++)tmp.insert((symbol)i); statement(tmp,tx,lev); tmp=statbegsys;tmp.insert(SEMICOLON); while( tmp.find(sym)!=tmp.end()) {if(sourceEnd)return;if (sym ==SEMICOLON||sym ==ENDSYM) getsym();else if(sym=PERIOD){error(26);getsym();}elseerror(10);tmp=fsys;for(i=SEMICOLON;i<=ENDSYM;i++)tmp.insert((symbol)i); if(sourceEnd)return; if(sym==ENDSYM)break;statement(tmp,tx,lev);}if( sym ==ENDSYM) getsym();else if(!sourceEnd) error(17);}else if(sym ==WHILESYM) {cx1= cx;getsym();symset tmp=fsys;tmp.insert(DOSYM);condition(tmp,tx,lev); cx2= cx;句的开始位置gen(JPC,0,0);if(sym ==DOSYM) getsym();elseerror(18); statement(fsys,tx,lev); gen(JMP,0,cx1); code[cx2].a= cx;} else if(sym == REPEATSYM) {symset temp1, temp2; temp1=fsys,temp1.insert(SEMICOLON),temp1.insert(UNTILSYM); cx1= cx;getsym(); statement(temp1,tx,lev); temp2 = statbegsys;temp2.insert(SEMICOLON); while(temp2.find(sym) != temp2.end()){if(sym == SEMICOLON) getsym();else error(34);statement(temp1,tx,lev);}if(sym == UNTILSYM){ getsym(); condition(fsys,tx,lev); gen(JPC,0,cx1);}else error(34);} symset setT; test(fsys,setT,19);}//statement end// 记下当前代码分配位置, 这是 while 循环的开始// 记下当前代码分配位置, 这是 while 的 do 中的语// 表达式处理void PL0::expression(symset fsys,int tx,int lev){symbol addop;symset tmp=fsys;for(int t=PLUS;t<=MINUS;t++) tmp.insert((symbol)t);if( sym>=PLUS&&sym<=MINUS){ addop= sym; getsym();term(tmp,tx,lev);if( addop ==MINUS)gen(OPR,0,1);}elseterm(tmp,tx,lev);while (sym >=PLUS&&sym<=MINUS){addop= sym;getsym(); term(tmp,tx,lev); if (addop ==PLUS) gen(OPR,0,2);elsegen(OPR,0,3);}}// expression end// 项处理void PL0::term(symset fsys,int tx,int lev){if(sourceEnd)return;symbol mulop;symset tmp=fsys;for(int t=TIMES;t<=SLASH;t++)tmp.insert((symbol)t);factor(tmp,tx,lev);while( sym>=TIMES && sym<=SLASH){mulop= sym;getsym();factor(tmp,tx,lev);if (mulop ==TIMES)gen(OPR,0,4);elsegen(OPR,0,5);}}// term end// 因子处理void PL0:: factor(symset fsys,int tx,int lev){int i;test(facbegsys,fsys,24);while(facbegsys.find(sym)!=facbegsys.end()) {if( sym ==IDENT) {i= position(id,tx);if( i == 0)error(11);elseswitch(table[i].kind){case CONSTANT: gen(LIT,0,table[i].other.val); break;case VARIABLE: gen(LOD,lev-table[i].other.inOther.level,table[i].other.inOther.adr); break;case PROCEDURE: error(21); break;}getsym();}else if (sym ==NUMBER){if (num>amax){error(31);num= 0;}gen(LIT,0,num);getsym();}else if( sym ==LPAREN){getsym();symset tmp=fsys;tmp.insert(RPAREN);expression(tmp,tx,lev);if (sym == RPAREN)getsym();elseerror(22);} test(fsys,facbegsys,23);}}//factor end// 条件处理void PL0::condition(symset fsys,int tx,int lev){symbol relop;symset tmp=fsys;tmp.insert(EQL),tmp.insert(NEQ),tmp.insert(LSS),tmp.insert(LEQ),tmp.insert(GTR),tmp.i nsert(GEQ);if( sym == ODDSYM){expression(fsys,tx,lev);gen(OPR,0,6);}else{expression(tmp,tx,lev);if(tmp.find(sym)==tmp.end())error(20);else{relop= sym;getsym();expression(fsys,tx,lev);switch(relop){case EQL: gen(OPR,0,8);break;case NEQ: gen(OPR,0,9);break;case LSS: gen(OPR,0,10);break;case GEQ: gen(OPR,0,11);break;case GTR: gen(OPR,0,12);break;case LEQ: gen(OPR,0,13);break;}}}}//condition end// 对目标代码的解释执行程序void PL0::interpret(){int err1=errorString.size(); if(err1>0){cout<<"存在%d 个错误:"<<err1<<endl;for(int i=0;i<err1;i++) cout<<errorString[i]<<endl;//return;}const int stacksize = 500;int p=0,b=1,t=0;//program-,base-,topstack-registersinstruction i;// instruction registerint s[stacksize+1]={0};// datastorecout<<" Start PL/0\n";do{i= code[p];p= p+1;{case LIT:t= t+1;s[t]= i.a; break;case OPR: switch(i.a) //operator {case 0:// return t= b-1; p= s[t+3]; b= s[t+2]; break;case 1:s[t]= -s[t]; break;case 2:t= t-1;s[t]= s[t]+s[t+1]; break;case 3:t= t-1;s[t]= s[t]-s[t+1]; break;case 4:t= t-1;s[t]= s[t]*s[t+1];break;case 5:t= t-1;s[t]= s[t] / s[t+1];break;case 6:if(s[t]%2) s[t]=1;elses[t]=0;break;case 8:t= t-1;if(s[t]==s[t+1]) s[t]=1;elses[t]=0;break;case 9:t= t-1;if(s[t]==s[t+1]) s[t]=0;elses[t]=1;break;case 10:t= t-1;if(s[t]<s[t+1]) s[t]=1;elses[t]=0;break;case 11:t= t-1;if(s[t]>=s[t+1]) s[t]= 1;else s[t]=0;break;case 12:t= t-1;if(s[t]>s[t+1]) s[t]= 1;else s[t]=0;break;case 13:t= t-1;if(s[t]<=s[t+1])s[t]= 1;elses[t]=0;break;case 14:cout<<" "<<s[t];t=t-1;break;case 15:cout<<endl;break;case 16:t=t+1;cout<<"?";s[t]=0;cin>>s[t];break;};break;case LOD:t= t+1;s[t]= s[base(i.l,b,s)+i.a]; break; case STO:s[base(i.l,b,s)+i.a]= s[t];t= t-1;break;case CAL:// generate new block marks[t+1]= base(i.l,b,s);s[t+2]= b;s[t+3]= p;b= t+1;p=i.a;break;case INT:t= t+i.a;break; case JMP:p= i.a;break; caseJPC:if (s[t] == 0)p= i.a; t= t-1; break;}//switch end }while(p!=0); cout<<" End PL/0\n";} // interpret end// 通过静态链求出数据区的基地址int PL0::base(int l,int b,int s[]) {int b1;b1= b;//find base l levels down while(l>0){b1= s[b1];l= l-1;}return b1;}// 保存代码void PL0::SaveCode(){ if(fout)for (int i=0;i<cx;i++)fprintf(fout,"%d %s %d %d\n ",i,mnemonic[code[i].f],code[i].l,code[i].a);}TestPLO.cpp 代码:#include "pl0.h"void main(){PL0 cp("testPas2.txt","nasm.txt");symset fsys;fsys.insert(PERIOD); fsys.insert(CONSTSYM),fsys.insert(VARSYM),fsys.insert(PROCSYM); fsys.insert(BEGINSYM),fsys.insert(CALLSYM),fsys.insert(IFSYM),fsys.insert(WHILESYM);cp.getsym();cp.block(0,0,fsys); cp.SaveCode(); cp.interpret();// 词法分析,分析一个词// 分程序分析处理功能// 保存代码// 对目标代码的解释执行程序}实验运行结果:运行的的文件见下图右侧:实验中我是固定了文件名的,可以是改写成动态输入,由于在测试中我把所有的测试语句都放在同一个文件中了,没有太多的必要。

相关文档
最新文档