Как я могу выяснить, ANTLR грамматический сбой при разборе ввода, специальная отметка времени в лог-файле - PullRequest
1 голос
/ 06 марта 2019

ВХОД:

9 марта 10:19:07 западная информация tmm1 [17280]: 01870003: 6:
/Common/mysaml.app/mysaml:Common: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 - нет. В дереве разбора показано, что день установлен для всего остального ввода. Не понимаю, как это возможно.

Ошибка парсера:

строка 1: 4 несоответствующий вход '9' ожидает INTEGER

enter image description here

1 Ответ

1 голос
/ 07 марта 2019

Синтаксический анализатор (то есть правила, начинающиеся со строчной буквы) и лексер (заглавная первая буква) ведут себя немного по-другому:

  • Анализатор знает, какой токен он ожидает, и пытается сопоставить его (кроме случаев, когда у него есть несколько альтернатив - затем он просматривает следующие токены, чтобы увидеть, какую альтернативу выбрать)
  • Однако лексер ничего не знает о правилах синтаксического анализатора - он соответствует тому, что может соответствовать текущему вводу. Когда несколько правил лексера могут совпадать с префиксом ввода:
    • Это будет соответствовать (и выдавать токен) правилу, которое соответствует самой длинной последовательности
    • Если несколько правил могут совпадать с одной и той же последовательностью, правило, находящееся ранее в файле (ближе к верху), выигрывает.

Таким образом, ваш ввод, скорее всего, будет маркирован на *:

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 может быть целым числом, шестнадцатеричным номером или идентификатором сеанса), это различие должно входить в синтаксический анализатор, так как оно может быть решено только на основе контекста (где в предложении это произошло ), а не содержанием самого 123. Точно так же, если [17280] может быть либо ALPHA (независимо от того, что это) или INTEGER в скобках, это решение должно быть включено в синтаксический анализатор, потому что это не может быть решено только просмотром [17280] (теперь оно в лексере из-за к правилу ALPHA).


* Вероятный токенизация основан на вводе с вашего скриншота, который находится на одной строке, тогда как сам ввод - на двух строках - не уверен, является ли это преднамеренным или результатом переноса строки.

...