C++模板”>>”编译问题与词法消歧设计

2013-10-10 09:40:46 | 新闻来源:叶凡网络 | 点击量:1082

     反而不能在C++11中编译了因为根据规范第一个”被解释成了模版参数结束符。如果要在C++11中编译,这个例子在C++98中是能正确编译的>>被解释成了位移运算。需要显式地加上括号:

     通常将编译过程笼统为5个主要阶段:词法分析(LexicAnalysi语法分析(Pars语义分析(SemantAnalysi优化(Optimiz代码生成(CodeGener这5个阶段类似Unix管道模型,编译理论中。上一个阶段的输出作为下一个阶段的输入。其中,词法分析是根据输入源代码文本流,分割出词,识 别类别,发生词法元素(Token流,如:

int a = 10; 

      就会根据这些词法元素匹配相应的语法规则。学习编译原理时,教科书中对于词法分析的介绍主要是基于正则表达式的言 下之意就是普通语言的词法规则是可以通过正则表达式描述的比方,C语言的变量名规则是包括字母、数字或下划线,并且以字母或下划线开头”这就可以用 正则表达式[a-zA -Z][a-zA -Z0-9]*表达。但是实践中我发现不论是主流语言,还是自己设计的DSL都大量存在不能简单通过正则表达式进行词法分析的例子。来看C++98模版例子:?经过词法分析会得到[Type,"int",Identifier,"a",AssignOperator,"=",IntLiteral,10]后续的语法分析阶段。

map> 

      原因在于它把“>>识别成了位右移运算符而不是两个模版右括号,上面这段代码会被C++98编译器中报语法错误。C++98中必须在两个括号中间加空格,写成

map > 

据我所知,除此了C++模版。经典的FORPA N语言的语法规则更是大量存在词法歧义。

      这类问题的根源在于词法分析的依据只是简单的词法规则,并不具备所有的语法信息,而词法歧义必需提升一层在语法规则中消除。所 以,自己设计一些DSL时候干脆就把词法分析和语法分析合二为一了相当于让语法分析在字符层次上去进行,而不是经典的词法元素层次上,这就是所谓 ScannerlessPars采用这种方法的例子并不少见,TeX, 认为从本质上讲。Wiki,Makefil和Perl6等语言的语法分析器都属此类。

      但是同时也破坏了词法和语法分析简单清晰的管道结构,ScannerlessPars方法弥补了词法规则无法消歧的问题。总体上增加了实现和理解的复杂度。另外,像C++这样大型的语言,如果开始是有词法分析的稍微碰到一个歧义就整个转成ScannerlessPars未免也显得太夸张了这个问题困扰了很久,直到最近才找到一个满意的解决方案。还是以上面”>>为例,知道现在C++11已经允许不加空格了那么C++11编译器是如何处置这个词法歧义的呢?答案是词法分析阶段既然分析不好”>>干脆就不分析 直接把”>>交给语法分析器来分析,其他没有词法歧义的照旧。当我知道这个方案的时候不由得感叹:妙!理论上,词法分析是可以什么也不做的全部把字符一 一交给语法分析器也没有问题,所以,干脆让词法分析只做有把握的局部,解决不了交给语法分析器,这样就既保留了管道结构,又解决了词法歧义。

下面我再来看看C++11规范关于这个问题的定义:

 

 

14.2Nameoftemplatspecial[temp.names]###

theistakenastheenddelimitratherthanagreater-thanoperator.Similarly,thefirstnon-nest>>istreatastwoconsecutbutdistinct>tokens,thefirstofwhichistakenastheendofthetemplate-argument-listandcompletthetemplate-id.[Note:Thesecond>tokenproducbythireplacrulemaiterminanenclostemplate-idconstructoritmaibepartofadifferconstructe.g.acast.endnote]

 

 

 

 

C++11中,     可见。词法分析器是把”>>直接当成两个”>传给了语法分析器,然后在语法分析中如果匹配了template-argument-li语法,第一个”>符号会被直接认为是模版结束符,而不是大于,也不是位移符号。根据这个定义,构造了一个例子:

template 

  • class Foo { }; 
  •   Foo<3>>1> foo;  Foo<3>>1> foo; 
  • 上一篇:移动应用开发指南:Native、Hybrid与HTML5 下一篇:Server 2012 R2 Essentials超酷新功能