资源简介
在《算法+数据结构=程序》一书中,Niklaus Wirth 设计的 PL/0 语言编译器分成两部分,把源语言翻译成中间语言的编译器和中间语言解释器,编译器用的是递归下降的预测分析方法中间语言是一种栈机器代码,其指令集是根据 PL/0 语言的需要来设计的。编译器源码及测试程序可从。一条指令由三个域组成:
(1)操作码 f:上面已经列出了所有 8 种操作码。
(2)层次差 l:这里的层次差就是 5.3.2 节介绍嵌套深度时的 n p − n a 。该域仅用于存取指令和调用指令。
(3)多用途 a:在运算指令中,a 的值用来区分不同的运算;在其他情况,a 或是一个数(lit,int),或是一个程序地址(jmp,jpc,cal),或是一个数据地址(lod,sto)。
编译器对 PL/0 源程序进行一遍扫描,并逐行输出源程序。在源程序无错的情况下,编译器每编译完一个分程序,就列出该分程序的代码,这由编译器的 listcode 过程完成。每个分程序的第一条指令是 jmp 指令,其作用是绕过该分程序声明部分产生的代码(即绕过内嵌过程的代码)。listcode 过程没有列出这条代码。 解释器是编译器中的一个过程,若源程序无错,则编译结束时调用解释过程 interpret。由于 PL/0 语言没有输出语句,解释器按执行次序,每遇到对变量赋值时就输出该值。 由于 PL/0 语言是过程嵌套语言,因此程序运行时,活动记录栈中每个活动记录需要包含控制链和访问。活动记录栈的栈顶以外的存储空间作为代码执行过程中所需要的计算栈,无需另外设立计算栈。
代码片段和文件信息
// pl/0 compiler with code generation
#include
#include
#include “pl0.h“
void error(long n){
long i;
printf(“ ****“);
for (i=1; i<=cc-1; i++){
printf(“ “);
}
printf(“^%2d\n“n);
err++;
}
void getch() {
if(cc==ll){
if(feof(infile)){
printf(“************************************\n“);
printf(“ program incomplete\n“);
printf(“************************************\n“);
exit(1);
}
ll=0; cc=0;
printf(“%5d “ cx);
while((!feof(infile))&&((ch=getc(infile))!=‘\n‘)){
printf(“%c“ch);
ll=ll+1; line[ll]=ch;
}
printf(“\n“);
ll=ll+1; line[ll]=‘ ‘;
}
cc=cc+1; ch=line[cc];
}
void getsym(){
long ijk;
while(ch==‘ ‘||ch==‘\t‘){
getch();
}
if(isalpha(ch)){ // identified or reserved
k=0;
do{
if(k a[k]=ch; k=k+1;
}
getch();
}while(isalpha(ch)||isdigit(ch));
if(k>=kk){
kk=k;
}else{
do{
kk=kk-1; a[kk]=‘ ‘;
}while(k }
strcpy(ida); i=0; j=norw-1;
do{
k=(i+j)/2;
if(strcmp(idword[k])<=0){
j=k-1;
}
if(strcmp(idword[k])>=0){
i=k+1;
}
}while(i<=j);
if(i-1>j){
sym=wsym[k];
}else{
sym=ident;
}
}else if(isdigit(ch)){ // number
k=0; num=0; sym=number;
do{
num=num*10+(ch-‘0‘);
k=k+1; getch();
}while(isdigit(ch));
if(k>nmax){
error(31);
}
}else if(ch==‘:‘){
getch();
if(ch==‘=‘){
sym=becomes; getch();
}else{
sym=nul;
}
}else if(ch==‘<‘){
getch();
if(ch==‘=‘){
sym=leq; getch();
}else if(ch==‘>‘){
sym=neq; getch();
}else{
sym=lss;
}
}else if(ch==‘>‘){
getch();
if(ch==‘=‘){
sym=geq; getch();
}else{
sym=gtr;
}
}else{
sym=ssym[(unsigned char)ch]; getch();
}
}
void gen(enum fct x long y long z){
if(cx>cxmax){
printf(“program too long\n“);
exit(1);
}
code[cx].f=x; code[cx].l=y; code[cx].a=z;
cx=cx+1;
}
void test(unsigned long s1 unsigned long s2 long n){
if (!(sym & s1)){
error(n);
s1=s1|s2;
while(!(sym & s1)){
getsym();
}
}
}
void enter(enum object k){ // enter object into table
tx=tx+1;
strcpy(table[tx].nameid);
table[tx].kind=k;
switch(k){
case constant:
if(num>amax){
error(31);
num = 0;
}
table[tx].val=num;
break;
case variable:
table[tx].level=lev; table[tx].addr=dx; dx=dx+1;
break;
case proc:
table[tx].level=lev;
break;
}
}
long position(char* id){ // find identifier id in table
long i;
strcpy(table[0].nameid);
i=tx;
while(strcmp(table[i].nameid)!=0){
i=i-1;
}
return i;
}
void constdeclaration(){
if(sym==ident){
getsym();
if(sym==eql||sym==becomes){
if(sym==becomes){
error(1);
}
getsym();
if(sym==number){
enter(constant); getsym();
}els
属性 大小 日期 时间 名称
----------- --------- ---------- ----- ----
文件 2804 2011-04-19 21:24 pl0.h
文件 11886 2010-01-28 11:54 pl0.c
....... 716 2009-11-26 22:48 tests.pl0
文件 1530 2009-11-09 15:01 multiply.res
文件 281 2009-11-08 22:54 multiply.pl0
----------- --------- ---------- ----- ----
17217 5
- 上一篇:基于单片机全自动洗衣机毕业设计
- 下一篇:lwip官方文档英文 lwip移植优化必备
相关资源
- PL0语言编译器分析实验报告
- Engineering a Compiler
- 把玩编译器,Clang 有意思
- MCS-51智能反编译器 v1.0中文版(51单片
- GCC编译器官方文档
- 老版本MQL4编译器
- ubuntu环境qt配置交叉编译器
- Pascal编译器11个阶段程序
- Sample语言编译器(词法分析、正规式
- C0语言编译器
- 编译原理实验 小型编译器
- 编译原理课程设计 SAL的编译器
- EXE程序反编译器,将EXE程序还原为代
- c0文法编译器
- Mini-C编译器设计与实现%2B论文%2Bppt%
- 清华大学编译原理的PL/0源代码
- 自己动手实现Lua:虚拟机、编译器和
- 增强版的pl0编译器,支持for循环及b
- PL语言编译器扩充 编译原理大作业实
- 编译原理课程设计PL/0
- 一个简单编译器前端包括词法分析,
- EverEdit+v4.1.0.4379+破解补丁
- 编译原理LR(0)文法分析器Windows Ve
- Lex_Yacc 编译器设计及参考文档
- 编译原理实验-简单的PL0编译器
- nasm 汇编编译器 最新版 含linux和wind
- 扩展C0文法编译器源代码北航编译技术
- 编译原理基于antlr的编译器
- Tiny+编译器源代码
- minGW 最新版
评论
共有 条评论