1.上下文无关文法
1.该文法是几型文法?并画出该文法的语法树。
答:2型,与上下文无关文法
2.指出该文法的所有短语,直接短语,句柄和素短语。
- 一个句型的语法树中任一子树的叶节点所组成的符号串都是该句型的短语。
1. 对于第一层的非终结符 S ,其叶节点所组成的短语是(S,(a))
2. 对于第二层的非终结符 L ,其叶节点所组成的短语是S,(a)
3. 对于第三层的非终结符 L ,其叶节点所组成的短语是S
4. 对于第三层的非终结符 S ,其叶节点所组成的短语是(a)
5. 对于第四层的非终结符 L ,其叶节点所组成的短语是a
6. 对于第五层的非终结符 S ,其叶节点所组成的短语是
故短语有
① (S,(a))
② S,(a)
③ S
④ (a)
⑤ a
-一个句型的语法树中任一最小子树的叶节点所组成的符号串都是该句型的短语。(最小子树:不再含有子树的树)
故直接短语有
① S
② a
---
- 句柄是最左边的直接短语
-
故句柄为
① S
- 有后往前对短语进行判断,如果短语中至少含有一个终结符,而且除它自身之外不再含任何更小的素短语,那么称该短语为素短语
① 对于短语 a ,a不含其他任何更小的素短语。故短语 a 为素短语
② 对于短语 (a) ,(a) 含素短语 a。故短语 (a) 不是素短语
③ 对于短语 S ,S 不含终结符。故短语 S 不是素短语
④ 对于短语 S,(a) ,S,(a) 含素短语a。故短语 S,(a) 不是素短语
⑤ 对于短语 (S,(a)) ,(S,(a)) 含素短语a。故短语 (S,(a)) 不是素短语
故素短语为
① a
3.指出下列符号串哪些是句子,哪些是句型
S aa (L) (aa)
- 根据句子与句型的定义,句型包含句子,句子是句型的一些特例
所以句型有:
1. S
2. aa
3. (L)
4. (aa)
句子有:
1. aa
2. (aa)
2.词法分析
- 正规文法转正规式:
-
正规式转化为DFA
- 正规式转化为NFA
转化规则
2. NFA转化为DFA
ε-closure(x) = {x,5,1} (注:对x求ε闭包,就是看x读入任意个ε可以到达的状态,然后将这些状态放到一起,构成一个状态)
ε-closure({5,3}) = {5,3,1}
ε-closure({5,4}) = {5,4,1}
move({x,5,1},a) = {5,3} (注:{x,5,1}状态读一个a到{5,3}状态)
move({x,5,1},b) = {5,3} (注:{x,5,1}状态读一个b到{5,4}状态)
画出对应的状态转换矩阵:
对于本题,矩阵分为三列,第一列表示第一行表示起始状态的ε闭包即ε-closure(x),第二列为状态集合I的a弧转换的ε闭包即ε-closure(move({x,5,1},a)),第三列为状态集合I的b弧转换的ε闭包即ε-closure(move({x,5,1},b))。
若有n个可输入字符,则矩阵分为n + 1 列 。 {注:其实以上说法并不是很恰当,但有助于理解}若Ia,Ib
中的状态集未出现在第一列中,则把它加入第一列,再求Ia,Ib,直到Ia,Ib中的状态全部在第一列中出现为止。
将上述状态装换矩阵重新标号,按照新的矩阵画出DFA即可。
2. DFA最小化
1. 无用状态:从该自动机的开始状态出发,输入任何串也不能到达的那个状态,或者从这个状态没有通路到达终态。
2. 等价状态:从两个状态出发可以得到相同的状态集合,则称这两个状态为等价状态。
3. 化简DNF算法的步骤:
1. 划分状态集
2. 合并状态:取没组中的代表状态,删去其他等价状态
3. 无用状态可以直接删去
【注:第一次划分状态集以终态和非终态为划分标准】
【注:合并状态时要注意对应的状态转换弧】
3.语法分析
1.1 消除左递归
其实文法G5就是 : S->Sa|b 提取’->'右边的S,并连接S′ 即 S->bS′.
S′是固定写法:就是把之前在S后面的放到S′的前面,并加上ε即 S′ -> aS′|ε
1.2 消除间接左递归
1.3消除一切左递归:
【注:其实就是先看有没有直接左递归,有的话就先消除直接左递归,没有就先带入,化出直接左递归再消除。】
- 求FIRST集,FOLLOW集,SELECT集,并判断给定文法是否为LL(1)型文法
【注:以下是对上面三步通俗但恰当的理解
1.X -> a|ε 或 X->ε X推出的第一个是终结符,FIRST(X) = {a,ε} 或 FIRST(X) = {ε}
3. X->Y…且Y->a X推出的第一个是非终结符,FIRST(X) = FIRST(Y)={a}, 若X->Y…且Y->ε,则FIRST(X) = FIRST(Y)={ε}其实这么写可能是错的,但是也想不出更准确地表达了。意会。。。
3. X->Y1Y2…Yi 如:Y1 -> a|ε,Y2 -> b|ε,Y3->c 则FIRST(X) = (FIRST(Y1) - {ε})∪(FIRST(Y2) - {ε})∪(FIRST(Y3) 若Y1 ->
a|ε,Y2 -> b|ε,Y3->c|ε 则FIRST(X) =
(FIRST(Y1)∪(FIRST(Y2)∪(FIRST(Y3) 】
Q1.求该文法的非终结符的FIRST集
Q2. 求该文法非终结符的FOLLOW集
【注:第一步很好理解,关键是第二步。
第二步理解为:假设求B的FOLLOW集。检查‘->’右侧的B后有没有跟其他符号。
- 若跟了其他符号,且该符号是非终结符,则把FIRST(β) - {ε}加入FOLLOW(B)中
- 若跟了其他符号,且该符号是终结符β,则直接把β加入到FOLLOW(B)中 (这两步其实是一步,拆开可能好理解一点)
- 若没有跟其他符号,则把‘->’左边的FOLLOW集加入到FOLLOW(B)中
- 若跟着其他符号,且该符号是非终结符β,且ε∈FIRST(β) ,则把‘->’左边的FOLLOW集加入到FOLLOW(B)中。
】
本题具体求解方法:
3.求该文法每个产生式的SELECT集,并判断该文法是否为LL(1)型文法
给定上下文无关文法的产生式A→α, A∈VN,α∈V*, 若α不能推导出ε,则SELECT(A→α)=FIRST(α)
如果α能推导出ε则:SELECT(A→α)=(FIRST(α) –{ε})∪FOLLOW(A)
需要注意的是,SELECT集是针对产生式而言的。
本题集体解法:
3.预测分析表
【注:预测分析表就是一个二维表,每一行的第一列填该文法的非终结符,每一列填的第一行填输入串(包括#)。分析表的重点在第二步和第三步。下面结合具体表来解释
】
构造该文法的预测分析表
4.LR分析
- 构造识别活前缀的DFA
1.1 项目
在文法G中每个产生式的右部适当位置添加一个圆点构成项目
【注:拓广文法是要把S->S′作为初态(拓广文法后保证了S′仅在左部出现),圆点在最后出现的项目作为终态。以上是构造识别活前缀的NFA的内容】
1.2 项目集规范族
每个项目集对应一个DFA状态,他们的全体称为这个文法的项目集规范族
【注:这是从初态开始生成DFA生成过程,S0状态首先包含S′->.E,(A->α.Bβ,B属于非终结符,则要把非终结符B所能推导出的圆点在最左边的项目全部加入S0)
,然后加入E->.aA,E->.bB。 S0可以接收E,a,b(找圆点后的第一个符号)到达S1,S2,S3。以此类推。 】
- LR(0)分析表的构造
【注:表上方的DFA是上一题构造出来的。
S0可意接收终结符a到状态S2,则在Action表第一行第一列填S2。(对应构造步骤1)
S0还可以接收非终结符E到状态S1,则在Goto表第一行第一列填1。(对应构造步骤1)
S1如果接收#,到达接收状态即填ACC。 (对应构造步骤3)
S6状态,圆点在最后,表示应该进行归约操作,即在Action表的每一列都填r1。(E->aA对应该文法的第一条产生式所以是r1,以此类推)(对应构造步骤2】
3.LR(1)分析表构造
【注:这是从初态开始生成DFA过程。 S0状态首先包含S′->.S,#
(参考上方LR(1)项目集构造规则,其实就是固定写法),然后将S->.aAd S->bAc S->.aec S->.bed
加入到S0(A->α.Bβ,a B属于非终结符,则要把非终结符B所能推导出的圆点在最左边的项目全部加入S0。对于S来说,它是非终结符,后边是β为空的情况,则说明S可以预判到的符号为FIRST(a),就是#号,即S->.aAd,#
S->bAc,# S->.aec,# S->.bed,#) 。
S0可以接收S,a,b(找圆点后的第一个符号)到达S1,S2,S3。以此类推。
S2中S->a.Ad,# 圆点后面跟的是非终结A,所以把A能推导出的圆点在最左边的项目全部加入即加入 A->.e 又在S->a.Ad,#中 A后面跟的是终结符d所FIRST(βa) = {d},也就是A能预判到的字符是d,即A->.e,d
S3中S->b.Ac,# 圆点后面跟的是非终结A,所以把A能推导出的圆点在最左边的项目全部加入即加入 A->.e 又在S->b.Ac,#中 A后面跟的是终结符c所FIRST(βa) = {c},也就是A能预判到的字符是c,即A->.e,c
,以此类推。 ∗ ∗ ‘ − > ’左端的非终结符能预判到什么字符,就在后面加该产生式后后加上 , 该字符 ∗ ∗ \color{red}{**‘->’左端的非终结符能预判到什么字符,就在后面加该产生式后后加上 ,该字符**} ∗∗‘−>’左端的非终结符能预判到什么字符,就在后面加该产生式后后加上,该字符∗∗】
【注:LR(1)分析表大体上和LR(0)差不多,只是在一些地方有一点改动。 1状态接收了#,就是接收态。在Action表1行#列填acc。
只有1是接受#,其他都是预判#。 对于状态5,如果接收终结符c,转移到状态9,在Action表5行c列填S9, ∗ ∗ 如果预判到的是 d ,那就做归约,做归约的产生式是第五条产生式,所以在 5 行 d 列填 r 5 。 ∗ ∗ \color{red}{**如果预判到的是d,那就做归约,做归约的产生式是第五条产生式,所以在5行d列填r~5~。**} ∗∗如果预判到的是d,那就做归约,做归约的产生式是第五条产生式,所以在5行d列填r 5 。∗∗
对于状态7,如果接收终结符d转移到状态11,如果预判到c则做归约。 其余和LR(0)构造方法一样。 】