1 增加语句for(<语句>;<条件>;<语句>)
Step1: 在pl0.h中修改
pl0.h中在enum symbol { } 符号枚举集中加入
forsym, 并更改符号的个数 symnum
Step2: 增加保留字名字并增加对应的保留字符号
名字: strcpy(&(word[6][0]),"for");
符号: wsym[6]=forsym;
(注: 顺序按26个字母的顺序重新排列)
Step3: 增加语句开始符号集
statbegsys[forsym]=true;
Step4: 语句处理函数内添加关于for语句的处理
//int i , cx1 , cx2 , cx3 , cx4 , cx5; (cx3,cx4,cx5为新增加的地址)
if(sym == forsym)
{
getsymdo;
if(sym != lparen) error(34);//没有左括号出错
else
{
getsymdo;
statementdo(nxtlev, ptx, lev); //S1代码
//语句缺少分号出错
if(sym != semicolon) error(10);
else
{
/*cx是当前指令的地址 保存判断条件操作的 位置 */
cx1=cx;
getsymdo;
conditiondo(nxtlev, ptx, lev); //E代码
if(sym != semicolon) error(10);
else
{
cx2=cx;
gendo(jpc,0,0);
cx3=cx;
gendo(jmp,0,0);
getsymdo;
cx4=cx;
//S2代码
statementdo(nxtlev, ptx, lev);
if(sym != rparen) error(22); //缺少右括号出错
else
{
gendo(jmp,0,cx1); // 回头重新判断条件
getsymdo;
cx5=cx;
statementdo(nxtlev, ptx, lev); //S3代码
code[cx3].a=cx5;
gendo(jmp,0,cx4);
code[cx2].a=cx; // 反填跳出循环的地址,与if类似
}
}
}
}
}
2 扩充语句if <条件> then <语句> else <语句>
Step1: 在pl0.h中修改
pl0.h中在enum symbol { } 符号枚举集中加入
elsesym, 并更改符号的个数 symnum
Step2: 增加保留字名字并增加对应的保留字符号
名字: strcpy(&(word[4][0]),"else");
符号: wsym[4]=elsesym;
(注: 顺序按26个字母的顺序重新排列)
Step3: 语句处理函数内添加关于if语句的处理
if(sym==ifsym) /*准备按照if语句处理*/
{
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[thensym]=true;
nxtlev[dosym]=true; /*后跟符号为then或do*/
conditiondo(nxtlev,ptx,lev); /*调用条件处理(逻辑运算)函数*/
if(sym==thensym)
{
getsymdo;
}
else
{
error(16); /*缺少then*/
}
cx1=cx; /*保存当前指令地址*/
gendo(jpc,0,0); /*生成条件跳转指令,跳转地址暂写0*/
statementdo(fsys,ptx,lev); /*处理then后的语句*/
if(sym==semicolon)
{
getsymdo;
if(sym==elsesym) /*then语句后出现else*/
{
getsymdo;
cx2=cx;
/*cx为当前的指令地址,cx+1即为then语句执行后的else语句的位置,回填地址*/
code[cx1].a=cx+1;
gendo(jmp,0,0);
statementdo(fsys,ptx,lev);
/*经statement处理后,cx为else后语句执行
完的位置,它正是前面未定的跳转地址,回填地址*/
code[cx2].a=cx;
}
else
{
/*经statement处理后,cx为then后语句执行完的位置,它正是前面未定的跳转地址*/
code[cx1].a=cx;
}
}
else
{
error(5);
}
}
3 增加语句repeat <语句> until <条件>
Step1: 在pl0.h中修改
pl0.h中在enum symbol { } 符号枚举集中加入
repeatsym, untilsym, 并更改符号的个数 symnum
Step2: 增加保留字名字并增加对应的保留字符号
名字: strcpy(&(word[11][0]),"repeat");
strcpy(&(word[13][0]),"until");
符号: wsym[11]=repeatsym;
wsym[13]=untilsym;
(注: 顺序按26个字母的顺序重新排列)
Step3: 增加语句开始符号集
statbegsys[repeatsym]=true;
Step4: 语句处理函数内添加关于repeat语句的处理
else if(sym==repeatsym)
{
cx1=cx; /*保存当前指令地址*/
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[untilsym]=true;
statementdo(fsys,ptx,lev);
if(sym==semicolon)
{
getsymdo;
if(sym==untilsym)
{
getsymdo;
conditiondo(fsys,ptx,lev);
/*经condition处理后,cx1为repeat后循环语句的位置,条件为假时一直循环*/
gendo(jpc,0,cx1);
}
}
else
{
error(5);
}
}
4. 增加自增自减运算
对于++和–的扩充,分为两种情况:
作为语句的情况
例如: ++i,--i,i++,i--;
作为表达式的因子的情况
例如: b:=a++;b:=a--;
b:=++a;b:=--a;
第一种作为语句情况的扩充:
Step1: 在pl0.h中修改
pl0.h中在enum symbol { } 符号枚举集中加入
addadd, subsub, 并更改符号的个数 symnum
Step2: 语句处理函数内添加关于++ 和–的处理
else if(sym==addadd) /*检测到后置++符号*/
{
getsymdo;
// 如果++后面跟的量可以在名字表中找到
if(i!=0)
{
gendo(lod,lev-table[i].level,table[i].adr);
gendo(lit,0,1);
gendo(opr,0,2);
gendo(sto,lev-table[i].level,table[i].adr);
}
}
else if(sym==subsub) /*检测到后置--符号*/
{
getsymdo;
// 如果 -- 后面跟的量可以在名字表中找到
if(i!=0)
{
gendo(lod,lev-table[i].level,table[i].adr);
gendo(lit,0,1);
gendo(opr,0,3);
gendo(sto,lev-table[i].level,table[i].adr);
}
}
if(sym==addadd) /*检测到前置++符号*/
{
getsymdo;
if(sym==ident) /*后面跟的是变量*/
{
i=position(id,*ptx);
if(i==0)
{
error(11);
}
else
{
if(table[i].kind!=variable)
{
/*++后没跟变量,出错*/
error(12);
i=0;
}
else
{
/*++后跟变量,处理生成中间代码*/
getsymdo;
/*先取 值到栈顶*/
gendo(lod,lev-table[i].level,table[i].adr);
gendo(lit,0,1); /*将1放到栈顶*/
gendo(opr,0,2); /*加法,即+1,栈顶加次栈顶*/
/*出栈取值到内存*/
gendo(sto,lev-table[i].level,table[i].adr);
}
}
}
}
else if(sym==subsub) /*检测到前置--符号*/
{
getsymdo;
if(sym==ident) /*后面跟的是变量*/
{
i=position(id,*ptx);
if(i==0)
{
error(11);
}
else
{
/*--后没跟变量,出错*/
if(table[i].kind!=variable)
{
error(12);
i=0;
}
else /*--后跟变量,处理生成中间代码*/
{
if(table[i].kind==variable) /*后跟变量*/
{
getsymdo;
/*先取值到栈顶*/
gendo(lod,lev-table[i].level,table[i].adr);
gendo(lit,0,1); /*将1放到栈顶*/
gendo(opr,0,3); /*减法,即-1,栈顶减次栈顶*/
/*出栈取值到内存*/
gendo(sto,lev-table[i].level,table[i].adr);
}
}
}
}
}
第二种作为语句情况的扩充:
Step1: 添加因子开始符号集
facbegsys[addadd]=true; /*前置++*/
facbegsys[subsub]=true; /*前置--*/
Step2: 在因子处理函数factor中添加 ++和–相关处理
if(sym==addadd) /*因子出2现b:=a++类型*/
{
gendo(lit,lev-table[i].level,1); /*将值入栈*/
/*加法,即+1,栈顶加次栈顶*/
gendo(opr,lev-table[i].level,2);
/*出栈取值到内存*/
gendo(sto,lev-table[i].level,table[i].adr);
/*取值到栈顶*/
gendo(lod,lev-table[i].level,table[i].adr);
gendo(lit,0,1);
gendo(opr,0,3); /*栈顶值减*/
getsymdo;
}
else if(sym==subsub) /*因子出现b:=a--类型*/
{
gendo(lit,lev-table[i].level,1); /*将值入栈*/
/*减法,即-1,栈顶减次栈顶*/
gendo(opr,lev-table[i].level,3);
/*出栈取值到内存*/
gendo(sto,lev-table[i].level,table[i].adr);
gendo(lod,lev-table[i].level,table[i].adr);
gendo(lit,0,1);
gendo(opr,0,2); /*栈顶值加*/
getsymdo;
}
else if(sym==addadd) /*因子出现b:=++a类型*/
{
getsymdo;
if(sym==ident)
{
getsymdo;
i=position(id,*ptx);
if(i==0)
{
error(11);
}
else
{
if(table[i].kind==variable) /*变量*/
{
/*先加后再用a*/
/*先取值到栈顶*/
gendo(lod,lev-table[i].level,table[i].adr);
gendo(lit,0,1);/*将值入栈*/
gendo(opr,0,2);/*加法,即+1,栈顶加次栈顶*/
/*出栈取值到内存*/
gendo(sto,lev-table[i].level,table[i].adr);
/*取值到栈顶*/
gendo(lod,lev-table[i].level,table[i].adr);
}
}
}
}
else if(sym==subsub) /*因子出现b:=--a类型*/
{
getsymdo;
if(sym==ident)
{
getsymdo;
i=position(id,*ptx);
if(i==0)
{
error(11);
}
else
{
if(table[i].kind==variable) /*变量*/
{
/*先减后再用a*/
/*先取值到栈顶*/
gendo(lod,lev-table[i].level,table[i].adr);
gendo(lit,0,1); /*将值入栈*/
gendo(opr,0,3); /*减法,即-1,栈顶减次栈顶*/
/*出栈取值到内存*/
gendo(sto,lev-table[i].level,table[i].adr);
/*取值到栈顶*/
gendo(lod,lev-table[i].level,table[i].adr);
}
}
}
}
5. 增加+=,-=,*=,/=运算
Step1: 在pl0.h中修改
pl0.h中在enum symbol { } 符号枚举集中加入
addequal,subequal, timeseql, slasheql,, 并更
改符号的个数 symnum
Step2: 在getSym()函数中处理:
if(ch=='+')
{
getchdo;
if(ch=='=')
{
sym=addequal;
getchdo;
}
else{
sym=plus;
}
}
else
{
if(ch=='-')
{
getchdo;
if(ch=='=')
{
sym=subequal;
getchdo;
}else{
sym=minus;
}
}
else
{
if(ch=='*')
{
getchdo;
if(ch=='=')
{
sym=timeseql;
getchdo;
}
else
{
sym=times;
}
}
else
{
if(ch=='/')
{
getchdo;
if(ch=='=')
{
sym=slasheql;
getchdo;
}
getchdo;
} else{
sym=slash;
}
}else{
/*当符号不满足上述条件时,全部按照单字符号处理*/
sym=ssym[ch];
if(sym!=period)
{
getchdo;
}
}
}
}
Step3: 在语句处理函数中添加处理
else if(sym==addequal) /*检测到+=符号*/
{
getsymdo;
/*找到变量地址并将其值入栈*/
gendo(lod,lev-table[i].level,table[i].adr);
if(sym==semicolon)
{
getsymdo;
printf("+=后面直接跟了分号");
}
memcpy(nxtlev,fsys,sizeof(bool)* symnum);
expressiondo(nxtlev,ptx,lev);
gendo(opr,0,2);
if(i!=0)
{
gendo(sto,lev-table[i].level,table[i].adr);
}
}
else if(sym==subequal) /*检测到-=符号*/
{
getsymdo;
/*找到变量地址并将其值入栈*/
gendo(lod,lev-table[i].level,table[i].adr);
if(sym==semicolon)
{
getsymdo;
}
memcpy(nxtlev,fsys,sizeof(bool)* symnum);
expressiondo(nxtlev,ptx,lev);
gendo(opr,0,3);
if(i!=0)
{
gendo(sto,lev-table[i].level,table[i].adr);
}
}
else if(sym==timeseql) /*检测到*=符号*/
{
getsymdo;
/*找到变量地址并将其值入栈*/
gendo(lod,lev-table[i].level,table[i].adr);
if(sym==semicolon)
{
getsymdo;
}
memcpy(nxtlev,fsys,sizeof(bool)* symnum);
expressiondo(nxtlev,ptx,lev);
gendo(opr,0,4);
if(i!=0)
{
gendo(sto,lev-table[i].level,table[i].adr);
}
}
else if(sym==slasheql) /*检测到/=符号*/
{
getsymdo;
/*找到变量地址并将其值入栈*/
gendo(lod,lev-table[i].level,table[i].adr);
if(sym==semicolon)
{
getsymdo;
}
memcpy(nxtlev,fsys,sizeof(bool)* symnum);
expressiondo(nxtlev,ptx,lev);
gendo(opr,0,5);
if(i!=0)
{
gendo(sto,lev-table[i].level,table[i].adr);
}
}