《编译原理》实验指导书
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[rparen]=true; nxtlev[comma]=true;
/* write的后跟符号为) or , */
/* 调用表达式处理,此处与read不
expressiondo(nxtlev,ptx,lev);
同,read为给变量赋值 */
gendo(opr,0,14); /* 生成输出指令,输出栈顶的值 */
}
while(sym==comma);
if(sym!=rparen)error(33); /* write()中应为完整表达式 */ else { getsymdo; }
}
gendo(opr,0,15); /* 输出换行 */
} else { if(sym==callsym) /* 准备按照call语句处理 */ { getsymdo;
if(sym!=ident)error(14); /* call后应为标识符 */
else { i=postion(id,*ptx);
if(i==0)error(11); /* 过程未找到 */ else { if(table[i].kind==procedur) { gendo(cal,lev-table[i].level,table[i].adr);
call指令 */
}
else error(15);
/* call后标识符应为过程 */
}
getsymdo;
}
} else { if(sym==ifsym) /* 准备按照if语句处理 */
{
getsymdo;
《编译原理》课程组 /* 生成
30 of 37
《编译原理》实验指导书
} else {
/* 循环调用语句处理函数,直到下一个符号不是语句开始符号或收statementdo(nxtlev,ptx,lev);
while(inset(sym,statbegsys)||sym==semicolon) { }
if(sym==endsym) { }
else error(17);
/* 缺少end或; */
getsymdo;
if(sym==semicolon) { }
else error(10);
/* 缺少; */
statementdo(nxtlev,ptx,lev);
getsymdo;
到end */
} else {
if(sym==beginsym) /* 准备按照复合语句处理 */ {
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[semicolon]=true; nxtlev[endsym]=true;
/* 后跟符号为分号或end */
memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[thensym]=true; nxtlev[dosym]=true; if(sym==thensym) { }
else error(16); gendo(jpc,0,0); code[cx1].a=cx;
/* 缺少then */
/* 生成条件跳转指令,跳转地址未知,暂时写0 */ /* 经statement处理后,cx为then后语句执行完的位
cx1=cx; /* 保存当前指令地址 */
statementdo(fsys,ptx,lev); /* 处理then后的语句 */
getsymdo;
/* 后跟符号为then或do */
conditiondo(nxtlev,ptx,lev); /* 调用条件处理(逻辑运算)函数 */
置,它正是前面未定的跳转地址 */
《编译原理》课程组 31 of 37
《编译原理》实验指导书
*/ */ }
/* 表达式处理 */
int expression(bool* fsys,int* ptx,int lev) {
if(sym==plus||sym==minus) /* 开头的正负号,此时当前表达式被看作一个正的或负的项 */ {
addop=sym; getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[plus]=true; nxtlev[minus]=true;
/* 保存开头的正负号 */
enum symbol addop; /* 用于保存正负号 */ bool nxtlev[symnum];
/* 参数意义见block和enter函数 */
} return 0;
}
}
}
}
}
testdo(fsys,nxtlev,19); /* 检测语句结束的正确性 */
}
memset(nxtlev,0,sizeof(bool)*symnum); /* 语句结束无补救集合
if(sym==dosym) { }
else error(18);
/* 缺少do */
statementdo(fsys,ptx,lev); /* 循环体 */ gendo(jmp,0,cx1); /* 回头重新判断条件 */ code[cx2].a=cx;
/* 反填跳出循环的地址,与if类似 */
getsymdo;
if(sym==whilesym) /* 准备按照while语句处理 */ {
cx1=cx; /* 保存判断条件操作的位置 */ getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[dosym]=true;
/* 后跟符号为do */
/* 调用条件处理 */
conditiondo(nxtlev,ptx,lev); gendo(jpc,0,0);
cx2=cx; /* 保存循环体的结束的下一个位置 */
/* 生成条件跳转,但跳出循环的地址未知
《编译原理》课程组 32 of 37
《编译原理》实验指导书
termdo(nxtlev,ptx,lev); /* 处理项 */
if(addop==minus)gendo(opr,0,1); /* 如果开头为负号生成取负指令 */
}
else /* 此时表达式被看作项的加减 */ { memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[plus]=true; nxtlev[minus]=true;
termdo(nxtlev,ptx,lev); /* 处理项 */ }
while(sym==plus||sym==minus) { addop=sym; getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[plus]=true; nxtlev[minus]=true;
termdo(nxtlev,ptx,lev); /* 处理项 */ if(addop==plus) { gendo(opr,0,2);
/* 生成加法指令 */
}
else gendo(opr,0,3);
/* 生成减法指令 */
} return 0;
}
/* 条件处理 */
int condition(bool* fsys,int* ptx,int lev) /* 参数意义见block和enter函数 */
{ enum symbol relop; bool nxtlev[symnum]; if(sym==oddsym) /* 准备按照odd运算处理 */
{ getsymdo;
expressiondo(fsys,ptx,lev); gendo(opr,0,6);
/* 生成odd指令 */ } else { /* 逻辑表达式处理 */
memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[eql]=true;nxtlev[neq]=true; nxtlev[lss]=true;nxtlev[leq]=true;
nxtlev[gtr]=true;nxtlev[geq]=true; 《编译原理》课程组 33 of 37
《编译原理》实验指导书
expressiondo(nxtlev,ptx,lev);
if(sym!=eql&&sym!=neq&&sym!=lss&&sym!=leq&&sym!=gtr&&sym!=geq)error(20); else { relop=sym; getsymdo;
expressiondo(fsys,ptx,lev); switch(relop) { case eql: gendo(opr,0,8); break;
case neq:
gendo(opr,0,9); break;
case lss:
gendo(opr,0,10); break;
case geq:
gendo(opr,0,11); break;
case gtr:
gendo(opr,0,12); break;
case leq:
gendo(opr,0,13);
break;
}
}
} return 0;
}
/* 项处理 */
int term(bool* fsys,int* ptx,int lev) /* 参数意义见block和enter函数 */ { enum symbol mulop; /* 用于保存乘除法符号 */ bool nxtlev[symnum]; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[times]=true; nxtlev[slash]=true;
factordo(nxtlev,ptx,lev); /* 处理因子 */ while(sym==times||sym==slash)
{
《编译原理》课程组 34 of 37