📜  LL(1) 解析算法

📅  最后修改于: 2021-09-28 09:56:38             🧑  作者: Mango

先决条件 — 构建 LL(1) 解析表。
LL(1)解析是编译器设计的语法分析阶段的一种自顶向下的解析方法。 LL(1) 解析所需的组件是输入字符串、堆栈、给定语法的解析表和解析器。在这里,我们讨论一个解析器,它确定是否可以从给定的语法(或解析表)生成给定的字符串。
令给定文法为 G = (V, T, S, P)
其中V-变量符号集、T-终端符号集、S-起始符号、P-产生集。

LL(1) 解析器算法:
Input- 1. stack = S //stack 最初只包含 S。
2.输入字符串=w$
其中 S 是语法的开始符号, w 是字符串, $ 用于字符串。
3. PT 是给定语法的解析表,形式为矩阵或二维数组。

输出 –确定给定的字符串可以由给定的语法(解析表)产生,否则会产生错误。

脚步:

1. while(stack is not empty) {

       // initially it is S
2.     A = top symbol of stack;  

       //initially it is first symbol in string, it can be $ also
3.     r = next input symbol of given string; 
4.     if (A∈T or A==$) {
5.         if(A==r){
6.             pop A from stack;
7.             remove r from input;
8.         }
9.         else
10.             ERROR();
11.     }
12.     else if (A∈V) {
13.         if(PT[A,r]= A⇢B1B2....Bk) {
14.             pop A from stack;
             
                // B1 on top of stack at final of this step
15.             push Bk,Bk-1......B1 on stack  
16.         }
17.         else if (PT[A,r] = error())
18.             error();
19.     }
20. } 
// if parser terminate without error() 
// then given string can generated by given parsing table.

时间复杂度
众所周知,语言的文法大小是有限的。例如,有限数量的变量、终端和产生式。如果文法是有限的,那么它的 LL(1) 解析表也是大小为 O(V*T) 的有限。让

  • p是所有产生式的 RHS 中字符串的最大长度,并且
  • l是给定字符串的长度,

lp大很多。 if算法第 4 行的块总是运行 O(1) 时间。 else if算法中第 12 行的块将O(|P|*p)作为单个下一个输入符号的上限。 while 循环可以运行超过l次,但我们已经考虑了O(|P|*p) 中单个下一个输入符号的重复while 循环。所以总的时间复杂度为

T(l) = O(l)*O(|P|*p)
              = O(l*|P|*p)
              = O(l)           { as l >>>|P|*p }

该算法的时间复杂度是输入字符串的长度顺序。

与上下文无关语言(CFL)的比较:
LL(1) 语法中的语言是 CFL 的适当子集。使用 CYK 算法,我们可以找到给定上下文无关文法 (CFG) 的字符串的成员资格。 CYK 花费O(l 3 )时间进行 CFG 的成员资格测试。但是对于 LL(1) 语法,我们可以使用上述算法在O(l)时间内进行成员资格测试,这是线性的。如果我们知道给定的 CFG 是 LL(1) 语法,那么使用 LL(1) 解析器进行解析而不是 CYK 算法。

例子 –
令文法G = (V, T, S’, P ) 为

S' → S$
S → xYzS | a
Y → xYz | y

此语法的解析表( PT )

  a x y z $
S’ S’ → S$ S’ → S$ error error error
S S → a S → xYzS error error error
Y error Y → xYz Y → y error error
Let string1 = xxyzza,

我们必须用这个字符串添加$
我们将使用上面的解析算法,流程示意图:

对于string1,我们得到了一个空栈,while 循环或算法没有错误地终止。因此, string1属于给定语法G 的语言。

Let string2 = xxyzzz,

和上面一样,我们将使用算法来解析string2,这是图

对于string2 ,在上图的最后阶段,堆栈的顶部是S并且字符串的下一个输入符号是z ,但在PT[S,z] = error 中。算法因错误而终止。因此, string2不在语法G的语言中。