以下文法是 LL(1) 吗?
Are the following grammars LL(1)?
S -> Abc|aAcb
A -> b|c|ε
我认为第一个是LL(1)
S -> aAS|b
A -> a|bSA
但问题是第二个。没有冲突问题,但是我觉得不满足右递归。
我不确定这些问题。
第一个语法不是 LL(1),因为有几个冲突,例如输入 bc
,LL 解析器将需要 look-ahead 的 2 个标记来解析它:
- 进入规则
S
- 进入规则
A
- 认字
b
- 加载下一个令牌
c
- 退出规则
A
- 预计还有一个
b
,但当前令牌是c
- 回到
A
- 向后移动一个标记,再次移动到
b
- 退出规则
A
不识别任何东西(因为 epsilon)
- 识别引用规则
A
后的 b
字符,该字符在未使用任何标记的情况下“跳转”
- 加载下一个令牌
c
- 认识
c
- 成功
对于输入 acb
,您在 S
的第二个备选方案中有类似的情况。语法没有二义性,因为最终只有一种可能的语法树。它不是 LL(1),实际上是 LL(2)。
第二种语法是确定性的——只有一种方法可以解析根据语法有效的任何输入。这意味着它可以被 LL(1) 解析器用于解析。
我制作了一个工具 (Tunnel Grammar Studio),可以检测非确定性语法的语法冲突并生成解析器。 ABNF (RFC 5234) 中的这种语法类似于语法:
S = 'a' A S / 'b'
A = 'a' / 'b' S A
正确的递归本身不会在语法内部产生歧义。产生正确的递归歧义的一种方法是在这个语法中有一些悬空元素:
S = 'c' / 'a' S 0*1 'b'
您可以将其解读为:规则 S
识别字符 c
或字符 a
后跟规则 S
本身并且可能(零次或一次)后跟字符 b
.
由于悬垂 b
字符,向上语法具有与右递归相关的歧义。这意味着对于输入 aacb
,有不止一种方法来解析它:识别 S
中的第一个 a
;再次进入S
;认识第二个a
;再次进入S
并识别c
;退出 S
一次;那么有两个选择:
情况一)识别b
字符,退出S
两次或情况二)先退出S
一次,然后识别b
字符。两种情况都是这些(来自 TGS 的可视化调试器的屏幕截图):
该文法因此是有歧义的(即不是 LL(1)),因为可以为某些有效输入生成不止一个语法树。对于此输入,可能的树只有两棵,但对于输入 aaacb
有三棵树,因为 aaacbb
有三棵树,因为可能有 3 个地方可以 'attach'两个 b
个字符,其中两个位置将有 b
,一个将留空。对于输入 aaacbbb
当然只有一种可能的语法树,但是如果至少有一个输入有不止一种可能的语法树,则语法被定义为有歧义。
S -> Abc|aAcb
A -> b|c|ε
我认为第一个是LL(1)
S -> aAS|b
A -> a|bSA
但问题是第二个。没有冲突问题,但是我觉得不满足右递归。 我不确定这些问题。
第一个语法不是 LL(1),因为有几个冲突,例如输入 bc
,LL 解析器将需要 look-ahead 的 2 个标记来解析它:
- 进入规则
S
- 进入规则
A
- 认字
b
- 加载下一个令牌
c
- 退出规则
A
- 预计还有一个
b
,但当前令牌是c
- 回到
A
- 向后移动一个标记,再次移动到
b
- 退出规则
A
不识别任何东西(因为 epsilon) - 识别引用规则
A
后的b
字符,该字符在未使用任何标记的情况下“跳转” - 加载下一个令牌
c
- 认识
c
- 成功
对于输入 acb
,您在 S
的第二个备选方案中有类似的情况。语法没有二义性,因为最终只有一种可能的语法树。它不是 LL(1),实际上是 LL(2)。
第二种语法是确定性的——只有一种方法可以解析根据语法有效的任何输入。这意味着它可以被 LL(1) 解析器用于解析。
我制作了一个工具 (Tunnel Grammar Studio),可以检测非确定性语法的语法冲突并生成解析器。 ABNF (RFC 5234) 中的这种语法类似于语法:
S = 'a' A S / 'b'
A = 'a' / 'b' S A
正确的递归本身不会在语法内部产生歧义。产生正确的递归歧义的一种方法是在这个语法中有一些悬空元素:
S = 'c' / 'a' S 0*1 'b'
您可以将其解读为:规则 S
识别字符 c
或字符 a
后跟规则 S
本身并且可能(零次或一次)后跟字符 b
.
由于悬垂 b
字符,向上语法具有与右递归相关的歧义。这意味着对于输入 aacb
,有不止一种方法来解析它:识别 S
中的第一个 a
;再次进入S
;认识第二个a
;再次进入S
并识别c
;退出 S
一次;那么有两个选择:
情况一)识别b
字符,退出S
两次或情况二)先退出S
一次,然后识别b
字符。两种情况都是这些(来自 TGS 的可视化调试器的屏幕截图):
该文法因此是有歧义的(即不是 LL(1)),因为可以为某些有效输入生成不止一个语法树。对于此输入,可能的树只有两棵,但对于输入 aaacb
有三棵树,因为 aaacbb
有三棵树,因为可能有 3 个地方可以 'attach'两个 b
个字符,其中两个位置将有 b
,一个将留空。对于输入 aaacbbb
当然只有一种可能的语法树,但是如果至少有一个输入有不止一种可能的语法树,则语法被定义为有歧义。