2011-02-18 59 views
1

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

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

谢谢你的帮助, 查理。

PS:我打算使用Haskell的Parsec库编写解析器。编辑:此外,根据SK逻辑,Parsec可以处理一个无限的前瞻(LL(k)?) - 但我想这个问题仍然代表了这种类型的语法。

+0

秒差距能够无限先行的。出于表现以外的原因,您不需要限制LL(1)。 – 2011-02-18 14:00:19

+0

它不一定是LL(k),它可以是上下文相关的。所以,你唯一需要担心的是避免左递归。 – 2011-02-18 14:09:35

回答

3

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

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

  2. 获得像if-then-elsecase表达式一样工作的simper构造。

  3. 更进一步依赖于您正在编写语法的语言。

Definetly看看其他编程语言的语法作为参考(可惜我没在1分钟内发现任何完整LL语法任何语言上网,但LR语法应作为参考有用的太)。例如:

ANSI C grammar

Python grammar

,当然在维基百科关于LL的一些小例子文法Wikipedia LL Parser,你可能已经签出。

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

2

同时有确定的算法,如果一个语法是LL(K)。解析器生成器实现它们。如果可能,还有将语法转换为LL(k)的启发式。

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

更重要的是,它很可能是语法,你考虑你的语言最佳要求2和4之间的k,因为几个常见的编程结构做。

1

所以第一关,你不一定要你的语法是LL(1)。它使得编写解析器变得更简单并且可能提供更好的性能,但这确实意味着你的语言可能最终比通常使用的语言更冗长(通常不是LL(1))。

如果没关系,你的下一步是通过语法精神上步骤,想象可以在这一点上出现的所有可能性,并检查他们是否可以通过他们的第一个标志来区分。

有拇指的两个主要规则来进行语法LL(1)

  1. 如果选择题可以在给定的点出现,他们可以 开始同样的道理,在前面讲添加关键字你选择了哪一个 。
  2. 如果你有一个可选的或重复的部分,使 确保它之后结束令牌,该令牌不能作为可选/重复部分的第一个标记。在可能的地方生产的开始
  3. 避免选装件。它使前两步变得更容易。