防火墙配置解析器外来输入
Firewall configuration parser extraneous input
我正在尝试为某些防火墙设备编写配置解析器。我是第一次使用 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 不喜欢结尾的 'end' 文本,尽管它在 configblock
规则中,并且它没有被另一个规则使用...
感谢您的帮助!
输入 end
被标记为 WORD
。这是因为当词法分析器可以为多个规则匹配相同的字符时,第一个定义的规则 "wins"。解决方案,将关键字移到 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]+
.
最后,"anchor" 带有 EOF
标记的解析器的启动规则始终是一个好主意:这样您就可以强制解析器使用整个标记流,并且不要中途停止。
我正在尝试为某些防火墙设备编写配置解析器。我是第一次使用 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 不喜欢结尾的 'end' 文本,尽管它在 configblock
规则中,并且它没有被另一个规则使用...
感谢您的帮助!
输入 end
被标记为 WORD
。这是因为当词法分析器可以为多个规则匹配相同的字符时,第一个定义的规则 "wins"。解决方案,将关键字移到 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]+
.
最后,"anchor" 带有 EOF
标记的解析器的启动规则始终是一个好主意:这样您就可以强制解析器使用整个标记流,并且不要中途停止。