编译原理实验2.2-LL(1)分析法 下载本文

编译原理实验报告

—LL(1)分析法程序

实验2.2 LL(1)分析法

一、实验目的:

1.根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。

2.本次实验的目的主要是加深对预测分析LL(1)分析法的理解。

二、实验平台

Windows + VC++6.0 程序: “3-LL1.cpp”

三、实验内容

1.对下列文法,用LL(1)分析法对任意输入的符号串进行分析:

(1)E→TG

(2)G→+TG|-TG (3)G→ε (4)T→FS (5)S→*FS|/FS (6)S→ε (7)F→(E) (8)F→i 程序功能:

输入: 一个以 # 结束的符号串(包括 + - * /( )i # ):例如:i+i*i-i/i# 输出: 经完善程序目前能对所有输入串进行正确的分析.

算法思想:栈用于存放文法符号,分析开始时,栈底先放一个‘#’,然后,放进文法开始符号。同时,假定输入串之后也总有一个‘#’,标志输入串结束。现设置一个文法分析表(见表1),矩阵M[A,a]中存放着一条关于A的产生式,指出当A面临符号a时所采用的侯选。

对任何(X,a)其中X为栈顶符号,程序每次都执行下述动作之一: ? 如果X=a=‘#’,则输出分析成功,停止分析过程;

? 如果X=a且不等于‘#’,则把X从栈顶逐出,让a指向下一个输入符号;

? 如果X是一个非终结符,则查看分析表M.若M[A,a]中存放着关于X的一个产生式,那么首先把X从栈顶逐出,然后,把产生式的右部符号串按反序一一推进栈内,若右部符号为ε,则就什么都不进栈。把产生式推进栈内的同时应做这个产生式相应的语义动作,例如字符i匹配成功,字符出错,相应的产生式等。

输出如下: 输出每一步骤分析栈和剩余串的变化情况, 及每一步所用

的产生式都明确显示出来。

运行步骤:

? 首先在相同的路径下建一文本文档例如11.txt,将表达式写入文档内如i+i*i-i/i#;

? 运行程序,显示界面如下,输入相应的文件名字,(输入输出文件名是自行定义)

? 打开pp.txt文件,文法分析结果如下:

步骤 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 分析栈 #E #GT #GSF #GSi #GS #G #GT+ #GT #GSF #GSi #GS #GSF* #GSF #GSi #GS #G #GT- #GT #GSF #GSi #GS #GSF/ #GSF #GSi #GS #G # 剩余输入串 i+i*i-i/i# i+i*i-i/i# i+i*i-i/i# i+i*i-i/i# +i*i-i/i# +i*i-i/i# +i*i-i/i# i*i-i/i# i*i-i/i# i*i-i/i# *i-i/i# *i-i/i# i-i/i# i-i/i# -i/i# -i/i# -i/i# i/i# i/i# i/i# /i# /i# i# i# # # # 使用的产生式或匹配 E->TG T->FS F->i i匹配! S->^ G->+TG +匹配! T->FS F->i i匹配! S->*FS *匹配! F->i i匹配! S->^ G->-TG -匹配! T->FS F->i i匹配! S->/FS /匹配! F->i i匹配! S->^ G->^ 分析成功

错误提示:

1>.输入i++i*i#,结果如下

步骤 1 2 3 4 5 6 7 8 分析栈 #E #GT #GSF #GSi #GS #G #GT+ #GT 剩余输入串 i++i*i# i++i*i# i++i*i# i++i*i# ++i*i# ++i*i# ++i*i# +i*i# 使用的产生式或匹配 E->TG T->FS F->i i匹配! S->^ G->+TG +匹配! T出错! 存在的问题:现在只能是遇到错误就停止,而没能实现同步符号ll(1)分析。 2>.输入非法字符i+a#结果如下:

文法分析如下

输入串中有非法字符

2.完善的功能:

(1) 输出完整的分析过程。即详细输出每一步骤分析栈和剩余串的变化情况, 及每一步所用的产生式.

(2) 输出最终的分析结果, 即输入串 “合法”或 “非法”.

(3)示例程序只能完成 + 、* 、(、)的语法分析,现在的程序加入了 - 和 / 的语法分析

(4)将测试用的表达式事先放在文本文件中,一行存放一个表达式,以分号分割。同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;

3.备注:

1. 在“所用产生式”一列中,

如果对应有推导,则写出所用产生式;如果为匹配终结符,则写明匹配的终结符;

如分析异常出错则,写为“分析出错”;如成功结束则写为“分析成功”。 4.文法分析表

表1

E G T S F

i E->TG T->FS F->i + G->+TG S->ε * S->*FS ( E->TG T->FS F->(E) ) - / # G->ε G->ε G->-TG S->ε S->ε S->/FS S->ε 2. 对一个新的文法实现LL(1)分析

2.1利用上次作业中的新闻法进行改善,文法如下

S->aH H->aMd H->d M->Ab M->ε A->aM A->ε

(1)程序代码:WDM.cpp的文件 (2)输入: 一个以 # 结束的符号串:

例如: aaabd# (3)输出: 步骤:

第一步,首先判断是否有非法字符,如有则提示“输入非法字符”,若无则进行字符串分析;

第二步,将# S 进分析栈 即分析从S开始,S为开始符,首先使用产生式S->aH,分析串a,分析字符为a,剩余字符串aabd#,

第三步,分析第二个字符a,对S->aH中的非终结符H进行分析,使用H->aMd, 反序将符号一一推进栈中,字符a匹配成功,剩余字符串abd#; 第四步,使用产生式M->Ab,以‘bA’s顺序进栈,剩余字符串abd#;

第五步,对非终结符A分析,再将产生式A->aM,进栈同时将A推出栈;第三个a匹配成功,剩余串bd#;

第六步,使用产生式M->ε,此时什么都不用进栈;剩余串bd#; 第七步,栈内剩余两个终结符,最后以#结束; 第八步,分析到栈底,代表分析成功最后以#结束。 (4)分析表M:

产生式S->aH,H->aMd,M->Ab, A->aM不能推出空,所以select集

Select(S->aH)=first(aH)={a} Select(H->aMd)=first(aMd)={a} Select(M->Ab)=first(Ab)={a, ε} Select(A->aM)=first(aM)={a, ε}

产生式M->ε,A->ε能推出空,所以select集

Select(M->ε)=(first(ε)-{ ε})∪follow(M)={ b,d,#}

Select(A->ε)= (first(ε)-{ ε})∪follow(A)={b,#}

S H M A a S->aH H->aMd M->Ab A-d M->ε b M->ε A->ε # M->ε A->ε 运行步骤同上,结果如下:

步骤 1 2 3 4 5 6 7 8 9 10 11 分析栈 #S #Ha #H #dMa #dM #dbA #dbMa #dbM #db #d # 剩余输入串 aaabd# aaabd# aabd# aabd# abd# abd# abd# bd# bd# d# # 推导用产生式或是匹配 S->aH a匹配! H->aMd a匹配! M->Ab A->aM a匹配! M->^ b匹配! d匹配! 分析成功

四.心得体会

通过这次试验,我们对LL(1)有了更深的理解,更加理解LL(1)文法的分析过程及实现方法。学会了设计,编制,调试语法及语义分析程序,对程序进行改善处理以达到更好的实现效果。当然,时间原因,还有好多东西没有学习到,在以后的学习过程中,就要多查资料,多问老师或同学,提高自己的能力。