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语言的目标指令是一种假想的栈式计算机的汇编语言,其格式如下:

 

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 = 3;
13 
14 enum Token
15 {
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, GE
20 };
21 enum SymbolType
22 {
23     CONST, VARIABLE, PROCEDURE
24 };
25 struct Symbol
26 {
27     int type;
28     char name[maxIdLength + 1];
29     int value;
30     int level;
31     int address;
32 };
33 enum
34 {
35     LIT, LOD, STO, CAL, INT, JMP, JPC, OPR
36 };
37 enum OPS
38 {
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 = 15
42 };
43 struct PCode
44 {
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
", 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 == '	' || ch == '
' || ch == '
')
 55     {
 56         if ((ch = fgetc(in)) == EOF)
 57         {
 58             return -1;
 59         }
 60         if (ch == '
')
 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++] = '';
 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++] = '';
 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         else
125         {
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         else
136         {
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         else
147         {
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     else
182         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     do
195     {
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 = 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     do
227     {
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     else
322         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     else
454     {
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         else
503             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         else
522             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         else
542         {
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                     else
586                     {
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                     else
599                     {
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!
");
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!
"); return;
723                     }
724                     }
725                     break;
726         }
727         default:
728             printf("Unexpected instruction!
"); 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 << ":	" << 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+a
end;
begin
  read(b);
  while b#0 do
    begin
      call  p;
      write(2*c);
      read(b)
     end
end
原文地址:https://www.cnblogs.com/sdxk/p/4134697.html