《PL0编译原理课程设计(3109006080何路生)(共25页).doc》由会员分享,可在线阅读,更多相关《PL0编译原理课程设计(3109006080何路生)(共25页).doc(25页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、精选优质文档-倾情为你奉上课 程 设 计 课程名称_ 编译原理_ _题目名称_编译原理课程设计_ _学生学院_ 计算机学院_专业班级_ 09级计科5班 _学 号 学生姓名_ 何路生_指导教师_张巍_2011 年 12 月29 日一 课程设计目的在分析理解一个教学型编译程序(如PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。达到进一步了解程序编译过程的基本原理和基本实现方法的目的。二 课程设计要求课内实验:对PL/0作以下修改扩充:(1)增加单词:保留字 ELSE,FOR,STEP,UNTIL,RETURN运算符 +=,-=,+,-,(2)修改单词:不等号# 改
2、为 (3)增加条件语句的ELSE子句,要求:写出相关文法,语法图,语义规则。课程设计:基本内容(成绩范围:“中”、“及格”或“不及格”)(1)扩充赋值运算:+= 和 -=(2)扩充语句(Pascal的FOR语句):FOR := STEP UNTIL DO (3)增加运算:+ 和 -。选做内容(成绩评定范围扩大到:“优”和“良”)(1)增加类型: 字符类型; 实数类型。(2)扩充函数: 有返回值和返回语句; 有参数函数。(3)增加一维数组类型(可增加指令)。(4)其他典型语言设施。三 课程设计环境与工具(1)计算机及操作系统:PC机,Windows7(2)实现工具:C+Builder6(3)教学
3、型编译程序:PL/0 四 结构设计说明a) PL/0编译程序的结构图Pl0 源 程 序词法分析程序语法分析程序代码生产程序目 标 程 序表 格 管 理 程 序出 错 处 理 程 序b) PL/0编译程序的过程或函数的功能表1、void Error(int n) :错误处理,打印出错位置和错误编码2、void GetCh():漏掉空格,读取一个字符3、void GetSym():词法分析,读取一个单词4、void GEN(FCT X, int Y, int Z):生成目标代码,并送入目标程序区5、void TEST(SYMSET S1, SYMSET S2, int N):测试当前单词符号是否合
4、法6、void ENTER(OBJECTS K, int LEV, int &TX, int &DX):登录名字表7、int POSITION(ALFA ID, int TX):查找标识符在名字表中的位置8、void ConstDeclaration(int LEV,int &TX,int &DX):常量说明处理9、void VarDeclaration(int LEV,int &TX,int &DX):变量说明处理10、void CharDeclaration(int LEV,int &TX,int &DX):字符说明处理11、void RealDeclaration(int LEV,int
5、 &TX,int &DX):实数说明处理12、void ListCode(int CX0):列出目标代码清单13、void FACTOR(SYMSET FSYS, int LEV, int &TX) :因子处理14、void TERM(SYMSET FSYS, int LEV, int &TX) :项处理15、void EXPRESSION(SYMSET FSYS, int LEV, int &TX):表达式处理16、void CONDITION(SYMSET FSYS,int LEV,int &TX) :条件处理17、void STATEMENT(SYMSET FSYS,int LEV,in
6、t &TX) :语句部分处理18、void Block(int LEV, int TX, SYMSET FSYS) :分程序分析处理过程19、int BASE(int L,int B,int S):通过静态链求出数据区的基地址20、void Interpret() :对目标代码的解释执行程序21、void _fastcall TForm1:ButtonRunClick(TObject *Sender):进行编译,RUNc) PL/0编译程序的总体流程图启动置初值调用getsym取单词调用block过程是否为源程序结束符源程序是否有错误调用解释过程interpret解释执行目标执行目标程序结束出
7、错打印错误NNYYd) 词法分析词法分析是编译的第一个阶段,它的主要任务是从左向右逐个字符地对源程序进行扫描,产生一个个单词序列用于语法分析。PL/0词法分析程序GETSYM的功能是为语法分析提供单词用的,是语法分析的基础,把输入的字符串形式的源程序分割成一个个单词符号。经过词法分析程序分析出来的单词,对语言固有的单词只给出类别存放在全程变量SYM中,而对用户定义的单词(标识符或常数)既给出类别又给值,其类别放在SYM中,值放在全程变量ID或全程变量NUM中,全部单词种类由编译程序定义的纯量类型SYMBOL给出,称为语法词汇表。词法分析程序GETSYM将完成下列任务:(1)滤空格 (2)识别保
8、留字 (3)识别标识符(4)拼数 (5)拼复合词 (6)输出源程序e) 语法分析PL/0编译程序的语法分析采用了自顶向下的递归的子程序法。语法分析同时也根据程序的语义生成相应三元代码,并提供了出错处理的机制。语法分析主要由分程序分析过程(BLOCK)、常量定义分析过程(ConstDeclaration)、变量定义分析过程(Vardeclaration)、语句分析过程(Statement)、表达式处理过程(Expression)、项处理过程(Term)、因子处理过程(Factor)和条件处理过程(Condition)构成。这些过程在结构上构成一个嵌套的层次结构。f) 语义分析PL/0 的语义分析
9、主要进行以下检查:(1) 是否存在标识符先引用未声明的情况;(2) 是否存在己声明的标识符的错误引用;(3) 是否存在一般标识符的多重声明。g) 中间代码生成h) 语法错误处理PL/0编译程序对语法错误的处理采用两种办法:(1)对于一些易于校正的错误,如丢了逗号、分号等,指出出错的位置,加以校正,继续进行分析。 (2)对于难于校正的错误,给出错误的位置与性质,跳过后面一些单词,直到下一个可以进行正常语法分析的语法单位。错误类型如下0 过程开始部分说明不正确1 常数说明中=写成:=2 常数说明中=后应为整数或实数或字符3 常数说明中的标识符后应是=4 const, var, procedure后
10、应为标识符5 漏掉了,或;6 过程说明后的符号不正确(应该是语句开始符,或过程定义符)7 应是语句开始符8 程序体内语句部分的后跟符不正确9 程序结尾丢了句号.10 语句间漏了;11 标识符未说明12 赋值语句中,赋值号左部标识符属性应是变量13 变量后不能是此符号14 call后应为标识符15 call后标识符属性应为过程16 条件语句中丢了then17 丢了end或;18 while型循环语句丢了do19 语句后的符号不正确20 应为关系运算符21 表达式内标识符属性不能是过程22 表达式中漏掉右括号(23 因子后的非法符号24 表达式的开始符不能是此符号31 数越界五 设计过程(一) 课
11、内实验内容(1)增加单词:保留字 ELSE(ELSESYM),FOR(FORSYM),STEP(STEPSYM),UNTIL(UNTILSYM),RETURN(SYM)运算符 +=(ADDEQUALSYM),-=(MINUSEQUALSYM),+(INCSYM),-(DECSYM),(ANDSYM),(ORSYM),(NOTSYM)typedef enum NUL, IDENT, NUMBER, PLUS, MINUS, TIMES, SLASH, ODDSYM, EQL, NEQ, LSS, LEQ, GTR, GEQ, LPAREN, RPAREN, COMMA, SEMICOLON, P
12、ERIOD, BECOMES, BEGINSYM, ENDSYM, IFSYM, THENSYM, WHILESYM, WRITESYM, READSYM, DOSYM, CALLSYM, CONSTSYM, VARSYM, PROCSYM, PROGSYM , ELSESYM , FORSYM,STEPSYM,UNTILSYM,RETURNSYM , ANDSYM,ORSYM,NOTSYM,LESSTHAN,MORETHAN, ADDEQUALSYM,MINUSEQUALSYM,INCSYM,DECSYM,CHARSYM,INTSYM,REALSYM,OFSYM SYMBOL; /51cha
13、r *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 , ELSESYM,FORSYM,STEPSYM,UNTILSYM,RETU
14、RNSYM, ANDSYM,ORSYM,NOTSYM,LESSTHAN,MORETHAN ADDEQUAL,MINUSEQUAL,INC,DEC,CHARSYM,INTSYM,REALSYM,OFSYM;其中黑斜体为新加入的SYMBOL。再将上述黑斜体关键字加到KWORD和将相应的SYM加到WSYM,按字母顺序排列void _fastcall TForm1:ButtonRunClick(TObject *Sender) for (CH= ; CH=; CH+) SSYMCH=NUL; strcpy(KWORD 1,ADDEQUAL);strcpy(KWORD 2,BEGIN); strcpy(
15、KWORD 3,CALL);strcpy(KWORD4,CHAR); strcpy(KWORD5,CONST);strcpy(KWORD6,DEC); strcpy(KWORD 7,DO); strcpy(KWORD 8,ELSE); strcpy(KWORD 9,END);strcpy(KWORD 10,FOR); strcpy(KWORD 11,IF);strcpy(KWORD 12,INC); strcpy(KWORD13,INT);strcpy(KWORD 14,MINUSEQUAL); strcpy(KWORD 15,ODD); strcpy(KWORD 16,PROCEDURE);
16、 strcpy(KWORD 17,PROGRAM); strcpy(KWORD18,READ); strcpy(KWORD19,REAL);strcpy(KWORD 20,RETURN); strcpy(KWORD 21,STEP);strcpy(KWORD22,THEN); strcpy(KWORD23,UNTIL);strcpy(KWORD24,VAR); strcpy(KWORD25,WHILE);strcpy(KWORD26,WRITE); /添加了 保留字 ELSE,FOR,STEP,UNTIL,RETURN ,CHAR ,INT , REAL WSYM 1=ADDEQUALSYM;
17、WSYM 2=BEGINSYM; WSYM 3=CALLSYM;WSYM 4=CHARSYM;WSYM 5=CONSTSYM; WSYM 6=DECSYM;WSYM 7=DOSYM; WSYM 8=ELSESYM; WSYM 9=ENDSYM; WSYM 10=FORSYM; WSYM11=IFSYM; WSYM 12=INCSYM;WSYM 13=INTSYM;WSYM 14=MINUSEQUALSYM; WSYM 15=ODDSYM; WSYM 16=PROCSYM; WSYM 17=PROGSYM; WSYM18=READSYM;WSYM19=REALSYM; WSYM 20=RETUR
18、NSYM; WSYM21=STEPSYM; WSYM22=THENSYM; WSYM 23=UNTILSYM; WSYM24=VARSYM; WSYM25=WHILESYM; WSYM26=WRITESYM; SSYM+=PLUS; SSYM-=MINUS; SSYM*=TIMES; SSYM/=SLASH; SSYM(=LPAREN; SSYM)=RPAREN; SSYM=EQL; SSYM,=COMMA; SSYM.=PERIOD; SSYM#=NEQ; SSYM;=SEMICOLON; SSYM=MORETHAN;SSYM&=ANDSYM; SSYM|=ORSYM;SSYM!=NOTSY
19、M;(二) 课程设计内容1. 增加运算符+=,-=,+,-a) 词法分析 在GetSym()中完成INC(+ +)、DEC(- -)、ADDEQUAL(=)、MINUSEQUAL(- =)的词法分析,代码修改如下:/-GetSym()增加功能- else if(CH = +) GetCh(); if(CH = =) /增加+= SYM = ADDEQUALSYM; GetCh(); else if(CH = +) /增加+ SYM = INCSYM; GetCh(); else SYM = PLUS; else if(CH = -) GetCh(); if(CH = =) /增加-= SYM
20、= MINUSEQUALSYM; GetCh(); else if(CH = -) /增加- SYM = DECSYM; GetCh(); else SYM = MINUS; else SYM=SSYMCH; GetCh(); b) 后+ +和后- -的实现根据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加 后INC 和 后DEC 操作,首先对语句处理程序STATEMENT进行如下修改:根据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加 后INC 和 后DEC 操作,首先对语句处理程序STATEMENT进行如下修改:根据以上语法图,我们只
21、要对语句处理程序和因子处理程序进行修改添加,即可实现增加 后INC 和 后DEC 操作,首先对语句处理程序STATEMENT进行如下修改:/-后的+ -case IDENT:. else if (SYM=INCSYM) /语句中的+运算 if (i!=0) GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GEN(LIT,0,1); GEN(OPR,0,2); if (i!=0) GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GetSym(); else if (SYM=DECSYM) /语句中的-运算 if (i
22、!=0) GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GEN (LIT,0,1); GEN (OPR,0,3); if (i!=0) GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GetSym (); break;在接受到SYM=IDENT后,如果SYM为INC,则主要执行这四条指令:GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR) 将IDENT的值放到栈顶,GEN(LIT,0,1); 将常数1放到栈顶,GEN(OPR,0,2) 次栈顶加栈顶,GEN(STO,LEV-TAB
23、LEi.vp.LEVEL,TABLEi.vp.ADR);将栈顶内容保存到IDENT中。这样就完成了语句中的+运算。如果SYM为DEC,则主要执行这四条指令:GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR) 将IDENT的值放到栈顶,GEN(LIT,0,1); 将常数1放到栈顶,GEN(OPR,0,3) 次栈顶减栈顶,GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);将栈顶内容保存到IDENT中。这样就完成了语句中的-运算。其次,再对因子处理程序FACTOR修改如下:if(SYM=INCSYM|SYM=DECSYM) /因子
24、中的+和-运算 count.length+; count.idcount.length=i; GEN(LIT,0,1); if(SYM=INCSYM) GEN(OPR,0,2);count.icount.length=1; GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/将栈顶送入变量单元 GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /将变量送入栈顶 GEN(LIT,0,-1); GEN(OPR,0,2); /如果为INC,则加1 else GEN(OPR,0,3);count.icount.length=-1
25、; GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/将栈顶送入变量单元 GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /将变量送入栈顶 GEN(LIT,0,1);GEN(OPR,0,2); /否则减一对后+和后的处理思想是,在表达式中不进行自加/自减操作,但在送往变量的时候进行c) 前+和前-的实现语法树:语句+indentindent根据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加 前INC 和 前DEC 操作,首先对语句处理程序STATEMENT进行如下修改:/- 前的+- ca
26、se INCSYM: /前+ GetSym(); if (SYM = IDENT) i=POSITION(ID,TX); if (i=0) Error(11); else if (TABLEi.KIND!=VARIABLE) /*ASSIGNMENT TO NON-VARIABLE*/ Error(12); i=0; if (i!=0) GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GEN(LIT,0,1); GEN(OPR,0,2); if (i!=0) GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GetS
27、ym(); else Error(45); break; case DECSYM: /前- GetSym(); if (SYM = IDENT) i=POSITION(ID,TX); if (i=0) Error(11); else if (TABLEi.KIND!=VARIABLE) /*ASSIGNMENT TO NON-VARIABLE*/ Error(12); i=0; if (i!=0) GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GEN (LIT,0,1); GEN (OPR,0,3); if (i!=0) GEN(STO,LEV-TAB
28、LEi.vp.LEVEL,TABLEi.vp.ADR); GetSym (); else Error(45); break;再对因子处理,对于前+、前-,只在EXPRESSION中处理,因子部分只处理后+、后操作因子+indentindentelse if(SYM = INCSYM) /前+ GetSym(); if (SYM = IDENT) i=POSITION(ID,TX); if (i=0) Error(11); else if (TABLEi.KIND!=VARIABLE) /*ASSIGNMENT TO NON-VARIABLE*/ Error(12); i=0; if (i!=0
29、) GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GEN(LIT,0,1); GEN(OPR,0,2); if (i!=0) GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /将栈顶送入变量单元 GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /将变量送入栈顶 GetSym(); else Error(45); else if(SYM = DECSYM) /前- GetSym(); if (SYM = IDENT) i=POSITION(ID,TX); if (i=0) E
30、rror(11); else if (TABLEi.KIND!=VARIABLE) /*ASSIGNMENT TO NON-VARIABLE*/ Error(12); i=0; if (i!=0) GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GEN (LIT,0,1); GEN (OPR,0,3); if (i!=0) GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /将栈顶送入变量单元 GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /将变量送入栈顶 GetSym ()
31、; else Error(45); d) 扩充+=和-=操作语法树:根据图3,在语句处理STATEMENT中,在已经处理INC和DEC的基础上,添加对ADDEQUAL(+=)运算和MINUSEQUAL(-=)运算的扩充,相关代码添加如下:case IDENT:else if (SYM=ADDEQUALSYM) /增加运算符+= if (i!=0) GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GetSym(); EXPRESSION(FSYS,LEV,TX); GEN(OPR,0,2); if (i!=0) GEN(STO,LEV-TABLEi.vp.
32、LEVEL,TABLEi.vp.ADR); else if (SYM=MINUSEQUALSYM) /增加运算符-= if (i!=0) GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); GetSym(); EXPRESSION(FSYS,LEV,TX); GEN(OPR,0,3); if (i!=0) GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); break;2. 增加Pascal的FOR语句:表达式UNTIL表达式STEPE表达式:=ident/-添加FOR功能 case FORSYM: GetSym(); i
33、f(SYM != IDENT) Error(47); else i=POSITION(ID,TX);if(i = 0) Error(11);else if (TABLEi.KIND!=VARIABLE) /*ASSIGNMENT TO NON-VARIABLE*/Error(12); i=0; GetSym(); if(SYM = BECOMES) GetSym();else Error(13); EXPRESSION(SymSetUnion(SymSetNew(STEPSYM),FSYS),LEV,TX);if(i != 0) GEN(STO,LEV-TABLEi.vp.LEVEL,TABL
34、Ei.vp.ADR); /把栈顶的值送到变量 / GetSym(); if(SYM=STEPSYM) GetSym(); else Error(46); CX1=CX;GEN(JMP,0,0); CX3=CX; EXPRESSION(SymSetUnion(SymSetNew(UNTILSYM),FSYS),LEV,TX); GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /将变量送回栈顶 GEN(OPR,0,2); GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/把栈顶的值送到变量 / GetSym(); if(SYM=UNTILSYM) GetSym(); else Error(47); CODECX1.A=CX; EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX); /终止条件 GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /将变量送回栈顶 GEN(OPR,0,11); CX2=CX;GEN(JPC,0,0); / G