L L ( 1 ) LL(1) LL(1)文法后面两个两个条件都是为了保证预测分析表每个单元格中至多有一个产生式,这样预测分析时的工作每一步都是确定的。名称中的‘1’表示分析时每一步只需向右查看一个符号,实际上是通过 F o l l o w ( A ) Follow(A) Follow(A)实现的。第二个L表示最左推导,因此,在预测分析程序中应用某个产生式之后,将产生式的右部符号反序入栈,优先推导栈顶元素,即最左推导。
考虑 X X X为非终结符号的情形即可,终结符号的 F i r s t First First是只有自己作为元素构成的集合,进一步,候选式 α = A B \alpha=AB α=AB的 F i r s t ( α ) = F i r s t ( A ) First(\alpha)=First(A) First(α)=First(A),因此,只需要考虑非终结符号即可。前面三点执行一次,最后两点需迭代执行,因为 Y Y Y集合也是不断变化的,具体说是某个 Y i Y_i Yi变化,会通过产生式 X ⟶ Y . . . X\longrightarrow Y... X⟶Y...或者 X ⟶ Y 1 Y 2 . . . Y k X\longrightarrow Y_1Y_2...Y_k X⟶Y1Y2...Yk 引起 X X X的变化。
F i r s t ( X ) First(X) First(X)本质上是 X X X推导到最后,产生所有式子的第一个字符集合,因此 Y 1 Y 2 . . . Y i − 1 Y_1Y_2...Y_{i-1} Y1Y2...Yi−1均包含 ϵ \epsilon ϵ的话,在它们均产生 ϵ \epsilon ϵ的式子中 Y i Y_{i} Yi的首符集也可以称为 X X X推导式子的首符,因此将 Y i Y_{i} Yi的首符集加入 X X X的首符集,此前 Y j ≤ ( i − 1 ) Y_{j\leq(i-1)} Yj≤(i−1)已经执行了该操作。
算法执行过程,首先执行①②③,之后,反复对所有产生式不断执行④⑤(循环遍历),直到所有 F i r s t First First集合不再变化。
这里重复步骤中的①实际上也只执行一次,因为 F i r s t ( β ) First(\beta) First(β)不会变化,这里 β \beta β可以是终结/非终结符号。可以移至初始化步骤中。
F e l l o w ( A ) Fellow(A) Fellow(A)是可以紧跟着 A A A之后出现的终结字符集合, F i r s t , F e l l o w First,Fellow First,Fellow均是终结字符的集合,而且可以简化为仅对非终结字符进行求取。
非常明确,执行该产生式,要么出现 α \alpha α首符集中的字符,要么首符集中含有空字 ϵ \epsilon ϵ,且是当前非终结符 A A A的 F o l l o w Follow Follow中含有的某个终结符 b b b,自动匹配(? )。
这里 α \alpha α首符集中含有 ϵ \epsilon ϵ实际上有 A → α → ϵ A\rightarrow \alpha \rightarrow\epsilon A→α→ϵ,因为只有某个字符可以推导出 ϵ \epsilon ϵ时,才将其加入首符集。因此,执行该产生式必须保证紧跟着 A A A的字符可以和当前输入 b b b匹配(字符 b b b在 F o l l o w ( A ) Follow(A) Follow(A)中出现)。
reference
山东大学编译原理郑艳伟老师ppt