ANTLR 语法设计

下面学习如何编写语法

如何定义语法规则

一种语言模式就是一种递归的语法结构。

我们需要从一系列有代表性的输入文件中归纳出一门语言的结构。在完成这样的归纳工作后,我们就可以正式使用ANTLR语法来表达这门语言了。

编写语法和编写软件很相似,差异在于我们处理的是语言规则,而非函数或者过程(procedure)。

在深入研究语法的细节之前,一件大有裨益的事情是:讨论语法的整体结构以及如何建立初始的语法框架

语法由一个为该语法命名的头部定义和一系列可以相互引用的语言规则组成。

grammar MyG; rule1: <<stuff>>; rule2: <<more stuff>>; ...

设计良好的语法反映了编程世界中的功能分解或者自顶向下的设计。这意味着我们对语言结构的辨识是从最粗的粒度开始,一直进行到最详细的层次,并把它们编写成为语法规则。所以,我们的第一个任务是找到最粗粒度的语言结构,将它作为我们的起始规则。在英语中,我们可以使用sentence规则作为起始规则。对于一个XML文件,我们可以使用document规则作为起始规则。

设计起始规则的内容实际上就是使用英语伪代码来描述输入文本的整体结构,这和我们编写软件的过程有点类似。

例如,一个CSV文件就是一系列以换行符为终止的行(a comma-separated-value file is a sequence of rows terminated by newlines)。其中,is a左侧的单词file就是规则名,右侧的全部内容就是规则定义中的<<stuff>>,即:

file: <<sequence of rows that are terminated by newlines>>;

接着,我们描述起始规则右侧所指定的那些元素。它右侧的名词通常是词法符号或者尚未定义的规则。其中,词法符号是那些我们的大脑能够轻易识别出的单词、标点符号或者运算符。正如英语语句中的单词是最基本元素一样,词法符号是文法的基本元素。起始规则引用了其他的、需要进一步细化的语言结构, 如上面的例子中的“行”row。

一个行就是一系列由逗号分隔的字段(a row is a sequence of fields separated by commas)。接下来,一个字段就是一个数字或者字符串(a field is a number or string)。我们的伪代码如下所示:

file: <<sequence of rows that are terminated by newlines>> ; row: <<sequence of fields separated by commas>> ; field: <<number or string>> ;

当我们完成对规则的定义后,我们的语法草稿就成形了。在刚开始的时候,辨识一条语法规则并使用伪代码编写右侧的内容是一项充满挑战的工作,不过,它会随着你为不同语言编写语法的过程变得越来越容易。

使用ANTLR语法表达语言

现在我们拥有了伪代码,还需要将它翻译为ANTLR标记,从而得到一个能够正常工作的语法。

常见的语言模式包括:序列(sequence)、选择(choice)、词法符号依赖(token dependency),以及嵌套结构(nested phrase)。

在之前的 ,我们见过这些模式的一些例子。随着学习的深入,我们会用正式的语法规则将特定的模式表达出来,通过这种方式,我们就能够掌握基本的ANTLR标记的用法。

序列模式

登录一台POP服务器并获取第一条消息的指令序列为:

USER parrt PASS secret RETR 1

其中指令RETR 1是由RETR关键字(保留字),一个操作数和一个换行符构成。

使用ANTLR语法来表述这样的序列,只需要按照顺序将它们列出即可:

retr : 'RETR' INT '\n' ; // 匹配“关键字-整数-换行符”序列 INT : [0-9]+ ; WS : [ \t]+ -> skip ;

注意,可以直接使用类似'RETR'的常量字符串来表示任意简单字符序列,诸如关键字或者标点符号等。

使用语法规则来为编程语言的特定结构命名,这就好像我们在编程时将若干个语句组合成一个函数。在上例中,我们将RETR命名为retr规则。这样,在语法的其他地方,就可以直接把规则名作为简称来引用RETR。

序列模式的变体包括:

带终止符的序列模式

带分隔符的序列模式

CSV文件同时使用了这两种模式。上面我们定义出了CSV文件的语法规则,下面用ANTLR语法来表达:

file : (row '\n')* ; // 以换行符作为终止符的序列 row : field (',' field)* ; // 以','作为分隔符的序列 field: INT | STRING ;

简单解释一下:

file规则使用带终止符的序列模式来匹配零个或多个row'\n'序列。其中序列中的每个元素都以\n字符结束;

row规则使用带分隔符的序列模式来匹配一个field后面跟着零个或多个','field序列的情形。 ,隔开了所有的field;

选择模式

在ANTLR的规则中,使用|符号表示或者的含义,称作备选分支(alternatives)。

比如上面CSV语法中用到的field: INT | STRING ;,表示字段可以是整数或者字符串。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zggpzw.html