PL0编译器功能扩充
编译原理课程设计报告---PL0编译程序改进及完善
燕山大学《编译原理课程设计》题目:《PL/0编译程序改进及完善》姓名:简越班级:06级计算机应用3班学号:060104010084日期:2009年7月15日设计题目:PL/0编译程序改进及完善。
设计目的:阅读研究,改进设计和调试一个简单的编译程序。
加深对编译理论和过程的了解。
设计要求:1.有选择的对PL/0编译源程序补充,完善.2.设计编译典型的运行实例,以便反应出自己作出改进后的编具有的功能。
设计思想:PL/0语言可以看成PASCAL语言的子集,它的编译程序是一个编译解释执行系统。
PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关。
PL/0的编译程序和目标程序的解释执行程序都是用PASCAL语言书写的,因此PL/0语言可在配备PASCAL语言的任何机器上实现。
其编译过程采用一趟扫描方式,以语法分析程序为核心,词法分析和代码生成程序都作为一个独立的过程,当语法分析需要读单词时就调用词法分析程序,而当语法分析正确需要生成相应的目标代码时,则调用代码生成程序。
用表格管理程序建立变量、常量和过程表示符的说明与引用之间的信息联系。
当源程序编译正确时,PL/0编译程序自动调用解释执行程序,对目标代码进行解释执行,并按用户程序的要求输入数据和输出运行结果。
主要变量说明:/*变量说明*/FILE* fas; /*输出名字表*/FILE* fa; /*输出虚拟机代码*/FILE* fa1; /*输出源文件及其各行对应的首地址*/FILE* fa2; /*输出结果*/bool listswitch; /*显示虚拟机代码与否*/bool tableswitch; /*显示名字表与否*/char ch; /*获取字符的缓冲区,getch使用*/enum symbol sym; /*当前的符号*/char id[al+1]; /*当前ident,多出的一个字节用于存放0*/ int num; /*当前number*/int cc,ll; /*getch使用的计数器,cc表示当前字符(ch)的位置*/int cx; /*虚拟机代码指针,取值范围[0,cxmax-1]*/char line[81]; /*读取行缓冲区*/char a[al+1]; /*临时符号,多出的一个字节用于存放0*/ struct instruction code[cxmax]; /*存放虚拟机代码的数组*/char word[norw][al]; /*保留字*/enum symbol wsym[norw]; /*保留字对应的符号值*/enum symbol ssym[256]; /*单字符的符号值*/char mnemonic[fctnum][5]; /*虚拟机代码指令名称*/bool declbegsys[symnum]; /*表示声明开始的符号集合*/bool statbegsys[symnum]; /*表示语句开始的符号集合*/bool facbegsys[symnum]; /*表示因子开始的符号集合*//* 目标指令*/1、LIT:将常量值取到运行栈顶.2、LOD:将变量放到运行栈顶.3、STO:将栈顶的内容送入某变量单元中.4、CAL:调用过程的指令.5、INT:为被调用的过程(或主程序)在运行栈中开辟数据区.6、JMP:无条件转移指令.7、JPC:条件转移指令,当栈顶的布尔值为真时, 顺序执行,否则转向域的地址.8、OPR:系运算符和算术运算指令.将栈顶和次栈顶的内容进行运算,结果存放栈顶./*函数说明*/void error(int n,int line)说明:出错处理函数,打印出错信息,错误总数加1。
PL0编译程序讲解ppt课件
begin { 读入n } read(n); sum := 0; while n > 0 do begin m := n; fact := 1; call factorial; sum := sum + fact; n := n - 1; end; { 输出n !数值取到栈顶,a为常数值 将变量值取到栈顶,a为偏移量,l为层差 将栈顶内容送入某变量单元中,a为偏移量,l为层差 调用过程,a为过程地址,l为层差 在运行栈中为被调用的过程开辟a个单元的数据区 无条件跳转至a地址 条件跳转,当栈顶布尔值非真则跳转至a地址,否则顺序执行
过程调用结束后,返回调用点并退栈 栈顶元素取反 次栈顶与栈顶相加,退两个栈元素,结果值进栈 次栈顶减去栈顶,退两个栈元素,结果值进栈 次栈顶乘以栈顶,退两个栈元素,结果值进栈 次栈顶除以栈顶,退两个栈元素,结果值进栈 栈顶元素的奇偶判断,结果值在栈顶
( 1) jmp 0 2 转向过程p入口 ( 2) int 0 3 为过程p开辟空间
( 3) lod 1 3
const var
a=10; b,c;
( 4) lit 0 10
procedure
p;
( 5) opr 0 2 ( 6) sto 1 4 ( 7) opr 0 0 退栈并返回调用点 ( 8) int 0 5 ( 9) opr 0 16 (10) sto 0 3
VAR D;(* P的局部变量说明部分 *) PROCEDURE Q; (* P的局部过程说明部分 *) VAR X;
BEGIN READ(X); D:=X; IF X#0 DO CALL P;
END; BEGIN
CALL Q; WRITE(D); END; BEGIN CALL P; END.
PL0编译程序
PL/0语言编译系统春秋五霸目录1 PL/0语言及编译系统2 驱动代码3 编译程序4 解释程序①词法分析②语法分析③语义分析及目标代码生成1 PL/0语言编译系统PL/语言编译系统PL/0语言编译系统是世界著名计算机科学家N.Wirth编写的。
对PL/0编译程序进行实例分析,有助于对一般编译过程和编译程序结构的理解。
PL/0语言功能简单、结构清晰、可读性强,又具备了一般高级语言的必须部分,因而PL/0语言的编译程序能充分体现一个高级语言编译程序实现的基本技术和步骤,是一个非常合适的编译程序教学模型。
PL/0源程序PL/0编译系统语法语义分析程序词法分析程序目标代码代码生成程序表格管理程序出错处理程序PL/0源程序PL/0编译系统构成类P-code程序PL/0编译程序输出数据输入数据类P-code虚拟机类P-code解释程序PL/0语言文法的EBNF表示●〈程序〉∷=〈分程序〉.●〈分程序〉∷=[〈常量说明部分〉][〈变量说明部分〉][〈过程说明部分〉]〈语句〉●〈常量说明部分〉∷=CONST〈常量定义部分〉{,〈常量定义〉};●〈常量定义〉 ::= 〈标识符〉=〈无符号整数〉;●〈无符号整数〉∷=〈数字〉{〈数字〉}●〈变量说明部分〉∷=V AR〈标识符〉{,〈标识符〉};●〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}PL/0语言文法的EBNF表示●<过程说明部分>::=<过程首部><分程序>{;<过程说明部分>}●<过程首部>::=PROCEDURE<标识符>;●<语句>::=<赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|<空>●<赋值语句>::= <标识符>:=<表达式>●<复合语句>::= BEGIN<语句>{;<语句>}END●<条件>::= <表达式><关系运算符><表达式>PL/0语言文法的EBNF表示●<表达式>::=[+|-]<项>{<加法运算符><项>}●<项>::= <因子>{<乘法运算符><因子>}●<因子>::= <标识符>|<无符号整数>|‘(’<表达式>‘)’PL/0语言文法的EBNF表示●<加法运算符>::= +|-●<乘法运算符>::= *|/●<关系运算符>::= =|#|<|<=|>|>=●<条件语句>::= IF<条件>THEN<语句>●<过程调用语句>::= CALL<标识符>●<当型循环语句>::= WHILE<条件>DO<语句>●<读语句>::= READ’(’<标识符>{,<标识符>}‘)’PL/0语言文法的EBNF表示●<写语句>::= WRITE’(’<表达式>{,<表达式>}‘)’●<字母>::= a|b|…|X|Y|Z●<数字>::= 0|1|…|8|9指令过程调用相关指令类P-code 虚 拟机指令系 统…存取指令int 0 a cal l ajmp 0 alit 0 alod l a sto l a指令一元运算和比较指令类P-code 虚 拟机指令系 统…二元运算指令opr 0 5opr 0 1opr 0 6opr 0 2opr 0 3 opr 0 4指令转移指令类P-code 虚 拟机指令系 统输入输出指令二元运算指令opr 0 13 jmp 0 ajpc 0 aopr 0 8 opr 0 10opr 0 12opr 0 14opr 0 16opr 0 15opr 0 9opr 0 112 驱动代码词法分析主要函数:main()函数功能:驱动整个编译系统的运行变量说明:fa.tmp 输出虚拟机代码fa1.tmp 输出源文件及其各行对应的首地址fa2.tmp 输出结果fas.tmp 输出名字表main函数int main(){……/*打开源程序文件*/If 打开源程序文件成功{…… /*初始化输出文件信息*/init(); /*初始化各类名字和符号信息*/err=0; /*初始化错误数*/…… /*初始化其他信息*/if(-1!=getsym()) /*成功读取第一个单词*/{……main函数if(-1==block(0,0,nxtlev)) /*调用编译程序*/{…… /*编译过程未成功结束关闭所有已打开的文件,返回*/}…… /*编译过程结束关闭所有已打开的输出文件*/if(sym!=period) /*当前符号不是程序结束符’.’*/{error(9); /*提示9号出错信息:缺少程序结束符’.’*/}if(err==0) /*未发现程序中的错误*/{……interpret(); /*调用解释程序,执行所产生的类P-code代码*/……main函数else{printf("Errors in pl/0 program");}}…… /*关闭已打开的文件*/}else{printf(“Can‘t open file! \n”);/*打开源程序文件不成功*/}printf("\n");return 0; /*返回*/}集合运算函数int inset(int e,bool* s){/*返回e在数组s中的值*/return s[e];}int addset(bool* sr,bool* s1,bool* s2,int n){/*逻辑或运算*/int i;for(i=0;i<n;i++){sr[i]=s1[i]||s2[i];}return 0;}集合运算函数int subset(bool* sr,bool* s1,bool* s2,int n){/*s1[i]为true,s2[i]为false时,sr[i]才为true*/int i;for(i=0;i<n;i++){sr[i]=s1[i]&&(!s2[i]);}return 0; }int mulset(bool* sr,bool* s1,bool* s2,int n){/*逻辑与运算*/int i;for(i=0;i<n;i++){sr[i]=s1[i]&&s2[i]; }return 0;}错误处理函数void error(int n){char space[81];memset(space,32,81);printf("-------%c\n",ch);fprintf(fa1,"-------%c\n",ch);space[cc-1]=0;//出错时当前符号已经读完,所以cc-1printf("****%s!%d\n",space,n);fprintf(fa1,"****%s!%d\n",space,n);err++;}PL/O语言的出错信息表:出错编号出错原因1:常数说明中的“=”写成“∶=”。
PL/0编译器的实现文档
第二章PL/0编译程序的实现【课前思考】复习第1章介绍的一个高级程序设计语言编译程序的功能和实现的步骤。
编译程序就是一个语言的翻译程序,通常是把一种高级程序设计语言(称源语言)书写的程序翻译成另一种等价功能语言(称目标语言)的程序。
换句话说,编译是指把一种用源语言表示的算法转换到另一种等价的用目标语言表示的算法。
编译程序实现的必要步骤有词法、语法、语义分析和代码生成。
此外必需有符号表管理程序和出错处理程序。
本章介绍的PL/0编译程序的实现是用PASCAL语言书写的【学习目标】本章目的:以PL/0语言编译程序为实例,学习编译程序实现的基本步骤和相关技术,对编译程序的构造和实现得到一些感性认识和建立起整体概念,为后面的原理学习打下基础。
◇了解并掌握用语法图和扩充的巴科斯-瑙尔范式(EBNF)对PL/0语言的形式描述。
◇了解并掌握PL/0语言编译程序构造和实现的基本技术和步骤。
◇了解并掌握PL/0语言编译程序的目标程序在运行时数据空间的组织管理。
【学习指南】◇要求读者阅读PL/0语言编译程序文本,了解一个编译程序构造的必要步骤和实现技术。
一个编译程序的实现比较复杂,读懂一个典型的程序从设计思想到实现技术也有一定难度,特别是入门开始需要耐心。
一但读懂,不仅了解编译程序的实现方法和技术,还可学到许多编程技巧和好的编程风格。
◇阅读PL/0语言编译程序文本时,应从整体结构开始逐步细化,弄清楚每个过程的功能和实现方法及过程之间的相互关系。
◇建议用一个PL/0源程序的例子为导引作为阅读PL/0语言编译程序文本的入门,然后再逐步全面读懂。
◇通过对PL/0语言编译程序某些指定功能的扩充,加深对编译程序构造步骤和实现技术的理解,并能在实践中应用。
【难重点】重点:◇弄清源语言(PL/0)、目标语言(类pcode)与实现语言(C)这3个语言之间的关系和作用。
◇掌握用语法图和扩充的巴科斯-瑙尔范式(EBNF)对一个高级程序设计语言的形式描述。
PL0编译器说明文档
PL0编译器说明文档名称:PL0编译器作者:蒋伟学号:010*******程序用途:对PL0程序进行词法分析,语法分析,生产中间代码及解释执行。
开发工具:Borland Delphi 7.0时间:2004年4月◆程序模块说明项目文件:PL0.dpr单元文件(共10个):CiFaFenXi.pas 词法分析模块Defination.pas 变量,数组定义模块Excute.pas 解释执行模块Main.pas 主窗体模块My_Statememt.pas 说明窗体模块Preface.pas 欢迎窗体模块Proc_Func.pas 其它一些过程,函数Result_Form.pas 结果窗体模块SanYuanShi.pas 生成中间代码模块YuFaFenXi.pas 语法分析模块窗体(4个):Main.dfm 主窗体My_Statememt.dfm 说明窗体Preface.dfm 欢迎窗体Result_Form.dfm 结果窗体◆界面说明工具栏中依次为:新建,打开,保存,复制,剪切,粘贴,删除,撤销,词法分析(及其窗口),语法分析(及其窗口),生成中间代码(及其窗口),解释执行,结果观察窗口,帮助,说明。
程序窗体内有4个子窗体,分别为程序输入窗体(Memo1),语法分析窗体(Memo2),词法分析窗体(Memo3)和中间代码窗体(Memo4)。
考虑到整体界面美观,其中词法分析窗体(Memo3)和中间代码窗体(Memo4)始终重叠,不能同时显示。
其它窗体均可以随时通过按钮显示或隐藏。
另外,还设有执行结果观察窗体ResultForm,自动生成,也可以随时显示或隐藏。
◆程序设计思路该编译程序对待编译的程序文本进行3次扫描。
第一次为词法分析,扫描结束后生成单词表wordlist[i],第二次进行语法分析,扫描单词表wordlist[i],分析语法错误,在程序确认无误后可以生成中间代码,即进行第三次扫描,仍然扫描单词表wordlist[i],生成中间代码表code[i]。
编译原理课程设计---PL0编辑器扩充
编译原理课程设计题目 __ _PL0编辑器扩充__ __ 学院计算机学院专业软件工程2013 年 1 月 4 日一.课程设计目的与要求1、课程设计目的:在分析理解一个教学型编译程序(如PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。
达到进一步了解程序编译过程的基本原理和基本实现方法的目的。
2、课程设计要求:基本内容(成绩范围:“中”、“及格”或“不及格”)(1)扩充赋值运算:*= 和/=扩充语句(Pascal的FOR语句):①FOR <变量>:=<表达式> TO <表达式> DO <语句>②FOR <变量>:=<表达式> DOWNTO <表达式> DO <语句>其中,语句①的循环变量的步长为2,语句②的循环变量的步长为-2。
(3)增加运算:++ 和--。
选做内容(成绩评定范围扩大到:“优”和“良”)(1)增加类型:①字符类型;②实数类型。
(2)扩充函数:①有返回值和返回语句;②有参数函数。
(3)增加一维数组类型(可增加指令)。
(4)其他典型语言设施。
二、结构设计方案1、结构设计说明:PL/0的编译程序以语法分析程序为核心,词法分析程序和代码生成程序都作为一个独立的过程,当语法分析需要读单词时就用词法分析程序,而当语法分析正确需生成相应的目标代码时,则调用代码生成程序。
此外,用表格管理程序建立变量,常量和过程标识符的说明与引用之间的信息联系。
用出错处理程序对词法和语法分析遇到的错误给出在源程序中出错的位置和错误性质。
2、各功能模块图示:3. 各功能模块作用表:3. 符号名字表结构:struct tablestruct{char name[al]; /*名字*/enum object kind; /*类型:const,var,array or procedure*/ int val; /*数值,仅const使用*/int level; /*所处层,仅const不使用*/int adr; /*地址,仅const不使用*/int size; /*需要分配的数据区空间,仅procedure使用*/ };4. 保留关键字枚举结构:enum symbol{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, elsesym, forsym, tosym,downtosym, returnsym, pluseql, minuseql, plusplus,minusminus, };5.名字表中标识符枚举类型:enum object{constant, /*常量*/variable, /*变量*/procedur, /*过程*/};6.运行时存储组织和管理对于源程序的每一个过程(包括主程序),在被调用时,首先在数据段中开辟三个空间,存放静态链SL、动态链DL和返回地址RA。
编译原理课程设计报告PL0编译器的扩充
课程设计课程名称编译原理题目名称PL/0编译器的扩充学生学院运算机学院专业班级运算机科学与技术12(4) 2014 年12 月28日一、实验目的与要求大体内容(成绩范围:“中”、“合格”或“不合格”)(1)扩充赋值运算:*= 和 /=(2)扩充语句(Pascal的FOR语句):FOR <变量>:=<表达式>STEP<表达式> UNTIL<表达式>Do<语句>选做内容(成绩评定范围扩大到:“优”和“良”)(1)增加类型:①字符类型;②实数类型。
(2)增加注释; 注释由/*和*/包括;(3)扩充函数:①有返回值和返回语句;②有参数函数。
(4)增加一维数组类型(可增加指令)。
(5)其他典型语言设施。
二、实验环境与工具一、源语言:PL/0语言,PL/0语言是PASCAL语言的子集,它的编译程序是一个编译解析执行系统,后缀名为.PL0;二、目口号言:生成文件后缀为*.COD的目标代码3、实现平台:Borland C++Builder 64、运行平台:Windows三、设计概述1、结构设计说明(1)PL/0编译系统的结构框架源语言:源语言是基于C语言写的PL/0编译程序——PL0语言(可以看成Pascal 语言的子集)目口号言:假想的栈式运算机计算语言,即类PCODE指令代码。
指令格式如下:其中f代表功能码,l表示层次差,a的含义对不同的指令有所区别。
四、设计分析(一)扩充赋值运算:*= 和/=需要增加2个运算符*= 和/=,用下面表格概念的SYM代替运算符*= /=SYM表示TIMESBECOMES SLASHBECOMES *= 和/=的语法描述图:(二)扩充语句(Pascal的FOR语句)因为在Pascal中的FOR语句描述为:FOR <变量>:=<表达式> STEP <表达式> UNTIL <表达式> DO <语句>因此增加FOR,STEP,UNTIL,DOFOR语句语法描述图为:五、程序设计1)增加所需要的保留字和运算符,实现*=和/=,和FOR语句,应该增加TIMESBECOMES,SLASHBECOMES,FOR,STEP,UNTIL,DO。
第1章 引论2 PL0编译程序的实现
BNF引入的符号: < > 用左右尖括号括起来的字表示语法构造成分, 或称语法单位,为非终结符 ∷= ‘定义为’ | ‘或’ EBNF引入的符号: { } 表示花括号内的语法成分可重复 [ ] 表示方括号内的语法成分为任选项 ( ) 表示圆括号内的成分优先
一个用EBNF描述的例子:
<整数>∷=[+|-]<数字>{<数字>} <数字>∷=0|1|2|3|4|5|6|7|8|9 <整数>∷=[+|-]<非零数字>{<数字>}|0 <非零数字>∷=1|2|3|4|5|6|7|8|9 <数字>∷=0|1|2|3|4|5|6|7|8|9
Const a=10; var b,c; procedure p; begin c:=b+a; 在运行栈中申请3个栈空间 end; 取b入栈 begin 取10入栈 read(b); call p; 次栈顶与栈顶相加 write(c); 存入c end. 退出过程p 在运行栈中申请5个栈空间 从命令行读入输入置于栈顶 将栈顶值存入变量b 调用过程p 将变量c取至栈顶 栈顶值输出至屏幕 SL:静态链 换行 DL:动态链 RA:返回地址 结束程序
PL/0 语言的语法描述图
程序
分程序
.
分程序
const
ident
=
number
, ;
var ident
, ; ;
procedure ident
;
分程序
语句
语句
ident call begin
:=
表达式 ident
语句 语句
end
;
PL0编译器功能扩充要点
Ningxia Normal UniversityPL0编译器题目 Pl0编译器功能扩充姓名学号院(系)数学与计算机科学学院专业班级计算机技术与科学2班时间 2014-1-51目录一、实验目的 ---------------------------- 3二、实验内容 ---------------------------- 3三、实验框图 ---------------------------- 4四、过程分析 ---------------------------- 61、词法过程分析 ----------------------- 62、语法过程分析 ----------------------- 63、整体过程分析 ----------------------- 74、扩充过程分析 ----------------------- 9五、测试结果 --------------------------- 11六、问题及感受 --------------------------- 122本次实验设计主要是在分析理解PL/0编译程序的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充,使其增加并且实现了更多的功能。
二、实验内容PL/0语言是Pascal语言的一个子集,这里分析的PL/0的编译程序包括了对PL/0语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。
PL/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。
词法分析和代码生成作为独立的子程序供语法分析程序调用。
语法分析的同时,提供了出错报告和出错恢复的功能。
在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。
扩充PL0语言是在PL0语言的基础上增加对整型一维数组的支持、扩充IF-THEN-ELSE条件语句、增加REPEAT语句。
如下所示:(1)整型一维数组,数组的定义格式为:VAR <数组标识名>(<下界>:<上界>)其中上界和下界可以是整数或者常量标识名访问数组元素的时候,数组下标是整型的表达式,包括整数、常量或者变量和它们的组合(2)扩充条件语句,格式为:<条件语句>::= IF <条件>THEN <语句>[ELSE <语句>] (3)增加REPEAT语句,格式为:<重复语句> ::= REPEAT <语句> UNTIL <条件>(4) 注释单行注释以 { 开始,以 } 结束,注释内容不包括{和 }31、基本工作流程图源程序执行结果2、语法分析图3、if-then-else 语句的流程图进入if语句4、增加开始程序5四、过程分析1、词法分析:词法分析子程序名为GETSYM,功能是从源程序中读出一个单词符号,把它的信息放入全局变量 SYM、ID和NUM中,字符变量放入CH中,语法分析器需要单词时,直接从这三个变量中获得。
PL 0 编译系统
BEGIN、 END、 IF、 THEN、......
运算符
、、、、:=、=、、、、……
标识符
自定义的变量名、常数名、过程名
常数
如:10,25,100等整数
界符
如:‘,’、‘.’、‘;’、‘(’、 ‘)’、……
第十八页,编辑于星期三:四点 二十六分。
PL/0编译程序的词法分析 《编译原理》
/*过程P的局部变量说明部分*/
PROCEDURE Q; /*过程P的局部过程说明部分*/
VAR X;
/*过程Q的局部变量说明部分*/ILE X#0
Q 的过程体
DO CALL P; END; BEGIN
WRITE(D); CALL Q; END
P 的过程体
PL/0编译系统
《编译原理》
PL/0 编译程序总体结构 PL/0 语言描述
PL/0 编译程序的词法分析 PL/0 编译程序的语法分析
PL/0 编译程序的语义分析和符号表
PL/0 编译程序的目标代码生成
PL/0 编译程序的错误处理 类 P-code 虚拟机
第三页,编辑于星期三:四点 二十六分。
每个节点都可以到达出口 从入口到出口的路径表示该语法单位的
一种合法中间形式(短语)
有两种类型的节点
内的文字表示所用到的其他语法单位
或
内的文字表示单词符号
第十二页,编辑于星期三:四点 二十六分。
PL/0 语言的语法描述图 《编译原理》
例:程序和分程序语法单位的语法描述图
程序
分程序
.
分程序
const
PL/0编译程序
T-型图
《编译原理》
PL/0
类P-code
PL0语言编译器的设计与实现
PL0语⾔编译器的设计与实现⼀、设计任务1.1程序实现要求PL/0语⾔可以看成PASCAL语⾔的⼦集,它的编译程序是⼀个编译解释执⾏系统。
PL/0的⽬标程序为假想栈式计算机的汇编语⾔,与具体计算机⽆关。
PL/0的编译程序和⽬标程序的解释执⾏程序都是⽤JAVA语⾔书写的,因此PL/0语⾔可在配备JDK的任何机器上实现。
其编译过程采⽤⼀趟扫描⽅式,以语法分析程序为核⼼,词法分析和代码⽣成程序都作为⼀个独⽴的过程,当语法分析需要读单词时就调⽤词法分析程序,⽽当语法分析正确需要⽣成相应的⽬标代码时,则调⽤代码⽣成程序。
⽤表格管理程序建⽴变量、常量和过程标⽰符的说明与引⽤之间的信息联系。
⽤出错处理程序对词法和语法分析遇到的错误给出在源程序中出错的位置和错误性质。
当源程序编译正确时,PL/0编译程序⾃动调⽤解释执⾏程序,对⽬标代码进⾏解释执⾏,并按⽤户程序的要求输⼊数据和输出运⾏结果。
1.2 PL/0语⾔的BNF描述(扩充的巴克斯范式表⽰法)<prog> → program <id>;<block><block> → [<condecl>][<vardecl>][<proc>]<body><condecl> → const <const>{,<const>};<const> → <id>:=<integer><vardecl> → var <id>{,<id>};<proc> → procedure <id>([<id>{,<id>}]);<block>{;<proc>}<body> → begin <statement>{;<statement>}end<statement> → <id> := <exp>|if <lexp> then <statement>[else <statement>]|while <lexp> do <statement>|call <id>([<exp>{,<exp>}])|<body>|read (<id>{,<id>})|write (<exp>{,<exp>})<lexp> → <exp> <lop> <exp>|odd <exp><exp> → [+|-]<term>{<aop><term>}<term> → <factor>{<mop><factor>}<factor>→<id>|<integer>|(<exp>)<lop> → =|<>|<|<=|>|>=<aop> → +|-<mop> → *|/<id> → l{l|d} (注:l表⽰字母)<integer> → d{d}注释:<prog>:程序;<block>:块、程序体;<condecl>:常量说明;<const>:常量;<vardecl>:变量说明;<proc>:分程序; <body>:复合语句;<statement>:语句;<exp>:表达式;<lexp>:条件;<term>:项; <factor>:因⼦;<aop>:加法运算符;<mop>:乘法运算符; <lop>:关系运算符。
编译原理实验3 编译程序程序扩充与改造
实验三:PL/0编译程序扩充与改造
计科082班刘谦益 080501207
基本要求:扩充PL/0语言为PL/1语言,其中增加IF S THEN S1 ELSE S2语句。
主要内容:改写、调试并测试PL/1语言编译程序;尝试改造PL/1为PL/2,使其支持REPEAT S UNTIL E语句、FOR S STEP E S1语句。
实验步骤:
1、编写若干PL/0语言程序,利用PL/0编译程序编译、运行,保证PL/0语言程
序的正确性。
PL语言编译器的基本工作流程如图所示:
源程序
执行结果
PL编译器基本工作流程
PL/0语言编译程序已经调试成功,如图:
用先写好的PL/0语言的编译程序来编译写好的百鸡问题的PL/0程序,得到的结果如图:
2、设计PL/1编译程序,利用已经编译通过的PL/0语言程序初步验证PL/1编译
程序的正确性。
设计PL/1编译程序只需将PL/0编译程序的7处进行修改
PL/1程序计算从0一直加到50的和:
var x,y;
begin
x:=0;
y:=0;
while x<=100 do
begin
x:=x+1;
y:=y+x;
if x<=50 then
write(x)
else
write(y);
end;
end.
调试结果:
实验总结:
通过这次试验我学会如何修改PL/0编译程序到PL/1编译程序,也学会了编写PL/1的程序,知道PL/1编译程序主要比PL/0程序多了else语句的分析.。
PL0编译概述讲解
类P-code虚拟机
指令 “OPR 0 0”
T’
《编译原理》
过程调用结束后,返回调用点并退栈 重置基址寄存器和栈顶寄存器
. . . RA’ DL’ . . . T . . . RA B DL SL . . . B = DL’ 返返返 返返返 返返 P 返 RA’ T = B’
B’
SL’ . . . RA DL ቤተ መጻሕፍቲ ባይዱL . . .
PL/0 语言的 EBNF 表示
例:PL/0 语言的EBNF表示
<程序> ::= <分程序>.
<分程序> ::= [<常量说明部分>] [<变量说明部分>] [<过程说明部分>] <语句>
《编译原理》
<常量说明部分> ::= CONST <常量定义> { ,<常量定义> } ; <常量定义> ::= <标识符> = <无符号整数> <无符号整数> ::= <数字> {<数字>} <变量说明部分> ::= VAR <标识符 > { , <标识符 > } ; <标识符> ::= <字母> {<字母>|<数字>} <过程说明部分> ::= <过程首部><分程序>{; <过程说明部分> }; <过程首部> ::= PROCEDURE <标识符> ;
PL/0 程序示例
计算最大公约数
var m, n, r, q; { 计算m和n的最大公约数 } procedure gcd; begin while r#0 do begin q := m / n; r := m - q * n; m := n; n := r; end end;
PL0编译器功能扩充
Ningxia Normal UniversityPL0编译器题目 Pl0编译器功能扩充姓名学号院(系)数学与计算机科学学院专业班级计算机技术与科学2班时间 2014-1-51目录一、实验目的 ---------------------------- 3二、实验内容 ---------------------------- 3三、实验框图 ---------------------------- 4四、过程分析 ---------------------------- 61、词法过程分析 ----------------------- 62、语法过程分析 ----------------------- 63、整体过程分析 ----------------------- 74、扩充过程分析 ----------------------- 9五、测试结果 --------------------------- 11六、问题及感受 --------------------------- 122本次实验设计主要是在分析理解PL/0编译程序的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充,使其增加并且实现了更多的功能。
二、实验内容PL/0语言是Pascal语言的一个子集,这里分析的PL/0的编译程序包括了对PL/0语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。
PL/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。
词法分析和代码生成作为独立的子程序供语法分析程序调用。
语法分析的同时,提供了出错报告和出错恢复的功能。
在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。
扩充PL0语言是在PL0语言的基础上增加对整型一维数组的支持、扩充IF-THEN-ELSE条件语句、增加REPEAT语句。
如下所示:(1)整型一维数组,数组的定义格式为:VAR <数组标识名>(<下界>:<上界>)其中上界和下界可以是整数或者常量标识名访问数组元素的时候,数组下标是整型的表达式,包括整数、常量或者变量和它们的组合(2)扩充条件语句,格式为:<条件语句>::= IF <条件>THEN <语句>[ELSE <语句>] (3)增加REPEAT语句,格式为:<重复语句> ::= REPEAT <语句> UNTIL <条件>(4) 注释单行注释以 { 开始,以 } 结束,注释内容不包括{和 }31、基本工作流程图源程序执行结果2、语法分析图3、if-then-else 语句的流程图进入if语句4、增加开始程序5四、过程分析1、词法分析:词法分析子程序名为GETSYM,功能是从源程序中读出一个单词符号,把它的信息放入全局变量 SYM、ID和NUM中,字符变量放入CH中,语法分析器需要单词时,直接从这三个变量中获得。
编译原理PL0教程
序言 (1)第一部分PL/0语言及其编译器 (2)1.PL/0语言介绍 (2)1.1 PL/0语言的语法图 (3)2.PL/0语言编译器 (6)2.1词法分析 (7)2.2 语法分析 (7)2.3 语义分析 (9)2.4 代码生成 (9)2.5 代码执行 (11)2.6 错误诊断处理 (13)2.7 符号表管理 (15)2.8其他 (16)第二部分上机实践要求 (17)第三部分PL/0语言编译器源程序 (19)1.一个例子 (19)1.1 PL/0语言源程序 (19)1.2 生成的代码(片段) (21)2.PL/0语言编译器源程序 (21)编译原理实践教程序言《编译原理和技术》的课程实践至少有两种可能的安排。
其一,为配合编译课程教学,而安排多次小型实践,分别支持编译程序的各个阶段。
其二,针对某一规模适中的语言来设计和实现一个相对完整、独立编译器。
《编译原理实践教程》作为《编译原理和技术》课程的延伸,其目的是让大家动手设计和实现某一规模适中的语言的编译器,该编译器不仅涉及编译程序的各个阶段,而且也强调了编译的总体设计、各个阶段的接口安排等等。
通过上机实践,来设计这个相对完整的编译器,一方面可以使学生增加对编译程序的整体认识和了解——巩固《编译原理和技术》课程所学知识,另一方面,通过上机练习,学生也可以学到很多程序调试技巧和设计大型程序一般的原则,如模块接口的协调,数据结构的合理选择等等。
为了使学生能尽早动手实践,我们建议把实践分成三部分,首先阅读本教程第一部分,在这部分就PL/0语言的语法及其编译程序的各个阶段作了简单介绍,以便对PL/0编译程序有个初步的印象。
其次要认真阅读理解第三部分所给出的PL/0编译器源程序,使上一阶段的初步印象得以加深、具体化。
最后按照第二部分的实验要求扩充PL/0语言的功能并加以实现。
第一部分 PL/0语言及其编译器1. PL/0语言介绍PL/0程序设计语言是一个较简单的语言,它以赋值语句为基础,构造概念有顺序、条件和重复(循环)三种。
PL0编译程序的实现
//设置保留字符号 wsym[0]=(symbol)beginsym; wsym[1]=(symbol)callsym; wsym[2]=(symbol)constsym; wsym[3]=(symbol)dosym; wsym[4]=(symbol)endsym; wsym[5]=(symbol)ifsym; wsym[6]=(symbol)oddsym; wsym[7]=(symbol)procsym; wsym[8]=(symbol)readsym; wsym[9]=(symbol)thensym; wsym[10]=(symbol)varsym; wsym[11]=(symbol)whilesym; wsym[12]=(symbol)writesym;
2. PL/0编译程序的结构 PL/0源程序 词法分析程 序 语法语义分析程序
表格管理程序
出错处理程序
代码生成程序
目标程序
PL/0编译系统的结构框架
PL/0源程序
PL/0编译程序
目标代码
解释执行程序
输入
输出
PL/0编译程序(包括主程 序)是由18个嵌套及并列 的过程或函数组成:
PL/O编译程序的过程与函数定义层次结构图
PL/O编译程序总体流程图
2.3PL/0编译程序的词法分析
词法分析程序GETSYM 功能 识别单词作为语法分析的输入,单词分为关键字、运 算符、界符、标识符和常数,其中前三类称为固有单 词,后二类称为用户定义单词。
PL/0编译程序设置的三个全程变量: SYM:存放单词的类别,如beginsym, ident ID: 存放用户所定义的标识符的值 NUM:存放用户定义的数
PLO编译器扩展实验报告
云南大学编译原理实验报告实验题目:PLO编译器扩展学院:信息学院专业:计算机科学与技术学号:20091060064姓名:刘继远目录一、实验目的 (1)二、实验内容 (1)三、源程序分析 (2)1、PL/0语言编译器的基本工作流程 (2)2、PL/0语言编译器主要函数的作用及其函数之间的调用 (3)3、编译器的语法语义分析 (4)(1)、编译器在进行语法语义分析时,各函数的调用关系 (4)(2)、递归子程序实现 (5)(3)、其他两大部分的功能 (6)1)、说明部分的分析 (6)2)、过程体的分析: (6)4、PL/0编译程序的目标代码结构和代码生成 (7)(1)、对分程序体人口的处理 (7)(2)、类pcode代码指令的详细解释 (7)5、PL/0编译程序的语法错误处理 (8)四、设计的基本思想 (9)1、对else语句的扩展: (9)2、对一维数组的扩展: (10)五、结果及分析 (16)1、对else语句扩展的测试结果 (16)2、对一维数组扩展的测试结果 (19)一、实验目的1.理解语法、语义分析程序为中心的单遍编译程序组织方法;2.理解编译程序的基本逻辑过程(词法分析、语法分析、语义分析及目标代码的生成;3.理解编译过程中的符号表、内存管理、错误处理的基本方法;二、实验内容在已知的PL0程序的基础上,修改PL/0编译程序和类P-code解释程序的源代码,以支持对PL/0语言所进行的如下扩充,并调试通过:(1)条件语句改为:<条件语句>::=IF <条件>THEN <语句>[ELSE <语句>] 问题:按照你的修改方式,如下PL/0代码执行后变量x的值是什么?你认为这样的结果是否合理?为什么?(2)增加整型一维数组变量,形式为:<数组变量声明>::=<标识符>( <下界>:<上界>)<数组变量引用>::= <标识符>( <表达式>)其中<下界>和<上界>是常量名或整数,例如:三、源程序分析1、PL/0语言编译器的基本工作流程如图1-1所示:源程序执行结果图1-1 PL/0编译器基本工作流程2、PL/0语言编译器主要函数的作用及其函数之间的调用它反映了编译程序工作的基理,如图1-2所示:图1-2 PL/0编译器函数调用3、编译器的语法语义分析(1)、编译器在进行语法语义分析时,各函数的调用关系从PL/0的语法描述图中可以清楚地看到,当对PL/0语言进行语法分析时,各个非终结符语法单元所对应的分析过程之间必须存在相互调用的关系。
PLO语言功能扩展(case语句和for语句)
编译原理实验报告一.实验目的:熟练掌握PLO语言编译程序的结构和功能;二.实验要求:扩充PLO语言的功能,增加for语句和case语句;已知for语句和case语句的语法如下: <for语句>::=for(赋值语句;关系表达式) do <语句><关系表达式>::=<表达式><关系运算符><表达式><case语句>::=<case><标识符>:{<常量>:<语句>}endcase .三.实验环境与工具:(1)计算机及操作系统:WindowsXP(2)程序设计语言:C(3)编译程序:PL/0(4)实现工具(平台):VC++6.0四.设计方案:1.概述:源语言:pl0目标语言:类pcode代码实现工具(平台):VC++6.02.结构设计说明:PlO所有子程序如下:过程或函数名简要功能说明main 初始化编译环境,建立关键字表,调用分程序Block对源文件进行编译,当编译正确时,自动调用解释执行程序,对目标代码进行解释执行。
error 出错处理,打印出错位置和错误性质编号。
并在信息栏输出错误信息。
getch 过滤空格,读取一个字符getsym 词法分析,读取一个单词gen 生成目标代码(类pcode代码),并送入目标程序区。
test 测试当前单词是否是合法block 分程序分析处理过程。
enter 登录过程说明对象包括变量、常量和过程名的属性信息到符号表。
position查找标识符在符号表中的位置。
constdeclaration常量定义处理,收集常量信息并登录到符号表。
vardeclaration变量定义处理,收集变量信息并登录到符号表。
listcode列出目标代码清单。
statement语法分析,语句部分处理。
expression表达式分析处理。
term项分析处理过程。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Ningxia Normal UniversityPL0编译器题目 Pl0编译器功能扩充姓名学号院(系)数学与计算机科学学院专业班级计算机技术与科学2班时间 2014-1-51目录一、实验目的 ---------------------------- 3二、实验内容 ---------------------------- 3三、实验框图 ---------------------------- 4四、过程分析 ---------------------------- 61、词法过程分析 ----------------------- 62、语法过程分析 ----------------------- 63、整体过程分析 ----------------------- 74、扩充过程分析 ----------------------- 9五、测试结果 --------------------------- 11六、问题及感受 --------------------------- 122本次实验设计主要是在分析理解PL/0编译程序的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充,使其增加并且实现了更多的功能。
二、实验内容PL/0语言是Pascal语言的一个子集,这里分析的PL/0的编译程序包括了对PL/0语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。
PL/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。
词法分析和代码生成作为独立的子程序供语法分析程序调用。
语法分析的同时,提供了出错报告和出错恢复的功能。
在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。
扩充PL0语言是在PL0语言的基础上增加对整型一维数组的支持、扩充IF-THEN-ELSE条件语句、增加REPEAT语句。
如下所示:(1)整型一维数组,数组的定义格式为:VAR <数组标识名>(<下界>:<上界>)其中上界和下界可以是整数或者常量标识名访问数组元素的时候,数组下标是整型的表达式,包括整数、常量或者变量和它们的组合(2)扩充条件语句,格式为:<条件语句>::= IF <条件>THEN <语句>[ELSE <语句>] (3)增加REPEAT语句,格式为:<重复语句> ::= REPEAT <语句> UNTIL <条件>(4) 注释单行注释以 { 开始,以 } 结束,注释内容不包括{和 }31、基本工作流程图源程序执行结果2、语法分析图3、if-then-else 语句的流程图进入if语句4、增加开始程序5四、过程分析1、词法分析:词法分析子程序名为GETSYM,功能是从源程序中读出一个单词符号,把它的信息放入全局变量 SYM、ID和NUM中,字符变量放入CH中,语法分析器需要单词时,直接从这三个变量中获得。
Getch过程通过反复调用Getch子过程从源程序过获取字符,并把它们拼成单词。
GETCH过程中使用了行缓冲区技术以提高程序运行效率。
词法分析器的分析过程:调用GETSYM时,它通过GETCH 过程从源程序中获得一个字符。
如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把SYM变量赋成相应的保留字类型值;如果没有查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过程的名字),把SYM置为IDENT,把这个单词存入ID变量。
查保留字表时使用了二分法查找以提高效率。
如果Getch获得的字符是数字,则继续用Getch获取数字,并把它们拼成一个整数或实数,然后把SYM置为 INTEGER或REAL,并把拼成的数值放入NUM变量。
如果识别出其它合法的符号(比如:赋值号、大于号、小于等于号等),则把SYM则成相应的类型。
如果遇到不合法的字符,把SYM置成NUL。
2、语法分析:语法分析子程序采用了自顶向下的递归子程序法,语法分析同时也根据程序的语义生成相应三元代码,并提供了出错处理的机制。
语法分析主要由分程序分析过程、参数变量分析过程、参数变量处理过程、数组处理过程、常量定义分析过程、变量定义分析过程、语句分析过程、表达式处理过程、项处理过程、因子处理过程和条件处理过程构成。
这些过程在结构上构成一个嵌套的层次结构。
除此之外,还有出错报告过程、代码生成过程、测试单词合法性及出错恢复过程、登录名字表过程、查询名字表函数以及列出类PCODE代码过程作过语法分析的辅助过程。
63、整体分析:语法分析开始后,首先调用分程序处理过程处理分程序。
过程入口参数置为: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 指令,用于从分程序返回。
常量定义过程:通过循环,反复获得标识符和对应的值,存入符号表。
符号表中记录下标识符的名字和它对应的值。
变量定义过程:与常量定义类似,通过循环,反复获得标识符,存入符号表。
符号表中记录下标识符的名字、它所在的层及它在所在层中的偏移地址。
7参变量定义过程:类似变量定义,将参变量,存入符号表中。
参变量处理过程:如果函数用参变量,依照形参的类型、个数,由实参进行赋值。
数组处理过程:计算数组括号内的偏移值,存入栈顶用于后面生成的STOARR和LODARR指令调用实际的数组中元素的地址。
语句处理过程:语句处理过程是一个嵌套子程序,通过调用表达式处理、项处理、因子处理等过程及递归调用自己来实现对语句的分析。
语句处理过程可以识别的语句包括赋值语句、read语句、write语句、++语句、--语句、+=语句、-=语句、if-else-then 语句、while语句、For语句、repeat语句。
当遇到begin/end 语句时,就递归调用自己来分析。
分析的同时生成相应的类PCODE指令。
赋值语句的处理:首先获取赋值号左边的标识符,从符号表中找到它的信息,并确认这个标识符确为变量名。
然后通过调用表达式处理过程算得赋值号右部的表达式的值并生成相应的指令保证这个值放在运行期的数据栈顶。
最后通过前面查到的左部变量的位置信息,生成相应的STO指令,把栈顶值存入指定的变量的空间,实现了赋值操作。
返回函数值也是用赋值语句进行返回值的储存。
对函数与过程调用的处理:首先判断读入的标识符属性为FUNCTION或PROCEDURE,从符号表中找到此标识符,获得其所在层次和偏移地址。
然后生成相应的cal指令。
至于调用子过程所需的保护现场等工作是由类PCODE解释程序在解释执行cal指令时自动完成的。
如果此标识符不在第0层而且是该层函数的函数名则作为返回值返回。
read语句的处理:在read语句合理前提下,由变量的类型生成相应的指令:8对于整型,第一条是16号操作的opr指令,实现从标准输入设备上读一个整数值,放在数据栈顶。
如果读入是实数就报错,第二条是sto指令,把栈顶的值存入read语句括号中的变量所在的单元。
对于实型,第一条是15号操作的opr指令,实现从标准输入设备上读一个实数值,放在数据栈顶。
第二条是sto指令,把栈顶的值存入read语句括号中的变量所在的单元。
对于字符型,第一条是20号操作的opr指令,实现从标准输入设备上读一个字符值,第二条是sto指令,把栈顶的值存入read语句括号中的变量所在的单元。
write语句的处理:与read语句相似。
在语法正确的前提下,生成指令:通过循环调用表达式处理过程分析write语句括号中的每一个表达式,生成相应指令保证把表达式的值算出并放到数据栈顶并生成指令,输出表达式的值,如果是数字类型则生成14号操作的opr指令,如果是字符类型则生成19号操作的opr指令。
4、扩充分析:增加错误分析功能在编译程序的过程中,往往我们的程序中存在着一些错误。
而在编译主体的时候我们已经列出了出错编号,为了清晰的了解出错原因,因此在初始化过程后增加了出错处理,打印出错位置和错误编码。
void error(int n){char space[81];memset(space,32,81);space[cc-1]=0; //出错时当前符号已经读完,所以cc-1 printf("****%s!%d\n",space,n);switch(n){………………………………}err++;}9增加if-then-else当编译程序编译到条件语句时,并不直到条件为假时的转移地址,必须等到条件为真的语句编译完后才知道转移地址。
还有当条件为真时语句执行完毕后,必须跳出 if 语句,否则就会接着执行else 后语句。
即再then后else前语句的最后加上一条无条件转移指令:jmp 0 ?,此时该地址也未知,因为编译程序还未编译 else 后语句,等到编译完 else后语句时,才知道该地址,所以必须保存该代码的地址,等下次回填。
在初始化与头文件中作相应改动初始化:strcpy(&(word[5][0]),"else");strcpy(&(word[14][0]),"to");wsym[5]=elsesym; /* add else*/wsym[14]=tosym;头文件:enum symbol{nul, ident, number, plus, minus,times, slash, oddsym, eql, neq,lss, leq, gtr, geq, lparen,rparen, comma, semicolon,period, becomes,pluseq,minuseq,plusone,minusone,beginsym, endsym, ifsym, thensym, whilesym,writesym, readsym, dosym, callsym, constsym,varsym, procsym,elsesym,tosym}增加++a与--a、增加a++与a--功能和增加+=与-=功能++a与--a的操作是将a的值自加与自减1,但是参与程序中与a 值相关的运算的时候,使用的仍然是未经过自加或自减的a值。