首页 > 代码库 > PL/0编译程序

PL/0编译程序

Pl/0语言文法的BNF表示:

〈程序〉→〈分程序>.

〈分程序〉→ [<常量说明部分>][<变量说明部分>][<过程说明部分>]〈语句〉

 <常量说明部分> → CONST<常量定义>{ ,<常量定义>};

 <常量定义> → <标识符>=<无符号整数>

 <无符号整数> → <数字>{<数字>}

 <变量说明部分> → VAR<标识符>{ ,<标识符>};

 <标识符> → <字母>{<字母>|<数字>}

 <过和说明部分> → <过程首部><分程序>;{<过程说明部分>}

 <过程首部> → procedure<标识符>;

 <语句> → <赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|<空>

 <赋值语句> → <标识符>:=<表达式>

 <复合语句> → begin<语句>{ ;<语句>}<end>

 <条件> → <表达式><关系运算符><表达式>|ood<表达式>

 <表达式> → [+|-]<项>{<加减运算符><项>}

 <项> → <因子>{<乘除运算符><因子>}

 <因子> → <标识符>|<无符号整数>|(<表达式>)

 <加减运符> → +|-

 <乘除运算符> → *|/

 <关系运算符> → =|#|<|<=|>|>=

 <条件语句> → if<条件>then<语句>

 <过程调用语句> → call<标识符>

 <当型循环语句> → while<条件>do<语句>

 <读语句> → read(<标识符>{ ,<标识符>})

 <写语句> → write(<标识符>{,<标识符>})

 <字母> → a|b|c…x|y|z

 <数字> → 0|1|2…7|8|9

 

一. 为PL/0语言建立一个词法分程序GETSYM(函数)

把关键字、算符、界符称为语言固有的单词,标识符、常量称为用户自定义的单词。为此设置三个全程量:SYM,ID,NUM 。

 SYM:存放每个单词的类别,为内部编码的表示形式。

 ID:存放用户所定义的标识符的值,即标识符字符串的机内表示。

 NUM:存放用户定义的数。

 GETSYM要完成的任务:

  1. 滤掉单词间的空格。
  2. 识别关键字,用查关键字表的方法识别。当单词是关键字时,将对应的类别放在SYM中。如IF的类别为IFSYM,THEN的类别为THENSYM。
  3. 识别标识符,标识符的类别为IDENT,IDRNT放在SYM中,标识符本身的值放在ID中。关键字或标识符的最大长度是10。
  4. 拼数,将数的类别NUMBER放在SYM中,数本身的值放在NUM中。
  5. 拼由两个字符组成的运算符,如:>=、<=等等,识别后将类别存放在SYM中。
  6. 打印源程序,边读入字符边打印。

由于一个单词是由一个或多个字符组成的,所以在词法分析程序GETSYM中定义一个读字符过程GETCH。

二. 为PL/0语言建立一个语法分析程序BLOCK(函数)

PL/0编译程序采用一遍扫描的方法,所以语法分析和代码生成都有在BLOCK中完成。BLOCK的工作分为两步:

a) 说明部分的处理

说明部分的处理任务就是对每个过程(包括主程序,可以看成是一个主过程)的说明对象造名字表。填写所在层次(主程序是0层,在主程序中定义的过程是1层,随着嵌套的深度增加而层次数增大。PL/0最多允许3层),标识符的属性和分配的相对地址等。标识符的属性不同则填写的信息不同。

所造的表放在全程量一维数组TABLE中,TX为指针,数组元素为结构体类型数据。LEV给出层次,DX给出每层的局部量的相对地址,每说明完一个变量后DX加1。

例如:一个过程的说明部分为:

  const a=35,b=49;

  var c,d,e;

  procedure p;

var g;

对它的常量、变量和过程说明处理后,TABLE表中的信息如下:

  

NAME: a

NAME: b

NAME: c

NAME: d

NAME: e

NAME: p

KIND: CONSTANT

KIND: CONSTANT

KIND: VARIABLE

KIND: VARIABLE

KIND: VAEIABLE

KIND: PROCEDURE

VAL: 35

VAL: 49

LEVEL: LEV

LEVEL: LEV

LEVEL: LEV

LEVEL: LEV

 

 

ADR: DX

ADR: DX+1

ADR: DX+2

ADR: 

NAME: g

KIND: VARIABLE

        。

        。

        。

LEVEL: LEV+1

ADR: DX

     。

对于过程名的ADR域,是在过程体的目标代码生成后返填过程体的入口地址。

TABLE表的索引TX和层次单元LEV都是以BLOCK的参数形式出现,在主程序调用BLOCK时实参的值为0。每个过程的相对起始位置在BLOCK内置初值DX=3。

2.语句处理和代码生成   

对语句逐句分析,语法正确则生目标代码,当遇到标识符的引用则去查TABLE表,看是否有过正确的定义,若有则从表中取出相关的信息,供代码生成用。PL/0语言的代码生成是由过程GEN完成。GEN过程有三个参数,分别代表目标代码的功能码、层差、和位移量。生成的目标代码放在数组CODE中。CODE是一维数组,数组元素是结构体类型数据。

PL/0语言的目标指令是一种假想的栈式计算机的汇编语言,其格式如下:

 

fla

其中f代表功能码,l代表层次差,a代表位移量。

目标指令有8条:

① LIT:将常数放到运栈顶,a域为常数。

② LOD:将变量放到栈顶。a域为变量在所说明层中的相对位置,l为调用层与说明层的层差值。

③ STO:将栈顶的内容送到某变量单元中。a,l域的含义与LOD的相同。

④ CAL:调用过程的指令。a为被调用过程的目标程序的入中地址,l为层差。

⑤ INT:为被调用的过程(或主程序)在运行栈中开辟数据区。a域为开辟的个数。

⑥ JMP:无条件转移指令,a为转向地址。

⑦ JPC:条件转移指令,当栈顶的布尔值为非真时,转向a域的地址,否则顺序执行。

⑧ OPR:关系和算术运算。具体操作由a域给出。运算对象为栈顶和次顶的内容进行运算,结果存放在次顶。a域为0时是退出数据区。

三. 建立一个解释执行目标程序的函数

编译结束后,记录源程序中标识符的TABLE表已退出内存,内存中只剩下用于存放目标程序的CODE数组和运行时的数据区S。S是由解释程序定义的一维整型数组。解释执行时的数据空间S为栈式计算机的存储空间。遵循后进先出的规则,对每个过程(包括主程序)当被调用时,才分配数据空间,退出过程时,则所分配的数据空间被释放。

为解释程序定义四个寄存器:

1. I:指令寄存器,存放当前正在解释的一条目标指令。

2. P:程序地址寄存器,指向下一条要执行的目标指令(相当于CODE数组的下标)。

3. T:栈顶寄存器,每个过程运行时要为它分配数据区(或称为数据   段),该数据区分为两部分。

静态部分:包括变量存放区和三个联单元。

动态部分:作为临时工作单元和累加器用。需要时临时分配,用完立即释放。栈顶寄存器T指出了当前栈中最新分配的单元(T也是数组S的下标)。

4. B:基地址寄存器,指出每个过程被调用时,在数据区S中给出它分配的数据段起始地址,也称为基地址。每个过程被调用时,在栈顶分配三个联系单元。这三个单元的内容分别是:

SL:静态链,它是指向定义该过程的直接外过程运行时数据段的基地址。

DL:动态链,它是指向调用该过程前正在运行过程的数据段的基地址。

RA:返回地址,记录调用该过程时目标程序的断点,即当时的程序地址寄存器P的值。

        具体的过程调用和结束,对上述寄存器及三个联系单元的填写和恢复由下列目标指令完成。

1. INT  0  a

a:为局部量个数加3

2. OPR  0  0

恢复调用该过程前正在运行过程(或主程序)的数据段的基地址寄存器的值,恢复栈顶寄存器T的值,并将返回地址送到指令寄存器P中。

3. CAL  l  a

a为被调用过程的目标程序的入口,送入指令地址寄存器P中。

CAL指令还完成填写静态链,动态链,返回地址,给出被调用过程的基地址值,送入基址寄存器B中。

 

 例:一个Pl/0源程序及生成的目标代码:

const a=10;

var b,c;

procedure p;

begin

  c:=b+a

end;

2 int  0  3

3 lod  1  3

4 lit  0  10

5 opr  0  2

6 sto  1  4

7 opr  0  0

begin

  read(b);

  while b#0 do

    begin

      call  p;

      write(2*c);

      read(b)

     end

end .

8 int  0  5

9 opr  0  16

10 sto  0  3

11 lod  0  3

12 lit  0  0

13 opr  0  9

14 jpc  0  24

15 cal  0  2

16 lit   0  2

17 lod  0  4

18 opr  0  4

19 opr  0  14

20 opr  0  15

21 opr  0  16

22 sto  0  3 

23 jmp  0  11

24 opr  0  0

 下面是comp.h文件

 1 #pragma once 2 #include <iostream> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <string> 6 #include <algorithm> 7 #include <vector> 8  9 using namespace std;10 11 const static int maxIdLength = 10;12 const static int numLinkData = http://www.mamicode.com/3;13 14 enum Token15 {16     TMP, IDENT, NUM, PERIOD, CONSTSYM, COMMA, LPAREN, RPAREN, EQ, SEMICOLON, COLON,17     ASSIGN, VARSYM, PROCSYM, BEGINSYM, ENDSYM, ODDSYM, IFSYM, THENSYM,18     CALLSYM, WHILESYM, DOSYM, WRITESYM, READSYM, PLUS, MINUS, TIMES, SPLASH,19     NEQ, LSS, LE, GT, GE20 };21 enum SymbolType22 {23     CONST, VARIABLE, PROCEDURE24 };25 struct Symbol26 {27     int type;28     char name[maxIdLength + 1];29     int value;30     int level;31     int address;32 };33 enum34 {35     LIT, LOD, STO, CAL, INT, JMP, JPC, OPR36 };37 enum OPS38 {39     OP_RET = 0, OP_ADD = 2, OP_MINUS = 3, OP_TIMES = 4, OP_DIV = 5,40     OP_NEQ = 9, OP_EQ = 8, OP_LSS = 7, OP_LE = 6, OP_GT = 10, OP_GE = 11,41     OP_READ = 16, OP_WRITE = 1542 };43 struct PCode44 {45     int op;46     int l;47     int a;48     PCode(int op = -1, int l = 0, int a = 0)49     {50         this->op = op;51         this->l = l;52         this->a = a;53     }54 };55 56 extern const char CodeTable[8][4];57 58 vector<Symbol> symTable(1000);59 vector<PCode> code(1000);60 extern int sym, num;61 extern char id[maxIdLength + 1];62 extern int pc;63 extern int line;64 FILE *f;65 66 int findKeyword(const char *str);67 68 int getSym(FILE *in);69 70 inline int getSym()71 {72     return getSym(f);73 }74 75 int block(int level, int index);76 int constDeclaration(int index);77 int varDeclaration(int level, int index);78 int procDeclaration(int level, int index);79 int statement(int level, int index);80 int assignStatement(int level, int index);81 int ifStatement(int level, int index);82 int whileStatement(int level, int index);83 int callStatement(int level, int index);84 int readStatement(int level, int index);85 int writeStatement(int level, int index);86 int compositeStatement(int level, int index);87 int condition(int level, int index);88 int expression(int level, int index);89 int term(int level, int index);90 int factor(int level, int index);91 92 int find(int from, int to, const char *name);93 void printErr(const char *err);94 95 inline void genCode(int op, int l, int a);96 97 void interprete();

 

下面是 comp.cpp文件

  1 #include "comp.h"  2   3 const char CodeTable[8][4] = { "LIT", "LOD", "STO", "CAL", "INT", "JMP", "JPC", "OPR" };  4   5 int sym, num;  6 char id[maxIdLength + 1];  7 int pc = 1;  8 int line = 1;  9  10 void printErr(const char *err) 11 { 12     printf("Line %d:%s\n", line, err); 13     exit(1); 14 } 15  16 int findKeyword(const char *str) 17 { 18     if (!strcmp(str, "const")) 19         return CONSTSYM; 20     if (!strcmp(str, "var")) 21         return VARSYM; 22     if (!strcmp(str, "procedure")) 23         return PROCSYM; 24     if (!strcmp(str, "begin")) 25         return BEGINSYM; 26     if (!strcmp(str, "end")) 27         return ENDSYM; 28     if (!strcmp(str, "odd")) 29         return ODDSYM; 30     if (!strcmp(str, "if")) 31         return IFSYM; 32     if (!strcmp(str, "then")) 33         return THENSYM; 34     if (!strcmp(str, "call")) 35         return CALLSYM; 36     if (!strcmp(str, "while")) 37         return WHILESYM; 38     if (!strcmp(str, "do")) 39         return DOSYM; 40     if (!strcmp(str, "write")) 41         return WRITESYM; 42     if (!strcmp(str, "read")) 43         return READSYM; 44     return -1; 45 } 46  47 int getSym(FILE *in) 48 { 49     extern int sym, num; 50     extern char id[maxIdLength + 1]; 51     char buf[maxIdLength + 1]; 52     int pos = 0; 53     char ch =  ; 54     while (ch ==   || ch == \t || ch == \r || ch == \n) 55     { 56         if ((ch = fgetc(in)) == EOF) 57         { 58             return -1; 59         } 60         if (ch == \n) 61             line++; 62     } 63     if (isalpha(ch)) 64     { 65         while (isalpha(ch) || isdigit(ch)) 66         { 67             if (pos >= maxIdLength) 68                 return -1; 69             buf[pos++] = ch; 70             ch = fgetc(in); 71         } 72         ungetc(ch, in); 73         buf[pos++] = \0; 74         sym = findKeyword(buf); 75         if (sym<0) 76         { 77             sym = IDENT; 78             strcpy(id, buf); 79             return 0; 80         } 81     } 82     else if (isdigit(ch)) 83     { 84         while (isdigit(ch)) 85         { 86             if (pos >= maxIdLength) 87                 return -1; 88             buf[pos++] = ch; 89             ch = fgetc(in); 90         } 91         ungetc(ch, in); 92         buf[pos++] = \0; 93         sym = NUM; 94         num = atoi(buf); 95         return 0; 96     } 97     else if (ch == () 98         sym = LPAREN; 99     else if (ch == ))100         sym = RPAREN;101     else if (ch == =)102         sym = EQ;103     else if (ch == #)104         sym = NEQ;105     else if (ch == +)106         sym = PLUS;107     else if (ch == -)108         sym = MINUS;109     else if (ch == *)110         sym = TIMES;111     else if (ch == /)112         sym = SPLASH;113     else if (ch == ,)114         sym = COMMA;115     else if (ch == ;)116         sym = SEMICOLON;117     else if (ch == .)118         sym = PERIOD;119     else if (ch == :)120     {121         ch = fgetc(in);122         if (ch == =)123             sym = ASSIGN;124         else125         {126             ungetc(ch, in);127             sym = COLON;128         }129     }130     else if (ch == >)131     {132         ch = fgetc(in);133         if (ch == =)134             sym = GE;135         else136         {137             ungetc(ch, in);138             sym = GT;139         }140     }141     else if (ch == <)142     {143         ch = fgetc(in);144         if (ch == =)145             sym = LE;146         else147         {148             ungetc(ch, in);149             sym = LSS;150         }151     }152     else return -1;153     return 0;154 }155 156 int block(int level, int index)157 {158     int count = 0, dx = 0;159     int tpc = pc;160     genCode(JMP, 0, 0);161     bool flag = false;162     if (sym == CONSTSYM)163     {164         165         count = constDeclaration(index);166     }167     if (sym == VARSYM)168     {169         getSym();170         count += (dx = varDeclaration(level, index + count));171     }172     if (sym == PROCSYM)173     {174         flag = true;175         getSym();176         int px = count + index;177         count += procDeclaration(level + 1, px);178     }179     if (!flag)180         pc--;181     else182         code[tpc].a = pc;183     genCode(INT, 0, numLinkData + dx);184     statement(level, index + count);185     genCode(OPR, 0, OP_RET);186     return count;187 }188 189 int constDeclaration(int index)190 {191     Symbol sb;192     sb.type = CONST;193     int count = 0;194     do195     {196         getSym();197         if (sym != IDENT)198             printErr("identifier expected!");199         if (find(0, index + count, id) >= 0)200             printErr("duplicated identifier!");201         strcpy(sb.name, id);202         getSym();203         if (sym != EQ)204             printErr("a ‘=‘ expected!");205         getSym();206         if (sym != NUM)207             printErr("number expected!");208         sb.value =http://www.mamicode.com/ num;209         symTable[index + count++] = sb;210         getSym();211         if (!(sym == COMMA || sym == SEMICOLON))212             printErr("comma or semicolon expected!");213     } while (sym != SEMICOLON);214     getSym();215     return count;216 }217 218 int varDeclaration(int level, int index)219 {220     Symbol sb;221     sb.type = VARIABLE;222     sb.level = level;223     sb.address = 0;224     int count = 0;225     int tsym = sym;226     do227     {228         if (sym != IDENT)229             printErr("identifier expected!");230         if (find(0, index + count, id) >= 0)231             printErr("duplicated expected!");232         strcpy(sb.name, id);233         symTable[index + count++] = sb;234         sb.address++;235         getSym();236         if (!(sym == COMMA || sym == SEMICOLON))237             printErr("comma or semicolon expected!");238         tsym = sym;239         getSym();240     } while (tsym != SEMICOLON);241     return count;242 }243 244 int procDeclaration(int level, int index)245 {246     int count = 0;247     if (sym != IDENT)248         printErr("identifier expected!");249     Symbol sb;250     strcpy(sb.name, id);251     sb.type = PROCEDURE;252     sb.level = level - 1;253     sb.address = pc;254     symTable[index + count++] = sb;255     getSym();256     if (sym != SEMICOLON)257         printErr("semicolon expected!");258     getSym();259     block(level, index + count);260     if (sym != SEMICOLON)261         printErr("semicolon expected!");262     getSym();263     if (sym == PROCSYM)264     {265         getSym();266         count += procDeclaration(level, index + count);267     }268     return count + 1;269 }270 271 int find(int from, int to, const char *name)272 {273     for (int i = to - 1; i >= from; i--)274     if (!strcmp(name, symTable[i].name))275         return i;276     return -1;277 }278 279 void genCode(int op, int l, int a)280 {281     PCode pcode(op, l, a);282     code[pc++] = pcode;283 }284 285 int statement(int level, int index)286 {287     if (sym == IFSYM)288     {289         getSym();290         ifStatement(level, index);291     }292     else if (sym == WHILESYM)293     {294         getSym();295         whileStatement(level, index);296     }297     else if (sym == CALLSYM)298     {299         getSym();300         callStatement(level, index);301     }302     else if (sym == WRITESYM)303     {304         getSym();305         writeStatement(level, index);306     }307     else if (sym == READSYM)308     {309         getSym();310         readStatement(level, index);311     }312     else if (sym == BEGINSYM)313     {314         getSym();315         compositeStatement(level, index);316     }317     else if (sym == IDENT)318     {319         assignStatement(level, index);320     }321     else322         return 0;323     return 0;324 }325 326 int ifStatement(int level, int index)327 {328     condition(level, index);329     int cpc = pc;330     genCode(JPC, 0, 0);331     if (sym != THENSYM)332         printErr("then clause expected!");333     getSym();334     statement(level, index);335     code[cpc].a = pc;336     return 0;337 }338 339 int whileStatement(int level, int index)340 {341     int cpc = pc;342     condition(level, index);343     int jpc = pc;344     genCode(JPC, 0, 0);345     if (sym != DOSYM)346     {347         printErr("do expected!");348     }349     getSym();350     statement(level, index);351     genCode(JMP, 0, cpc);352     code[jpc].a = pc;353     return 0;354 }355 356 int callStatement(int level, int index)357 {358     if (sym != IDENT)359         printErr("syntax error!");360     int i = find(0, index, id);361     if (i<0)362         printErr("identifier not found!");363     if (symTable[i].type != PROCEDURE)364         printErr("syntax error!");365     genCode(CAL, level - symTable[i].level, symTable[i].address);366     getSym();367     return 0;368 }369 370 int readStatement(int level, int index)371 {372     if (sym != LPAREN)373         printErr(" ( expected");374     getSym();375     while (sym != RPAREN)376     {377         if (sym != IDENT)378             printErr("variable expected!");379         int i = find(0, index, id);380         if (i<0)381             printErr("identifier not found!");382         if (symTable[i].type != VARIABLE)383             printErr("variable expected!");384         genCode(OPR, 0, OP_READ);385         genCode(STO, level - symTable[i].level, symTable[i].address + numLinkData);386         getSym();387         if (sym != COMMA&&sym != RPAREN)388             printErr("syntax error!");389     }390     getSym();391     return 0;392 }393 394 int writeStatement(int level, int index)395 {396     if (sym != LPAREN)397         printErr(" ( expected");398     getSym();399     while (sym != RPAREN)400     {401         expression(level, index);402         genCode(OPR, 0, OP_WRITE);403         if (sym != COMMA&&sym != RPAREN)404             printErr("syntax error!");405     }406     getSym();407     return 0;408 }409 410 int compositeStatement(int level, int index)411 {412     statement(level, index);413     while (sym == SEMICOLON)414     {415         getSym();416         statement(level, index);417     }418     if (sym != ENDSYM)419         printErr("end expected!");420     getSym();421     return 0;422 }423 424 int assignStatement(int level, int index)425 {426     int i = find(0, index, id);427     if (i<0)428     {429         printErr("Variable not found!");430     }431     if (symTable[i].type == CONST)432         printErr("constant can‘t be a r-value!");433     getSym();434     if (sym != ASSIGN)435     {436         printErr(":= expected!");437     }438     getSym();439     expression(level, index);440     genCode(STO, level - symTable[i].level, numLinkData + symTable[i].address);441     return 0;442 }443 444 int condition(int level, int index)445 {446     if (sym == ODDSYM)447     {448         getSym();449         expression(level, index);450         genCode(LIT, 0, 0);451         genCode(OPR, 0, OP_NEQ);452     }453     else454     {455         expression(level, index);456         int op = sym;457         if (sym != NEQ&&sym != EQ&&sym != LSS&&sym != LE&&sym != GT&&sym != GE)458             printErr("error!");459         getSym();460         expression(level, index);461         switch (op)462         {463         case NEQ:464             genCode(OPR, 0, OP_NEQ); break;465         case EQ:466             genCode(OPR, 0, OP_EQ); break;467         case LSS:468             genCode(OPR, 0, OP_LSS); break;469         case LE:470             genCode(OPR, 0, OP_LE); break;471         case GT:472             genCode(OPR, 0, OP_GT); break;473         case GE:474             genCode(OPR, 0, OP_GE); break;475         }476     }477     return 0;478 }479 480 int expression(int level, int index)481 {482 483     int op = sym;484     if (sym == PLUS || sym == MINUS)485     {486         getSym();487     }488     factor(level, index);489     if (op == MINUS)490     {491         genCode(LIT, 0, 0);492         genCode(OPR, 0, OP_MINUS);493     }494 do{495     op = sym;496     if (sym == PLUS || sym == MINUS)497     {498         getSym();499         factor(level, index);500         if (op == PLUS)501             genCode(OPR, 0, OP_ADD);502         else503             genCode(OPR, 0, OP_MINUS);504     }505 } while (sym == PLUS || sym == MINUS);506     return 0;507 }508 509 int factor(int level, int index)510 {511     512         term(level, index);513         int op = sym;514         if (op != TIMES&&op != SPLASH)515             return 0;516     do{517         getSym();518         term(level, index);519         if (op == TIMES)520             genCode(OPR, 0, 4);521         else522             genCode(OPR, 0, OP_DIV);523         op = sym;524     } while (sym == TIMES || sym == SPLASH);525     return 0;526 }527 528 int term(int level, int index)529 {530     if (sym == IDENT)531     {532         int i = find(0, index, id);533         if (i<0)534         {535             printErr("Identifier not found!");536         }537         if (symTable[i].type == CONST)538             genCode(LIT, 0, symTable[i].value);539         else if (symTable[i].type == VARIABLE)540             genCode(LOD, level - symTable[i].level, numLinkData + symTable[i].address);541         else542         {543             printErr("error!");544         }545         getSym();546     }547     else if (sym == NUM)548     {549         genCode(LIT, 0, num);550         getSym();551     }552     else if(sym==LPAREN)553     {554         getSym();555         expression(level, index);556         if (sym != RPAREN)557             printf(") expected");558         getSym();559     }560     else{561         printErr("error!");562     }563     return 0;564 }565 566 void interprete()567 {568     const static int ret_addr = 0, dynamic_link = 1, static_link = 2;569     PCode ir;570     int ip = 1, sp = 0, bp = 0;571     int stack[1000] = { 0 };572     int sp_stack[10];573     int sp_top = 0;574     while (ip<pc)575     {576         ir = code[ip++];577         switch (ir.op)578         {579         case LIT:580             stack[sp++] = ir.a; break;581         case LOD:582         {583                     if (ir.l == 0)584                         stack[sp++] = stack[bp + ir.a];585                     else586                     {587                         int outer_bp = stack[bp + static_link];588                         while (--ir.l)589                             outer_bp = stack[outer_bp + static_link];590                         stack[sp++] = stack[outer_bp + ir.a];591                     }592                     break;593         }594         case STO:595         {596                     if (ir.l == 0)597                         stack[bp + ir.a] = stack[sp - 1];598                     else599                     {600                         int outer_bp = stack[bp + static_link];601                         while (--ir.l)602                             outer_bp = stack[outer_bp + static_link];603                         stack[outer_bp + ir.a] = stack[sp - 1];604                     }605                     break;606         }607         case CAL:608         {609                     stack[sp + ret_addr] = ip;610                     stack[sp + dynamic_link] = bp;611                     stack[sp + static_link] = bp;612                     ip = ir.a;613                     bp = sp;614                     break;615         }616         case INT:617         {618                     sp_stack[sp_top++] = sp;619                     sp += ir.a;620                     break;621         }622         case JMP:623         {624                     ip = ir.a;625                     break;626         }627         case JPC:628         {629                     if (stack[sp - 1] == 0)630                         ip = ir.a;631                     break;632         }633         case OPR:634         {635                     switch (ir.a)636                     {637                     case OP_RET:638                     {639                                    ip = stack[bp + ret_addr];640                                    bp = stack[bp + dynamic_link];641                                    sp = sp_stack[--sp_top];642                                    if (sp_top <= 0)643                                    {644                                        printf("program exited normally!\n");645                                        return;646                                    }647                                    break;648                     }649                     case OP_ADD:650                     {651                                    stack[sp - 2] = stack[sp - 1] + stack[sp - 2];652                                    sp--;653                                    break;654                     }655                     case OP_MINUS:656                     {657                                      stack[sp - 2] = stack[sp - 1] - stack[sp - 2];658                                      sp--;659                                      break;660                     }661                     case OP_TIMES:662                     {663                                      stack[sp - 2] = stack[sp - 1] * stack[sp - 2];664                                      sp--;665                                      break;666                     }667                     case OP_DIV:668                     {669                                    stack[sp - 2] = stack[sp - 2] / stack[sp - 1];670                                    sp--;671                                    break;672                     }673                     case OP_NEQ:674                     {675                                    stack[sp - 2] = (stack[sp - 2] != stack[sp - 1]) ? 1 : 0;676                                    sp--;677                                    break;678                     }679                     case OP_EQ:680                     {681                                   stack[sp - 2] = (stack[sp - 2] == stack[sp - 1]) ? 1 : 0;682                                   sp--;683                                   break;684                     }685                     case OP_LSS:686                     {687                                    stack[sp - 2] = (stack[sp - 2]<stack[sp - 1]) ? 1 : 0;688                                    sp--;689                                    break;690                     }691                     case OP_LE:692                     {693                                   stack[sp - 2] = (stack[sp - 2] <= stack[sp - 1]) ? 1 : 0;694                                   sp--;695                                   break;696                     }697                     case OP_GT:698                     {699                                   stack[sp - 2] = (stack[sp - 2]>stack[sp - 1]) ? 1 : 0;700                                   sp--;701                                   break;702                     }703                     case OP_GE:704                     {705                                   stack[sp - 2] = (stack[sp - 2] >= stack[sp - 1]) ? 1 : 0;706                                   sp--;707                                   break;708                     }709                     case OP_READ:710                     {711                                     cout << "Please input a number:" << endl;712                                     cin >> stack[sp++];713                                     break;714                     }715                     case OP_WRITE:716                     {717                                      cout << stack[sp - 1] << endl;718                                      break;719                     }720                     default:721                     {722                                printf("Unexpected operation!\n"); return;723                     }724                     }725                     break;726         }727         default:728             printf("Unexpected instruction!\n"); return;729         }730     }731 }732 733 int main(int argc, char *argv[])734 {735     f = fopen("test.txt","r");736     getSym();737     block(0, 0);738     for (int i = 1; i<pc; i++)739     {740         cout << i << ":\t" << CodeTable[code[i].op] << " " << code[i].l << " " << code[i].a << endl;741     }742     interprete();743     return 0;744 }

下面是test.txt文件

const a=10;var b,c;procedure p;begin  c:=b+aend;begin  read(b);  while b#0 do    begin      call  p;      write(2*c);      read(b)     endend

 

PL/0编译程序