哪位大哥帮帮忙,编译原理的实验pl0的程序
1、分析原来的IF语句的BNF
<条件语句>::=IF <条件>THEN <语句>
和扩展后的IF语句的BNF
<条件语句>::=IF <条件>THEN <语句>[ELSE <语句>]
在原有的程序上把if----then 扩展为if then else(不是改程序里的if then,而是实现能分析if then else,原有的只能分析if then)
2、pl0的一维数组扩充
分析BNF
<数组变量声明>::=<标识符> ( <下界>: <上界>)
<数组变量引用>::= <标识符> ( <表达式> )
在实现上的要求
找到应该修改的地方,进行修改和扩充
[解决办法]
下面是代码生成与解释执行部分:
//增加两个虚拟机指令 lda, sta, 分别用来从数组中取数和存到数组中//数组元素的访问和存储,是将()后的当成表达式,先处理,得到元素的索引,放在栈顶//最后根据数组的首地址,得到某个元素的地址#define arraycoefdo(a,b,c) if(-1==arraycoef(a,b,c)) return -1/** 数组元素索引计算与“虚拟机”生成*/int arraycoef(bool *fsys, int *ptx, int lev){ bool nxtlev[symnum]; int i = position(id, *ptx); getsymdo; if (sym == lparen) /* 索引是括号内的表达式 */ { getsymdo; memcpy(nxtlev, fsys, sizeof(bool)*symnum); nxtlev[rparen] = true; expressiondo(nxtlev, ptx, lev); if (sym == rparen) { gendo(lit, 0, table[i].data); gendo(opr, 0, 3); /* 系数修正,减去下界的值 */ return 0; } else { error_no(22); /* 缺少右括号 */ } } else { error_no(51); /* 数组访问错误 */ } return -1;}//表达式中访问元素:int factor(bool* fsys, int* ptx, int lev){ ... if(sym == ident) { ... case variable: gendo(lod, lev-table[i].level, table[i].adr); break; case array: /* 名字为数组名 */ arraycoefdo(fsys, ptx, lev); gendo(lda, lev-table[i].level, table[i].adr); /* 找到变量地址并将其值入栈 */ break; }}//将结果存到表达式中,数组处理仅仅在获得左值时与普通变量不同int statement(bool* fsys, int* ptx, int lev){ int i, cx1, cx2; bool nxtlev[symnum]; if (sym == ident) /* 准备按照赋值语句处理 */ { i = position(id, *ptx); if (i == 0) { error_no(11); /* 变量未找到 */ } else { enum fct fct1 = sto; switch(table[i].kind) { case array: arraycoefdo(fsys, ptx, lev); fct1 = sta; /* 数组保存,要多读一个栈 */ /* go through */ case variable: { getsymdo; if(sym == becomes) { getsymdo; } else { error_no(13); /* 没有检测到赋值符号 */ } memcpy(nxtlev, fsys, sizeof(bool)*symnum); expressiondo(nxtlev, ptx, lev); /* 处理赋值符号右侧表达式 */ if(i != 0) { /* expression将执行一系列指令,但最终结果将会保存在栈顶,执行sto命令完成赋值 */ gendo(fct1, lev-table[i].level, table[i].adr); } } break; default: error_no(12); /* 赋值语句格式错误 */ i = 0; break; }//switch }//if (i == 0) } else { ... } return 0;}////以下是虚拟机解释增加的两个虚拟机代码的处理////刚刚想了下,其实应该可以不增加lda和sta,利用opr定义类似的操作就可以了void interpret(){ ... case lda: /* 数组元素访问,当前栈顶为元素索引,执行后,栈顶变成元素的值 */ s[t-1] = s[base(i.l,s,b) + i.a + s[t-1]]; break; case sta: /* 栈顶的值存到数组中,索引为栈顶之下的那个值 */ t-=2; s[base(i.l,s,b) + i.a + s[t]] = s[t+1]; break; ...}