【问题标题】:What does a parser for C++ do until it can differentiate between comparisons and template instantiations?C++ 解析器在区分比较和模板实例之前会做什么?
【发布时间】:2019-03-31 08:55:22
【问题描述】:

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

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

  // a b c may be declared here
};

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

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

【问题讨论】:

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


    【解决方案1】:

    虽然使用 GLR 技术解析 C++ 肯定是可能的(参见Ira Baxter 的一些答案),但我相信在 gcc 和 clang 等常用编译器中常用的方法正是延迟解析函数体,直到类定义完成。 (由于 C++ 源代码在被解析之前通过预处理器,解析器在令牌流上工作,这是必须保存的内容才能重新解析函数体。我不认为重新解析源代码是可行的。 )

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

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

    【讨论】:

    • 非常有用的答案,尽管它可以使用一些关于 gcc/clang 延迟解析的参考。
    • @panoskj:两个编译器都是开源的;您可以自己阅读代码。我不打算在这里对解析代码做一个完整的描述,特别是因为我有一段时间没有看它们了。
    • @rici:不清楚你是否阅读了 gcc/clang 代码,在这种情况下,我会相信你的话。
    【解决方案2】:

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

    • Clang 不需要词法分析器:信息从词法分析器到解析器是单向传播的

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

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

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

    【讨论】:

    • “Clang 不需要 lexer hack”。好的,这是对 lexer hack 的改进,但从您的描述中听起来他们用相应的 icky parser hack 替换它。一个人的意见。
    • 虽然我接受了另一个答案,因为它本身更完整,但您提供的文章确实很有见地,我建议阅读它。
    猜你喜欢
    • 2016-05-25
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多