05-语法规则的定义(1)

设计

ANTLR生成的分析器是自顶向下的,所以在对语法进行设计时也推荐使用自顶向下的方式,这种分析方式比自底向上的方式更贴近人类的思维和表达方式。

比如我们的TestL规则,一份TestL文件(doc)包含很多的条目(item),每个item由几个部分组成(tokens)……。

然后写出规则就可以了。

基本规则的表示

  • [],任意一个[]内的字符,比如[0-9]表示任意一个数字
  • ~[],任意一个不是[]内的字符,比如 ~[0-9]表示不能为数字。
  • +,表示之前的字符,至少有一个,比如[a-z]+表示任意英文字母串。
  • *,表示之前的字符,可以0个,可以多个。比如[a-z]*表示可以0个字母,也可以表示一个字母串。
  • |,表示或
  • ?,表示出现0次或1次
  • [1-9][0-9],表示一个数,如123。其首位不能为0。
  • \t,tab键。
  • \r,回车键。
  • \n,换行符。

windows下一个换行是用\r\n表示的。空白符往往使用[ \r\n\t]表示,第一个是空格。

‘blabla’,单引号包围起来的可以理解成关键字,antlr会将之作为一个整体,识别成一个token。

TestL规则的诠释

grammar TestL;

doc:        item+;

item:       NAME '{' STRING '}' AGE '{' NUM '}' HEIGHT '{' NUM '}';

NAME:       'Name';
AGE:        'Age';
HEIGHT:     'Height';
STRING:     ~[ \t\r\n{}0-9]+;
NUM:        [1-9][0-9]*;

SPACE:      [ \t\r\n]->skip;

grammar TestL;

说明该语法名为TestL。如果把lexer和parser分开,则使用lexerGrammar和parserGrammar。

doc:item+;

说明doc结构由至少一条item结构组成。

item: NAME ‘{’ STRING ‘}’ AGE ‘{’ NUM ‘}’ HEIGHT ‘{’ NUM ‘}’;

说明item结构由后面这些结构组成。

NAME: ‘Name’;
AGE: ‘Age’;
HEIGHT: ‘Height’;

这三个是关键词,类似于cpp里的关键词一样,作为一个整体token。

STRING: ~[ \t\r\n{}0-9]+;

多个非数字非空白非大括号的字符构成的串。

NUM: [1-9][0-9]*;

首位不为0的数,比如123。但0123是不合法的。

SPACE: [ \t\r\n]->skip;

空白符号跳过,不做任何处理。

优先级的处理

有时候两种结构在某些条件下无法区分,这就牵扯到解析优先级的问题。

比如上面的STRING和NUM。假如两者定义为

STRING:     ~[ \t\r\n{}]+;
NUM:        [1-9][0-9]*;

则当面对一个12345的串时,是没有办法区别开的,它适用于STRING规则,也适用于NUM规则。antlr会自动处理这种情况,优先使用前面的规则解析之。当STRING在前面时,12345就会解析成STRING,反之解析成NUM。

我们测试一下。

修改TestL.g4文件,重新生成java文件,编译,并使用grun加载。输入:

Name{小强}Age{12}Height{150}
ctrl+z

然后解析出错了:
解析出错了
12被解析成了STRING,但这里需要的是NUM。当我们把两个规则的顺序颠倒一下,如下:

NUM:        [1-9][0-9]*;
STRING:     ~[ \t\r\n{}]+;

重新生成、编译、加载之,输入:

Name{小强}Age{12}Height{150}
ctrl+z

成功解析,如图:
成功解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

温铜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值