如果我为具有一系列语句的类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尽可能干净。
答案 0 :(得分:7)
一种非常常见的方式是:
<block-statement> ::= '{' <statement-list> '}' ;
<statement-list> ::= /* empty */ | <statement-list> <statement> ;
<statement> ::= <whatever> ';' ;
然后您定义实际语句而不是键入<whatever>
。将尾随分号作为单个语句的一部分包含在内而不是将它们放在非终端列表的定义中似乎更清晰。
答案 1 :(得分:2)
您可以找到C here的BNF,我认为它来自K&amp; R,您可以查看。您还可以查看SQL BNF here,它可以提供有关制定良好序列的更多信息。
这将提供一些会议信息。
就AST生成而言,无论你的定义如何'笨拙',它都能正确解析所有排列的来源。然后只需添加动作来构建AST。
确保为正确的解析器生成器构建语法,例如LL或LR解析器,因为您可能会遇到缩减问题,这意味着某些规则需要以新的方式重写。请参阅eliminating left recursion。
您可能还想查看Bison / Yacc示例,例如these或these。另请查看Dragon Book和一本名为“C中的现代编译器实现”的书