Compilers_2

PL/0 是一个小巧的高级语言。

只有整数类型,是相当完全的可嵌套的分程序(block)的程序结构,

分程序中可以有常量定义、变量声明和无参过程声明,过程体又是分程序。

有赋值语句、条件语句、循环语句、过程调用语句、复合语句和空语句。

Program → Block .
Block → [ConstDecl] [VarDecl][ProcDecl] Stmt
ConstDecl → const ConstDef {, ConstDef} ;
ConstDef → ident = number
VarDecl → var ident {, ident} ;
ProcDecl → procedure ident ; Block ; {procedure ident ; Block ;}
Stmt → ident := Exp | call ident | begin Stmt {; Stmt} end |
if Cond then Stmt | while Cond do Stmt | ε
Cond → odd Exp | Exp RelOp Exp
RelOp → = | <> | < | > | <= | >=
Exp → [+ | − ] Term {+ Term | − Term}
Term → Factor {∗ Factor | / Factor}
Factor → ident | number | ( Exp )


ident 是字母开头的字母数字串
number 是无符号整数
begin、call、const、do、end、if、odd、procedure、then、var、while 是保留字


PL/0 语言编译器有两部分,把源语言翻译成中间语言的编译器和中间语言解释器,编译器用的是递归下降的预测分析方法,并采用了一种紧急方式的错误恢复方法

中间语言是一种栈机器代码,其指令集是:

(1)lit:将常数装入栈顶的指令;
(2)lod:将变量的值装入栈顶的指令;
(3)sto:对应于赋值语句的存储指令;
(4)cal:对应于过程调用的指令;
(5)int:增加栈顶寄存器的值,完成对局部变量的存储分配的指令;
(6)jmp,jpc:对应条件语句和循环语句的无条件转移和条件转移的控制转移指令;
(7)opr:包括一组算术和关系运算的指令。

一条指令由三个域组成:
(1)操作码f:上面已经列出了所有8 种操作码。
(2)层次差l:这里的层次差就是5.3.2 节介绍嵌套深度时的np − na。该域仅用于存取
指令和调用指令。
(3)多用途a:在运算指令中,a 的值用来区分不同的运算;在其他情况,a 或是一个数(lit,int),或是一个程序地址(jmp,jpc,cal),或是一个数据地址(lod,sto)。

编译器对 PL/0 源程序进行一遍扫描,并逐行输出源程序。在源程序无错的情况下,编译器每编译完一个分程序,就列出该分程序的代码,这由编译器的listcode 过程完成。每个分程序的第一条指令是jmp 指令,其作用是绕过该分程序声明部分产生的代码(即绕过内嵌过程的代码)。listcode 过程没有列出这条代码。


1.)初始化:

保留字表(word)

        /* 设置保留字名字,按照字母顺序,便于折半查找 */
strcpy(&(word[0][0]), "begin");
strcpy(&(word[1][0]), "call");
strcpy(&(word[2][0]), "const");
strcpy(&(word[3][0]), "do");
strcpy(&(word[4][0]), "else");//ELSE
strcpy(&(word[5][0]), "end");
strcpy(&(word[6][0]), "if");
strcpy(&(word[7][0]), "odd");
strcpy(&(word[8][0]), "procedure");
strcpy(&(word[9][0]), "read");
strcpy(&(word[10][0]), "then");
strcpy(&(word[11][0]), "var");
strcpy(&(word[12][0]), "while");
strcpy(&(word[13][0]), "write");

保留字表中每一个保留字对应的symbol类型()      

        /* 设置保留字符号 */
wsym[0] = beginsym;
wsym[1] = callsym;
wsym[2] = constsym;
wsym[3] = dosym;
wsym[4] = elsesym;else
wsym[5] = endsym;
wsym[6] = ifsym;
wsym[7] = oddsym;
wsym[8] = procsym;
wsym[9] = readsym;
wsym[10] = thensym;
wsym[11] = varsym;
wsym[12] = whilesym;
wsym[13] = writesym;

类 PCODE 指令助记符表 ( mnemonic )

        /* 设置指令名称 */
strcpy(&(mnemonic[lit][0]), "lit");
strcpy(&(mnemonic[opr][0]), "opr");
strcpy(&(mnemonic[lod][0]), "lod");
strcpy(&(mnemonic[sto][0]), "sto");
strcpy(&(mnemonic[cal][0]), "cal");
strcpy(&(mnemonic[inte][0]), "int");
strcpy(&(mnemonic[jmp][0]), "jmp");
strcpy(&(mnemonic[jpc][0]), "jpc");

声明开始集合 ( declbegsys )

        /* 设置声明开始符号集 */
declbegsys[constsym] = true;
declbegsys[varsym] = true;
declbegsys[procsym] = true;

表达式开始集合 ( statbegsys ) 

         /* 设置语句开始符号集 */
statbegsys[beginsym] = true;
statbegsys[callsym] = true;
statbegsys[ifsym] = true;
statbegsys[whilesym] = true;
statbegsys[readsym] = true; // thanks to elu
statbegsys[writesym] = true;

项开始符号集合 ( facbegsys )

        /* 设置因子开始符号集 */
facbegsys[ident] = true;
facbegsys[number] = true;
facbegsys[lparen] = true;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值