为什么`int test {}`是C语言BNF中的函数定义

why is `int test {}` a function definition in C language BNF

我对著名的 The syntax of C in Backus-Naur Form 很感兴趣并研究了一段时间,让我感到困惑的是有些语法对我来说是错误的,但根据 BNF 却被认为是正确的。

例如int test {},这是什么?我认为这是 C 中的错误语法,但事实是 BNF 认为这是一个函数定义:

int -> type_const -> type_spec -> decl_specs
test-> id -> direct_declarator -> declarator
'{' '}' -> compound_stat
decl_specs declarator compound_stat -> function_definition

我用 bison 试过,它认为输入 int test {} 是正确的形式,但我在 C 编译器上试过,它无法编译。

所以有问题:

  1. int test {} 语法是否正确?
  2. 如果语法正确,那是什么意思,为什么编译器无法识别它?
  3. 如果是错误的语法,我能说BNF不严谨吗?这是否意味着现代C编译器不坚持这个BNF?

语法是必需的,但不足以描述一个有效的 C 程序。为此,您还需要来自标准的 constraints。一个更简单的例子是 0++,它遵循 C 表达式的语法,但肯定不是有效的程序片段...

C11 6.9.1p2:

  1. The identifier declared in a function definition (which is the name of the function) shall have a function type, as specified by the declarator portion of the function definition. [162]

脚注 162 解释说,约束的意图typedef 不能使用 ,即

typedef int F(void);
F f { /* ... */ }

将无效,即使这样的 typedef 可用于函数 声明 ,即

F f;

将声明函数

int f(void);

但是仅仅存在这个约束也证明BNF文法本身在这种情况下是不够的。因此,您是正确的,因为 grammar 会将这样的片段视为函数定义。

BNF 形式是描述语言语法的一种精确方式,即如何精确地从原始输入开始获取解析树。

对于每种语言,您可以定义无数种描述该语言的语法。这些描述同一种语言的文法的属性可能相差很大。

如果你学习 C 语言的语法,请注意它不是上下文无关的,而是上下文敏感的,这意味着,选择规则或其他规则的决定取决于输入中该点周围的内容。

阅读 lexer hack 了解如何正确解释 C 语法的 Backus Naur 形式。