Antlr4 令牌存在搞乱解析
Antlr4 token existence messing up parsing
第一次发帖,如果我违反了规则,我深表歉意。
我正在使用 Antlr4 创建一个日志解析器,但我 运行 遇到了一些我不明白的问题。
我正在尝试解析以下输入日志序列:
USA1-RR-SRX240-EDGE-01 created 10.20.30.40/50985->11.12.13.14/443
语法如下:
grammar Juniper;
WS : (' '|'\t')+ -> skip ;
NL : '\r'? '\n' -> skip ;
fragment DIGIT : '0'..'9' ;
NUMBER : DIGIT+ ;
IPADDRESS : NUMBER '.' NUMBER '.' NUMBER '.' NUMBER ;
SLASH : '/' -> skip ;
RIGHTARROW : '->' -> skip ;
CREATED: 'created' -> skip ;
HOSTNAME : [a-zA-Z0-9\-]+ ;
/* Input sample for rule: USA1-RR-SRX240-EDGE-01 created 10.20.30.40/50985->11.12.13.14/443 */
testcase : HOSTNAME WS CREATED WS IPADDRESS SLASH NUMBER RIGHTARROW IPADDRESS SLASH NUMBER NL;
它失败了,我终究无法弄清楚原因。我知道令牌识别错误与我为 HOSTNAME 定义的令牌有关,该令牌在字符 class 中包含破折号,但我不确定如何修复它。
$ antlr4 Juniper.g4 && javac Juniper*.java && grun Juniper testcase -tree
USA1-RR-SRX240-EDGE-01 created 10.20.30.40/50985->11.12.13.14/443
line 1:48 token recognition error at: '>'
line 1:30 mismatched input '10.20.30.40' expecting WS
(testcase SA1-RR-SRX240-EDGE-01 10.20.30.40 50985- 11.12.13.14 443)
请注意上面输出的第二行是我粘贴到 grun 中然后按回车键和按 control+D 的数据。
非常感谢对此的任何帮助,现在我一直在敲键盘。
识别 ->
的问题是 HOSTNAME 匹配任何字母、数字和短划线的序列,其中包括 50985-
。由于该匹配项比 NUMBER 匹配项 (50985
) 长,因此 HOSTNAME 获胜。这显然不是你想要的。
解析日志行通常需要上下文相关的扫描器,而标准解析器生成器——更面向解析编程语言——并不总是理想的工具。在这种情况下,例如,HOSTNAME 不能出现在它被识别的上下文中,因此它甚至不应该出现在可能的标记列表中。
当然,你可以定义一个由 ip 号和端口组成的令牌,用斜杠分隔,这将解决歧义,但(在我看来)这将是次优的,因为你最终会重新扫描它令牌来解析它。
第一次发帖,如果我违反了规则,我深表歉意。 我正在使用 Antlr4 创建一个日志解析器,但我 运行 遇到了一些我不明白的问题。
我正在尝试解析以下输入日志序列:
USA1-RR-SRX240-EDGE-01 created 10.20.30.40/50985->11.12.13.14/443
语法如下:
grammar Juniper;
WS : (' '|'\t')+ -> skip ;
NL : '\r'? '\n' -> skip ;
fragment DIGIT : '0'..'9' ;
NUMBER : DIGIT+ ;
IPADDRESS : NUMBER '.' NUMBER '.' NUMBER '.' NUMBER ;
SLASH : '/' -> skip ;
RIGHTARROW : '->' -> skip ;
CREATED: 'created' -> skip ;
HOSTNAME : [a-zA-Z0-9\-]+ ;
/* Input sample for rule: USA1-RR-SRX240-EDGE-01 created 10.20.30.40/50985->11.12.13.14/443 */
testcase : HOSTNAME WS CREATED WS IPADDRESS SLASH NUMBER RIGHTARROW IPADDRESS SLASH NUMBER NL;
它失败了,我终究无法弄清楚原因。我知道令牌识别错误与我为 HOSTNAME 定义的令牌有关,该令牌在字符 class 中包含破折号,但我不确定如何修复它。
$ antlr4 Juniper.g4 && javac Juniper*.java && grun Juniper testcase -tree
USA1-RR-SRX240-EDGE-01 created 10.20.30.40/50985->11.12.13.14/443
line 1:48 token recognition error at: '>'
line 1:30 mismatched input '10.20.30.40' expecting WS
(testcase SA1-RR-SRX240-EDGE-01 10.20.30.40 50985- 11.12.13.14 443)
请注意上面输出的第二行是我粘贴到 grun 中然后按回车键和按 control+D 的数据。
非常感谢对此的任何帮助,现在我一直在敲键盘。
识别 ->
的问题是 HOSTNAME 匹配任何字母、数字和短划线的序列,其中包括 50985-
。由于该匹配项比 NUMBER 匹配项 (50985
) 长,因此 HOSTNAME 获胜。这显然不是你想要的。
解析日志行通常需要上下文相关的扫描器,而标准解析器生成器——更面向解析编程语言——并不总是理想的工具。在这种情况下,例如,HOSTNAME 不能出现在它被识别的上下文中,因此它甚至不应该出现在可能的标记列表中。
当然,你可以定义一个由 ip 号和端口组成的令牌,用斜杠分隔,这将解决歧义,但(在我看来)这将是次优的,因为你最终会重新扫描它令牌来解析它。