编译原理期末项目
- 修改资料中所给的PL0编译程序,使之能够编译给定的PL0源程序,并将中间代码和栈顶结果输出到文件中。
- 安装Free Pascal
- 首先,我将资料中给定的编译程序复制下来,直接在命令行使用fpc命令进行编译,结果出错。经过仔细对比,因为Word排版的问题,有很多符号方面的错误,例如“非/取反”符号直接复制到Pascal代码中会消失,这也是造成了我后续很多错误的一个主要原因。其次,还有“小于等于/大于等于”,复制下来的代码都是有错误的,不是编译器能够编译的符号,所以我得将其拆分为"<"和"="这种形式。
- 接着,编译程序还是会出问题,因为编译程序中虽然有输出语句,但是并没有读入程序的地方,所以需要在最后进行读入。其次,因为需要将结果输出到文件中,所以我在一开始打开了一个输出文件result.txt,然后在代码中的每一句write后都加一句,将结果输出到文件中。当然,需要在一开始声明变量。
//code
input : text;
output : text;
sfile: string;
//code
Begin
writeln('Please input source program file name : ');
readln(sfile);
assign(input,sfile);
assign(output, 'result.txt');
reset(input);
rewrite(output);
//code
writeln;
close(input);
close(output);
readln(sfile);
End.1- 修改之后,依然是不能够运行,经过调试后,问题出现在condition部分,其处理的情况太少了,于是我根据代码所需,补充了剩下的一部分,完成了编译程序。编译,能够正常运行。
- 详见result.txt。
- 在上次的实验的基础上,为编译程序添加Write与Read语句,使得PL0源程序能够使用Write和Read语句,将结果输出到文件中。
- 同 Part 1。
- 首先,将编译程序头的一个变量从11变为13,因为要添加两条命令。
norw = 13;- 同时,也要修改symbol和fct,添加write与read命令。
Type
symbol = (nul, ident, number, plus, minus, times, slash, oddsym,
eql, neq, lss, leq, gtr, geq, lparen, rparen, comma, semicolon,
period, becomes, beginsym, endsym, ifsym, thensym,
whilesym, dosym, callsym, constsym, varsym, procsym,readsym,writesym );
alfa = packed array [1..al] Of char;
objectType = (constant, variable, procedures);
symset = set Of symbol;
fct = (lit, opr, lod, sto, cal, int, jmp, jpc, red, wrt); - 再者,在condition中添加wirte与read语句,这是最为重要的一部分。
Else If sym = readsym
Then
Begin
getsym;
If sym = lparen
Then
Repeat
getsym;
If sym = ident
Then
Begin
i := position(id);
If i = 0
Then error(11)
Else If table[i].kind <> variable
Then
Begin
error(12);
i := 0
End
Else With table[i] Do
gen(red,lev-level,adr)
End
Else error(4);
getsym;
Until sym <> comma
Else error(40);
If sym <> rparen
Then error(22);
getsym
End
Else If sym = writesym
Then
Begin
getsym;
If sym = lparen
Then
Begin
Repeat
getsym;
expression([rparen,comma]+fsys);
gen(wrt,0,0);
Until sym <> comma;
If sym <> rparen
Then error(22);
getsym
End
Else error(40)
End;- 最后,在主程序中修改word,wsym以及mnemonic,添加两个条目,具体如下:
Begin
writeln('Please input source program file name : ');
readln(sfile);
assign(input,sfile);
assign(output, 'result.txt');
reset(input);
rewrite(output);
For ch := 'A' To ';' Do
ssym[ch] := nul;
word[1] := 'begin ';
word[2] := 'call ';
word[3] := 'const ';
word[4] := 'do ';
word[5] := 'end ';
word[6] := 'if ';
word[7] := 'odd ';
word[8] := 'procedure ';
word[9] := 'read ';
word[10] := 'then ';
word[11] := 'var ';
word[12] := 'while ';
word[13] := 'write ';
wsym[1] := beginsym;
wsym[2] := callsym;
wsym[3] := constsym;
wsym[4] := dosym;
wsym[5] := endsym;
wsym[6] := ifsym;
wsym[7] := oddsym;
wsym[8] := procsym;
wsym[9] := readsym;
wsym[10] := thensym;
wsym[11] := varsym;
wsym[12] := whilesym;
wsym[13] := writesym;
ssym['+'] := plus;
ssym['-'] := minus;
ssym['*'] := times;
ssym['/'] := slash;
ssym['('] := lparen;
ssym[')'] := rparen;
ssym['='] := eql;
ssym[','] := comma;
ssym['.'] := period;
ssym['<'] := lss;
ssym['>'] := gtr;
ssym[';'] := semicolon;
mnemonic[lit] := 'LIT';
mnemonic[opr] := 'OPR';
mnemonic[lod] := 'LOD';
mnemonic[sto] := 'STO';
mnemonic[cal] := 'CAL';
mnemonic[int] := 'INT';
mnemonic[jmp] := 'JMP';
mnemonic[jpc] := 'JPC';
mnemonic[red] := 'RED ';
mnemonic[wrt] := 'WRT ';
declbegsys := [constsym, varsym, procsym];
statbegsys := [beginsym, callsym, ifsym, whilesym];
facbegsys := [ident, number, lparen];
cc := 0;
cx := 0;
ll := 0;
ch := ' ';
kk := al;
getsym;
block(0, 0, [period]+declbegsys+statbegsys);
If sym <> period Then error(9);
If err = 0 Then interpret
Else write('ERRORS IN PL/0 PROGRAM');
writeln;
close(input);
close(output);
readln(sfile);
End.1- 详见result.txt。