PL/0编译程序
Pl/0语言文法的BNF表示:
〈程序〉→〈分程序>.
〈分程序〉→ [<常量说明部分>][<变量说明部分>][<过程说明部分>]〈语句〉
<常量说明部分> → CONST<常量定义>{ ,<常量定义>};
<常量定义> → <标识符>=<无符号整数>
<无符号整数> → <数字>{<数字>}
<变量说明部分> → VAR<标识符>{ ,<标识符>};
<标识符> → <字母>{<字母>|<数字>}
<过和说明部分> → <过程首部><分程序>;{<过程说明部分>}
<过程首部> → procedure<标识符>;
<语句> → <赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|<空>
<赋值语句> → <标识符>:=<表达式>
<复合语句> → begin<语句>{ ;<语句>}<end>
<条件> → <表达式><关系运算符><表达式>|ood<表达式>
<表达式> → [+|-]<项>{<加减运算符><项>}
<项> → <因子>{<乘除运算符><因子>}
<因子> → <标识符>|<无符号整数>|(<表达式>)
<加减运符> → +|-
<乘除运算符> → *|/
<关系运算符> → =|#|<|<=|>|>=
<条件语句> → if<条件>then<语句>
<过程调用语句> → call<标识符>
<当型循环语句> → while<条件>do<语句>
<读语句> → read(<标识符>{ ,<标识符>})
<写语句> → write(<标识符>{,<标识符>})
<字母> → a|b|c…x|y|z
<数字> → 0|1|2…7|8|9
一. 为PL/0语言建立一个词法分程序GETSYM(函数)
把关键字、算符、界符称为语言固有的单词,标识符、常量称为用户自定义的单词。为此设置三个全程量:SYM,ID,NUM 。
SYM:存放每个单词的类别,为内部编码的表示形式。
ID:存放用户所定义的标识符的值,即标识符字符串的机内表示。
NUM:存放用户定义的数。
GETSYM要完成的任务:
- 滤掉单词间的空格。
- 识别关键字,用查关键字表的方法识别。当单词是关键字时,将对应的类别放在SYM中。如IF的类别为IFSYM,THEN的类别为THENSYM。
- 识别标识符,标识符的类别为IDENT,IDRNT放在SYM中,标识符本身的值放在ID中。关键字或标识符的最大长度是10。
- 拼数,将数的类别NUMBER放在SYM中,数本身的值放在NUM中。
- 拼由两个字符组成的运算符,如:>=、<=等等,识别后将类别存放在SYM中。
- 打印源程序,边读入字符边打印。
由于一个单词是由一个或多个字符组成的,所以在词法分析程序GETSYM中定义一个读字符过程GETCH。
二. 为PL/0语言建立一个语法分析程序BLOCK(函数)
PL/0编译程序采用一遍扫描的方法,所以语法分析和代码生成都有在BLOCK中完成。BLOCK的工作分为两步:
a) 说明部分的处理
说明部分的处理任务就是对每个过程(包括主程序,可以看成是一个主过程)的说明对象造名字表。填写所在层次(主程序是0层,在主程序中定义的过程是1层,随着嵌套的深度增加而层次数增大。PL/0最多允许3层),标识符的属性和分配的相对地址等。标识符的属性不同则填写的信息不同。
所造的表放在全程量一维数组TABLE中,TX为指针,数组元素为结构体类型数据。LEV给出层次,DX给出每层的局部量的相对地址,每说明完一个变量后DX加1。
例如:一个过程的说明部分为:
const a=35,b=49;
var c,d,e;
procedure p;
var g;
对它的常量、变量和过程说明处理后,TABLE表中的信息如下:
NAME: a NAME: b NAME: c NAME: d NAME: e NAME: p |
KIND: CONSTANT KIND: CONSTANT KIND: VARIABLE KIND: VARIABLE KIND: VAEIABLE KIND: PROCEDURE |
VAL: 35 VAL: 49 LEVEL: LEV LEVEL: LEV LEVEL: LEV LEVEL: LEV |
ADR: DX ADR: DX+1 ADR: DX+2 ADR: |
NAME: g 。 。 。 |
KIND: VARIABLE 。 。 。 |
LEVEL: LEV+1 。 。 。 |
ADR: DX 。 。 。 |
对于过程名的ADR域,是在过程体的目标代码生成后返填过程体的入口地址。
TABLE表的索引TX和层次单元LEV都是以BLOCK的参数形式出现,在主程序调用BLOCK时实参的值为0。每个过程的相对起始位置在BLOCK内置初值DX=3。
2.语句处理和代码生成
对语句逐句分析,语法正确则生目标代码,当遇到标识符的引用则去查TABLE表,看是否有过正确的定义,若有则从表中取出相关的信息,供代码生成用。PL/0语言的代码生成是由过程GEN完成。GEN过程有三个参数,分别代表目标代码的功能码、层差、和位移量。生成的目标代码放在数组CODE中。CODE是一维数组,数组元素是结构体类型数据。
PL/0语言的目标指令是一种假想的栈式计算机的汇编语言,其格式如下:
f | l | a |
其中f代表功能码,l代表层次差,a代表位移量。
目标指令有8条:
① LIT:将常数放到运栈顶,a域为常数。
② LOD:将变量放到栈顶。a域为变量在所说明层中的相对位置,l为调用层与说明层的层差值。
③ STO:将栈顶的内容送到某变量单元中。a,l域的含义与LOD的相同。
④ CAL:调用过程的指令。a为被调用过程的目标程序的入中地址,l为层差。
⑤ INT:为被调用的过程(或主程序)在运行栈中开辟数据区。a域为开辟的个数。
⑥ JMP:无条件转移指令,a为转向地址。
⑦ JPC:条件转移指令,当栈顶的布尔值为非真时,转向a域的地址,否则顺序执行。
⑧ OPR:关系和算术运算。具体操作由a域给出。运算对象为栈顶和次顶的内容进行运算,结果存放在次顶。a域为0时是退出数据区。
三. 建立一个解释执行目标程序的函数
编译结束后,记录源程序中标识符的TABLE表已退出内存,内存中只剩下用于存放目标程序的CODE数组和运行时的数据区S。S是由解释程序定义的一维整型数组。解释执行时的数据空间S为栈式计算机的存储空间。遵循后进先出的规则,对每个过程(包括主程序)当被调用时,才分配数据空间,退出过程时,则所分配的数据空间被释放。
为解释程序定义四个寄存器:
1. I:指令寄存器,存放当前正在解释的一条目标指令。
2. P:程序地址寄存器,指向下一条要执行的目标指令(相当于CODE数组的下标)。
3. T:栈顶寄存器,每个过程运行时要为它分配数据区(或称为数据 段),该数据区分为两部分。
静态部分:包括变量存放区和三个联单元。
动态部分:作为临时工作单元和累加器用。需要时临时分配,用完立即释放。栈顶寄存器T指出了当前栈中最新分配的单元(T也是数组S的下标)。
4. B:基地址寄存器,指出每个过程被调用时,在数据区S中给出它分配的数据段起始地址,也称为基地址。每个过程被调用时,在栈顶分配三个联系单元。这三个单元的内容分别是:
SL:静态链,它是指向定义该过程的直接外过程运行时数据段的基地址。
DL:动态链,它是指向调用该过程前正在运行过程的数据段的基地址。
RA:返回地址,记录调用该过程时目标程序的断点,即当时的程序地址寄存器P的值。
具体的过程调用和结束,对上述寄存器及三个联系单元的填写和恢复由下列目标指令完成。
1. INT 0 a
a:为局部量个数加3
2. OPR 0 0
恢复调用该过程前正在运行过程(或主程序)的数据段的基地址寄存器的值,恢复栈顶寄存器T的值,并将返回地址送到指令寄存器P中。
3. CAL l a
a为被调用过程的目标程序的入口,送入指令地址寄存器P中。
CAL指令还完成填写静态链,动态链,返回地址,给出被调用过程的基地址值,送入基址寄存器B中。
例:一个Pl/0源程序及生成的目标代码:
const a=10;
var b,c;
procedure p;
begin
c:=b+a
end;
2 int 0 3
3 lod 1 3
4 lit 0 10
5 opr 0 2
6 sto 1 4
7 opr 0 0
begin
read(b);
while b#0 do
begin
call p;
write(2*c);
read(b)
end
end .
8 int 0 5
9 opr 0 16
10 sto 0 3
11 lod 0 3
12 lit 0 0
13 opr 0 9
14 jpc 0 24
15 cal 0 2
16 lit 0 2
17 lod 0 4
18 opr 0 4
19 opr 0 14
20 opr 0 15
21 opr 0 16
22 sto 0 3
23 jmp 0 11
24 opr 0 0
下面是comp.h文件
#pragma once
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <vector> using namespace std; const static int maxIdLength = ;
const static int numLinkData = ; enum Token
{
TMP, IDENT, NUM, PERIOD, CONSTSYM, COMMA, LPAREN, RPAREN, EQ, SEMICOLON, COLON,
ASSIGN, VARSYM, PROCSYM, BEGINSYM, ENDSYM, ODDSYM, IFSYM, THENSYM,
CALLSYM, WHILESYM, DOSYM, WRITESYM, READSYM, PLUS, MINUS, TIMES, SPLASH,
NEQ, LSS, LE, GT, GE
};
enum SymbolType
{
CONST, VARIABLE, PROCEDURE
};
struct Symbol
{
int type;
char name[maxIdLength + ];
int value;
int level;
int address;
};
enum
{
LIT, LOD, STO, CAL, INT, JMP, JPC, OPR
};
enum OPS
{
OP_RET = , OP_ADD = , OP_MINUS = , OP_TIMES = , OP_DIV = ,
OP_NEQ = , OP_EQ = , OP_LSS = , OP_LE = , OP_GT = , OP_GE = ,
OP_READ = , OP_WRITE =
};
struct PCode
{
int op;
int l;
int a;
PCode(int op = -, int l = , int a = )
{
this->op = op;
this->l = l;
this->a = a;
}
}; extern const char CodeTable[][]; vector<Symbol> symTable();
vector<PCode> code();
extern int sym, num;
extern char id[maxIdLength + ];
extern int pc;
extern int line;
FILE *f; int findKeyword(const char *str); int getSym(FILE *in); inline int getSym()
{
return getSym(f);
} int block(int level, int index);
int constDeclaration(int index);
int varDeclaration(int level, int index);
int procDeclaration(int level, int index);
int statement(int level, int index);
int assignStatement(int level, int index);
int ifStatement(int level, int index);
int whileStatement(int level, int index);
int callStatement(int level, int index);
int readStatement(int level, int index);
int writeStatement(int level, int index);
int compositeStatement(int level, int index);
int condition(int level, int index);
int expression(int level, int index);
int term(int level, int index);
int factor(int level, int index); int find(int from, int to, const char *name);
void printErr(const char *err); inline void genCode(int op, int l, int a); void interprete();
下面是 comp.cpp文件
#include "comp.h" const char CodeTable[][] = { "LIT", "LOD", "STO", "CAL", "INT", "JMP", "JPC", "OPR" }; int sym, num;
char id[maxIdLength + ];
int pc = ;
int line = ; void printErr(const char *err)
{
printf("Line %d:%s\n", line, err);
exit();
} int findKeyword(const char *str)
{
if (!strcmp(str, "const"))
return CONSTSYM;
if (!strcmp(str, "var"))
return VARSYM;
if (!strcmp(str, "procedure"))
return PROCSYM;
if (!strcmp(str, "begin"))
return BEGINSYM;
if (!strcmp(str, "end"))
return ENDSYM;
if (!strcmp(str, "odd"))
return ODDSYM;
if (!strcmp(str, "if"))
return IFSYM;
if (!strcmp(str, "then"))
return THENSYM;
if (!strcmp(str, "call"))
return CALLSYM;
if (!strcmp(str, "while"))
return WHILESYM;
if (!strcmp(str, "do"))
return DOSYM;
if (!strcmp(str, "write"))
return WRITESYM;
if (!strcmp(str, "read"))
return READSYM;
return -;
} int getSym(FILE *in)
{
extern int sym, num;
extern char id[maxIdLength + ];
char buf[maxIdLength + ];
int pos = ;
char ch = ' ';
while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
{
if ((ch = fgetc(in)) == EOF)
{
return -;
}
if (ch == '\n')
line++;
}
if (isalpha(ch))
{
while (isalpha(ch) || isdigit(ch))
{
if (pos >= maxIdLength)
return -;
buf[pos++] = ch;
ch = fgetc(in);
}
ungetc(ch, in);
buf[pos++] = '\0';
sym = findKeyword(buf);
if (sym<)
{
sym = IDENT;
strcpy(id, buf);
return ;
}
}
else if (isdigit(ch))
{
while (isdigit(ch))
{
if (pos >= maxIdLength)
return -;
buf[pos++] = ch;
ch = fgetc(in);
}
ungetc(ch, in);
buf[pos++] = '\0';
sym = NUM;
num = atoi(buf);
return ;
}
else if (ch == '(')
sym = LPAREN;
else if (ch == ')')
sym = RPAREN;
else if (ch == '=')
sym = EQ;
else if (ch == '#')
sym = NEQ;
else if (ch == '+')
sym = PLUS;
else if (ch == '-')
sym = MINUS;
else if (ch == '*')
sym = TIMES;
else if (ch == '/')
sym = SPLASH;
else if (ch == ',')
sym = COMMA;
else if (ch == ';')
sym = SEMICOLON;
else if (ch == '.')
sym = PERIOD;
else if (ch == ':')
{
ch = fgetc(in);
if (ch == '=')
sym = ASSIGN;
else
{
ungetc(ch, in);
sym = COLON;
}
}
else if (ch == '>')
{
ch = fgetc(in);
if (ch == '=')
sym = GE;
else
{
ungetc(ch, in);
sym = GT;
}
}
else if (ch == '<')
{
ch = fgetc(in);
if (ch == '=')
sym = LE;
else
{
ungetc(ch, in);
sym = LSS;
}
}
else return -;
return ;
} int block(int level, int index)
{
int count = , dx = ;
int tpc = pc;
genCode(JMP, , );
bool flag = false;
if (sym == CONSTSYM)
{ count = constDeclaration(index);
}
if (sym == VARSYM)
{
getSym();
count += (dx = varDeclaration(level, index + count));
}
if (sym == PROCSYM)
{
flag = true;
getSym();
int px = count + index;
count += procDeclaration(level + , px);
}
if (!flag)
pc--;
else
code[tpc].a = pc;
genCode(INT, , numLinkData + dx);
statement(level, index + count);
genCode(OPR, , OP_RET);
return count;
} int constDeclaration(int index)
{
Symbol sb;
sb.type = CONST;
int count = ;
do
{
getSym();
if (sym != IDENT)
printErr("identifier expected!");
if (find(, index + count, id) >= )
printErr("duplicated identifier!");
strcpy(sb.name, id);
getSym();
if (sym != EQ)
printErr("a '=' expected!");
getSym();
if (sym != NUM)
printErr("number expected!");
sb.value = num;
symTable[index + count++] = sb;
getSym();
if (!(sym == COMMA || sym == SEMICOLON))
printErr("comma or semicolon expected!");
} while (sym != SEMICOLON);
getSym();
return count;
} int varDeclaration(int level, int index)
{
Symbol sb;
sb.type = VARIABLE;
sb.level = level;
sb.address = ;
int count = ;
int tsym = sym;
do
{
if (sym != IDENT)
printErr("identifier expected!");
if (find(, index + count, id) >= )
printErr("duplicated expected!");
strcpy(sb.name, id);
symTable[index + count++] = sb;
sb.address++;
getSym();
if (!(sym == COMMA || sym == SEMICOLON))
printErr("comma or semicolon expected!");
tsym = sym;
getSym();
} while (tsym != SEMICOLON);
return count;
} int procDeclaration(int level, int index)
{
int count = ;
if (sym != IDENT)
printErr("identifier expected!");
Symbol sb;
strcpy(sb.name, id);
sb.type = PROCEDURE;
sb.level = level - ;
sb.address = pc;
symTable[index + count++] = sb;
getSym();
if (sym != SEMICOLON)
printErr("semicolon expected!");
getSym();
block(level, index + count);
if (sym != SEMICOLON)
printErr("semicolon expected!");
getSym();
if (sym == PROCSYM)
{
getSym();
count += procDeclaration(level, index + count);
}
return count + ;
} int find(int from, int to, const char *name)
{
for (int i = to - ; i >= from; i--)
if (!strcmp(name, symTable[i].name))
return i;
return -;
} void genCode(int op, int l, int a)
{
PCode pcode(op, l, a);
code[pc++] = pcode;
} int statement(int level, int index)
{
if (sym == IFSYM)
{
getSym();
ifStatement(level, index);
}
else if (sym == WHILESYM)
{
getSym();
whileStatement(level, index);
}
else if (sym == CALLSYM)
{
getSym();
callStatement(level, index);
}
else if (sym == WRITESYM)
{
getSym();
writeStatement(level, index);
}
else if (sym == READSYM)
{
getSym();
readStatement(level, index);
}
else if (sym == BEGINSYM)
{
getSym();
compositeStatement(level, index);
}
else if (sym == IDENT)
{
assignStatement(level, index);
}
else
return ;
return ;
} int ifStatement(int level, int index)
{
condition(level, index);
int cpc = pc;
genCode(JPC, , );
if (sym != THENSYM)
printErr("then clause expected!");
getSym();
statement(level, index);
code[cpc].a = pc;
return ;
} int whileStatement(int level, int index)
{
int cpc = pc;
condition(level, index);
int jpc = pc;
genCode(JPC, , );
if (sym != DOSYM)
{
printErr("do expected!");
}
getSym();
statement(level, index);
genCode(JMP, , cpc);
code[jpc].a = pc;
return ;
} int callStatement(int level, int index)
{
if (sym != IDENT)
printErr("syntax error!");
int i = find(, index, id);
if (i<)
printErr("identifier not found!");
if (symTable[i].type != PROCEDURE)
printErr("syntax error!");
genCode(CAL, level - symTable[i].level, symTable[i].address);
getSym();
return ;
} int readStatement(int level, int index)
{
if (sym != LPAREN)
printErr(" ( expected");
getSym();
while (sym != RPAREN)
{
if (sym != IDENT)
printErr("variable expected!");
int i = find(, index, id);
if (i<)
printErr("identifier not found!");
if (symTable[i].type != VARIABLE)
printErr("variable expected!");
genCode(OPR, , OP_READ);
genCode(STO, level - symTable[i].level, symTable[i].address + numLinkData);
getSym();
if (sym != COMMA&&sym != RPAREN)
printErr("syntax error!");
}
getSym();
return ;
} int writeStatement(int level, int index)
{
if (sym != LPAREN)
printErr(" ( expected");
getSym();
while (sym != RPAREN)
{
expression(level, index);
genCode(OPR, , OP_WRITE);
if (sym != COMMA&&sym != RPAREN)
printErr("syntax error!");
}
getSym();
return ;
} int compositeStatement(int level, int index)
{
statement(level, index);
while (sym == SEMICOLON)
{
getSym();
statement(level, index);
}
if (sym != ENDSYM)
printErr("end expected!");
getSym();
return ;
} int assignStatement(int level, int index)
{
int i = find(, index, id);
if (i<)
{
printErr("Variable not found!");
}
if (symTable[i].type == CONST)
printErr("constant can't be a r-value!");
getSym();
if (sym != ASSIGN)
{
printErr(":= expected!");
}
getSym();
expression(level, index);
genCode(STO, level - symTable[i].level, numLinkData + symTable[i].address);
return ;
} int condition(int level, int index)
{
if (sym == ODDSYM)
{
getSym();
expression(level, index);
genCode(LIT, , );
genCode(OPR, , OP_NEQ);
}
else
{
expression(level, index);
int op = sym;
if (sym != NEQ&&sym != EQ&&sym != LSS&&sym != LE&&sym != GT&&sym != GE)
printErr("error!");
getSym();
expression(level, index);
switch (op)
{
case NEQ:
genCode(OPR, , OP_NEQ); break;
case EQ:
genCode(OPR, , OP_EQ); break;
case LSS:
genCode(OPR, , OP_LSS); break;
case LE:
genCode(OPR, , OP_LE); break;
case GT:
genCode(OPR, , OP_GT); break;
case GE:
genCode(OPR, , OP_GE); break;
}
}
return ;
} int expression(int level, int index)
{ int op = sym;
if (sym == PLUS || sym == MINUS)
{
getSym();
}
factor(level, index);
if (op == MINUS)
{
genCode(LIT, , );
genCode(OPR, , OP_MINUS);
}
do{
op = sym;
if (sym == PLUS || sym == MINUS)
{
getSym();
factor(level, index);
if (op == PLUS)
genCode(OPR, , OP_ADD);
else
genCode(OPR, , OP_MINUS);
}
} while (sym == PLUS || sym == MINUS);
return ;
} int factor(int level, int index)
{ term(level, index);
int op = sym;
if (op != TIMES&&op != SPLASH)
return ;
do{
getSym();
term(level, index);
if (op == TIMES)
genCode(OPR, , );
else
genCode(OPR, , OP_DIV);
op = sym;
} while (sym == TIMES || sym == SPLASH);
return ;
} int term(int level, int index)
{
if (sym == IDENT)
{
int i = find(, index, id);
if (i<)
{
printErr("Identifier not found!");
}
if (symTable[i].type == CONST)
genCode(LIT, , symTable[i].value);
else if (symTable[i].type == VARIABLE)
genCode(LOD, level - symTable[i].level, numLinkData + symTable[i].address);
else
{
printErr("error!");
}
getSym();
}
else if (sym == NUM)
{
genCode(LIT, , num);
getSym();
}
else if(sym==LPAREN)
{
getSym();
expression(level, index);
if (sym != RPAREN)
printf(") expected");
getSym();
}
else{
printErr("error!");
}
return ;
} void interprete()
{
const static int ret_addr = , dynamic_link = , static_link = ;
PCode ir;
int ip = , sp = , bp = ;
int stack[] = { };
int sp_stack[];
int sp_top = ;
while (ip<pc)
{
ir = code[ip++];
switch (ir.op)
{
case LIT:
stack[sp++] = ir.a; break;
case LOD:
{
if (ir.l == )
stack[sp++] = stack[bp + ir.a];
else
{
int outer_bp = stack[bp + static_link];
while (--ir.l)
outer_bp = stack[outer_bp + static_link];
stack[sp++] = stack[outer_bp + ir.a];
}
break;
}
case STO:
{
if (ir.l == )
stack[bp + ir.a] = stack[sp - ];
else
{
int outer_bp = stack[bp + static_link];
while (--ir.l)
outer_bp = stack[outer_bp + static_link];
stack[outer_bp + ir.a] = stack[sp - ];
}
break;
}
case CAL:
{
stack[sp + ret_addr] = ip;
stack[sp + dynamic_link] = bp;
stack[sp + static_link] = bp;
ip = ir.a;
bp = sp;
break;
}
case INT:
{
sp_stack[sp_top++] = sp;
sp += ir.a;
break;
}
case JMP:
{
ip = ir.a;
break;
}
case JPC:
{
if (stack[sp - ] == )
ip = ir.a;
break;
}
case OPR:
{
switch (ir.a)
{
case OP_RET:
{
ip = stack[bp + ret_addr];
bp = stack[bp + dynamic_link];
sp = sp_stack[--sp_top];
if (sp_top <= )
{
printf("program exited normally!\n");
return;
}
break;
}
case OP_ADD:
{
stack[sp - ] = stack[sp - ] + stack[sp - ];
sp--;
break;
}
case OP_MINUS:
{
stack[sp - ] = stack[sp - ] - stack[sp - ];
sp--;
break;
}
case OP_TIMES:
{
stack[sp - ] = stack[sp - ] * stack[sp - ];
sp--;
break;
}
case OP_DIV:
{
stack[sp - ] = stack[sp - ] / stack[sp - ];
sp--;
break;
}
case OP_NEQ:
{
stack[sp - ] = (stack[sp - ] != stack[sp - ]) ? : ;
sp--;
break;
}
case OP_EQ:
{
stack[sp - ] = (stack[sp - ] == stack[sp - ]) ? : ;
sp--;
break;
}
case OP_LSS:
{
stack[sp - ] = (stack[sp - ]<stack[sp - ]) ? : ;
sp--;
break;
}
case OP_LE:
{
stack[sp - ] = (stack[sp - ] <= stack[sp - ]) ? : ;
sp--;
break;
}
case OP_GT:
{
stack[sp - ] = (stack[sp - ]>stack[sp - ]) ? : ;
sp--;
break;
}
case OP_GE:
{
stack[sp - ] = (stack[sp - ] >= stack[sp - ]) ? : ;
sp--;
break;
}
case OP_READ:
{
cout << "Please input a number:" << endl;
cin >> stack[sp++];
break;
}
case OP_WRITE:
{
cout << stack[sp - ] << endl;
break;
}
default:
{
printf("Unexpected operation!\n"); return;
}
}
break;
}
default:
printf("Unexpected instruction!\n"); return;
}
}
} int main(int argc, char *argv[])
{
f = fopen("test.txt","r");
getSym();
block(, );
for (int i = ; i<pc; i++)
{
cout << i << ":\t" << CodeTable[code[i].op] << " " << code[i].l << " " << code[i].a << endl;
}
interprete();
return ;
}
下面是test.txt文件
const a=;
var b,c;
procedure p;
begin
c:=b+a
end;
begin
read(b);
while b# do
begin
call p;
write(*c);
read(b)
end
end
PL/0编译程序的更多相关文章
- PL/0语言编译器的设计与实现
一.设计任务 1.1程序实现要求 PL/0语言可以看成PASCAL语言的子集,它的编译程序是一个编译解释执行系统.PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关. PL/0的编译程序和 ...
- 北航 编译实践 PL/0文法
编译实践-PL\0编译系统实现 姓名: 专业: 计算机科学与技术 学院: 软件学院 提交时间: 2013年12月25日 北京航空航天大学·软件学院 编译实践-PL\0编译系统实现 实验要求 以个人 ...
- 编译原理--05 用C++手撕PL/0
前言 目录 01 文法和语言.词法分析复习 02 自顶向下.自底向上的LR分析复习 03 语法制导翻译和中间代码生成复习 04 符号表.运行时存储组织和代码优化复习 05 用C++手撕PL/0 在之前 ...
- PL/0编译器实践---后记
花了几天时间,把清华版的<编译原理>一书中的PL/0编译器实践了一遍.颇有收获,记录如下: 理解代码的技巧,如何理解一份代码,比如这个程序,其逻辑相对于一般程序就比较复杂了,如何翻译,虚拟 ...
- PL/0 词法分析器
PL/0 词法分析器 #include<stdio.h> #include <ctype.h> #include <stdlib.h> #include <s ...
- PL/0编译器(java version)–Praser.java
1: package compiler; 2: 3: import java.io.IOException; 4: import java.util.BitSet; 5: 6: /** 7: ...
- PL/0编译器(java version) - MainFrame.java
1: /* 2: * To change this license header, choose License Headers in Project Properties. 3: * To chan ...
- PL/0与Pascal-S编译器程序详细注释
学校编译课的作业之一,要求阅读两个较为简单的编译器的代码并做注释, 个人感觉是一次挺有意义的锻炼, 将自己的心得分享出来与一同在进步的同学们分享. 今后有时间再做进一步的更新和总结,其中可能有不少错误 ...
- PL/0语言词法分析器
前言:关于词法分析的基础知识的介绍可以看一下这篇博客,我再累述估计也不会有这篇讲的清楚QAQ. https://www.cnblogs.com/yanlingyin/archive/2012/04/1 ...
随机推荐
- 「JXOI2018」游戏
注意输出的应该是 所有方案的和,,而不是期望. 我们不妨把依赖关系建图,可以发现 所有没有入度的点都被查水表了一次 是 游戏结束的 充要条件. 于是我们只需要知道有多少没有入度的点,然后再排列算一算就 ...
- Tiny 6410的Linux学习总结!
1.Tiny6410的Linux系统修改IP地址: vi /etc/eth0-setting 2.Ubuntu14.04自动以root身份登录系统: /etc/lightdm/lig ...
- ASIHTTPRequest学习(三)
刚刚开始学习ASIHttpRequest,今天通过自己写的一个小demo分享一下学习心得. 首先,要想在ios项目中使用ASIHttpRequest,必须添加下列框架和类库: ASIHttpReque ...
- Unity定制 Image、Text的对象生成
2016.4.14 昨天看到 雨凇的 Unity3D研究院之UGUI一个优化效率小技巧: http://www.xuanyusong.com/archives/4006 完好了他所说的代码: usi ...
- 新人补钙系列教程之:AS 与 JS 相互通信
比较常用的,AS 调用 JS private function callJS():void{ ExternalInterface.addCallback("callbackQQPay&quo ...
- idea 去掉never used 提示
- dmz主机就是DNAT功能的体现
端口映射和DMZ是提供内网和外网映射的,具体各自如下:DMZ:就相当于DNAT(Destination NAT),只对目的IP地址做地址转换.也就是说,收到目的IP为自己WAN口的包,统统转发给内网的 ...
- 经典的排序算法java实现版
/** * * @author yuzhiping * @version 1.0 * 功能说明:计算机领域经典的算法 * */ public class sortAlgorithm<T exte ...
- 系统重装 U盘安装XP操作系统开机出现提示txtsetup.sif怎么办
你的这个问题 是安装xp时把xp做成u盘出现的 原因是xp没有在根本上支持这种安装 到win7后才支持的 解决方法有以下几种 1,刻录成cd 2重新下载xp ghost版的不会出现这个问题 3证实Ul ...
- vscode - 使用Settings进行同步扩展以及配置信息等
1. 创建token(记住要复制上面的token): https://github.com/settings/tokens. 2. 创建gist id https://gist.github.com/ ...