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


69

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

谁能用这个例子或其他例子解释它吗?

X→Yz | 一种

Y→bZ | ε

Z→ε

Answers:


110

要检查语法是否为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时才减少,而z与其他任何项都不冲突。同样,由于相同的原因,(6)中的冲突也消失了。

希望这可以帮助!


1
在您的LL(1)语法讨论中,X和Y之间是否没有FIRST / FIRST冲突?它们都包含b。
John Roberts

3
@ JohnRoberts-当同一非终端的两个生产具有重叠的FIRST集时,发生FIRST / FIRST冲突。即使X和Y在其FIRST集合中包含b,语法中也没有非终结符,具有两个产生式,其中一个以X开头,其中一个以Y开头。这有意义吗?
templatetypedef

4
@ JohnRoberts-是的,完全正确。FIRST / FIRST冲突只能涉及单个非终端的生产。直观上,该错误将导致您在LL(1)表的同一个框中填充两个不同的生成,因此这些生成的左侧必须具有相同的非终结符。
templatetypedef

1
@ JohnRoberts-我可能对此有误,但我已经教过两次编译器课程,并且阅读了两本有关解析的书。我对此很有信心,我是正确的。所有LL(1)冲突都会导致在解析表中具有两个或多个条目,并且只有在非终结符有两个不能拆分的产生式时,才会发生这种情况。反过来,只有当场景发生冲突时才发生这种情况。下面来看看例子:research.microsoft.com/en-us/um/people/abegel/cs164/ll1.html,其中,E,T和F都(和int。在FIRST
templatetypedef

1
我认为我相信维基百科的老师。您能看看我自己对此的疑问吗?stackoverflow.com/questions/15161636/making-a-grammar-ll1
约翰·罗伯茨

13

如果您没有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的第一组和F的A组中(A可解析为epsilon B作为f)。

请注意,如果没有epsilon生产,则不会发生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]包含两个Productions,因此在选择哪个规则方面存在混淆。因此不是LL(1)。

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

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

检查3:语法不应含糊不清。

These are some simple checks.

1
通过提供有关如何应用此规则的示例以及可能用于备份声明的来源,可以改善您的答案。
ankh-morpork,2015年

1
感谢您的评论。我添加了一个示例和一些其他有用的信息。
Anil Kumar

1

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

在LL(1)中

  • 第一个L代表从左到右扫描输入。Second L代表最左导数。1代表每一步使用一个输入符号。

对于“检查语法为LL(1)”,您可以绘制预测分析表。而且,如果您在表中找到任何多个条目,则可以说语法不是LL(1)。

它们也是检查语法是否为LL(1)的捷径。 快捷方式


0

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

1.如果产生:A-> a1 | a2 | a3 | a4 | ..... | an。然后,First(a(i))交集First(a(j))必须为phi(空集)[a(i)-下标i。]

2.对于每个非终端'A',如果First(A)包含epsilon,则First(A)交集Follow(A)必须为phi(空集)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.