_Atomic类型说明符和限定符之间的C11语法歧义

我正在尝试根据N1570编写C11的lex / yacc语法。 我的大部分语法都是从信息性语法摘要中逐字复制的,但是出现了一些yacc冲突。 我设法解决了除了一个之外的所有问题:当’_Atomic’用作类型说明符和用作类型限定符时,似乎存在一些歧义。

在说明符forms中,_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是一个类型限定符。 (作为函数的返回类型,它没有多大意义,但我认为是有效的)。 现在采取这种替代forms

 int _Atomic (*f)(int); 

通常类型限定符可以在int ,这应该等同于另一个声明。 但是现在_Atomic后面跟着括号,所以它必须被解释为一个类型说明符,然后是语法错误。 我认为甚至可以编写一个示例,其中*f可以替换为有效的typedef

看看6.7.2.4 p4的第一个短语

与primefaces类型关联的属性仅对作为左值的表达式有意义。

这清楚地表明他们不希望返回类型的函数符合_Atomic标准。

编辑:

会出现同样的歧义

 _Atomic int (*A)[3]; 

这是完全合理的(指向三个primefaces整数数组的指针),我们应该能够重写为

 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(); } 

这个重新声明在main内部作为一个function。 并且所有四行都是相同function的有效原型。 现在使用_Atomic作为限定符

 typedef int toto; int main(void) { int _Atomic (toto)(void); return toto(); } 

这应该是有效的const版本。 现在我们在这里有一个案例,其中_Atomic后跟括号内部的类型,但它不是类型说明符。

好吧,无论我们是否能够提出语法模糊的情况都没关系。 N1570第6.7.2.4节第4段规定:

如果_Atomic关键字后面紧跟左括号,则将其解释为类型说明符(具有类型名称),而不是类型限定符。

为了强制执行此操作,我只是将_Atomic设置为说明符,将_Atomic设置为我的lex规则中的单独标记的限定符。

 "_Atomic"/{WHITESPACE}*"(" {return ATOMIC_SPECIFIER;} "_Atomic" {return ATOMIC_QUALIFIER;} 

我对lex / yacc和解析器生成器一般都比较新,但我的直觉说这是一种黑客行为。 同时,lex中的尾随上下文语法还有什么用呢?