1.文法的二义性判断
二义性:一个文法存在某个句子对应两棵不同的语法树,则称这个文法是二义的。也就是该句子有两个不同的最左(最右)推导。 例子: 证明下列文法G(S)是二义的。 S->Ac|aB A->ab B->bc 就是自己定义一个句子然后说明这个句子有两个语法树就可以了
2.语法分析树
推导可以表达成树状结构
和推导所用的顺序无关(最左、最右、其他)
特点:
1)树中的每个内部节点代表非终结符
2)每个叶节点代表终结符
3)每一步推导代表如何从双亲结点生成他的直接孩子结点
3.判断文法类型
1)文法的分类
0型:G = (VT , VN , S , P) 规则形式:α → β ,α,β∈(VT , VN) *,α ≠ ε 推导:γαδ ⇒ γβδ
1型(上下文有关):规则α → β 有|α|≤|β| 规则形式:ξAη→ξγη,A ∈ VN,ξ , γ , η ∈(VT , VN) * , γ ≠ ε
2型(上下文无关) 规则形式:A → β , A∈VN , β ∈(VT , VN) *
3型(右线性/左线性/正规文法) A → aB或者A → a(右线性) A → Ba或者A → a(左线性) a∈ VT∪{ε}
2)文法的判别
判别小技巧:
从上图我们可以看出,四种文法中,从0型到3型,其规则和约定越来越多,限制条件也越来越多,所以,我们可以从最复杂的3型进行判断,如果不符合3型的,那再看是不是2型的,不是2型的,再看是不是1型的,依次向下判断,最后答案取其最高的符合规则。
3型文法遵循的规范是: 判别式的左边必须只有一个字符,且必须是非终结符; 判别式的右边最多只能有两个字符,且当判别式的右边有两个字符时必须有一个为终结符而另一个为非终结符。当判别式的右边只有一个字符时,此字符必须为终结符; 对于3型文法中的所有产生式,其右边有两个字符的产生式,这些产生式右边两个字符中终结符和非终结符的相对位置一定要固定,如果一个产生式右边的两个字符的排列是:终结符+非终结符,那么所有产生式右边只要有两个字符的,都必须前面是终结符而后面是非终结符,这是右线性文法。要么就全是:非终结符+终结符的形式,称为左线性文法。 在2型文法的基础上,产生式的右边字符数不超过2个且所有产生式要么都是左递归,要么都是右递归 例如:S->aB B->bC C->c 注: S->aB B->Cb C->c 不成立,因为字符串既有左递归,又有右递归 2型文法遵循的规范是: 与3型文法的第一点相同,即:左边必须有且仅有一个非终结符。 2型文法所有产生式的右边可以含有若干个终结符和非终结符(只要是有限的就行,没有个数限制)。 在1型文法的基础上,左部只有一个非终结符 例如:S->aBC B->b C->c 1型文法遵循的规范是: 1型文法所有产生式左边可以含有一个、两个或两个以上的字符,但其中必须至少有一个非终结符。 与2型文法第二点相同。 0型文法的基础上,右边字符个数不小于左边字符个数。 例如: S->aBC a->Bb C->c 0型文法遵循的规范是: 我们能描述出来的,都属于这个类型,即0型。
最后答案取其最高的符合规则。
4.求一个句型短语、直接短语、句柄
1)短语
那么,abp为此句型的短语 总结来说:一个句型的语法树中任一子树叶结点所组成的符号串都是该句型的短语,由这概念,那么我们自然可以想到,b也应该是该句型的一个短语。
2)直接短语
跟短语比,限定高度为2的子树。 如果子树中不再包含其他的子树,即A只能推导出b,而b不能再推出其他的式子,则b为此句型的直接短语。
3)句柄
直接短语中的最左直接短语为该句型的句柄
4)例子
首先要先画出抽象语法分析树,如图。如果能够画出对应的抽象语法树,则表明此表达式是文法的一个句型。
按照以上的语法树可知,E=T*F为此文法的一个句型:
短语:T*F E+T*F 直接短语: T*F 句柄:T*F
5.正则表达式
C语言当中的标识符的正则定义 digit->0|1|2|...|9 letter_->A|B|...|Z|a|b|...|z|_ id->letter_(letter_|digit)*
(整型或浮点型)无符号数的正则定义 digit ->0|1|2|...|9 digits ->digit digit* optionalFraction -> .digits|ε optionalExponent → ( E(+|-|ε)digits )|ε number → digits optionalFraction optionalExponent
C语言无符号整数的正则定义 十进制整数的RE:(1|...|9)(0|...|9)*|0 八进制整数的RE:0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)* 十六进制整数的RE:0x(1|...|9|a|...| f |A|…|F)(0|...|9|a|...| f |A|…|F )*
6.消除左递归、回溯以及计算FIRST和FOLLOW集
1)左递归的消除
如果自一个文法中,存在一个非终端符号A,使得对某个串α,存在一个推导A→(*)Aα.(其中 →(*)表示可以经过多步推导。)则该文法为左递归文法(left recursive).由于自顶向下语法分析方法不能处理左递归的文法,因此需要一个转换方法来消除左递归。 对于左递归的产生式 A → Aα | β, 替换为非左递归的产生式如下(其中,ε表示空串): A → βA’ A’ → αA’ | ε 举个例子: 对于文法 E → E+T | T T → T*F | F F → (E) | id 通过使用上述的方法,将其转换成非左递归的文法,结果如下: E → TE’ E’ → +TE’ | ε T → FT’+ T’ → +FT’ | ε F → (E) | id 在上述的过程中,E → E+T | T被替换为E→TE’ 和 E’ → +TE’|ε。类似的,T和T’的新产生式也是通过消除立即左递归得到的。
消除直接左递归的一般形式
A → A α1 | A α2 | … | A αn | β1 | β2 | … | βm (αi ≠ ε, βj不以A开头) ⬇ A -> β1 A′ | β2 A′ | … | βm A′ A′ -> α1 A′ | α2 A′ | … | αn A′ | ε
消除间接左递归
例: S-> Aa|b A-> Ac|Sd|ε 将S的定义代入A-产生式,得到: A-> Ac|Aad|bd|ε 消除A-产生式的直接左递归? A->A(c|ad)|bd|ε A->A(c|ad)|(bd|ε) 应用公式得到: A->(bd|ε)A' A'->(c|ad)A'|ε 展开: A->bdA'|A' A'->cA'|adA'|ε
提取左公因子
例子: 文法G S->aAd|aBe A->c B->b ↓ 文法G' S->aS' S'->Ad|Be A->c B->b
2)LL(1)文法
文法G是LL(1)的,当且仅当G的任意两个具有相同左部的产生式A → α | β 满足下面的条件: 1)不存在终结符a使得α 和β都能够推导出以a开头的串 2)α 和β至多有一个能推导出ε 3)如果 β ->* ε,则FIRST (α)∩FOLLOW(A) =Φ; 如果 α ->* ε,则FIRST (β)∩FOLLOW(A) =Φ; 第一个“L”表示从左向右扫描输入 第二个“ L”表示产生最左推导 “1”表示在每一步中只需要向前看一个输入符号来决定语法分析动作
3)FIRST和FOLLOW集
FIRST(首终结符集):
简单的说 FIRST 集就是一个文法符号串的开始符号集合。 设 G=(VT,VN,S,P)是上下文无关文法, FIRST(α)={a|α=>aβ,a∈VT,α,β∈v*} 若 α=> ε(经过0或多步推导可以推出为空串),则规定 ε ∈ FIRST(α) FIRST(α) 是 α 的所有可能推导的开头终结符或可能的 ε。
计算文法符号X的FIRST(X)
FIRST ( X ):可以从X推导出的所有串首终结符构成的集合 如果 X ->* ε,那么 ε∈FIRST ( X ) 例: E-> TE' FIRST(E)={( id } E'-> +TE'|ε FIRST(E')={ + ε } T-> FT' FIRST(T)={ ( id } T'-> *FT'|ε FIRST(T')={ * ε } F -> (E)|id FIRST(F)={( id }
例子: 求FIRST集
给定文法 G[S]: (1)S -> Af (2)S -> Be (3)A -> a (4)A -> cA (5)B -> b (6)B -> dB
详解:
求(1)中的 Af 的 FIRST 集,注意,因为如果推出为空时用 ε,所以 A 后面的 f 是没用的,我们只分析 A 的第一个终结符的集。 因为(3)和(4)都是由 A 推导,所以两个都考虑 FIRST(Af) = FIRST(a) ∪ FIRST(cA) = {a,c} 同理可求出: FIRST(Be) FIRST(a) FIRST(cA) FIRST(dB)
FOLLOW(后随集)
简单的说 FOLLOW 集就是一个文法符号的后跟终结符号的集合。
设 G =(VT,VN,S,P)是上下文无关文法,A∈VN,S是开始符号。 FOLLOW(A)={a|S=>*…Aa…,a ∈VT} 若有 S=>*…A(就是说 A 已经是最后一个时,没有后面的),则规定 # ∈ FOLLOW(A)
FOLLOW(A) 是所有出现在紧接 A 之后的终结符或 “#”;
FOLLOW计算规则
(1)对于文法的开始符号 S,置 # 到 FOLLOW(S) 中; (2)若 A -> αBaβ 是一个产生式,a 为终结符,则把 a 加至 FOLLOW(B) 中; (3)若 A -> αBβ 是一个产生式,则把 FIRST(β) - {ε} 加至 FOLLOW(B) 中; (4)若 A -> αB 是一个产生式,或 A -> αBβ 是一个产生式,而 β =*> ε, 则把 FOLLOW(A) 加至 FOLLOW(B)
7.构造正则表达式的最小化DFA
1)正规化转为NFA
运用到下图的规则
给个例子:
2)子集构造法
下面给出一个NFA到DFA转化的一个例子,以a(b|c)*为例:
3)DFA的最小化:Hopcroft算法