2009-11-04 96 views
1

如果我为具有一系列语句的类C语言编写语法,那么定义语法的最常用方法是什么?用于语句顺序的BNF语法

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

<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尽可能地干净。

回答

7

一个非常普遍的方法是:

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

然后你定义的实际语句,而不是打字<whatever>。包含尾随分号作为单个语句的一部分似乎更清晰,而不是将它们放在非终端列表的定义中。

+0

我喜欢这个。我唯一的问题是我不确定大多数解析器生成器(我使用TinyPG)是否支持/ *空* /生产。我的印象是它不那么犹太教。 – captncraig 2009-11-04 18:02:50

+0

没关系。在看完C语法后,艾登发布了它可以是: :: = | captncraig 2009-11-04 18:05:44

+0

我一直在使用我的Bison语法:-)实际上,我从O'Reilly的书籍* lex和yacc *中获得它,作者系统地使用/ * empty * /来强调空的规则真的存在为了某件事。如果您的解析器生成器不支持这种评论,那么您当然可以放弃它。 – 2009-11-04 18:13:51

2

您可以找到C here的BNF,我认为它来自K & R,您可以查看该文件。你也可以看看SQL BNF here,它可以提供更多关于制定好序列的信息。

这将提供一些约定信息。

就AST的产生而言,真正无关紧要的是您的定义是如何为所有排列正确解析源代码。然后只需添加行动来建立您的AST。

只要确定您正在为正确的解析器生成器(如LL或LR解析器)构造您的语法,因为您可能遇到复位问题,这将意味着需要以新方式重写一些规则。请参阅eliminating left recursion

您可能还想看看Bison/Yacc的例子,如thesethese。还检查了Dragon Book和一本书,叫做“现代编译器实现在C”