编写编程语言解析器的最佳实践

时间:2009-02-20 16:07:48

标签: c++ parsing programming-languages conventions

编写解析器时是否应该遵循最佳实践?

7 个答案:

答案 0 :(得分:19)

所接受的智慧是使用解析器生成器+语法,这似乎是一个很好的建议,因为您使用的是一个严格的工具,并且可能会减少工作中的错误和潜在的错误。

要使用解析器生成器,语法必须是无上下文的。如果您正在设计要解析的语言,那么您可以控制它。如果您不确定,那么如果您开始语法路线,可能会花费很多精力。即使它在实践中是无上下文的,除非语法是巨大的,否则手动编写递归的正确解析器可能更简单。

不依赖上下文不仅可以使解析器生成器成为可能,而且还可以使手动编码解析器更加简单。你最终得到的是每个短语一个(或两个)函数。如果你干净地组织和命名代码并不是比语法更难看(如果你的IDE可以向你展示调用hierachies那么你几乎可以看到语法是什么)。

优点: -

  • 更简单的构建
  • 更好的表现
  • 更好地控制输出
  • 可以应对小偏差,例如:使用不是100%无上下文的语法

我并不是说语法总是不合适,但通常效益很小,而且往往不会受到成本和风险的影响。

(我认为他们的论点似是有吸引力,并且对他们存在普遍偏见,因为它是一种表明一个人更懂计算机科学知识的方式。)

答案 1 :(得分:10)

几条建议:

  • 了解你的语法 - 以合适的形式写下来
  • 选择合适的工具。使用Spirit2x在C ++中进行,或者选择antlr,yacc或任何适合您的外部解析器工具
  • 你需要解析器吗?也许regexp就足够了?或者也许破解perl脚本来做这个伎俩?编写复杂的解析器需要时间。

答案 2 :(得分:7)

不要过度使用正则表达式 - 虽然它们有它们的位置,但它们根本没有能力处理任何类型的真正解析。你可以推动他们,但你最终会撞墙或最终导致无法维护的混乱。你最好找一个可以处理更大语言集的解析器生成器。如果你真的不想进入工具,你可以看一下递归下降解析器 - 这是一个非常简单的手工编写小解析器的模式。它们不像大型解析器生成器那样灵活或功能强大,但它们的学习曲线要​​短得多。

除非您的性能要求非常严格,否则请尝试将各个图层分开 - 词法分析器读入单个标记,解析器将这些标记排列到树中,然后语义分析检查所有内容并链接引用,然后是最后阶段输出正在生产的任何东西。保持逻辑的不同部分分开将使以后更容易维护。

答案 3 :(得分:7)

首先阅读大部分Dragon book

如果你知道如何构建它们,解析器并不复杂,但它们并不是那种如果你投入足够的时间,你最终会到达那里的东西。在现有知识库的基础上进行构建会更好。 (否则期望写出并扔掉几十次)。

答案 4 :(得分:5)

是的。尝试生成它,而不是写。考虑使用yacc,ANTLR,Flex / Bison,Coco / R,GOLD Parser生成器等。只有当现有的解析器生成器都不符合您的需求时,才能手动编写解析器。

答案 5 :(得分:3)

  • 选择正确类型的解析器,有时候递归后代就足够了,有时你应该使用LR解析器(还有很多类型的LR解析器)。
  • 如果您有复杂的语法,请构建一个抽象语法树。
  • 尝试很好地识别词法分析器的内容,语法的一部分以及语义问题。
  • 尽量使解析器与词法分析器实现最少耦合。
  • 为用户提供良好的界面,使他不知道解析器的实现。

答案 6 :(得分:2)

首先,不要尝试使用相同的技术来解析所有内容。有许多可能的用例,从IP地址(一些特殊代码)到C ++程序(需要具有符号表反馈的工业级解析器)和用户输入(需要非常好地处理)快速)到编译器(通常可以花费一点时间解析)。如果您需要有用的答案,可能需要指定您正在做的事情。

其次,要记住一个语法来解析。它越复杂,规范就越正式化。试着过于正式的错误。

第三,嗯,这取决于你正在做什么。