C++的解析器在可以区分比较和模板实例化之前会做什么?

What does a parser for C++ do until it can differentiate between comparisons and template instantiations?

本文关键字:实例化 什么 比较 C++      更新时间:2023-10-16

读完这个问题后,我想知道当主要的C++编译器像这样解析代码时会发生什么(关于 AST(:

struct foo 
{
void method() { a<b>c; }
// a b c may be declared here
};

他们是像 GLR 解析器那样处理它还是以不同的方式处理它?还有什么其他方法可以解析这种情况和类似的情况?

例如,我认为可以推迟解析方法的主体,直到解析整个结构,但这真的可能和实用吗?

虽然当然可以使用GLR技术来解析C++(参见Ira Baxter的一些答案(,但我相信gcc和clang等常用编译器中常用的方法恰恰是将函数体的解析推迟到类定义完成。(由于C++源代码在解析之前会通过预处理器,因此解析器处理令牌流,这是为了重新解析函数体而必须保存的内容。我不认为重新解析源代码是可行的。

当函数定义完成时很容易知道,因为大括号({}(必须平衡,即使不知道尖括号如何嵌套。

C++ 并不是在处理声明之前延迟解析的唯一有用语言。例如,允许用户定义具有不同优先级的新运算符的语言将要求在知道运算符的名称和优先级后(重新(解析所有表达式。一个更病态的例子是COBOL,其中ORa = b OR c中的优先级取决于c是整数(a等于bc之一(还是布尔值(a等于bc为真(。以这种方式设计语言是否是一个好主意是另一个问题。

答案显然取决于编译器,但 Eli Bendersky 的文章 Clang如何处理 C/C++ 的类型/变量名称歧义解释了 Clang 是如何做到的。我将简单地指出文章中的一些关键点:

Clang不需要词法分析器
  • 黑客:信息从词法分析器到解析器的单一方向

  • Clang 通过使用符号表知道标识符何时为类型

  • C++要求声明在整个类中可见,即使在它前面出现的代码中也是如此

  • Clang通过对声明进行完整的解析/语义分析来解决这个问题,但将定义留待以后使用;换句话说,它是词法化的,但在所有声明的类型都可用后进行解析。