我试图为一些防火墙设备编写一个配置解析器。我是第一次使用ANTLR。
我想解析的是典型的下列文本。
config wireless-controller global
set name ''
set location ''
set max-retransmit 3
set data-ethernet-II disable
set link-aggregation disable
set mesh-eth-type 8755
set fiapp-eth-type 5252
set discovery-mc-addr 221.0.4.254
set max-clients 0
set rogue-scan-mac-adjacency 6
set ipsec-base-ip 172.252.0.4
set wtp-share disable
set ap-log-server disable
set ap-log-server-ip 0.0.0.0
set ap-log-server-port 0
end
输入的数据是带有配置行的 "config "块。我已经想好了这些规则。
1 │ grammar Fortigate ;
2 │
3 │ /*
4 │ * Tokens
5 │ */
6 │
7 │ WHITESPACE : (' ' | '\t')+ -> skip ;
8 │ NEWLINE : ('\r'? '\n' | '\n' | '\r')+ ;
9 │ WORD : ([a-zA-Z0-9] | '.' | [\-_'"])+ ;
10 │ ENDBLOCK : 'end' ;
11 │ EDITSTART : 'edit' ;
12 │ NEXTEDIT : 'next' ;
13 │ /*
14 │ * Parser rules
15 │ */
16 │ configline : ('set'|'unset') WORD+ NEWLINE ;
17 │ startconfigblock : 'config' WORD+ NEWLINE ;
18 │ editline : EDITSTART '"'.+?'"' ;
19 │ editblock : editline configline+ NEXTEDIT NEWLINE ;
20 │ configblock : startconfigblock (editblock | configline)+ ENDBLOCK NEWLINE;
21 │
22 │ startRule : configblock+ ;
我仍然有问题,因为antlr似乎不喜欢以 "end\n "结束数据的解析。line 12:0 extraneous input 'end' expecting {'set', 'unset', 'end', 'edit'}
Antlr不喜欢结尾的 "结束 "文字,虽然它在后面的部分。configblock
规则,并且它没有被其他规则消耗......
谢谢你的帮助!
输入的内容 end
被标记为 WORD
. 这是因为当词典可以为多个规则匹配相同的字符时,先定义的那个规则 "获胜"。解决方法是,将关键字移到你的 WORD
规则。
ENDBLOCK : 'end' ;
EDITSTART : 'edit' ;
NEXTEDIT : 'next' ;
WORD : ([a-zA-Z0-9] | '.' | [\-_'"])+ ;
如果你想匹配 end
也作为 WORD
,然后引入一个这样的解析规则。
word
: WORD
| END
;
然后用这个 word
而不是在您的解析器规则中的 WORD
.
另外.., ([a-zA-Z0-9] | '.' | [\-_'"])+
可以改写为 [a-zA-Z0-9.\-_'"]+
和 (' ' | '\t')+
作为 [ \t]+
.
最后,在你的解析器的起始规则中使用 EOF
token:这样你就迫使解析器消耗整个 token 流,而不是中途停止。