编译原理实验报告.docx_第1页
编译原理实验报告.docx_第2页
编译原理实验报告.docx_第3页
编译原理实验报告.docx_第4页
编译原理实验报告.docx_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

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

文档简介

编译原理实验报告指导教师: 20一. 实验目的基本掌握计算机语言的词法分析程序的开发方法。以及掌握计算机语言的语 法分析程序设计与属性文法应用的实现方法。锻炼自己的编程能力和逻辑思维能 力,体会计算机编译器的奥妙之处二. 实验内容1编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法 分析程序。2.给定下列文法: Sid=E; Sif C then S Swhile C do S CEE CE=E用递归子程序法设计并实现语法分析程序,按照生成顺序输出产生式3.在第四章上机题的基础上,补充以下的语义处理功能,形成一个将源程序翻译成三地址代码序列的翻译程序:将表达式、赋值语句翻译成三地址代码将 If 条件语句、While 循环语句翻译成三地址代码三. 实验要求1 编制正规式以及正规文法,画出状态图;2 根据状态图,设计词法分析函数int scan( ),完成以下功能:1) 从键盘读入数据,分析出一个单词。2) 返回单词种别(用整数表示),3) 返回单词属性(不同的属性可以放在不同的全局变量中)。3 编写测试程序,反复调用函数scan( ),输出单词种别和属性。4 改写文法,构造语法分析程序,要求按照最左派生的顺序输出派生的产 生式序列;5 改写语法分析程序,构造三地址代码生成程序。6 处理的源程序存放在文件中,它可以包含多个语句;四系统设计完成整个系统,实现本个实验的要求,需要两个比较大的模块:词法分析器 和语法分析器。词法分析器的功能是将输入的程序串分解成一个一个独立的单词,并且记录 下每个单词的类型以及数值。这里词法分析器的实现有两种方法:调用一次词法 分析器,返回一个词的类型以及数值,以此类推;还有一种方法是条用一次词法 分析器将程序串的所有单词都分解出来并保存到一个地方(比如线形表)以便将 来使用。我采用的是前者,因为这样只需要对整个程序访问一遍语法分析器的功能是将已经分解好的单词按照一定的规范(产生式)组合起 来,由此来确定输入程序的意思。我的设计是“语法分析器调用词法分析器”, 当语法分析其分析进行不下去的时候调用词法分析器获取一个单词,继续进行分 析。而语义功能是镶嵌在语法分析其当中的,当语法分析器分析出用什么产生式 的时候作相应的语义处理。五系统实现词法分析器的实现词法的正规式描述标识符:|(|)*(|_|.) (|)*十 进 制 数 : (0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*)( |.)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*八进制数:0(0|(1|2|3|4|5|6|7) (0|1|2|3|4|5|6|7)*) (|.)(0|1|2|3|4|5|6|7) (0|1|2|3|4|5|6|7)*十六进制数:0x(0(|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f) (0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*) (|.)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f) (0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*运算符和分隔符:+ - * / = ( ) ;关键字:if then else while do、改变后的正规文法- - 0 - 0x -+| - |* |/ | |= |( | ) |;-if| then| else |while |do-a|b|c|d|e|f|g|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q| R|S|T|U|V|W|X|Y|Z-0|1|2|3|4|5|6|7|8|9- (|)|- (|_|.)- (|.)- (0|1|2|3|4|5|6|7)|- (0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f) |将状态合起来,得:(0)-(1)|0(4)|(12)|(17) (1)-(1)|. (2)(2)-(3) (3)-(3)(4)-.(2)|(5)|0(13)|x(8)|X(8) (5)-(5)|.(6)(6)-(7) (7)-(7)(8)-(9)|(9)|0(14) (9)-(9)|(9)|.(10) (10)-(11)|(11) (11)-(11)|(11)(12)-(12)|(12)|(12)|.(15)|_(15) (13)-.(6)(14)-.(10)(15)-(16)|(16)|(16) (16)-(16)|(16)|(16)、状态图:09091.230919.0707567004.170.1307x|X字母81f0f9.100f0f11分隔符12.|_014.字母或数字1516字母或数字17字母或数字、数据结构:char* arrBao5 = if,then,else,do,while;/保留字表typedef structchar typeTYPE_MAX;char valueVALUE_MAX;CNode;/词法分析的节点,保留分析出的 token 的种类和值、算法(伪码):bool MyScan(FILE* fp,CNode* &node)char temp; /当前读取的字符char s100;/保留字符串int si = 0; /对于控制 s 的下标int state = 0;/当前状态号node = new CNode;/返回的节点while(1)读取一个字符到 temp;if(temp = #) strcpy(node-type,#); strcpy(node-value,_); return false; /表示文件结束switch(state)case 0: /状态 0if(temp 为 0)state=4;添加当前字符; continue; if(temp 为 1 到 9) state=1;添加当前字符; continue; if(temp 为字母)state=12;添加当前字符; continue; if(temp 为分隔符) 保存相应的分隔符到 node;return true;if(temp 为空格或回车或 tab) continue;/忽略多个空格和回车和制表符else 出错处理; return false;case 1: /状态 1if(temp 为数字) state=4; 添加当前字符; continue; if(temp 为小数点) state=2; 添加当前字符; continue; if(temp 为分隔符) 保存为 INT10; return true;else 出错处理; return false;case 2: /状态 2if(temp 为数字) state=3;添加当前字符; continue;else 出错处理; return false;case 3: /状态 3if(temp 为数字) state=3;添加当前字符; continue;if(temp 为分隔符)保存为 REAL10;return true;else 出错处理; return false;case 4: /状态 4if(temp 为小数点)state=2;添加当前字符; continue; if(temp 为 17) state=5;添加当前字符; continue; if(temp 为 0)state=13;添加当前字符; continue; if(temp 为 x 或 X) state=8;添加当前字符; continue; if(temp 为分隔符) 保存为 INT10; return true;else 出错处理; return false;case 5: /状态 5if(temp 为小数点)state=6;添加当前字符; continue; if(temp 为 07) state=5;添加当前字符; continue; if(temp 为分隔符) 保存为 INT8;return true;else 出错处理; return false;case 6: /状态 6if(temp 为 07) state=7;添加当前字符; continue;else 出错处理; return false;case 7: /状态 7if(temp 为 07) state=7;添加当前字符; continue;if(temp 为分隔符)保存为 INT8;return true;else 出错处理; return false;case 8: /状态 8if(temp 为十六进制数)state=9;添 加 当 前 字 符 ;continue;if(temp 为 0)state=14;添 加 当 前 字 符 ;continue;else 出错处理; return false;case 9: /状态 9if(temp 为十六进制数)state=9;添 加 当 前 字 符 ;continue;if(temp 为小数点)state=10;添 加 当 前 字 符 ;continue;if(temp 为分隔符)保存为 INT16; return true;else 出错处理; return false;case 10:/状态 10if(temp 为十六进制数)state=11;添 加 当 前 字 符 ;continue;else 出错处理; return false;case 11:/状态 11if(temp 为十六进制数)state=11;添 加 当 前 字 符 ;continue;if(temp 为分隔符)保存为 INT16; return true;else 出错处理; return false;case 12:/状态 12if(temp 为数字或者字母)state=12;添加当前字符 ;continue;if(temp 为_或者.)state=15;添加当前字符 ;continue;if(temp 为分隔符)if(为保留字) 保存为保留字; return true;else 保存为 IDN;return true;else 出错处理; return false;case 13:/状态 13if(temp 为.) state=6;添加当前字符; continue; if(temp 为分隔符)保存为 INT8;return true; else 出错处理; return false;case 14:/状态 14if(temp 为.) state=10;添加当前字符; continue;if(temp 为分隔符)保存为 INT16; return true;else 出错处理; return false;case 15:/状态 15if(temp 为数字或者字母)state=16;添加当前字符 ;continue;if(temp 为分隔符)if(为保留字) 保存为保留字; return true;else 保存为 IDN;return true;else 出错处理; return false;case 16:/状态 16if(temp 为数字或者字母)state=16;添加当前字符 ;continue;if(temp 为分隔符)if(为保留字) 保存为保留字; return true;else 保存为 IDN;return true;else 出错处理; return false;/switch/while/主函数源程序int main() FILE* fp; fp=fopen(code1.txt,r); CNode* node; while(MyScan(fp,node) if(node != NULL)/分析成功printf(%st%sn,node-type,node-value);else printf(n);fclose(fp); getchar(); return 0;、测试测试用例:0 92+data 0x3f 00 while a+accxx do x=x-1;a=6.2+a*0X88.80;if ab then a=b else a=b-1+c;# 测试用例说明:本测试用例测试了十进制数,八进制数,十六进制数,十进制0, 八进制0,十进制小数,八进制小数,十六进制小数,各个关键字以及分隔符, 对于空格,回车,制表符的测试,基本上全了。由于词法分析器中不支持续编译(理由已在上面阐述),所以出错的例子无法在一个文件中给出,这里忽略。 分析的结果如下:(三)使用递归子程序法做三地址码生成器写在前面:递归子程序法的基本思路是:给每一个变量都编写一个函数,产 生式中如果存在变量则调用相应的程序。主函数中调用最开始的程序。这种方法 的思路非常清晰,容易理解,易于控制。我的理解是如果采用此种方法文法可以不是 LL(1)的,原因如下:首先, 文法必须是没有左递归的,否则系统栈会溢出。但是最左公因子可以不用提取出 来:在一个程序中可以先统一做某些操作,然后根据不同的 token 决定接下来走 哪一个分支。而这些“统一的操作”就是最左公因子。所以为了实现简便,也更 容易理解,我没有提取最左公因子。另外,这种方法中可以存在形如 A-B(+B) * 的产生式,因为在用子程序的时候这种产生式可以用循环控制(循环条件为下一 个 token 为+),将两者结合起来,如下的产生式 E-T1(+|-)T2)*也是合法的, 但用预约分析表决不允许这样的产生式出现,这也是递归子程序这种方法的灵活 以及更贴近最原始的产生式的体现。之后,在确定了程序应该进入那个分支后,需要在相应的分支之前加入语义 规则。以此来实现三地址码的生成。、语义规则。用递归子程序时,最左公因子可以不用提取,原因见上SS;S.next = 0;S.code = S.code|gen(S.next, ” :”)SID = ES.code = E.code|gen(IDN,”=”,E.place)Sif C then S1XC-isTrue = newlabel();X-begin = S-next;C-isFalse = X-begin;S1-next = X-begin;X-next = S1-next;S.code = C.code|gen(C.isTrue”:”)|S1.code|tmpX.codeX else SX.next = newlabel();S.next = X.next;S.begin = X.begin; X.iselse = true;X.code=gen(“goto”,X.next)|gen(X.begin,”:”)|S.codeX nullX.next = X.begin; X.iselse = false; X.code =”Swhile C doS1tmplabel = S.begin;S.begin = newlabel();C.isTrue =newlabel();S1.begin = tmpC-isTrue;C.isFalse = tmpS-next; S1.next = tmpS-begin; S.code=gen(S.begin,”:”)|C.code|gen(C.isTrue,”:”)|S1.code|gen(got o,S.begin)C E1E2C.code=E1.code|E2.code|gen(“if”,E1.place,”,E2.place)|gen(“goto”,C.isTrue)|gen(“goto”,C.isFalse)C E1E2C.code=E1.code|E2.code|gen(“if”,E1.place,”,E2.place)|gen(“goto”,C.isTrue)|gen(“goto”,C.isFalse)CE1=E2C.code=E1.code|E2.code|gen(“if”,E1.place,”=”,E2.place)|gen(“goto”,C.isTrue)|gen(“goto”,C.isFalse)ET1(+|-)T2)*If ET E.code = T.code; E.place = T.place; ElseE.place=newtemp()E.code=T1.code|T2.code|gen(E.place,”=”,T1.place,+or-,T2.place) T1.code=E.code;T1.place=E.place;TF1(*|/)F2)*If TF T.code = F.code; T.place = F.place; ElseT.place=newtemp() T.code=F1.code|F2.code|gen(T.place,”=”,F1.place,*or/,F2.place) F1.code=T.code;F1.place=T.place;F (E)F.place=E.place;F.code=E.code;FidF.place=;F.code=;Fint8F.place=int8.value;F.code=;Fint10F.place=int10.value;F.code=;Fint16F.place=int16.value;F.code=;、三地址码生成的数据结构typedef struct/Schar codeCODE_MAX;str_S_;typedef struct/Schar codeCODE_MAX;int begin,next;str_S;typedef struct/Xchar codeCODE_MAX;int begin,next;bool iselse;str_X;typedef struct/Cchar codeCODE_MAX;int isFalse,isTrue;str_C;typedef struct/Echar codeCODE_MAX;char placeVALUE_MAX;str_E;typedef struct/Tchar codeCODE_MAX;char placeVALUE_MAX;str_T;typedef struct/Fchar codeCODE_MAX;char placeVALUE_MAX;str_F;、语义分析的主要程序bool MyFunction_S_(FILE* fp, str_S_* &tmpS_) /S CNode* node;str_S* tmpS = new str_S;tmpS-next = 0; Lnum = 0;if(MyFunction_S(fp,tmpS) /调用 Sif(strcmp(Node-type,;)=0) /匹配;if(Lnum != 0)/需要有跳转sprintf(tmpS_-code,%snL%d:,tmpS-code,tmpS-next);else/不需要跳转sprintf(tmpS_-code,%sn,tmpS-code);return true;return false;bool MyFunction_S (FILE* fp, str_S* &tmpS)/S CNode* node;str_E* tmpE = new str_E; str_C* tmpC = new str_C; str_S* tmpS1= new str_S; str_X* tmpX = new str_X;if(getNext(fp) /读取一个字符if(strcmp(Node-type,IDN)=0) /如果为变量,走变量分支 char* tmpName = Node-value;/记录变量名 if(getNext(fp) /匹配变量/产生式匹配if(strcmp(Node-type,=)=0)/检查下是否为=if(getNext(fp)/匹配=if(MyFunction_E(fp,tmpE)/递归执行程序 E/语义操作sprintf(tmpS-code,%s%s=%sn,tmpE-code,tmpName,tmpE-place);return true;thenelse if (strcmp(Node-type,if)=0)/如果为 if,走 if 分支if(getNext(fp)/匹配 if tmpC-isTrue = newlabel();tmpX-begin = tmpS-next;/newlabel();tmpC-isFalse = tmpX-begin; tmpS1-next = tmpX-begin; tmpX-next = tmpS1-next;/产生式匹配if(MyFunction_C(fp,tmpC)/递归执行程序 Cif(strcmp(Node-type,then)=0) /检查当前字符是否为if(MyFunction_S(fp,tmpS1)/递归执行程序 Sif(MyFunction_X(fp,tmpX) /递归执行程序 X/语义操作if(tmpX-iselse)tmpS-next = tmpX-next;sprintf(tmpS-code,%sL%d :n%s%s,tmpC-code,tmpC-isTrue,tmpS1-code,tmpX-code);return true;else if (strcmp(Node-type,while)=0)/如果为 while,走 while分支int tmplabel = tmpS-begin;tmpS-begin = newlabel();/分配标签if(getNext(fp) /匹配 whileif(tmpS-begin 1)/如果不是第一个 while,不需要新 分配标签Lnum-;tmpS-begin = tmplabel;tmpC-isTrue = newlabel();tmpS1-begin = tmpC-isTrue;tmpC-isFalse = tmpS-next;/假出口则指向后续代码tmpS1-next = tmpS-begin;/后续代码需再输出一个标签if(MyFunction_C(fp,tmpC)/递归执行程序 Cif(strcmp(Node-type,do)=0) /匹配 do if(MyFunction_S(fp,tmpS1) /递归执行程序 S/语义操作if(tmpS-begin = 1)/第一个 whilesprintf(tmpS-code,L%d :n%sL%d :n%s gotoL%dn,tmpS-begin,tmpC-code,tmpC-isTrue,tmpS1-code,tmpS-begin);else /嵌套的 whilesprintf(tmpS-code,%sL%d:n%sgotoL%dn,tmpC-code,tmpC-isTrue,tmpS1-code,tmpS-begin);return true;return false;bool MyFunction_X (FILE* fp, str_X* &tmpX)/X CNode* node;str_S* tmpS = new str_S;if(strcmp(Node-type,else)=0) /如果当前为 else,走 else 分支tmpX-next = newlabel(); tmpS-next = tmpX-next; tmpS-begin = tmpX-begin;if(MyFunction_S(fp,tmpS) /递归执行 SL%d :nL%d:n%snL%d:,tmpX-next,tmpX-begin,tmpS-code,tmpX-next);sprintf(tmpX-code,gotoL%dnL%d:n%sn,tmpX-next,tmpX-begin,tmpS-code);tmpX-iselse = true;return true;else if (strcmp(Node-type,;)=0)/如果当前为;走空分支tmpX-next = tmpX-begin; sprintf(tmpX-code,); tmpX-iselse = true;return true;return false;bool MyFunction_C (FILE* fp, str_C* &tmpC)/C CNode* node;str_E* tmpE1 = new str_E;str_E* tmpE2 = new str_E;if(MyFunction_E(fp,tmpE1) /递归执行程序 Eif(strcmp(Node-type,)=0)/如果当前为,走分支if(getNext(fp)/匹配if(MyFunction_E(fp,tmpE2) /递归执行程序 Esprintf(tmpC-code,%s%sif%s%sgotoL%dngotoL%dn,tmpE1-code,tmpE2-code,tmpE1-place,tmpE2-place,tmpC-isTrue,tmpC-isFalse);return true;else if(strcmp(Node-type,,走分支 if(getNext(fp)/匹配code,%s%sif%scode,tmpE2-code,tmpE1-place,tmpE2-place,tmpC-isTrue,tmpC-isFalse);return true;else if(strcmp(Node-type,=)=0) /如果当前为=,走=分支 if(getNext(fp)/匹配= if(MyFunction_E(fp,tmpE2) /递归执行程序 Esprintf(tmpC-code,%s%sif%s=%sgotoL%dngotoL%dn,tmpE1-code,tmpE2-code,tmpE1-place,tmpE2-place,tmpC-isTrue,tmpC-isFalse);return true;return false;bool MyFunction_E (FILE* fp, str_E* &tmpE)/E CNode* node;str_T* tmpT1 = new str_T;str_T* tmpT2 = new str_T;bool isFirst = true;/是否为 E-T 运算的标签if(MyFunction_T(fp,tmpT1)/递归执行 Twhile(1)if(strcmp(Node-type,+)=0) /如果当前为+,算一个运算式T+T isFirst = false;/改变标签 if(getNext(fp)/匹配+ if(MyFunction_T(fp,tmpT2) /递归执行 Tstrcpy(tmpE-place,newtemp();sprintf(tmpE-code,%s%s%s=%s+%sn,tmpT1-code,tmpT2-code,tmpE-place,tmpT1-place,tmpT2-place);strcpy(tmpT1-code,tmpE-code);strcpy(tmpT1-place,tmpE-place);else if(strcmp(Node-type,-)=0) /如果当前为-,算一个运算式T-TisFirst = false;/改变标签 if(getNext(fp)/匹配- if(MyFunction_T(fp,tmpT2) /递归执行 Tstrcpy(tmpE-place,newtemp();sprintf(tmpE-code,%s%s%s=%s-%sn,tmpT1-code,tmpT2-code,tmpE-place,tmpT1-place,tmpT2-place);strcpy(tmpT1-code,tmpE-code);strcpy(tmpT1-place,tmpE-place);else break;if(isFirst) /E-T 的语义操作 strcpy(tmpE-code,tmpT1-code); strcpy(tmpE-place,tmpT1-place);return true;elsereturn false;bool MyFunction_T (FILE* fp, str_T* &tmpT)/T CNode* node;str_F* tmpF1 = new str_F;str_F* tmpF2 = new str_F;bool isFirst = true;/是否为 T-F 的标签if(MyFunction_F(fp,tmpF1) /递归执行 Fwhile(1)if(strcmp(Node-type,*)=0) /如果当前为*,算一个运算式 F*FisFirst = false;/改变标签 if(getNext(fp)/匹配* if(MyFunction_F(fp,tmpF2) /递归执行 Fstrcpy(tmpT-place,newtemp();sprintf(tmpT-code,%s%s%s=%s*%sn,tmpF1-code,tmpF2-code,tmpT-place,tmpF1-place,tmpF2-place);strcpy(tmpF1-code,tmpT-code);strcpy(tmpF1-place,tmpT-place);else if(strcmp(Node-type,/)=0) /如果当前为*,算一个运算式F/F isFirst = false;/改变标签 if(getNext(fp)/匹配/ if(MyFunction_F(fp,tmpF2)/递归执行 Fstrcpy(tmpT-place,newtemp();sprintf(tmpT-code,%s%s%s=%s/%sn,tmpF1-code,tmpF2-code,tmpT-place,tmpF1-place,tmpF2-place);strcpy(tmpF1-code,tmpT-code);strcpy(tmpF1-place,tmpT-place);else break;if(isFirst) /如果为 T-F 的语义操作 strcpy(tmpT-code,tmpF1-code); strcpy(tmpT-place,tmpF1-place);return true;elsereturn false;bool MyFunction_F (FILE* fp, str_F* &tmpF)/F CNode* node;str_E* tmpE = new str_E;if(strcmp(Node-type,()=0) /如果当前为(,走(E)分支if(getNext(fp)/匹配(if(MyFunction_E(fp,tmpE)/递归执行 Eif(strcmp(Node-type,)=0) /检查当前是否为右括号sprintf(tmpF-place,%s,tmpE-place); sprintf(tmpF-code,%s,tmpE-code); if(getNext(fp) /匹配右括号return true;else if(strcmp(Node-type,INT10)=0)/如果当前为 INT10 sprintf(tmpF-place,%s,Node-value);tmpF-code0 = 0;if(getNext(fp)/匹配 INT10 return true;else if(strcmp(Node-type,INT8)=0)/如果当前为 INT8 sprintf(tmpF-place,%s,Node-value);tmpF-code0 = 0;if(getNext(fp) /匹配return true;else if(strcmp(Node-type,INT16)=0)/如果当前为 INT16 sprintf(tmpF-place,%s,Node-value);tmpF-code0 = 0;if(getNext(fp)/匹配return true;else if(strcmp(Node-type,IDN)=0)/如果当前为变量sprintf(tmpF-place,%s,Node-value);tmpF-code0 = 0;if(getNext(fp)/匹配return true;return false;int main() FILE* fp; fp=fopen(code3.txt,r); str_S_* tmpS_ = new str_S_; while(1)if(MyFunction_S_(fp,tmpS_)printf(-This is a new sentence!n);printf(%sn, tmpS_-code);else if(strcmp(Node-type,#)=0)break;elseprintf(-This is a new sentence!n);printf(HERE IS AN ERROR!n);if(strcmp(Node-type,#)=0)/如果文件结束,退出break;else/如果文件没有结束,跳过此句,分析下一条语句for(MyScan(fp,Node);strcmp(Node-type,;)!=0; MyScan(fp,Node)fclose(fp); getchar(); return 0;注:这里采用的出错处理的方式:发现问题,提示问题,然后跳过此句,执行下一条语句(续编译)。我理解的续编译就是这样,因为一条语句中如果有错 误,发现错误的地方之后再进行这条语句的编译是毫无意义的。而且一条语句中 的错误会千奇百怪,如果花大量的精力在如何“改正”这些错误上面(为了这条 语句的“续编译”)得不偿失。而且我看目前的编译器基本上也都是这么做的。 注:由于出错处理是后加的,所以就将它的代码直接写在了 main 函数中,可以 将 main 函数中的相应部分再封装一下。这里没有如此做。、测试测试用例:while ab do a=1;while ab do while ab do a=1;if a2 then a=2;if a2 then if a3 then a=2;if a2 then b=3 else c=4;if a2 then a3;while (a3+15)0xa do if x2 = 07 thenwhile y2 then a3;) 以及综合语句(实验指导书上的例子)。出错处理的形式已在上面说明,而这个 程序支持续编译,所以可以有错误的语句在例子中。测试结果如下可以见到,在分析有问题的语句 if a2 then a3;时,程序输出 HERE IS AN ERROR!(处理方式比较简单)然后跳过此句(以分号作为语句的分界点)继续 向下进行编译。实验过程中遇到的问题这个实验的问题还是比较多的,主要是在语义规则上,具体点就是各个标号 的确定,什么时候需要 next,什么时候需要 begin,while 语句向回调转时候标 签的重复问题。解

温馨提示

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

最新文档

评论

0/150

提交评论