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



我对著名的 Backus-Naur 形式的 C 语法感兴趣并研究了一段时间,让我感到困惑的是,有些语法对我来说看起来是错误的,但根据 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

我用野牛尝试过这个,它认为输入int test {}是正确的形式,但我在 C 编译器上尝试过这个,它不会编译。

所以有问题:

  1. int test {}正确的语法?
  2. 如果它是一个正确的语法,这意味着什么,为什么编译器无法识别它?
  3. 如果这是一个糟糕的语法,我可以说BNF不严格吗? 这是否意味着现代C编译器不坚持使用这个BNF?

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

C11 6.9.1p2:

    函数
  1. 定义中声明的标识符(即函数的名称)应具有函数类型,由函数定义的声明符部分指定。[162]

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

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

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

F f;

将声明函数

int f(void);

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

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

对于每种语言,您可以定义无限多个描述该语言的语法。 描述同一语言的这些语法的属性可能有很大不同。

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

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

最新更新