{
enum fct f; int l; int a; };
struct instruction code[cxmax];/*存放虚拟机代码的数组*/
当编译结束之后,记录源程序中标识符的TABLE表已经没用了,因此存储区只需要以数组CODE存放的只读目标程序和运行时的数据区S。S是由解释程序定义的一维整型数组。代码如下:
int p, b, t; /*指令指针,指令基址,栈顶指针*/ struct instruction i; /*存放当前指令*/ int s[stacksize]; /*栈*/
/*虚拟机代码指令*/
/*引用层与声明层层次差*/ /*根据f的不同而不同*/
其中,有四个寄存器。分别为I指令寄存器,P程序地址寄存器,T栈顶寄存器,B基址寄存器。
对于源程序的每一个过程(包括主程序),在被调用时,首先在数据段中开辟三个空间,存放静态链SL、动态链DL和返回地址RA。
1. 静态链记录了定义该过程的直接外过程(或主程序)运行时最新数据段的基地址。 2. 动态链记录调用该过程前正在运行的过程的数据段基址。
3. 返回地址记录了调用该过程时程序运行的断点位置。对于主程序来说,SL、DL和RA
的值均置为0。
静态链的功能是在一个子过程要引用它的直接或间接父过程(这里的父过程是按定义过程时的嵌套情况来定的,而不是按执行时的调用顺序定的)的变量时,可以通过静态链,跳过个数为层差的数据段,找到包含要引用的变量所在的数据段基址,然后通过偏移地址访问它。
③语法分析方法
PL/0编译程序的语法分析采用了自顶向下的递归子程序法。语法分析从读入第一个单词开始由开始符『程序』出发,沿语法描述图箭头所指方向进行分析。当遇到非终结符时,则调用相对应的处理过程,从语法描述图也就进入了一个语法单元,再沿当前所进入的语法描述图的箭头方向进行分析,当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,则执行对应的语义程序(翻译程序)。再读入下一个单词继续分析。遇到分支点时将当前的单词与分支点上的多个终结符逐个比较,若都不匹配时可能是进入下一非终结符语法单位或是出错。
如果一个PL0语言程序的单词序列在整个语法分析中,都能逐个得到匹配,直到程序结束符『·』,这时说明所输入的程序是正确的。对于正确的语法分析进行对应的语义翻译,生成目标代码。
语法分析主要由分程序分析过程(BLOCK)常量定义分析过程(ConstDeclaration)、变量定义分析过程(Vardeclaration)、字符变量定义分析过程(Chardeclaration)、语句分析过程(Statement)、表达式处理过程(Expression)、项处理过程(Term)、因子处理过程(Factor)和条件处理过程(Condition)构成。这些过程在结构上构成一个嵌套的层次结构。
④中间代码表示
中间代码是是源程序的一种内部表示,复杂性介于源语言和目标机语言之间。 中间代码的表示方法有逆波兰式、三元式、树形、四元式等。
(1) 逆波兰记号是最简单的一种中间代码表示形式,早在编译程序出现之前,它就用于
表示算术表达式。
后缀表示法表示表达式,其最大的优点是易于栈式计算机处理表达式。 (2) 每个三元式由三个部分组成:
算符op
第一运算对象ARG1 第二运算对象ARG2
运算对象可能是源程序中的变量,也可能是某个三元式的结果,用三元式的编号表示。
(3) 树形表示是三元式表示的翻版。
(4) 四元式是一种比较普遍采用的中间代码形式: 算符op 运算对象ARG1 运算对象ARG2 运算结果RESULT
五、 开发过程和完成情况
(1)增加单词:保留字 ELSE,FOR,TO,DOWNTO,RETURN 运算符 *=,/=,++,--,&,||,!
1.1修改symbol枚举 enum symbo l{ 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, muleqsym,deviesym,pplus,mminus,andsym,logical_or,logical_not,charsym,charvalue, writecharsym,readcharsym }; 1.2 修改getSym(),增加以下语句 int getsym() { //乘等识别 else if(ch=='*') ..... //除等识别 else if(ch=='/') { getchdo; if (ch=='=') { sym= deviesym; { } getchdo; if (ch=='=') { } else { } sym = nul; sym= muleqsym; getchdo; } } getchdo; else { } sym = nul; //++、--识别 if (ch=='+') { } getchdo; if (ch=='+') // 自增检测 { } else { } sym = plus; sym=pplus; getchdo;