• 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
  • 相关阅读:
    Thinkphp的 is null 查询条件是什么,以及exp表达式如何使用
    thinkphp5多文件上传如何实现
    如何动态改变audio的播放的src
    js插件---10个免费开源的JS音乐播放器插件
    html5页面怎么播放音频和视频
    Thinkphp5图片上传正常,音频和视频上传失败的原因及解决
    leetcode
    HTML5 画一张图
    Linux内核和根文件系统引导加载程序
    [dp] hdu 4472 Count
  • 原文地址:https://www.cnblogs.com/sdxk/p/4134697.html
Copyright © 2020-2023  润新知