1

如果我正在为具有一系列语句的类 c 语言制作语法,那么定义语法的最标准方法是什么?

我的想法是做这样的事情:

<program> ::= <statement>
<statement> ::= <statement-head><statement-tail>
<statement-head> ::= <if-statement> | <var-declaration> | <assignment> | <whatever>
<statement-tail> ::= ; | ;<statement>

但这对我来说有点笨拙。我也考虑过制作

<program> ::= <statement>*

或者

<statement> ::= <statement-head> ; | <sequence>
<sequence>  ::= <statement> <statement>

类型制作。

是否有标准或公认的方式来做到这一点。我希望我的 AST 尽可能干净。

4

2 回答 2

7

一个非常常见的方法是:

<block-statement> ::= '{' <statement-list> '}' ;
<statement-list> ::= /* empty */ | <statement-list> <statement> ;
<statement> ::= <whatever> ';' ;

然后您定义实际语句而不是键入<whatever>. 将尾随分号作为单个语句的一部分而不是将它们放在列表非终结符的定义中似乎要干净得多。

于 2009-11-04T17:50:03.383 回答
2

你可以在这里找到 C 的 BNF ,我认为它取自 K&R,你可以查看。您还可以在此处查看 SQL BNF,它可能会提供有关制定良好序列的更多信息。

这将提供一些约定信息。

就 AST 生成而言,您的定义是否“笨拙”并不重要,因为它可以正确解析所有排列的源。然后只需添加操作来构建您的 AST。

只需确保您正在为正确的解析器生成器(例如 LL 或 LR 解析器)构建语法,因为您可能会遇到归约问题,这意味着某些规则需要以新的方式重写。请参阅消除左递归

您可能还想查看 Bison/Yacc 示例,例如thesethese。还可以查看Dragon Book和一本名为“Modern Compiler Implementation in C”的书

于 2009-11-04T17:39:51.017 回答