根据语法规则(即语言的文法),分析并识别出各种语法成分,如表达式、各种说明、各种语句、过程、函数等,并进行语法正确性检查
词法分析:3型(正则文法) 词法分析:字符串
语法分析:2型(上下文无关文法) 语法分析:符号串
本节主要分析自顶向下方法
推导顺序:有多个“非终结符”,优先用哪个?
避免二义性:避免文法有多个可用规则。
问题:左递归问题+回溯问题
常见方法:递归子程序法+LL分析法
给定符号串S,若预测是某一语法成分,则可根据该语法成分的文法,设法为S构造一棵语法树,若成功,则S最终被识别为某一语法成分,即 S ∈ L ( G [ Z ] ) S\in L(G[Z]) S∈L(G[Z]),其中G[Z]为某语法成分的文法。若不成功, 则 S ∉ L ( G [ Z ] ) S \notin L(G[Z]) S∈/L(G[Z])
若对于一个文法的某一句子(或句型)存在两棵不同的语法树,则该文法是二义性文法,否则是无二义性文法。
若一个文法的某句子存在两个不同的规范推导,则该文法是二义性的,否则是无二义性的。
若一个文法的某规范句型的句柄不唯一,则该文法是二义性的,否则是无二义性的。
PS:正则文法也会有二义性,但是可判定的(通过转换为自动机)
文法的二义性是不可判定的,因此解决方法是提出一些限制条件,称为无二义性的充分条件,当文法满足这些条件时,就可以判定文法是无二义性的。
令U是文法的任一非终结符,文法中有规则 U ∷ = U ⋅ ⋅ ⋅ ⋅ 或者 U = > U ⋅ ⋅ ⋅ U∷=U····或者U => U··· U::=U⋅⋅⋅⋅或者U=>U⋅⋅⋅
自顶向下分析的基本缺点是:不能处理具有左递归性的文法。
(如果在匹配输入串的过程中,假定正好轮到要用非终结符U直接匹配输入串,即要用U的右部符号串U¨¨去匹配,为了用U¨¨去匹配,又得用U去匹配,这样无限的循环下
去将无法终止。)
具体规则:
提因子:若: U ∷ = x y ∣ x w ∣ … . ∣ x z 则可改写为: U ∷ = x ( y ∣ w ∣ … . ∣ z ) U∷=xy|xw|….|xz则可改写为:U∷=x(y|w|….|z) U::=xy∣xw∣….∣xz则可改写为:U::=x(y∣w∣….∣z)
若有文法规则: U ∷ = x ∣ y ∣ … … ∣ z ∣ U v 可以改写为 U ∷ = ( x ∣ y ∣ … … ∣ z ) U∷=x|y|……|z|Uv可以改写为U∷=(x|y|……|z) U::=x∣y∣……∣z∣Uv可以改写为U::=(x∣y∣……∣z){ v v v}
其特点是:具有一个直接左递归的右部并位于最后,这表明该语法类U是由x或y……或z其后随有零个或多个v组成。
通过以上两条规则,就能消除文法的直接左递归,并保持文法的等价性。
概念:分析工作要部分地或全部地退回去。
造成回溯的条件:文法中,对于某个非终结符号的规则其右部有多个选择,并根据所面临的输入符号不能准确地确定所要的选择时,就可能出现回溯。
对于 U : : = α 1 ∣ α 2 ∣ α 3 U::= α_1 | α_2 | α_3 U::=α1∣α2∣α3
定义: F I R S T ( α i ) = FIRST(α_i) = FIRST(αi)={ a ∣ α i = > ∗ a … , a ∈ V t a | α_i =>^* a…, a \in V_t a∣αi=>∗a…,a∈Vt}
为了避免回溯,对文法的要求是: F I R S T ( α i ) ∩ F I R S T ( α j ) = φ ( i ≠ j ) FIRST(α_i) ∩ FIRST(α_j)=φ (i\neq j) FIRST(αi)∩FIRST(αj)=φ(i=j)
这种方法是通过向前多看几个符号来确定所选择的目标,从本质上来讲也有回溯的味道,因此比第一种方法费时,但是假读仅仅是向前侦察情况,不作任何语义处理工作
为了在不采取超前扫描的前提下实现不带回溯的自顶向下分析,文法需要满足两个条件:
在上述条件下,就可以根据文法构造有效的、不带回溯的自顶向下分析器。
对于第二点,我们只有 F I R S T FIRST FIRST集合是不够的:
定义 F O L L O W ( A ) = FOLLOW(A)= FOLLOW(A)={ a ∣ Z = > ∗ … A a … , a ∈ V t a| Z=>^*…Aa…,a∈V_t a∣Z=>∗…Aa…,a∈Vt}
A ∈ V n A \in V_n A∈Vn 该集合称为A的后继符号集合
特殊地: 若 Z = > ∗ . . . A 若Z =>^*...A 若Z=>∗...A 则 # ∈ F O L L O W ( A ) ∈FOLLOW(A) ∈FOLLOW(A)
不带回溯的充分必要条件是:对于G的
每一个非终结符A的任意两条规则 A : : = α ∣ β A::=α|β A::=α∣β,下列条件成立:
具体做法:对语法的每一个非终结符都编一个分析程序,当根据文法和当时的输入符号预测到要用某个非终结符去匹配输入串时,就调用该非终结符的分析程序
要注意子程序之间的接口,在程序编制时进入某个非终结符的分析程序时其所要分析的语法成分的第一个符号已读入sym中。
递归子程序法对应的是最左推导过程
F I R S T ( α i ) = FIRST(α_i) = FIRST(αi)={ a ∣ α i = > ∗ a … , a ∈ V t a | α_i =>^* a…, a \in V_t a∣αi=>∗a…,a∈Vt}
若 α = > ∗ ε ,则 ε ∈ F I R S T ( α ) α=>^*ε,则ε \in FIRST(α) α=>∗ε,则ε∈FIRST(α)
设 α = X 1 X 2 . . . X n , X i ∈ V n U V t (即 X i ∈ V ) α=X_1X_2...X_n, X_i∈V_n \ \ U \ \ V_t (即 X_i ∈V) α=X1X2...Xn,Xi∈Vn U Vt(即Xi∈V)
首先求出组成α的每一个符号 X i X_i Xi的FIRST集合
注意:要顺序往下做,一旦不满足条件,过程就要中断进行
得到 F I R S T ( X i ) ,即可求出 F I R S T ( α ) FIRST(X_i),即可求出FIRST(α) FIRST(Xi),即可求出FIRST(α)
第一个L:从左向右分析 (Left to right)
第二个L:产生“最左推导”(Left-most derivation)
k=1:向前查看“k=1”个符号,通过向前看1个符号就能够有效分析
无二义,无左递归,且能够消除回溯
因此判断LL(1)文法的条件就是为了在不采取超前扫描的前提下实现不带回溯的自顶向下分析所满足的条件
无左递归且
由三部分组成
主要实现如下操作
PS:文法没有 x→ε,则不需要计算 FOLLOW 集!!!!
LL(k)是无二义性的文法,其识别的语言都是确定型下推自动机所识别的语言,但反之不能保证一个确定型下推自动机与LL(k)等价。因此关系图如下:
一个无二义的CFG文法不一定能得到LL(k)文法
LL(k)文法总是一个LR(k)文法