GCC和LLVM-Clang似乎都在使用手写递归下降解析器,以及非机器生成的、基于Bison的、自下而上的解析。
请这里的人确认一下是这样的吗?如果是这样的话,为什么主流编译器框架使用手写解析器呢?
更新:这里有关于这个主题的有趣博客
发布于 2011-06-11 23:47:52
是:
发布于 2011-06-12 05:28:30
有一个民间定理说C很难解析,而C++本质上是不可能的。
这不是真的.
确实,C和C++很难使用LALR(1)解析器来解析,而不需要侵入解析机制和处理符号表数据。GCC实际上是用YACC和其他类似的黑客来解析它们的,是的,它是丑陋的。现在GCC用的是手写解析器,但仍然带有符号表黑客。Clang从未有过使用自动解析器生成器的尝试;Clang解析器AFAIK一直是手工编码的递归下降。
事实是,C和C++相对容易使用更强的自动生成解析器(例如,GLR解析器 )进行解析,并且不需要任何黑客攻击。埃尔萨 C++解析器就是一个例子。我们的C++前端是另一个(就像我们所有的“编译器”前端一样,GLR是非常棒的解析技术)。
我们的C++前端没有GCC的快,当然也比Elsa慢;我们很少投入精力对其进行仔细的调整,因为我们还有其他更紧迫的问题(然而,它已经被用于数百万行C++代码中)。埃尔莎可能会比GCC慢一些,原因很简单,因为它更笼统。考虑到现在处理器的速度,这些差异在实践中可能并不重要。
但是,今天广为传播的“真正的编译器”植根于10年或20年前的编译器。效率低下更重要,没有人听说过GLR解析器,所以人们做了他们知道如何做的事情。Clang当然是最近才出现的,但是民间定理在很长一段时间内保持了他们的“说服力”。
你不用再那样做了。您可以非常合理地使用GLR和其他类似的解析器作为前端,同时提高编译器的可维护性。
事实是,要获得一个与友好的邻里编译器行为相匹配的语法是很困难的。虽然几乎所有的C++编译器都实现了(大多数)原始标准,但它们也往往有许多黑暗的扩展,例如MS编译器中的DLL规范等等。如果您有一个强大的解析引擎,您可以花费时间尝试获得最终的语法以满足实际情况,而不是试图弯曲语法以满足解析器生成器的限制。
2012年11月编辑:自从编写这个答案以来,我们改进了C++前端,以处理完整的C++11,包括ANSI、GNU和MS变体方言。虽然有很多额外的内容,但我们不需要更改解析引擎;我们只是修改了语法规则。我们确实需要更改语义分析;C++11在语义上非常复杂,这项工作阻碍了使解析器运行的工作。
2015年2月编辑:.现在处理完整的C++14。(关于GLR对简单代码的解析,以及C++臭名昭著的“最烦人的解析”,请参见从c++代码中获取人类可读的AST )。
编辑2017年4月:现在处理(草稿) C++17。
发布于 2011-06-17 06:28:27
Clang的解析器是一个手写的递归下降解析器,其他几个开源和商业C和C++前端也是如此。
Clang使用递归下降解析器有以下几个原因:
总的来说,对于C++编译器来说,这并不重要: C++的解析部分并不简单,但它仍然是比较容易的部分之一,所以保持简单是值得的。语义分析--特别是名称查找、初始化、重载解析和模板实例化--比解析更加复杂。如果您想要证明,请检查代码的分发,并在Clang的"Sema“组件(用于语义分析)和它的"Parse”组件(用于解析)中提交。
https://stackoverflow.com/questions/6319086
复制相似问题