Dag*_*ang 4 c++ compiler-construction parsing
在经典的编译器理论中,前两个阶段是词法分析和解析.他们在管道中.词法分析将标记视为解析的输入.
但我遇到了一些在词法分析中很难被正确识别的案例.例如,以下有关C++模板的代码:
map<int, vector<int>>
在>>将被确认为在"常规"词法分析按位右移,但它是不正确的.我的感觉是很难将这种语法的处理分为两个阶段,lexing工作必须在解析阶段完成,因为正确解析>>依赖于语法,而不仅仅是简单的词法规则.
我想知道关于这个问题的理论和实践.另外,我想知道C++编译器如何处理这种情况?
C++标准要求实现执行词法分析以在解析阶段之前生成令牌流.根据词法分析规则,两个连续的>字符(未后跟=)将始终被解释为一个>>标记.C++标准提供的语法是根据这些标记定义的.
在语法中没有指定在某些上下文中(例如在期望>模板ID内部时)实现应该解释>>为两个>的要求.而是将规则指定为特例:
14.2模板特化名称[temp.names] ###
名称查找(3.4)后发现名称是模板名称或者operator-function-id或literal-operator-id引用一组重载函数,如果后面跟着函数模板,则其中任何成员都是函数模板a
<,<始终作为template-argument-list的分隔符,而不是less-than运算符.解析模板参数列表时,第一个非嵌套>被视为结束分隔符而不是大于运算符.类似地,第一个非嵌套>>被视为两个连续但不同的>标记,第一个被视为template-argument-list的结尾并完成 template-id.[注意:>此替换规则生成的第二个标记可以终止封闭的 模板ID构造,也可以是不同构造的一部分(例如演员).-结束注释]
注意:前面的规则,即在某些情况下<应被解释为<在一个模板参数列表.这是需要上下文以消除解析歧义的构造的另一个示例.
C++语法包含许多这样的歧义,在解析过程中无法解决这些歧义而没有关于上下文的信息.其中最为人所知的是最令人烦恼的解析,其中标识符可以根据上下文被解释为类型名称.
在C++中跟踪上述上下文需要一个实现来与解析阶段并行执行一些语义分析.这通常以语义动作的形式实现,当在给定的上下文中识别特定的语法构造时,该语义动作被调用.然后,这些语义操作构建一个表示上下文的数据结构,并允许有效的查询.这通常被称为符号表,但C++所需的结构几乎就是整个AST.
这些上下文敏感的语义动作也可用于解决歧义.例如,在识别名称空间主体的上下文中的标识符时,语义动作将检查该名称是否先前被定义为模板.然后将其结果反馈给解析器.这可以通过使用结果标记标识符标记,或者将其替换为与不同语法规则匹配的特殊标记来完成.
可以使用相同的技术将a标记<为模板参数列表的开头,或者>作为结束标记.上下文敏感的>>两个替换规则>基本上是相同的问题,可以使用相同的方法解决.