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\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         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!\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+a
end;
begin
  read(b);
  while b#0 do
    begin
      call  p;
      write(2*c);
      read(b)
     end
end
时间: 2024-10-14 16:31:57

PL/0编译程序的相关文章

PL/0语言编译程序设计1(C语言)

本文地址:http://www.cnblogs.com/archimedes/p/pl0-compiler1.html,转载请注明源地址. PL/0简介 以下内容摘自维基: PL/0,is similar to but much simpler than the general-purpose programming language Pascal, intended as an educational programming language. It serves as an example

PL/0语言编译器的设计与实现

一.设计任务 1.1程序实现要求 PL/0语言可以看成PASCAL语言的子集,它的编译程序是一个编译解释执行系统.PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关. PL/0的编译程序和目标程序的解释执行程序都是用JAVA语言书写的,因此PL/0语言可在配备JDK的任何机器上实现. 其编译过程采用一趟扫描方式,以语法分析程序为核心,词法分析和代码生成程序都作为一个独立的过程,当语法分析需要读单词时就调用词法分析程序,而当语法分析正确需要生成相应的目标代码时,则调用代码生成程序. 用

学习使用的PL/0编译器增强版PL/0plusplusCompiler(二)加入支持命令行参数

每次程序运行后输入源码文件名不是很好,于是做了支持命令行参数的改进.大体思路:在main函数入口加入命令行参数,进入main后判断文件名是否为空,为空就退出,否则就继续编译. 在main的括号中加入 int argc, char** argv 在main第一行加入 /*如果没有在命令行中输入文件名会提示输入源码文件名*/ if(argv[1]==NULL){ printf("请输入源程序!\n"); return; } 把这两行注释掉 // printf("Input pl/

编译原理 实验1 PL/0语言词法分析

PL/0语言词法分析 一. 实验目的 通过完成词法分析程序,了解词法分析的过程.编制一个读单词程序,对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,即基本保留字.标识符.常数.运算符.界符五大类. 二. 实验环境 操作系统:window xp 编写环境:visual c++ .c-free.turbo c 编写语言:c语言 分析语言:PL/0 三. 实验内容 对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,其词法描述如下: (1) 关键字:

PL/0与Pascal-S编译器程序详细注释

学校编译课的作业之一,要求阅读两个较为简单的编译器的代码并做注释, 个人感觉是一次挺有意义的锻炼, 将自己的心得分享出来与一同在进步的同学们分享. 今后有时间再做进一步的更新和总结,其中可能有不少错误,也请各位大佬不吝指正. 代码可以通过使用Lazarus等pascal环境执行. 源码仓库:https://github.com/luxiaodou/PL-0-and-Pascal-S-complier-trans PL0编译器源码 PL0语言是Pascal的一个子集,编译器也比较简单,逐行注释 p

PL/0语言词法分析器

前言:关于词法分析的基础知识的介绍可以看一下这篇博客,我再累述估计也不会有这篇讲的清楚QAQ. https://www.cnblogs.com/yanlingyin/archive/2012/04/17/2451717.html    默认大家已经对词法分析有了基本的了解了. 一:下面讨论PL/0语言的词法分析器的单词结构 1.关键字 关键字(共11个):空格分隔列表如下 begin  end  if  then  while  do  const  var  call  procedure  

PL/0 词法分析器

1 #include<stdio.h> 2 #include <ctype.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 typedef enum SymEnum 7 { 8 Identifier=0, //标识符 9 Const=1, //常数 10 Key=2, //关键字 11 Operator=3, //运算符 12 Delimiter=4 //界符 13 } SymEnum; 14 15 ch

学了编译原理能否用 Java 写一个编译器或解释器?

16 个回答 默认排序? RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和解释器.其实用什么语言来实现编译器并不是最重要的部分(虽然Java也不是实现编译器最方便的语言),最初用啥语言都可以. 我在大学的时候,我们的软件工程和计算机科学的编译原理课的作业好像都是可以用Java来写的.反正我印象中我给这两门课写的作业都是用的Java. ===================

0/1背包问题与动态规划

假设背包容量M=9:(P1,P2,P3,P4,P5,P6)=(15,18,40,56,30,10);(W1,W2,W3,W4,W,5,W6)=(3,2,5,8,5,1). 算法思想 变量解释: F(i):Si中第一对序偶在数组中的位置(下标) l, h:Si-1的第一对序偶和最后一对序偶在数组中的位置,即F(i-1)和F(i)-1. k: Si-1中当前要加入Si的序偶的位置. u: 在Si-1能够产生Si1序偶的最后一个位置,即对于u+1<=v<= h的序偶(Pv,Wv),有Wv+wi>