【问题标题】:How to identify whether a grammar is LL(1), LR(0) or SLR(1)?如何识别文法是 LL(1)、LR(0) 还是 SLR(1)?
【发布时间】:2012-01-19 18:21:22
【问题描述】:

您如何识别语法是 LL(1)、LR(0) 还是 SLR(1)?

谁能用这个例子或任何其他例子解释一下?

X → Yz |一个

Y → bZ | ε

Z → ε

【问题讨论】:

    标签: parsing grammar lr ll


    【解决方案1】:

    要检查语法是否为 LL(1),一种选择是构造 LL(1) 解析表并检查是否存在任何冲突。这些冲突可能是

    • FIRST/FIRST 冲突,其中必须为非终结符/终结符对预测两个不同的产生式。
    • FIRST/FOLLOW 冲突,其中预测了两种不同的产生式,一个表示应采用某些产生式并将其扩展为非零数量的符号,另一个表示应使用一个产生式,指示应最终扩展某些非终结符输出到空字符串。
    • FOLLOW/FOLLOW 冲突,其中指示非终结符最终应扩展为空字符串的两个产生式相互冲突。

    让我们通过为每个非终结符构建 FIRST 和 FOLLOW 集来试试你的语法。在这里,我们明白了

    FIRST(X) = {a, b, z}
    FIRST(Y) = {b, epsilon}
    FIRST(Z) = {epsilon} 
    

    我们也有 FOLLOW 集是

    FOLLOW(X) = {$}
    FOLLOW(Y) = {z}
    FOLLOW(Z) = {z}
    

    由此,我们可以构建如下的LL(1)解析表:

        a    b    z   $
    X   a    Yz   Yz  
    Y        bZ   eps
    Z             eps
    

    由于我们可以无冲突地构建此解析表,因此语法为 LL(1)。

    要检查语法是 LR(0) 还是 SLR(1),我们首先为该语法构建所有 LR(0) 配置集。在这种情况下,假设 X 是您的开始符号,我们得到以下信息:

    (1)
    X' -> .X
    X -> .Yz
    X -> .a
    Y -> .
    Y -> .bZ
    
    (2)
    X' -> X.
    
    (3)
    X -> Y.z
    
    (4)
    X -> Yz.
    
    (5)
    X -> a.
    
    (6)
    Y -> b.Z
    Z -> .
    
    (7)
    Y -> bZ.
    

    由此可知,文法不是LR(0),因为状态(1)和(6)存在移位/归约冲突。具体来说,因为我们有减少项目 Z → 。和 Y → .,我们不知道是将空字符串简化为这些符号还是转移其他符号。更一般地说,没有 ε-产生式的文法是 LR(0)。

    但是,这种语法可能是 SLR(1)。为了看到这一点,我们使用为特定非终结符设置的前瞻集来增加每个归约。这将返回这组 SLR(1) 配置集:

    (1)
    X' -> .X
    X -> .Yz [$]
    X -> .a  [$]
    Y -> .   [z]
    Y -> .bZ [z]
    
    (2)
    X' -> X.
    
    (3)
    X -> Y.z [$]
    
    (4)
    X -> Yz. [$]
    
    (5)
    X -> a.  [$]
    
    (6)
    Y -> b.Z [z]
    Z -> .   [z]
    
    (7)
    Y -> bZ. [z]
    

    现在,我们不再有轮班减少冲突。状态 (1) 中的冲突已被消除,因为我们仅在前瞻为 z 时进行归约,这与任何其他项都不冲突。同样,(6) 中的冲突也因同样的原因而消失了。

    希望这会有所帮助!

    【讨论】:

    • 在您的 LL(1) 语法讨论中 X 和 Y 之间没有 FIRST/FIRST 冲突吗?它们都包含 b。
    • @JohnRoberts-当同一个非终结符的两个产生式具有重叠的 FIRST 集时,就会发生 FIRST/FIRST 冲突。尽管 X 和 Y 在它们的 FIRST 集中包含 b,但在具有两个产生式的语法中没有非终结符,其中一个以 X 开头,一个以 Y 开头。这有意义吗?
    • @JohnRoberts- 是的,完全正确。 FIRST/FIRST 冲突只能涉及单个非终结符的产生式。直观地说,该错误会导致您在 LL(1) 表中使用两个不同的产生式填充同一个框,因此这些产生式的左侧必须具有相同的非终结符。
    • @JohnRoberts- 我可能弄错了,但我已经教过两次编译器课程,并且读过两本关于解析的书。我相当有信心我对此是正确的。所有 LL(1) 冲突都会导致解析表中有两个或更多条目,并且只有当非终结符的两个产生式无法分开时才会发生这种情况。反过来,只有当这些集合以一种在生产中很重要的方式发生碰撞时才会发生这种情况。看看这里的例子:research.microsoft.com/en-us/um/people/abegel/cs164/ll1.html,其中 E、T 和 F 都有 ( 和 int 在 FIRST。
    • 我认为我信任一位老师而不是维基百科。你能看看我自己关于这个的问题吗? stackoverflow.com/questions/15161636/making-a-grammar-ll1
    【解决方案2】:

    如果您没有 FIRST/FIRST 冲突且没有 FIRST/FOLLOW 冲突,则您的语法为 LL(1)。

    FIRST/FIRST 冲突示例:

    S -> Xb | Yc
    X -> a 
    Y -> a 
    

    通过仅查看第一个输入符号 a,您无法知道是应用产生式 S -> Xb 还是 S -> Yc,因为 a 在 X 和 Y 的第一个集合中。

    FIRST/FOLLOW 冲突示例:

    S -> AB 
    A -> fe | epsilon 
    B -> fg 
    

    通过只查看第一个输入符号 f,您无法决定是应用产生式 A -> fe 还是 A -> epsilon,因为 f 既在 A 的 FIRST 集合中,又在 A 的 FOLLOW 集合中(A 可以是解析为 epsilon,B 解析为 f)。

    请注意,如果您没有 epsilon-productions,则不会发生 FIRST/FOLLOW 冲突。

    【讨论】:

      【解决方案3】:

      简单回答:如果关联的 LL(1) 解析表在每个表项中最多有一个产生式,则称该文法为 LL(1)。

      Take the simple grammar A -->Aa|b.[A is non-terminal & a,b are terminals]
         then find the First and follow sets A.
          First{A}={b}.
          Follow{A}={$,a}.
      
          Parsing table for Our grammar.Terminals as columns and Nonterminal S as a row element.
      
              a            b                   $
          --------------------------------------------
       S  |               A-->a                      |
          |               A-->Aa.                    |
          -------------------------------------------- 
      

      由于 [S,b] 包含两个产生式,因此对于选择哪个规则存在混淆。因此它不是 LL(1)。

      一些简单的检查来查看语法是否为 LL(1)。 检查 1:语法不应该是递归的。 示例:E --> E+T。不是 LL(1),因为它是左递归的。 检查 2:语法应该是左因式。

      当两个或多个语法规则选择共享一个公共前缀字符串时,需要使用左分解。 示例:S-->A+int|A

      检查 3:语法不应有歧义。

      These are some simple checks.
      

      【讨论】:

      • 您的答案可以通过包括如何应用此规则的示例以及可能的来源来备份您的声明来改进。
      • 感谢您的评论。我添加了一个示例和一些其他有用的信息。
      【解决方案4】:

      LL(1) 语法是上下文无关的明确语法,可以被 LL(1) 解析器解析。

      在 LL(1) 中

      • 第一个 L 代表从左到右扫描输入。第二个 L 代表 对于最左推导。 1 代表在每个输入符号处使用一个输入符号 步骤。

      对于检查语法是 LL(1),您可以绘制预测解析表。如果您在表中发现任何多个条目,那么您可以说语法不是 LL(1)。

      它们也是检查语法是否为 LL(1) 的捷径。 Shortcut Technique

      【讨论】:

        【解决方案5】:

        通过这两个步骤,我们可以检查它是否为 LL(1)。 两个都得满足。

        1.如果我们有产生式:A->a1|a2|a3|a4|.....|an。 那么,First(a(i))相交First(a(j))一定是phi(空集)[a(i)-a下标i.]

        2.对于每个非终结符 'A',如果 First(A) 包含 epsilon 那么 First(A) 交点 Follow(A) 必须是 phi(空集)。

        【讨论】:

          猜你喜欢
          • 2015-10-05
          • 1970-01-01
          • 2016-04-14
          • 1970-01-01
          • 2011-09-23
          • 1970-01-01
          • 2016-08-07
          • 2015-10-07
          • 1970-01-01
          相关资源
          最近更新 更多