如何判断语言是否为LL(1)LR(0)SLR(1)

时间:2009-01-24 12:19:50

标签: parsing compiler-construction theory grammar bnf

是否有一种简单的方法可以确定语法是LL(1),LR(0),SLR(1)......只是通过查看语法而不进行任何复杂的分析?

例如:要确定BNF语法是否为LL(1),您必须计算First和Follow集 - 在某些情况下这可能很耗时。

有人知道如何更快地完成这项工作吗? 真的很感激任何帮助!

7 个答案:

答案 0 :(得分:34)

首先,有点迂腐。您无法确定语言是LL(1)来检查语法,您只能对语法本身进行声明。完全可以为存在LL(1)语法的语言编写非LL(1)语法。

解决这个问题:

  • 您可以为语法编写解析器并首先计算程序,然后为您设置跟随集和其他属性。毕竟,这是BNF语法的最大优势,它们是机器可理解的。

  • 检查语法并查找各种语法类型约束的违规。例如:LL(1)允许右递归而不是左递归,因此,包含左递归的语法不是LL(1)。 (对于其他语法属性,你将不得不在定义上花费一些时间,因为我现在不记得其他任何事情了。)。

答案 1 :(得分:15)

回答你的主要问题:对于一个非常简单的语法,可以在不构造FIRST和FOLLOW集的情况下确定它是否为LL(1),例如

  

A→A + A |一个

     

不是LL(1),而

     

A→a | B'/ P>

但是当你变得比这更复杂时,你需要做一些分析。

  

A→B |一个
  B→A + A

这不是LL(1),但可能不会立即显而易见

算术的语法规则很快变得非常复杂:

  

expr→term {'+'term}
  term→factor {'*'factor}
  因素→数量| '('expr')'

这个语法只处理乘法和加法,并且已经不能立即清楚语法是否为LL(1)。通过查看语法仍然可以对其进行评估,但随着语法的增长,它变得不那么可行。如果我们为整个编程语言定义语法,那几乎肯定会进行一些复杂的分析。

也就是说,有一些明显的迹象表明语法不是LL(1) - 就像上面的A→A + A - 如果你能在语法中找到任何这些,你就会知道它需要如果您正在编写递归下降解析器,则要重写。但是没有捷径可以验证语法 LL(1)。

答案 2 :(得分:9)

一方面,“语言/语法含糊不清”,a known undecidable question就像Post correspondencehalting问题一样。

答案 3 :(得分:9)

直接来自Aho等人的书“Compilers:Principles,Techniques,& Tools”。人

第223页:

语法G是LL(1)当且仅当时A - > alpha | beta 是G的两个不同产品,以下条件成立:

  1. 对于没有终端“a”, alpha beta 都会导出以“a”开头的字符串
  2. alpha beta 中的至多一个可以派生出空字符串
  3. 如果 beta 可以通过零次或多次转换达到空转换,则 alpha 不会从FOLLOW(A)中的终端派生任何字符串。同样,如果 alpha 可以通过零次或多次转换达到空转换,则 beta 不会从FOLLOW(A)中的终端派生任何字符串
  4. 本质上,这是验证语法通过成对不相交测试的问题,也不涉及左递归。或者更简洁的是左递归或模糊的语法G不能是LL(1)。

答案 4 :(得分:2)

检查语法是否含糊不清。如果是,则语法不是LL(1),因为没有歧义语法是LL(1)。

答案 5 :(得分:0)

你有ll(1)语法的快捷方式

1)如果A-> B1 | B2 | ....... | Bn     然后第一个(B1)交叉口第一个(B2)交叉口。第一个(Bn)=空集然后它是ll(1)语法

2)如果A-> B1 |ε      那么B1交点跟随(A)是空集

3)如果G是任何语法,使得每个非终端只得到一个产生,则语法为LL(1)

答案 6 :(得分:-2)

p0 S' → E
p1 E → id
p2 E → id ( E )
p3 E → E + id
  • 构造LR(0)DFA,为E设置的FOLLOW和SLR动作/转到表。
  • 这是LR(0)语法吗?证明你的答案。
  • 使用SLR表,显示LR解析器解析的步骤(移位,缩减,接受):
    id ( id + id )