1、编译方法 实 验 报 告实验名称:简单的语法分析程序设计实验要求1. 功能:对简单的赋值语句进行语法分析随机输入赋值语句,输出所输入的赋值语句与相应的四元式2. 采用递归下降分析程序完成(自上而下的分析)3. 确定各个子程序的功能并画出流程图4. 文法如下:5. 编码、调试通过采用标准输入输出方式。输入输出的样例如下:【样例输入】x:=a+b*c/d-(e+f)【样例输出】(说明,语句和四元式之间用 5 个空格隔开)T1:=b*c (*,b,c,T1)T2:=T1/d (/,T1,d,T2)T3:=a+T2 (+,a,T2,T3)T4:=e+f (+,e,f,T4)T5:=T3-T4 (-,T
2、3,T4,T5)x:=T5 (:=,T5,-,x) 【样例说明】程序除能够正确输出四元式外,当输入的表达式错误时,还应能检测出语法错误,给出相应错误提示。6. 设计 3-5 个赋值语句测试 实例,检验程序能否输出正确的四元式;当输入错误的句子时,检验程序能够给出语法错误的相应提示信息。7. 报告内容包括:递归程序的调用过程,各子程序的流程图和总控流程图,详细设计,3-5 个测试用例的程序运行截图及相关说明,有详细注释的程序代码清单等。目录1.语法分析递归下降分析算法 .51.1 背景知识 51.2 消除左递归 62.详细设计及流程图 .62.1 函数 void V( ) / V - a|b|c
3、|d|e.|z .62.2 函数 void A( ) / A - V:=E .72.3 函数 void E() /E - TE 72.4 函数 void T( ) / T - FT82.5 函数 void E1( ) /E- +TE|-TE|null82.6 函数 void T1() / T- *FT|/FT|null93.测试用例及截图 .93.1 测试用例 1 及截图 93.2 测试用例 2 及截图 103.3 测试用例 3 及截图 11代码清单 111.语法分析递归下降分析算法1.1 背景知识无回溯的自上向下分析技术可用的先决条件是:无左递归和无回溯。 无左递归:既没有直接左递归,也没有
4、间接左递归。无回溯:对于任一非终结符号 U 的产生式右部 x1|x2|xn,其对应的字的首终结符号两两不相交。如果一个文法不含回路,也不含以 为右部的产生式,那么可以通过执行消除文法左递归的算法消除文法的一切左递归(改写后的文法可能含有以 为右部的产生式) 。文法的左递归消除算法:1、将文法 G 的所有非终结符排序为 U1 ,U2 , ,Un; 2、For(i=1;i+;in) for j1 to i-1 把产生式 UiUj 替换成 Ui1| 2|m;其中:Uj 1| 2 | |m 消除 Ui 产生式中的直接左递归; 3.化简改写之后的文法,删除多余产生式。文法的直接左递归消除公式:直接左递归
5、形式:UUx|y; 其中:x,y(VNVT)* ,y 不以 U 打头。 直接左递归的消除:UyU UxU| 直接左递归的一般形式:UUx1|Ux2|Uxm|y1|y 2|yn;其中:xi ,y i 都不以 U 打头。 一般形式直接左递归的消除:Uy1U| y2U | ynUUx1U| x2U| | xmU| 回溯的消除的前提是文法不得含有左递归,可提左因子来消除回溯。1.2 消除左递归根据实验中给出的文法,进行消除左递归及回溯,得到下列的式子A - V:=EE - TEE- +TE|-TE|nullT - FTT- *FT|/FT|nullF - V|(E)V - a|b|c|d|e.|z2.
6、详细设计及流程图根据消除左递归后的文法,可以编写相应的函数。2.1 函数 void V( ) / V - a|b|c|d|e.|zvoid V() / V - a|b|c|d|e.|z 函数设计主要用来识别小写字母的,如果是小写字母的话,放入字符表,不是的话,输出语法错误。函数比较简单,代码如下:if(islower(ssym)Tablelist_n0 = ssym; /把读取的小写字母存入符号表,便于分析是生成中间代码Tablelist_n1 = 0;list_n+;sym+;elseprintf(“Operand Errors!n“); /运算对象错误SIGN=1;exit(0);2.2
7、函数 void A( ) / A - V:=Evoid A() / A - V:=E 函数主要用来实现赋值的操作,流程图如图 1 所示。开 始V( )ssym=:E( );Y输 出 表 达 式N输 出 错 误结 束图 1 A( ) 函数流程图2.3 函数 void E() /E - TE函数 E()里面主要递归调用函数 T( )和 E( )。当没有出现语法错误时就可正常的运行。函数比较简单,代码如下:if(SIGN=0)T();E1();2.4 函数 void T( ) / T - FT函数 T( )里面主要递归调用函数 F ( )和 T( )。当没有出现语法错误时就可正常的运行。函数比较简单
8、,代码如下:if(SIGN=0)F();T1();2.5 函数 void E1( ) /E- +TE|-TE|null函数 void E1() /E- +TE|-TE|null,主要用来实现加减法的语义分析。流程图如图 2 所示。开 始SIGN=0ssym = +|ssym=-输 出 三 地 址 式和 四 元 表 达 式p=sym; sym+T()YE1()结 束NN图 2 E1 ( ) 函数流程图2.6 函数 void T1() / T- *FT|/FT|null函数 void T1() / T- *FT|/FT|null,主要用来实现乘除法的语义分析。流程图如图 3所示。开 始SIGN=0
9、ssym = *|ssym=/输 出 三 地 址 式和 四 元 表 达 式p=sym; sym+F()YT1()结 束NN图 3 T1 ( ) 函数流程图3.测试用例及截图3.1 测试用例 1 及截图用例 1 为实验要求上的的用例。测试结果图 4 所示。图 4 测试用例 1 及结果截图3.2 测试用例 2 及截图用例 2 为出现大写字母,出现报错。测试结果图 5 所示。图 5 测试用例 2 及结果截图3.3 测试用例 3 及截图用例 3 为随意编写用例。测试结果图 6 所示。图 6 测试用例 3 及结果截图代码清单#include#include#include#include void A(
10、); / A - V:=Evoid E(); / E - TEvoid T(); / T - FTvoid E1(); / E- +TE|-TE|nullvoid T1(); / T- *FT|/FT|nullvoid F(); / F - V|(E)void V(); / V - a|b|c|d|e.|zchar s50,n=1; /s50用于存放输入的赋值表达式char Table503; /产生中间代码所需的符号表int SIGN,sym; /sym 为 s50中当前读入符号的下标int list_n=0; /符号表的下标/*消除左递归及回溯A - V:=EE - TEE- +TE|-T
11、E|nullT - FTT- *FT|/FT|nullF - V|(E)V - a|b|c|d|e.|z*/int main()SIGN = 0; /SIGN 用于指示赋值表达式是否出现错误sym=0;scanf(“%s“,if( s0 = 0) /没有输入的情况直接退出return 0;A();if(ssym!=0exit(0);return 0;void A() / A - V:=EV();if(ssym=:E();printf(“%s:=%s“,Tablelist_n-2,Tablelist_n-1);printf(“ (:=,%s,-,%s)n“,Tablelist_n-1,Table
12、list_n-2);elseprintf(“The assignment Symbol spelling mistakes!n“); /赋值号拼写错误SIGN=1;exit(0);void V() / V - a|b|c|d|e.|zif(islower(ssym)Tablelist_n0 = ssym; /把读取的小写字母存入符号表,便于分析是生成中间代码Tablelist_n1 = 0;list_n+;sym+;elseprintf(“Operand Errors!n“); /运算对象错误SIGN=1;exit(0);void E() /E - TEif(SIGN=0)T();E1();v
13、oid T() / T - FTif(SIGN=0)F();T1();void E1() /E- +TE|-TE|nullint p;if(SIGN=0)if(ssym = +|ssym=-)p=sym; /用 p 记录出现+ 或-时 sym 的值sym+;T();char ch3;ch0 = T;ch1 = n;ch2 = 0;if(sp = +)printf(“%s:=%s+%s“,ch,Tablelist_n-2,Tablelist_n-1); /输出三地址代码printf(“ (+,%s,%s,%s)n“, Tablelist_n-2,Tablelist_n-1,ch); /输出四元式
14、elseprintf(“%s:=%s-%s“,ch,Tablelist_n-2,Tablelist_n-1); /输出三地址代码printf(“ (-,%s,%s,%s)n“, Tablelist_n-2,Tablelist_n-1,ch); /输出四元式strcpy(Tablelist_n-2,ch); /将当前结果归结式放在符号表中list_n-;n+;E1();void T1() / T- *FT|/FT|nullint p;if(SIGN=0)if(ssym = *|ssym=/)p=sym;sym+;F();char ch3;ch0 = T;ch1 = n;ch2 = 0;if(sp
15、 = *)printf(“%s:=%s*%s“,ch,Tablelist_n-2,Tablelist_n-1); /输出三地址代码printf(“ (*,%s,%s,%s)n“, Tablelist_n-2,Tablelist_n-1,ch);/输出四元式elseprintf(“%s:=%s/%s“,ch,Tablelist_n-2,Tablelist_n-1); /输出三地址代码printf(“ (/,%s,%s,%s)n“, Tablelist_n-2,Tablelist_n-1,ch);/输出四元式strcpy(Tablelist_n-2,ch); /将当前结果归结式放在符号表中list_n-;n+;T1();void F() /F - V|(E)if(SIGN=0)if(ssym=()sym+;E();if(ssym=)sym+;elseprintf(“ERROR!n“);SIGN=1;exit(0);else if(islower(ssym) /判断 ssym是否是小写字母V();elseprintf(“ERROR!n“);SIGN=1;exit(0);