解析int(x)参数

fre*_*low 10 c c++ parsing function ambiguous-grammar

这是一个带有一个int参数的简单函数:

void f(int x) {}

f(42);
Run Code Online (Sandbox Code Playgroud)

这是另一个带有一个int参数的函数:

void g(int(x)) {}

g(42);
Run Code Online (Sandbox Code Playgroud)

现在让我们定义x一个类型:

typedef int x;
void h(int(x)) {}

h(42);
// warning: passing argument 1 of ‘h’ makes pointer from integer without a cast
Run Code Online (Sandbox Code Playgroud)

(这是我用gcc 4.8.2观察到的行为)

解析器编写者如何处理这种情况?

似乎经典的管道Lexer - > Parser - > Semantic Checker - > ......在这里不起作用.

jsc*_*410 12

你有效地定义h为:

void h(int(int)) {}
Run Code Online (Sandbox Code Playgroud)

该参数被解释为一个未命名的函数指针,它接受int并返回一个int.当您尝试传递42给它时,编译器会抱怨您正在尝试从整数中创建函数指针.

我认为你要求的是编译器如何处理(未命名)函数指针类型及其可能不明确的解析.你的问题与C++中最令人烦恼的解析有关.

在那里,他们决定,只要函数指针类型和另一种解析方式之间存在歧义,它就会被解释为函数指针.他们这样做是因为当你不希望它成为函数指针时还有其他方法可以消除歧义(例如 - 用括号括起来,使用{}初始化语法等).

深入了解解析器编写器如何处理此解析,这里是C11的词法分析器和语法:http://quut.com/c/ANSI-C-grammar-l-2011.html在您的示例中,之前typedef x将是一个IDENTIFIER令牌,之后,它将成为一个TYPEDEF_NAME令牌,因为分析器正在通过x现在是类型的符号表进行通知.在这种特殊情况下,解析是明确的.您似乎要引用的"管道反馈"在这种情况下通过符号表发生,其中词法分析器通过更高级别通知上下文,这些级别在编译过程中影响其输出.

编辑:由OP发现的 三篇 文章描述了这个问题以及它是如何通过一些C语言分析器/编译器非常好地解决的.基本上,几乎可以指定仅接受/生成合法C语法的无上下文语法(CFG).通过引入范围查找表,允许词法分析器适当地区分标识符和typedef名称,然后CFG [更重要的是LALR(1)解析器(例如 - yacc生成)]只接受/生成合法C语法可以指定.

这是一个比OP更可怕的例子:

typedef int x;

int main() { x x = 5; return x; }  /* crazily enough this is legal C syntax and a well formed C program */
Run Code Online (Sandbox Code Playgroud)


Vla*_*cow 6

介绍typedef之后

typedef int x;
Run Code Online (Sandbox Code Playgroud)

该函数具有以下定义

void h(int( int ) ) {}
Run Code Online (Sandbox Code Playgroud)

这是它的参数被声明为具有int( int )调整为指向函数的指针的函数类型.

您调用提供整数的函数:

h(42);
Run Code Online (Sandbox Code Playgroud)

没有从整数到函数指针的隐式转换.

我没有看到问题

似乎经典的管道Lexer - > Parser - > Semantic Checker - > ......在这里不起作用.

该参数替换为typedef.
x具有类型的编译器属性.所以它认为记录就像

type-specifier h(type-specifier( type-name ) ) {}
Run Code Online (Sandbox Code Playgroud)

  • 我想Fred正在询问在解析中使用非语法信息,即"x"的本质知识如何影响解析. (3认同)
  • @Cheers:标准正好讨论了这些事情中的零.至少,它没有讨论翻译的各个阶段,但弗雷德已经知道了.他要求的是_implementations_的正式级别的细节,而不是C++抽象机器的细节. (2认同)