如何找出ANTLR语法无法解析输入,日志文件中的特殊时间戳

时间:2019-03-06 20:38:48

标签: parsing antlr grammar

输入:

  

3月9日10:19:07西信息tmm1 [17280]:01870003:6:
   /Common/mysaml.app/mysaml:常见:00000000:helloasdfasdf asdfadf vgnfg

语法:

grammar scratch;
lines :       datestamp hostname level proc msgnum  module msgstring;
datestamp:    month day time;
//month :       MONTH;
day  :        INTEGER;
time :        INTEGER ':' INTEGER ':' INTEGER;
hostname :    STRING;
level :       ALPHA;
proc:         procname '[' procnum ']' ':';
procname :    STRING;
procnum :     INTEGER;
msgnum :      INTEGER ':' DIGIT':';
module :      '/' DOTSLASHSTRING ':' PARTITION ':' SESSID ':';
PARTITION:     STRING;
sessid :      HEX;
msgstring:      MSGSTRING;
DOTSLASHSTRING : [a-zA-Z./]+;
SESSID :      HEX;
INTEGER :     [0-9]+;
DIGIT:        [0-9];
STRING :      [a-zA-Z][a-zA-Z0-9]*;
HEX :         [a-f0-9]+;
//ALPHA:        [a-zA-Z]+;
ALPHA:         ('['|'(') .*? (']'|')');
MSGSTRING :   [a-zA-Z0-9':,_(). ]+ [\r];
 //         |   'Agent' MSGSTRING;
month : 'Jan' | 'Feb' | 'Mar' | 'Apr' | 'May' | 'Jun' | 'Jul' | 'Aug' | 'Sep' | 'Oct' | 'Nov' | 'Dec' ;
WS :          [ \t\r\n]+ -> skip;

问题:   语法分析树显示 month 已正确填充,但下一项 day 未正确填充。在分析树中,它显示 day 设置为整个输入的其余部分。不知道这怎么可能。

解析器错误为:

  

第1行:4的输入“ 9”不匹配,预期为INTEGER

enter image description here

1 个答案:

答案 0 :(得分:1)

解析器(即以小写字母开头的规则)和词法分析器(大写首字母)的行为略有不同:

  • 解析器知道期望的令牌并尝试与之匹配(除非它有多个替代方案-然后它会查看下一个令牌以查看选择哪种替代方案)
  • 词法分析器对解析器规则一无所知-它与当前输入匹配。当多个词法分析器规则可以匹配输入的前缀时:
    • 它将匹配(并发出令牌)与最长序列匹配的规则
    • 如果多个规则可以匹配同一序列,则文件中较早的规则(靠近顶部)将获胜。

因此,您的输入很可能会被标记为 *

MONTH          Mar
(WS)
SESSID         9  - SESSID matches and is higher up than INTEGER
(WS)
SESSID         10
':'            :
SESSID         19
':'            :
SESSID         07
(WS)
PARTITION      west  - same as STRING but higher up - STRING will never be matched
(WS)
PARTITION      info
(WS)
PARTITION      tmm1
ALPHA          [17280]  - matches longer sequence than just '[' in rule "proc"
':'            :
(WS)
SESSID         01870003
':'            :
SESSID         6
':'            :
(WS)
DOTSLASHSTRING /Common/mysaml.app/mysaml  - longer than just '/' in rule "module"
MSGSTRING      :Common:00000000: helloasdfasdf asdfadf vgnfg  - the rest can be matched to this rule

如您所见,这些令牌与解析器所期望的完全不同。

最重要的是,您的词法分析器规则中逻辑太多,即您试图将语义放入词法分析器中。它不适合该任务。如果单个输入序列可能意味着不同的含义(例如123可能是整数,十六进制数字或会话ID),则该区别需要进入解析器,因为只能根据上下文(在句子中的何处)来确定。发生),而不是123本身的内容。同样,如果[17280]可以是ALPHA(无论是什么)或放在括号中的INTEGER,则该决定需要进入解析器,因为不能仅通过查看{{1 }}(由于[17280]规则,现在在词法分析器中。)


*可能的标记化基于屏幕快照中的输入,这些输入全部在一行上,而相关输入本身在两行上-不确定这是故意的还是换行的结果。