如果 LR(1) 解析器无法解析,gcc/clang 如何解析 C++?
How does gcc/clang parse c++ if it can't be parsed by a LR(1) parser?
GCC/Clang 是手写解析器。我读到 post 说 C++ 不能被 LR(1) 解析器解析 (Why can't C++ be parsed with a LR(1) parser?)。如果是这样,为什么 GCC/Clang 是手写的递归下降解析器,而 LR(1) 比递归下降更强大?
GCC/Clang 不是严格的递归下降解析器;它们允许回溯(重新解析任意长度的文本),以及其他与理论纯度的偏差。回溯解析器严格来说比非回溯解析器更强大(但代价是不再是线性时间)。
当问题以这种方式表述时,解析 C++ 的真正复杂性就消失了。如果您将 C++ 剥离到附录 A 中 BNF 所描述的超集,那么您基本上只需要准备好考虑几种替代解析。您可以通过回溯来做到这一点——尝试一种可能性,如果失败,则尝试其他一些——或者通过并行探索,使用 GLR/GLL 或其他一些变体;没什么太痛苦的。但是真正的工作还是要面对的:
预处理器,不是特别复杂,但不能用任何类似于正式解析框架的东西来描述;
模板实例化,将语义分析混合到解析过程中(需要完成以发现正确的解析);
名称解析,有些人可能不认为这是解析的一部分,但在您知道特定标识符引用的语法对象之前,您不会继续下一步。 (如果您认为名称解析很简单,请重新阅读第 6.5 节(名称查找)中 C++ 标准的 13 页密集页面,然后继续阅读第 12 节中关于解析重载名称的 35 页。)
GCC/Clang 是手写解析器。我读到 post 说 C++ 不能被 LR(1) 解析器解析 (Why can't C++ be parsed with a LR(1) parser?)。如果是这样,为什么 GCC/Clang 是手写的递归下降解析器,而 LR(1) 比递归下降更强大?
GCC/Clang 不是严格的递归下降解析器;它们允许回溯(重新解析任意长度的文本),以及其他与理论纯度的偏差。回溯解析器严格来说比非回溯解析器更强大(但代价是不再是线性时间)。
当问题以这种方式表述时,解析 C++ 的真正复杂性就消失了。如果您将 C++ 剥离到附录 A 中 BNF 所描述的超集,那么您基本上只需要准备好考虑几种替代解析。您可以通过回溯来做到这一点——尝试一种可能性,如果失败,则尝试其他一些——或者通过并行探索,使用 GLR/GLL 或其他一些变体;没什么太痛苦的。但是真正的工作还是要面对的:
预处理器,不是特别复杂,但不能用任何类似于正式解析框架的东西来描述;
模板实例化,将语义分析混合到解析过程中(需要完成以发现正确的解析);
名称解析,有些人可能不认为这是解析的一部分,但在您知道特定标识符引用的语法对象之前,您不会继续下一步。 (如果您认为名称解析很简单,请重新阅读第 6.5 节(名称查找)中 C++ 标准的 13 页密集页面,然后继续阅读第 12 节中关于解析重载名称的 35 页。)