9

自 1999 年以来,我一直在为工作和娱乐而编程。我想学习新东西,最近我一直专注于解析,因为我的大部分工作是阅读、整合和分析数据。我还有大量重复性任务,我认为如果开销足够低,我可以用非常简单的特定领域语言表达这些任务。我有几个关于这个主题的问题。

  1. 我当前的大部分解析代码都没有定义正式的语法。我通常用我选择的语言把一些东西拼凑在一起,因为这很容易,我知道怎么做,而且我可以很快地编写代码。与我一起工作的其他人也很容易维护。与大多数程序员用来编写解析器的技巧相比,定义语法和生成真正的解析器(就像使用ANTLRYACC一样)来解析事物的优点和缺点是什么?
  2. 在 C++、Perl 和 Ruby 中编写基于语法的解析器的最佳解析器生成工具是什么?我查看了ANTLR并没有发现很多关于将 ANTLRv3 与 C++ 目标一起使用的信息,但除此之外这看起来很有趣。我应该阅读哪些与 ANTLR 类似的其他工具?
  3. 有兴趣了解更多关于解析的规范书籍和文章是什么?不幸的是,编译器课程不是我教育的一部分,因此非常欢迎基础材料。我听说过关于龙之书的好消息,但那里还有什么?
4

8 回答 8

4

这是我对您的(非常好的)问题的看法:

  1. 我认为解析器从实际存在语法的非平凡情况中受益最多。你必须知道解析器和语法是如何工作的才能想到这种技术,并不是每个开发人员都知道。
  2. lex/yacc 是较旧的 Unix 工具,可能对 C++ 开发人员有用。也许野牛也是。
  3. ANTRL 和它的配套书籍非常好。 “编写编译器和解释器”包含您可能喜欢的 C++ 示例。

GoF 解释器模式是另一种编写“小语言”的技术。看看那个。

于 2009-06-27T20:43:13.990 回答
4

在 1.,我会说主要优点是可维护性- 对语言进行一点更改只是意味着对语法进行相应的微小更改,而不是对代码中可能需要做的各个点进行细微的修改随着您想要更改的内容...数量级更高的生产力和更小的错误风险。

在 2. 和 3. 上,除了您已经找到的内容之外,我无法提出太多建议(我主要使用 Python 和pyparsing,并且可以根据许多以 Python 为中心的解析框架的经验发表评论,但对于 C++,我主要使用旧的yaccbison无论如何,并且我那本粗糙的龙书——实际上不是最新版本——是我为了这个目的而保留在我身边的所有东西……)。

于 2009-06-27T20:43:15.223 回答
2

Let's Build A Compiler是关于如何编写简单编译器的分步教程。代码是用 Delphi (Pascal) 编写的,但它足够基本,可以轻松翻译成大多数其他语言。

于 2009-06-27T20:38:51.097 回答
2

我会认真研究 Haskell 中基于单子组合子的解析(通常也处理词法分析)。我发现它让我大开眼界;使用这种方法从头开始构建解析器是多么容易,这真是令人惊讶。事实上,这非常简单,编写自己的解析器通常比尝试使用现有库要快。

最著名的例子可能是Parsec,它有一个很好的用户指南来解释如何使用它。Haskell wiki 的 Parsec 页面上列出了该库与其他语言(包括C++Ruby)的端口列表,尽管我不熟悉它们,所以我不能说它们与使用 Parsec 的距离有多近在哈斯克尔。

如果您想了解这些在内部是如何工作的以及如何编写自己的,我建议您从 Graham Hutton 的Haskell 编程的第 8 章(“函数解析器”)开始。一旦你很好地理解了那一章(可能需要多读几遍),你就会准备好。

于 2009-06-30T07:31:52.600 回答
1

在 perl 中,Parse::RecDescent 模块是第一个开始的地方。将教程添加到模块名称中,Google 应该能够找到大量教程来帮助您入门。

于 2009-06-27T20:42:55.257 回答
1

使用 BNF、EBNF 或类似的东西定义语法更容易,以后您将有更好的时间维护它。此外,您还可以找到很多语法定义的示例。最后但并非最不重要的一点是,如果您要与该领域的其他人谈论您的语法,最好你们都说同一种语言(BNF、EBNF 等)。

编写自己的解析代码就像重新发明轮子一样,容易出错。它的可维护性也较差。当然,它可以更灵活一些,对于小型项目,它也可能是一个不错的选择,但是使用现有的解析器生成器来获取语法并吐出代码应该可以满足我们的大部分需求。

对于 C++,我还建议使用 lex/yacc。对于 Ruby,这看起来是一个不错的选择:Coco/R(uby)

于 2009-06-27T20:51:33.007 回答
1

有趣的时机:今天早上我花了很多时间思考状态机和解析器,并试图弄清楚如何才能更多地了解它们。

对于 2,您可以看看Ragel(它对 C++ 和 Ruby 有好处)。

于 2009-06-27T21:08:20.460 回答
1

这是一个关于自包含(10 页!)、完全可移植的编译器的教程,可用于非常快速地设计和实现“低开销”DSL:

http://www.bayfronttechnologies.com/mc_tutorial.html

该站点将带您浏览 Val Schorre 1964 年关于 MetaII 的论文。是的,1964 年。这太棒了。这就是我在 1970 年了解编译器的方式。

于 2009-07-17T09:22:41.230 回答