现代编译器使用哪些解析器?

时间:2018-03-07 21:49:06

标签: parsing compiler-construction abstract-syntax-tree

我无法找到有关某些现代编译器解析器的任何信息,尤其是:

  • 打字稿
  • C#

他们使用LL(k),LR(k),混合物还是其他不同的东西?是否有任何网站列出了有关多种语言的编译器/解析器的信息?由于这些编译器通常被认为是“现代的”,我对它们的解析技术非常感兴趣。

1 个答案:

答案 0 :(得分:9)

所有这三个都使用特殊的,手工构建的解析器,松散地基于预测(自上而下)解析,对于自上而下解析是非确定性的情况,似乎需要任何kludges和hacks。

如果你想做的话,我当然不会推荐这个作为构建解析器的模型。使用解析器生成器构建解析器要容易得多;生成的解析器将更短,更容易阅读,如果你做得对,它将是自我记录的,因为用于生成解析器的语法正是你想要放在文档中的语法。

既然如此,你可能会合理地想知道为什么这么少"现代"语言使用解析器生成器。除了与编程心理学有关的解释之外,我对此没有很好的答案。手工编写解析器需要大量的工作和巨大的痛苦,但它远不是编写编译器的最大任务 - 良好的优化是一个更复杂的问题,并且没有简单的生成器工具 - 所以劳动力可能不会像人们想象的那样令人沮丧。显然可以用"仅解析大多数语言。几千个LoC,这似乎可以减少学习解析器生成器的细节。

一个常见的解释是,使用自上而下的解析器生成良好的编译器错误消息显然更容易,而良好的错误消息对于语言采用非常重要。 (例如,由于C ++模板中的小错别字导致的可挽回的错误消息显然是采用C ++的障碍。即使在今天,模板编译错误消息也难以阅读,但它们已经变得更好。)不是说用自下而上的语法编写好的编译器错误消息处理程序是不可能的,但是如何这样做并不总是很明显。

另一种解释是,大多数人似乎都想用自己的语言编写解析器(及其编译器)。通常的策略是使用其他令人讨厌的语言构建一个快速而肮脏的微型编译器,并使用它来引导正在开发的语言中的华丽优雅的编译器。 (这种心态导致了一个奇怪的事实,即大多数语言首先针对编译器编写进行了优化,尽管每种语言中只能编写一个编译器。)

引导策略使得使用解析器生成器变得困难,因为首先必须重写解析器生成器本身以生成新语言的代码。在一个完美的世界中,将新语言的代码生成改进现有的解析器生成器很容易,但实际情况却大相径庭。 (如果你想开展这个项目,我强烈建议使用Lemon解析器作为基础而不是yacc或bison的任何实现。它不会是微不足道的,但至少你不需要学习如何在M4施放法术。)

this bug report所述,手工构建解析器的主要缺点是没有简单的方法可以验证它们是否真正识别出版语法记录的语言。 Rust源代码树现在包含一个产生AST的Bison / Flex解​​析器,尽管Rust编译器没有使用它(用Rust编写,参见上文)。尽管存在缺陷,但this grammar与生成解析器相比,更接近于已发布的语法。但它并没有尝试产生任何形式的信息语法错误消息(或者,实际上,生成代码)。