在阅读this question之后,我想知道当主要的C ++编译器解析这样的代码时会发生什么(关于AST):
struct foo
{
void method() { a<b>c; }
// a b c may be declared here
};
他们是否像GLR解析器那样处理它或以其他方式处理它?还有什么其他方法可以解析这种情况和类似情况?
例如,我认为可以将方法主体的解析推迟到整个结构都解析完之后,但这真的可行吗?
答案 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,其中OR
中a = b OR c
的优先级取决于c
是否为整数(a
等于b
之一或c
)或布尔值(a
等于b
或c
为真)。以这种方式设计语言是否是一个好主意,这是另一个问题。