一、课内试验要求对PL/0作以下修改扩充:(1)增加单词:保留字ELSE,REPEAT,DOWHILE,RETURN运算符+=,-=,++,--(2)修改单词:不等号# 改为<>(3)增加条件语句的ELSE子句二、具体操作(一)增加保留字ELSE,REPEAT,DOWHILE,RETURN和运算符+=,-=,++,--的修改需要在头文件和主程序的init()初始化函数修改,相应的要增加关键字个数。
具体如下:《一》头文件PL0.h中修改的程序部分//*************************************# define norw 17//关键字增加了4个,13改为17 增加了保留字ELSE,REPEAT,DOWHILE,RETURN //*************************************/*符号*/enum 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,writesym, readsym, dosym, callsym, constsym,varsym, procsym,//****************************************************************//增加保留字else,repeat,dowhite,return,运算符+=,-=,++,--elsesym,repeatsym,dowhitesym,returnsym,addbecomes,//运算符+=minusbecomes,//运算符-=adddouble,//运算符++minusdouble,//运算符--//****************************************************************};//****************************************************************#define symnum 40 //关键字由原来的32个变为40个,则32改为40//****************************************************************《二》主程序文件PL0.cpp中修改的程序部分初始化函数void init();中修改部分:/*设置保留字名字,按照字母顺序,便于折半查找*/strcpy(&(word[0][0]),"begin");strcpy(&(word[1][0]),"call");strcpy(&(word[2][0]),"const");strcpy(&(word[3][0]),"do");//**********************************//添加增加的保留字,下标也要随着更改strcpy(&(word[4][0]),"dowhite");strcpy(&(word[5][0]),"else");//**********************************strcpy(&(word[6][0]),"end");strcpy(&(word[7][0]),"if");strcpy(&(word[8][0]),"odd");strcpy(&(word[9][0]),"procedure");strcpy(&(word[10][0]),"read");//**********************************strcpy(&(word[11][0]),"repeat");strcpy(&(word[12][0]),"return");//**********************************strcpy(&(word[13][0]),"then");strcpy(&(word[14][0]),"var");strcpy(&(word[15][0]),"while");strcpy(&(word[16][0]),"write");//***********************************/*设置保留字符号*/wsym[0]=beginsym;wsym[1]=callsym;wsym[2]=constsym;wsym[3]=dosym;//************************************//添加增加的保留字符号,下标也要随着更改wsym[4]=dowhitesym;wsym[5]=elsesym;//**********************************wsym[6]=endsym;wsym[7]=ifsym;wsym[8]=oddsym;wsym[9]=procsym;wsym[10]=readsym;//**********************************wsym[11]=repeatsym;wsym[12]=returnsym;//**********************************wsym[13]=thensym;wsym[14]=varsym;wsym[15]=whilesym;wsym[16]=writesym;(2)修改单词:不等号# 改为<>,即原来不等号#给<>替代,同时实现能在词法分析中分析出运算符+=,-=,++,--。
在词法分析中修改不等号<>和增加运算符+=,-=,++,--。
《一》初始化函数void init();中修改的程序:ssym['+']=plus;ssym['-']=minus;ssym['*']=times;ssym['/']=slash;ssym['(']=lparen;ssym[')']=rparen;ssym['=']=eql;ssym[',']=comma;ssym['.']=period;//ssym['#']=neq; //不等号给<>替代了,所以#字符将不能识别出来ssym[';']=semicolon;《二》词法分析函数int getsym();中修改的程序:if(ch=='<') /*检测小于或小于等于符号*/{getchdo;if(ch=='='){sym=leq;getchdo;}//*********************************************else if(ch=='>') //增加不等号<>{sym=neq; //不等于getchdo;}else{sym=lss; //小于}//*********************************************}else{if(ch=='>') /*检测大于或大于等于符号*/{getchdo;if(ch=='='){sym=geq;getchdo;}else{sym=gtr;}}else{//*********************************************//增加++和+=运算符if(ch=='+'){getchdo;if(ch=='+'){sym=adddouble;getchdo;}else if(ch=='='){sym=addbecomes;getchdo;}else sym=plus;}//*********************************************else{//*********************************************//增加--和-=运算符if(ch=='-'){getchdo;if(ch=='-'){sym=minusdouble;getchdo;}else if(ch=='='){sym=minusbecomes;getchdo;}else sym=minus;}//*********************************************else{sym=ssym[ch];/* 当符号不满足上述条件时,全部按照单字符号处理*/if(sym!=period){getchdo;}}}(3)增加条件语句的ELSE子句在语句处理函数int statement(bool* fsys,int * ptx,int lev);中修改的程序:if(sym==ifsym) /*准备按照if语句处理*/{getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[thensym]=true;nxtlev[dosym]=true; /*后跟符号为then或do*/nxtlev[elsesym]=true;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!=elsesym)//没有else分句{code[cx1].a=cx;}else //有else分句{getsymdo;cx2=cx;code[cx1].a=cx+1;//cx为当前的指令地址,cx+1即为then 语句执行后的else语句的位置,回填地址gendo(jmp,0,0);statementdo(fsys,ptx,lev);code[cx2].a=cx;/*经statement处理后,cx为else后语句执行完的位置,它正是前面未定的跳转地址,回填地址*/}//*****************************************************************************}三、测试测试分为两个部分:一个是词法分析测试,一个是else语句测试。