我正在努力为C11基于N1570编写一个lex / yacc语法.我的大部分语法从信息语法摘要逐字复制,但有一些yacc冲突出现.我设法解决了所有这些,除了一个:在’_Atomic’用作类型说明符和用作类型限定符之间似乎有一些歧义.
在说明符形式中,_Atomic紧跟着括号,所以我假设它与C的一些小的语法有关,这些语法允许声明符在括号中,因此允许括号立即遵循限定符.但是我的语法已经知道如何区分typedef名字和其他标识符,所以yacc应该知道的区别,不是吗?
我不能为了我的生活想到一个实际上是模糊的情况.
我怀疑它有帮助,但这是我使用yacc -v标志时得到的相关状态输出. “ATOMIC”显然是我的“_Atomic”的令牌名称
state 23 152 atomic_type_specifier: ATOMIC . '(' type_name ')' 156 type_qualifier: ATOMIC . '(' shift,and go to state 49 '(' [reduce using rule 156 (type_qualifier)] $default reduce using rule 156 (type_qualifier)
解决方法
是的,我认为规范中有歧义.采取
_Atomic int (*f)(int);
这里_Atomic是一个类型限定符. (作为一个函数的返回类型,它不太有意义,但是有效,我认为).现在采取这种替代形式
int _Atomic (*f)(int);
通常类型限定符可以在int之后,这应该等同于其他声明.但是现在_Atomic之后是括号,所以它必须被解释为一个类型说明符,然后是语法错误.我认为甚至可以做一个例子,其中* f可以被一个有效的typedef替换.
看看第6.7.2.4 p4段的第一句话
The properties associated with atomic types are meaningful only for
expressions that are lvalues.
这清楚地表明他们不希望返回类型的函数被_Atomic限定.
编辑:
会发生同样的歧义
_Atomic int (*A)[3];
这是完美的意义(指向三个原子整数的数组),我们应该能够重写
int _Atomic (*A)[3];
编辑2:要看到括号中的类型的标准不消除歧义,请使用以下有效的C99代码:
typedef int toto; int main(void) { const int toto(void); int const toto(void); const int (toto)(void); int const (toto)(void); return toto(); }
这是一个功能的重要部分.所有四行都是相同功能的有效原型.现在使用_Atomic作为限定词
typedef int toto; int main(void) { int _Atomic (toto)(void); return toto(); }
这应该是有效的作为与const的版本.现在我们在这里有一个案例,其中_Atomic后跟括号里面有一个类型,但它不是一个类型说明符.