现在的位置: 首页 > 综合 > 正文

6.8 歧义消解

2013年04月22日 ⁄ 综合 ⁄ 共 1850字 ⁄ 字号 评论关闭

6.8 歧义消解

1、在包含表达式语句声明的语法中存有歧义:以函数式显示类型转换(5.2.3)为最左子表达式的表达式语句可能无法同第一个声明符以左括号开头的声明区分开来。在这种情况下,语句是一个声明(即当一个语句即能为表达式语句又能为声明语句的时候,优先把它当成是声明语句) [注:为了消歧,可能需要检查整个语句以确定其为一个表达式语句还是声明。许多例子都可用此法消除歧义。例如:假定Tsimple-type-specifier7.1.5)

T(a)->m = 7;               // expression-statement

T(a)++;                //expression-statement

T(a,5)<<c;            //expression-statement

 

T(*d)(int);            //declaration

T(e)[5];                //declaration

T(f) = { 1, 2 };     // declaration

T(*g)(double(3)); // declaration

在例子的最后,指向T的指针g被初始化为double(3)。在语义上这无疑是非法的,但这并不影响句法分析。

2、下面的例子都是声明。

class T {

// ...

public:

T();

T(int);

T(int, int);

};

T(a);           //declaration

T(*b)();        //declaration

T(c)=7;         //declaration

T(d),e,f=3;     //declaration

extern int h;

T(g)(h,2);      //declaration

]

3、上述歧义消解方法是纯句法上的;也就是说,在此类声明中出现的名字的意义,不论它们是否为类型名,均不会被考虑或改变vc6与此不同,它会根据名字的语义信息来消歧,详见下面的论述)。必要的时候可对类模板进行实例化以确定一个限定名是否为type-name(在以前的标准中,消歧过程是不会对类模板进行实例化的)。消歧过程先于句法分析进行,被消歧过程解释为声明的语句可能是一个非法的声明。如果在句法分析过程中,位于模板参数中的名字的约束集不同于其在测试过程(消歧过程)中的约束集,那么程序是非法的。编译器不需要对此进行诊断。[注:这只发生在名字已被早先的声明声明过的情况下。因为消歧过程并不关心名字是否被声明,它不会利用名字的当前信息]例如:

struct T1 {

T1 operator()(int x) { return T1(x); }

int operator=(int x) { return x; }

T1(int) { }

};

struct T2 { T2(int){ } };

int a, (*(*b)(T2))(int), c, d;

 

void f() {

// disambiguation requires this to be parsed

// as a declaration

T1(a) = 3,

T2(4),                         // T2 will be declared as

(*(*b)(T2(c)))(int(d)); // a variable of type T1

// but this will not allow

// the last part of the

// declaration to parse

// properly since it depends

// on T2 being a type-name

}

(我是这样理解函数f中的代码的:首先是消歧过程对代码进行分析,消歧过程尝试将语句理解为声明,分析到T2的时候,按照标准的要求,它不会检查T2的语义信息,所以消歧过程不知道T2是一个类型名,它只认为T2是一个T1类型的变量,并且初始化为4;按照标准,消歧过程这时也不会改变T2的语义信息为变量,所以在符号表中T2仍然为类型名;所以接下来的分析能顺利的将(*(*b)(T2(c)))(int(d))理解为函数声明。所以在纯句法上,上述语句是一个合法的声明。消歧过程最后通知句法分析按声明分析当前语句,句法分析过程分析到T2的时候,将T2的语义信息置为类型为T1的变量,故而在分析接下来的函数声明时,将无法正确解析T2(c),因而报出错信息。

然而在vc6中,上述代码是能够通过编译的。但上述代码并没有被解释为声明,而是被解释为一逗号表达式,所以vc6的消歧过程要么利用了名字的语义信息,要么便是优先将语句解释为表达式。)

抱歉!评论已关闭.