编译原理实验解析Word文档格式.docx
《编译原理实验解析Word文档格式.docx》由会员分享,可在线阅读,更多相关《编译原理实验解析Word文档格式.docx(13页珍藏版)》请在冰点文库上搜索。
leftkuo,rightkuo;
分别对应:
保留字:
单字符:
[],双字符:
*=/=
修改#definenorw20/*关键字个数*/
相应的增加个数6
修改#definesymnum43
相应的改为symbol的个数
增加6个保留字的具体值,修改后如下所示:
/*设置保留字名字,按照字母顺序,便于折半查找*/
strcpy(&
(word[0][0]),"
begin"
);
(word[1][0]),"
call"
(word[2][0]),"
char"
(word[3][0]),"
const"
(word[4][0]),"
do"
(word[5][0]),"
else"
(word[6][0]),"
end"
(word[7][0]),"
for"
(word[8][0]),"
if"
(word[9][0]),"
odd"
(word[10][0]),"
procedure"
(word[11][0]),"
read"
(word[12][0]),"
real"
(word[13][0]),"
return"
(word[14][0]),"
step"
(word[15][0]),"
then"
(word[16][0]),"
until"
(word[17][0]),"
var"
(word[18][0]),"
while"
(word[19][0]),"
write"
增加6个保留字符号,修改后如下所示:
/*设置保留字符号*/
wsym[0]=beginsym;
wsym[1]=callsym;
wsym[2]=charsym;
wsym[3]=constsym;
wsym[4]=dosym;
wsym[5]=elsesym;
wsym[6]=endsym;
wsym[7]=forsym;
wsym[8]=ifsym;
wsym[9]=oddsym;
wsym[10]=procsym;
wsym[11]=readsym;
wsym[12]=realsym;
wsym[13]=returnsym;
wsym[14]=stepsym;
wsym[15]=thensym;
wsym[16]=untilsym;
wsym[17]=varsym;
wsym[18]=whilesym;
wsym[19]=writesym;
增加未定义的单字符:
ssym['
['
]=leftkuo;
]'
]=rightkuo;
2)修改GetSym()方法
设置找到保留字时的提示:
if(i-1>
j)
{
sym=wsym[k];
//这句表示为sym赋值保留字的值
printf("
找到保留字:
%s\n"
id);
}
与*=、/=相关的代码,包含识别单字符[、]
{
if(ch=='
*'
)/*检测*=或**/
{
getchdo;
if(ch=='
='
)
{
sym=timesequal;
printf("
找到*=\n"
getchdo;
}
else
sym=times;
}else{
/'
)/*检测/或/=*/
if(ch=='
{
sym=geq;
printf("
找到/=\n"
getchdo;
}
else
sym=gtr;
}else
)/*检测[*/
sym=leftkuo;
找到[\n"
}else
if(ch=='
)/*检测]*/
{
getchdo;
sym=rightkuo;
printf("
找到]\n"
}else
sym=ssym[ch];
/*当符号不满足上述条件时,全部按照单字符号处理*/
//getchdo;
//richard
if(sym!
=period)
{
getchdo;
}
//endrichard
}
}
2.修改单词
修改变量定义:
symbol中已有#原来的neq定义,所以不用修改
删除单字符定义//ssym['
#'
]=neq;
修改getSym:
if(ch=='
<
'
)/*检测小于或小于等于或不等于符号*/
{
getchdo;
if(ch=='
{
sym=leq;
getchdo;
}
else
)//找到<
{
sym=neq;
getchdo;
printf("
找到<
\n"
}
else
sym=lss;
}
1)语法图
2)修改STATEMENT()方法(只需要写出caseIFSYM:
部分的代码)
if(sym==ifsym)/*准备按照if语句处理*/
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[thensym]=true;
nxtlev[dosym]=true;
/*后跟符号为then或do*/
conditiondo(nxtlev,ptx,lev);
/*调用条件处理(逻辑运算)函数*//*栈顶存着TRUEORFALSE*/
if(sym==thensym)
getsymdo;
else
error(16);
/*缺少then*/
cx1=cx;
/*保存当前指令地址*/
gendo(jpc,0,0);
/*生成条件跳转指令,跳转地址暂写0*/
statementdo(fsys,ptx,lev);
/*处理then后的语句*/
code[cx1].a=cx;
/*经statement处理后,cx为then后语句执行
完的位置,它正是前面未定的跳转地址*/
if(sym==elsesym){
发现else\n"
getsymdo;
cx2=cx;
code[cx1].a=cx+1;
//gendo(jpc,0,0);
gendo(jmp,0,0);
statementdo(fsys,ptx,lev);
code[cx2].a=cx;
三.运行测试
1.扩充单词的测试(贴运行结果截图)
测试PL0代码:
for
step
until
char
real
return
[]
*=
/=.
测试结果:
2.修改单词的测试(需给出测试的PL0源码)
vara,b,c;
begin
a:
=1;
b:
ifa<
2thenc:
=a+b;
write(c);
end.
预期结果:
运行后输出2。
测试结果正确
3.扩充else的测试(需给出测试的PL0源码)
PL0源码
ifa>
=a+b
elsec:
=a-b;
write(a);
write(b);
完全正确
四.心得
老师讲课内容和实验紧密结合,所以实验做起来也比较顺心,基本上都是老师课上讲过的。
所以上实验课时把书本上的笔记拿来作参考,就很容易能够理解实验代码了。
不过在实际代码中还是会遇到一些问题,比如,最后一次实验的else字句的添加,其实代码确实写对了,但是就是不能检测到elsesym,修改了很多次内容,最后用单步调试,一个一个检查变量,发现读取if字句时只会读到then及后面跟的那条语句,而没有把else字句及else后面跟的语句一起读入,这是不符合if语句的语义语法分析过程的,于是我检查了C代码和PL测试源程序,发现PL测试源程序中的then+语句的语句后面多了一个分号,使得程序中把if条件then语句;
当成一个语句进行处理,而把else语句当成下一条语句,因此造成错误。
在编译原理课上和实验课学习到了很多东西,编译课使我了解了编译的一般原理,而实验课则加强了我对编译原理的认识,并且通过实际动手,在发现问题,解决问题中,提升了自己解决问题的能力。
感谢有这么认真尽职的老师们。