首页 > 代码库 > 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要完成的任务:
- 滤掉单词间的空格。
- 识别关键字,用查关键字表的方法识别。当单词是关键字时,将对应的类别放在SYM中。如IF的类别为IFSYM,THEN的类别为THENSYM。
- 识别标识符,标识符的类别为IDENT,IDRNT放在SYM中,标识符本身的值放在ID中。关键字或标识符的最大长度是10。
- 拼数,将数的类别NUMBER放在SYM中,数本身的值放在NUM中。
- 拼由两个字符组成的运算符,如:>=、<=等等,识别后将类别存放在SYM中。
- 打印源程序,边读入字符边打印。
由于一个单词是由一个或多个字符组成的,所以在词法分析程序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语言的目标指令是一种假想的栈式计算机的汇编语言,其格式如下:
f | l | a |
其中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编译程序