Jo *_*tes 11 c grammar yacc c11
我正在尝试根据N1570编写C11的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)
Run Code Online (Sandbox Code Playgroud)
好吧,我们是否可以提出一个语法模糊的案例并不重要.N1570第6.7.2.4节第4段规定:
如果_Atomic关键字后面紧跟左括号,则将其解释为类型说明符(具有类型名称),而不是类型限定符.
为了强制执行此操作,我简单地将_Atomic设置为说明符,将_Atomic设置为我的lex规则中的单独标记的限定符.
"_Atomic"/{WHITESPACE}*"(" {return ATOMIC_SPECIFIER;}
"_Atomic" {return ATOMIC_QUALIFIER;}
Run Code Online (Sandbox Code Playgroud)
我对lex/yacc和解析器生成器一般都比较新,但我的直觉说这是一种黑客行为.同时,lex中的尾随上下文语法还有什么用呢?
是的,我认为规范中存在歧义.采取
_Atomic int (*f)(int);
Run Code Online (Sandbox Code Playgroud)
这里_Atomic是一个类型限定符.(作为函数的返回类型,它没有多大意义,但我认为是有效的).现在采取这种替代形式
int _Atomic (*f)(int);
Run Code Online (Sandbox Code Playgroud)
通常类型限定符可以在之后出现int,这应该等同于另一个声明.但现在_Atomic后面跟着括号,所以它必须被解释为类型说明符,然后是语法错误.我认为甚至可以做一个*f可以被有效替换的例子typedef.
看看6.7.2.4 p4的第一个短语
与原子类型关联的属性仅对作为左值的表达式有意义.
这清楚地表明他们不希望返回类型的函数被_Atomic限定.
编辑:
会出现同样的歧义
_Atomic int (*A)[3];
Run Code Online (Sandbox Code Playgroud)
这是完全合理的(指向三个原子整数数组的指针),我们应该能够重写为
int _Atomic (*A)[3];
Run Code Online (Sandbox Code Playgroud)
编辑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();
}
Run Code Online (Sandbox Code Playgroud)
这toto内部重新声明main作为一种功能.并且所有四行都是相同功能的有效原型.现在使用_Atomic作为限定符
typedef int toto;
int main(void) {
int _Atomic (toto)(void);
return toto();
}
Run Code Online (Sandbox Code Playgroud)
这应该是有效的版本const.现在我们在这里有一个案例,_Atomic其后是括号内部的类型,但它不是类型说明符.