写出正确的LL(1)语法?

时间:2011-02-18 13:55:45

标签: parsing grammar recursive-descent ll

我正在尝试为编程语言编写一个(非常)小的解释器/编译器。我已经设置了语言的语法,现在我需要写下语言的语法。我打算使用LL(1)解析器,因为经过一些研究后,它似乎最容易使用。

我是这个领域的新手,但是从我收集的内容来看,强烈建议使用BNF或EBNF来形式化语法。但是,似乎并非所有语法都适合使用LL(1)解析器实现。因此,我想知道以LL(1)形式编写语法的正确(或推荐)方法是什么。

感谢您的帮助, 查理。

PS:我打算用Haskell的Parsec库编写解析器。

编辑:另外,根据SK逻辑,Parsec可以处理无限前瞻(LL(k)?) - 但我想这个问题仍然代表这种语法。

3 个答案:

答案 0 :(得分:3)

我不是这方面的专家,因为我只使用LR(0)解析器创建了一个类似的小项目。我建议采用的一般方法:

  1. 让算术工作。通过这个,为+, -, /, *等制定规则和派生,并确保解析器生成一个有效的抽象语法树。测试和评估不同输入的树,以确保它正确地执行算术。 一步一步做事。如果您遇到任何冲突,请在继续之前先解决。

  2. 让{simper}构造像if-then-elsecase表达式一样有效。

  3. 更进一步取决于你所编写语法的语言。

  4. 绝对检查出其他编程语言语法作为参考(遗憾的是,我没有在1分钟内找到任何在线任何语言的完整LL语法,但LR语法也应该作为参考有用)。例如:

    ANSI C grammar

    Python grammar

    当然,维基百科中有关LL语法Wikipedia LL Parser的一些小例子,你可能已经检查过了。

    我希望你能找到一些有用的东西

答案 1 :(得分:2)

有用于确定语法是否为LL(k)的算法。解析器生成器实现它们。如果可能的话,还有将语法转换为LL(k)的启发式方法。

但是您不需要将简单语言限制为LL(1),因为大多数现代解析器生成器(JavaCCANTLRPyparsing和其他人都可以处理任何语言LL(k)中的k。

更重要的是,您认为语言 best 的语法很可能需要k介于2和4之间,因为有几种常见的编程结构。

答案 2 :(得分:1)

首先,你不一定希望你的语法是LL(1)。它使得编写解析器更简单并且可能提供更好的性能,但它确实意味着您的语言可能最终会比常用语言(通常不是LL(1))更冗长。

如果没关系,你的下一步是精神上逐步完成语法,想象那时可能出现的所有可能性,并检查它们是否可以通过他们的第一个标记来区分。

制作语法LL(1)

有两个主要的经验法则
  1. 如果有多个选择可以出现在给定点,他们可以 从相同的标记开始,在前面添加一个关键字告诉你哪个 选择了。
  2. 如果您有可选或重复的部分,请制作 确定它后跟一个结尾标记,它不能作为可选/重复部分的第一个标记出现。
  3. 尽可能避免在生产开始时使用可选部件。它使前两个步骤变得更加容易。