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

时间:2018-10-26 14:56:05

标签: c++ parsing gcc compiler-construction clang

在阅读this question之后,我想知道当主要的C ++编译器解析这样的代码时会发生什么(关于AST):

struct foo 
{
  void method() { a<b>c; }

  // a b c may be declared here
};

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

例如,我认为可以将方法主体的解析推迟到整个结构都解析完之后,但这真的可行吗?

2 个答案:

答案 0 :(得分:2)

答案显然取决于编译器,但是Eli Bendersky的文章How Clang handles the type / variable name ambiguity of C/C++解释了Clang是如何做到的。我将简单地指出文章中的一些要点:

  • Clang无需进行lexer hack:信息从lexer到解析器沿单一方向传播

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

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

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

答案 1 :(得分:2)

尽管当然可以使用GLR技术来解析C ++(请参阅Ira Baxter的许多答案),但我相信,通用编译器(如gcc和clang)中常用的方法正是推迟对函数体的解析,直到完成类定义为止。 (由于C ++源代码在解析之前先经过预处理程序,因此解析器在令牌流上工作,这是必须保存的内容,以便重新解析函数体。我认为重新解析源代码不可行。 )

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

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