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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM