编译原理PL专业课程设计方案报告_第1页
编译原理PL专业课程设计方案报告_第2页
编译原理PL专业课程设计方案报告_第3页
编译原理PL专业课程设计方案报告_第4页
编译原理PL专业课程设计方案报告_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

课程设计班级:21301学号:姓名:马瑞泽baidu一.课程设计目标 在分析了解一个教学型编译程序(如PL/0)基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。达成深入了解程序编译过程基础原理和基础实现方法目标。二.课程设计要求1.基础内容(1)扩充赋值运算:+=和-=(2)扩充语句(PascalFOR语句):①FOR<变量>:=<表示式>TO<表示式>DO<语句>②FOR<变量>:=<表示式>DOWNTO<表示式>DO<语句>其中,语句①循环变量步长为2,语句②循环变量步长为-2。2.选做内容(1)增加运算:++和--。(2)增加类型:①字符类型;②实数类型。(3)扩充函数:①有返回值和返回语句;②有参数函数。(4)增加一维数组类型(可增加指令)。(5)其它经典语言设施。3.本人在课程设计中已实现功效(1)增加单词:保留字ELSE,FOR,TO,DOWNTO,REPEAT,UNTIL,RETURN运算符+=,-=,++,--(2)修改单词:不等号#改为<>(3)增加条件语句ELSE子句(4)扩充赋值运算:+=和-=(5)扩充语句 ①FOR<变量>:=<表示式>TO<表示式>DO<语句>②FOR<变量>:=<表示式>DOWNTO<表示式>DO<语句>(6)增加运算:++和--(包含前后++、--运算)(7)增加一维数组类型其它经典语言设施:REPEAT语句UNTIL语句三.课程设计环境和工具(1)计算机及操作系统:PC机,Win7(2)实现工具:VC++6.0,C语言教学型编译程序:PL/0四.结构设计说明PL/0编译程序结构图PL/0编译程序过程或函数功效表过程或函数名简明功效说明pl0主程序error犯错处理,打印犯错位置和错误编码getsym词法分析,读取一个单词getch遗漏空格,读取一个字符gen生成目标代码,并送入目标程序区test测试目前单词符号是否正当block分程序分析处理过程enter登录名字表position(函数)查找标识符在名字表中位置constdeclaration常量定义处理vardeclaration变量说明处理listode列出目标代码清单statement语句处理expression表示式处理term项处理factor因子处理condition条件处理interpret对目标代码解释实施程序base(函数)经过静态链求出数据区基地址PL/0编译程序总体步骤图调用解释过程interpret解释实施目标实施目标程序开启置初值调用解释过程interpret解释实施目标实施目标程序开启置初值词法分析词法分析是编译第一个阶段,它关键任务是从左向右逐一字符地对源程序进行扫描,产生一个个单词序列用于语法分析。PL/0词法分析程序GETSYM功效是为语法分析提供单词用,是语法分析基础,把输入字符串形式源程序分割成一个个单词符号。经过词法分析程序分析出来单词,对语言固有单词只给出类别存放在全程变量SYM中,而对用户定义单词(标识符或常数)既给出类别又给值,其类别放在SYM中,值放在全程变量ID或全程变量NUM中,全部单词种类由编译程序定义纯量类型SYMBOL给出,称为语法词汇表。词法分析器分析过程:调用GETSYM时,它经过GETCH过程从源程序中取得一个字符。假如这个字符是字母,则继续获取字符或数字,最终能够拼成一个单词,查保留字表,假如查到为保留字,则把SYM变量赋成对应保留字类型值;假如没有查到,则这个单词应是一个用户自定义标识符(可能是变量名、常量名或是过程名字),把SYM置为IDENT,把这个单词存入ID变量。查保留字表时使用了二分法查找以提升效率。假如Getch取得字符是数字,则继续用Getch获取数字,并把它们拼成一个整数或实数,然后把SYM置为INTEGER,并把拼成数值放入NUM变量。假如识别出其它正当符号(比如:赋值号、大于号、小于等于号等),则把SYM则成对应类型。假如碰到不正当字符,把SYM置成NUL。词法分析程序GETSYM将完成下列任务:(1)滤空格(2)识别保留字(3)识别标识符(4)拼数(5)拼复合词(6)输出源程序程序分程序语句条件程序分程序语句条件表示式项因子PL/0语法调用关系图PL/0编译程序语法分析采取了自顶向下递归子程序法。语法分析同时也依据程序语义生成对应三元代码,并提供了犯错处理机制。语法分析关键由分程序分析过程(BLOCK)、常量定义分析过程(ConstDeclaration)、变量定义分析过程(Vardeclaration)、语句分析过程(Statement)、表示式处理过程(Expression)、项处理过程(Term)、因子处理过程(Factor)和条件处理过程(Condition)组成。这些过程在结构上组成一个嵌套层次结构。除此之外,还有犯错汇报过程(Error)、代码生成过程(Gen)、测试单词正当性及犯错恢复过程(Test)、登录名字表过程(Enter)、查询名字表函数(Position)和列出类PCODE代码过程(Listcode)作过语法分析辅助过程。由PL/0语法图可知:一个完整PL/0程序是由分程序和句号组成。所以,本编译程序在运行时候,经过主程序中调用分程序处理过程block来分析分程序部分(分程序分析过程中还可能会递归调用block过程),然后,判定最终读入符号是否为句号。假如是句号且分程序分析中未犯错,则是一个正当PL/0程序,能够运行生成代码,不然就说明源PL/0程序是不正当,输出犯错提醒即可。语义分析PL/0语义分析关键进行以下检验:(1)是否存在标识符先引用未申明情况;(2)是否存在己申明标识符错误引用;(3)是否存在通常标识符多重申明。中间代码生成目标代码类pcode是一个假想栈式计算机汇编语言。自己添加覆盖了OPR014 栈顶值输出至屏幕(字符型)OPR015 栈顶值输出至屏幕(整数型)OPR016 栈顶值输出至屏幕(实数型)OPR017 屏幕输出换行OPR018 从命令行读入一个字符输入置于栈顶OPR019 从命令行读入一个整数输入置于栈顶OPR020 从命令行读入一个实数输入置于栈顶语法错误处理PL/0编译程序对语法错误处理采取两种措施:(1)对于部分易于校正错误,如丢了逗号、分号等,指出犯错位置,加以校正,继续进行分析。(2)对于难于校正错误,给犯错误位置和性质,跳过后面部分单词,直到下一个能够进行正常语法分析语法单位。错误类型以下0过程开始部分说明不正确1常数说明中"="写成":="2常数说明中"="后应为整数或实数或字符3常数说明中标识符后应是"="4const,var,procedure后应为标识符5遗漏了","或";"6过程说明后符号不正确(应该是语句开始符,或过程定义符)7应是语句开始符8程序体内语句部分后跟符不正确9程序结尾丢了句号"."10语句间漏了";"11标识符未说明12赋值语句中,赋值号左部标识符属性应是变量13变量后不能是此符号14call后应为标识符15call后标识符属性应为过程16条件语句中丢了"then"17丢了"end"或";"18while型循环语句丢了"do"19语句后符号不正确20应为关系运算符21表示式内标识符属性不能是过程22表示式中遗漏右括号"("23因子后非法符号24表示式开始符不能是此符号31数越界补充说明了:32read或write语句括号中标识符不是变量33read或write语句缺乏右括号")"34read或write语句缺乏左括号"("35read或write括号里应为变量自己增加了:45++或--后面应为变量46repeat缺乏until47for语句错误48for语句缺乏do49类型值不匹配50类型无法转换51只有整数能++或--52类型不正确TESTTESTSYM在S1中?打印犯错编号nS1:=S1+S2SYM在S1中?GETSYM返回YYNNTEST测试过程步骤图设计过程试验内容1.增加单词:保留字ELSE,FOR,TO,DOWNTO,REPEAT,UNTIL,RETURN运算符+=(PLUSBK),-=(MINUSBK),++(INC),--(DEC)首先要扩展SYMBOL,在此基础上再进行其它细节修改。要添加SYMBOL为:typedefenum{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,PROGSYM,ELSESYM,FORSYM,TOSYM,DOWNTOSYM,REPEATSYM,UNTILSYM,RETURNSYM,PLUSBK,MINUSBK,INC,DEC}SYMBOL;char*SYMOUT[]={"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","PROGSYM","ELSE","FOR","TO","DOWNTO","REPEAT","UNTIL","RETURN","PLUSBK","MINUSBK","INC”"DEC"};其中黑斜体为新加入SYMBOL。再将"ELSE","FOR","TO","DOWNTO",,"REPEAT","UNTIL","RETURN","PLUSBK","MINUSBK","INC","DEC"关键字加到KWORD和将对应SYM加到WSYM,按字母次序排列。和修改NEQ后以下void__fastcallTForm1::ButtonRunClick(TObject*Sender){for(CH='';CH<='^';CH++)SSYM[CH]=NUL;strcpy(KWORD[1],"BEGIN");strcpy(KWORD[2],"CALL");strcpy(KWORD[3],"CONST");strcpy(KWORD[4],"DEC");strcpy(KWORD[5],"DO");strcpy(KWORD[6],"DOWHILE");strcpy(KWORD[7],"DOWNTO");strcpy(KWORD[8],"ELSE");strcpy(KWORD[9],"END");strcpy(KWORD[10],"FOR");strcpy(KWORD[11],"IF");strcpy(KWORD[12],"INC");strcpy(KWORD[13],"MINUSBK");strcpy(KWORD[14],"ODD");strcpy(KWORD[15],"PLUSBK");strcpy(KWORD[16],"PROCEDURE");strcpy(KWORD[17],"PROGRAM");strcpy(KWORD[18],"READ");strcpy(KWORD[19],"REPEAT");strcpy(KWORD[20],"RETURN");strcpy(KWORD[21],"THEN");strcpy(KWORD[22],"TO");strcpy(KWORD[23],"VAR");strcpy(KWORD[24],"UNTIL");strcpy(KWORD[25],"WHILE");strcpy(KWORD[26],"WRITE");WSYM[1]=BEGINSYM;WSYM[2]=CALLSYM;WSYM[3]=CONSTSYM;WSYM[4]=DEC;WSYM[5]=DOSYM;WSYM[6]=DOWHILESYM;WSYM[7]=DOWNTOSYMs;WSYM[8]=ELSESYM;WSYM[9]=ENDSYM;WSYM[10]=FORSYM;WSYM[11]=IFSYM;WSYM[12]=INCSYM;WSYM[13]=MINUSBK;WSYM[14]=ODDSYM;WSYM[15]=PLUSBK;WSYM[16]=PROCSYM;WSYM[17]=PROGSYM;WSYM[18]=READSYM;WSYM[19]=REPEATSYM;WSYM[20]=RETURNSYM;WSYM[21]=THENSYM;WSYM[22]=TOSYM;WSYM[23]=VARSYM;WSYM[24]=UNTILSYM;WSYM[25]=WHILESYM;WSYM[26]=WRITESYM;SSYM['+']=PLUS;SSYM['-']=MINUS;SSYM['*']=TIMES;SSYM['/']=SLASH;SSYM['(']=LPAREN;SSYM[')']=RPAREN;SSYM['=']=EQL;SSYM[',']=COMMA;SSYM['.']=PERIOD;SSYM[';']=SEMICOLON;因为关键字增加到了26个,所以令constNORW=26;SYMBOL由原来33个值扩展为现在44个值,SYMOUT也由原来33个元素扩展为现在44个元素.我用个SYMMAX来统计SYMBOL值个数,所以,除了Error函数中可能出现作为参数“33”不被替换为“44”外,其它“33”均用“SYMMAX2.修改单词:不等号#改为<>只要修改GetSym()函数。当编译器检测到目前字符为“〈”时,接着检测下一个字符,假如是“〉”,则使SYM=NEQ。代码修改以下:if(CH=='<'){GetCh();if(CH=='='){SYM=LEQ;GetCh();}elseif(CH=='>'){SYM=NEQ;GetCh();}//增加<>为不等于号;elseSYM=LSS;}3.增加条件语句ELSE子句该条件语法描述图以下:语句语句只要在STATEMENT修改以下代码: caseIFSYM: GetSym(); CONDITION(SymSetUnion(SymSetNew(THENSYM,DOSYM),FSYS),LEV,TX); if(SYM==THENSYM)GetSym(); elseError(16); CX1=CX;GEN(JPC,0,0); STATEMENT(SymSetUnion(SymSetNew(ELSESYM),FSYS),LEV,TX);if(SYM!=ELSESYM)CODE[CX1].A=CX;//假如程序中没有else语句,实施JPC时跳到此地址else{//添加ELSE语句GetSym();CX2=CX;GEN(JMP,0,0);//跳过else语句CODE[CX1].A=CX;//假如程序中有else语句,实施JPC时跳到此地址STATEMENT(FSYS,LEV,TX);CODE[CX2].A=CX;//实施完then语句后跳出} break;ELSE子句扩充完成。课程设计内容1.增加运算符+=,-=,++,--词法分析在GetSym()中完成INC(++)、PLUSBK(+=)词法分析,代码修改以下:elseif(CH=='+'){GetCh();if(CH=='='){//增加+=SYM=PLUSBK;GetCh();}elseif(CH=='+'){//增加++SYM=INC;GetCh();}elseSYM=PLUS;}在GetSym()中完成DEC(--)、MINUSBK(-=)词法分析,代码修改以下:elseif(CH=='-'){GetCh();if(CH=='='){//增加-=SYM=MINUSBK;GetCh();}elseif(CH=='-'){//增加--SYM=DEC;GetCh();}elseSYM=MINUS;}b)扩充后++和后--操作存在INC和DEC操作语法图有以下两个:依据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加后INC和后DEC操作,首先对语句处理程序STATEMENT进行以下修改:CaseIDENT: i=POSITION(ID,TX); if(i==0)Error(11); else if(TABLE[i].KIND!=VARIABLE){/*ASSIGNMENTTONON-VARIABLE*/ Error(12);i=0; }GetSym(); if(SYM==BECOMES){GetSym();EXPRESSION(FSYS,LEV,TX); if(i!=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);}elseif(SYM==INC)//语句中++运算{if(i!=0)GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GEN(LIT,0,1);GEN(OPR,0,2);if(i!=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GetSym();}elseif(SYM==DEC)//语句中--运算{if(i!=0)GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GEN(LIT,0,1);GEN(OPR,0,3);if(i!=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GetSym();}在接收到SYM=IDENT后,假如SYM为INC,则关键实施这四条指令:GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR)将IDENT值放到栈顶,GEN(LIT,0,1);将常数1放到栈顶,GEN(OPR,0,2)次栈顶加栈顶,GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);将栈顶内容保留到IDENT中。这么就完成了语句中++运算。假如SYM为DEC,则关键实施这四条指令:GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR)将IDENT值放到栈顶,GEN(LIT,0,1);将常数1放到栈顶,GEN(OPR,0,3)次栈顶减栈顶,GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);将栈顶内容保留到IDENT中。这么就完成了语句中--运算。其次,再对因子处理程序FACTOR修改以下:if(SYM==IDENT){ i=POSITION(ID,TX); if(i==0)Error(11); else switch(TABLE[i].KIND){ caseCONSTANT:GEN(LIT,0,TABLE[i].VAL);GetSym();break; caseVARIABLE:GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GetSym();if(SYM==INC||SYM==DEC)//因子中++和--运算{GEN(LIT,0,1);if(SYM==INC)GEN(OPR,0,2);//假如为INC,则加1elseGEN(OPR,0,3);//不然减一GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将栈顶送入变量单元GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将变量送入栈顶GetSym();}break; casePROCEDUR:Error(21);break; } }这么,对后INC和后DEC操作就扩充完成c)扩充前++和前--操作存在前INC和前DEC操作语法图有以下两个: 语句语句++―-...........indentindent首先将STATBEGSYS[INC]=1; STATBEGSYS[DEC]=1; FACBEGSYS[INC]=1; FACBEGSYS[DEC]=1;其次依据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加前INC和前DEC操作,首先对语句处理程序STATEMENT进行以下修改:caseINC://前++GetSym();if(SYM==IDENT){i=POSITION(ID,TX); if(i==0)Error(11); elseif(TABLE[i].KIND!=VARIABLE){/*ASSIGNMENTTONON-VARIABLE*/Error(12);i=0;}if(i!=0)GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GEN(LIT,0,1);GEN(OPR,0,2);if(i!=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GetSym();}elseError(45);break;caseDEC://前--GetSym();if(SYM==IDENT){i=POSITION(ID,TX); if(i==0)Error(11); elseif(TABLE[i].KIND!=VARIABLE){/*ASSIGNMENTTONON-VARIABLE*/Error(12);i=0;}if(i!=0)GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GEN(LIT,0,1);GEN(OPR,0,3);if(i!=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GetSym();}elseError(45);break;再次,再对因子处理程序FACTOR修改以下:因子因子++―-...........indentindentelseif(SYM==INC){//前++GetSym();if(SYM==IDENT){i=POSITION(ID,TX); if(i==0)Error(11); elseif(TABLE[i].KIND!=VARIABLE){/*ASSIGNMENTTONON-VARIABLE*/Error(12);i=0;}if(i!=0)GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GEN(LIT,0,1);GEN(OPR,0,2);if(i!=0){GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将栈顶送入变量单元GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将变量送入栈顶}GetSym();}elseError(45);}elseif(SYM==DEC){//前--GetSym();if(SYM==IDENT){i=POSITION(ID,TX); if(i==0)Error(11); elseif(TABLE[i].KIND!=VARIABLE){/*ASSIGNMENTTONON-VARIABLE*/Error(12);i=0;}if(i!=0)GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GEN(LIT,0,1);GEN(OPR,0,3);if(i!=0){GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将栈顶送入变量单元GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将变量送入栈顶}GetSym();}elseError(45);}d)扩充+=和-=操作这两个操作全部是一个对变量进行赋值形式,其正当语句形式语法图以下所表示:依据图3,在语句处理STATEMENT中,在已经处理INC和DEC基础上,添加对PLUSBK(+=)运算和MINUSBK(-=)运算扩充,相关代码添加以下:elseif(SYM==PLUSBK)//增加运算符+={if(i!=0)GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GetSym();EXPRESSION(FSYS,LEV,TX);GEN(OPR,0,2);if(i!=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);}elseif(SYM==MINUSBK)//增加运算符-={if(i!=0)GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GetSym();EXPRESSION(FSYS,LEV,TX);GEN(OPR,0,3);if(i!=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);}这么就完成了对+=运算和-=运算添加。2.增加PascalFOR语句:a)格式以下: FOR<变量>:=<常数> TO(或DOWNTO)<常数> DO <语句>b)添加语句for语句语句语法图以下:首先,词法分析部分增加关键字在SYMBOL里增加FORSYM,TOSYM,DOWNTOSYM,对应SYMMAX=44;NORW=25;初始化中strcpy(KWORD[10],"FOR"); WSYM[10]=IFSYM;strcpy(KWORD[22],"TO"); WSYM[22]=TOSYM;strcpy(KWORD[7],"DOWNTO"); WSYM[7]=DOWNTOSYM;其次,修改STATEMENT,代码以下:caseFORSYM://添加FOR语句。GetSym();if(SYM!=IDENT)Error(47);elsei=POSITION(ID,TX); if(i==0)Error(11); elseif(TABLE[i].KIND!=VARIABLE){/*ASSIGNMENTTONON-VARIABLE*/ Error(12);i=0;}GetSym();if(SYM==BECOMES)GetSym(); elseError(13); EXPRESSION(SymSetUnion(SymSetNew(TOSYM,DOWNTOSYM),FSYS),LEV,TX); if(i!=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);if(SYM==TOSYM){//假如是to语句CX1=CX;//统计目前地址入口GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//取ident变量值到栈顶GetSym();EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX);//取表示式值到栈顶GEN(OPR,0,13);//判定变量是否小于或等于栈顶CX2=CX;GEN(JPC,0,0);GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GEN(LIT,0,1);GEN(OPR,0,2);GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //变量加一if(SYM==DOSYM){//实施DO后语句GetSym();STATEMENT(FSYS,LEV,TX);}elseError(48);GEN(JMP,0,CX1);CODE[CX2].A=CX;}elseif(SYM==DOWNTOSYM){//假如为down语句CX1=CX;GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GetSym();EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX);GEN(OPR,0,11);//变量大于或等于栈顶CX2=CX;GEN(JPC,0,0);GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);GEN(LIT,0,1);GEN(OPR,0,3);GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR); //变量减一if(SYM==DOSYM){//实施DO后语句GetSym();STATEMENT(FSYS,LEV,TX);}elseError(48);GEN(JMP,0,CX1);CODE[CX2].A=CX;}elseError(47);break;//添加FOR语句。FOR语句扩充完成。3.增加一维数组类型首先设置一维数组左右括号:ssym['[']=lepa;//一维数组左括号[ssym[']']=ripa;//一维数组右括号]增加指令:strcpy(&(mnemonic[gar][0]),"gar");//依据栈顶偏移地址从数组中取值到新栈顶strcpy(&(mnemonic[sar][0]),"sar");//依据次栈顶偏移地址把栈顶值存入数组strcpy(&(mnemonic[shd][0]),"shd");//将栈顶值下移到次栈顶,栈顶出栈,即次栈顶成为栈顶strcpy(&(mnemonic[del][0]),"del");//出栈顶strcpy(&(mnemonic[jud][0]),"jud");//判定数组下标正当性strcpy(&(mnemonic[tra][0]),"tra");//将数组下标范围入栈,gendo(tra,0,数组下标最大值);增加标识符类型属性:/*--标识符类型属性--*/enumobject{constant,variable,procedur,array,//数组};在block()函数中添加以下代码:for(i=tx0+1;i<=tx;i++){switch(table[i].kind){caseconstant: printf("%dconst%s",i,table[i].name); printf("val=%d\n",table[i].val); fprintf(fas,"%dconst%s",i,table[i].name); fprintf(fas,"val=%d\n",table[i].val);break;casevariable:printf("%dvar%s",i,table[i].name);printf("lev=%daddr=%d\n",table[i].level,table[i].adr);fprintf(fas,"%dvar%s",i,table[i].name);fprintf(fas,"lev=%daddr=%d\n",table[i].level,table[i].adr);break;caseprocedur:printf("%dproc%s",i,table[i].name);printf("lev=%daddr=%dsize=%d\n",table[i].level,table[i].adr,table[i].size); fprintf(fas,"%dproc%s",i,table[i].name); fprintf(fas,"lev=%dadr=%dsize=%d\n",table[i].level,table[i].adr,table[i].size); break; casearray://数组变量 printf("%dvar-array%s",i,table[i].name); printf("lev=%daddr=%dsize=%d\n",table[i].level,table[i].adr,table[i].size); fprintf(fas,"%dvar-array%s",i,table[i].name);fprintf(fas,"lev=%daddr=%dsize=%d\n",table[i].level,table[i].adr,table[i].size); } }在enter()函数添加以下代码: switch(k) { caseconstant:/*常量名字*/ if(num>amax) { error(31); num=0; } table[(*ptx)].val=num; break; casevariable:/*变量名字*/ table[(*ptx)].level=lev; table[(*ptx)].adr=(*pdx); table[(*ptx)].size=0; (*pdx)++; break;/*过程名字*/ caseprocedur: table[(*ptx)].level=lev; break; casearray:/*数组名字*/ table[(*ptx)].level=lev; table[(*ptx)].adr=(*pdx)-arraysize; table[(*ptx)].size=arraysize; break; }在Vardeclaration()函数中添加数组变量申明,代码以下:intvardeclaration(int*ptx,intlev,int*pdx){ inti; charidtemp[al+1];//临时保留数组名字 if(sym==ident) { strcpy(idtemp,id); getsymdo; //假如是数组 if(sym==lepa)//数组左中括号 { getsymdo; if(sym==number)//a[]中中括号里是数字话 { *pdx=*pdx+num;//为数组分配空间 arraysize=num;//保留数组长度 } else { if(sym==ident)//a[]中中括号里是变量话 { //要检验是不是以申明常量 i=position(id,*ptx);//查找名字表 if(i==0) { error(11);//标识符未说明 } else { if(table[i].kind==constant)//标识符属性是常量 { *pdx=*pdx+table[i

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论