6

我对著名的巴科斯-瑙尔形式的 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?
4

2 回答 2

3

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

C11 6.9.1p2

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

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

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

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

F f;

将声明函数

int f(void);

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

于 2019-03-22T08:48:07.240 回答
1

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

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

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

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

于 2019-03-22T09:51:48.993 回答