【发布时间】:2012-01-19 18:21:22
【问题描述】:
您如何识别语法是 LL(1)、LR(0) 还是 SLR(1)?
谁能用这个例子或任何其他例子解释一下?
X → Yz |一个
Y → bZ | ε
Z → ε
【问题讨论】:
您如何识别语法是 LL(1)、LR(0) 还是 SLR(1)?
谁能用这个例子或任何其他例子解释一下?
X → Yz |一个
Y → bZ | ε
Z → ε
【问题讨论】:
要检查语法是否为 LL(1),一种选择是构造 LL(1) 解析表并检查是否存在任何冲突。这些冲突可能是
让我们通过为每个非终结符构建 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) 中的冲突也因同样的原因而消失了。
希望这会有所帮助!
【讨论】:
int 在 FIRST。
如果您没有 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 冲突。
【讨论】:
简单回答:如果关联的 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.
【讨论】:
LL(1) 语法是上下文无关的明确语法,可以被 LL(1) 解析器解析。
在 LL(1) 中
对于检查语法是 LL(1),您可以绘制预测解析表。如果您在表中发现任何多个条目,那么您可以说语法不是 LL(1)。
它们也是检查语法是否为 LL(1) 的捷径。 Shortcut Technique
【讨论】:
通过这两个步骤,我们可以检查它是否为 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(空集)。
【讨论】: