ANTLR сопоставляет неправильные токены - PullRequest
0 голосов
/ 06 марта 2020

mytest.g4

lexer grammar mytest;

fragment HEX: '0' [xX] [0-9a-fA-F]+;
fragment INT: [0-9]+;
fragment WS: [\t ]+;
fragment NL: WS? ('\r'* '\n')+;

INFO: 'InfoFromDb' -> mode(INFO_MODE);
ID: 'ID from database' -> mode(ID_MODE);

mode INFO_MODE;
INFO_INTERMEDIATE: ':' WS*;// -> channel(HIDDEN);
//INFO_DATA: ~[\r\n]+; //(~('\r' | '\n'))+;
INFO_DATA: HEX ',' WS* [A-Za-z]+ WS* INT; //line 24:13 token recognition error at: '0xF8, F'
INFO_END: NL -> mode(DEFAULT_MODE);

mode ID_MODE;
ID_INTERMEDIATE: ':' WS* -> channel(HIDDEN);
ID_DATA: ~[\r\n]+;
// let's throw away the next token, but also use it to exit this mode
ID_END: NL -> skip, pushMode(DEFAULT_MODE);

pars.g4

parser grammar pars;
options {
  tokenVocab=mytest;
}

the_id: ID ID_DATA;
info: INFO INFO_INTERMEDIATE INFO_DATA INFO_END;

input

InfoFromDb: 0xF8, FooData 3
ID from database: 0x3, Blah ID: 0, Meta ID: 0, MetaB: 1

, когда я проверяю правило синтаксического анализатора the_id с помощью ввода. .. это дает дерево разбора:

  • InfoFromDb
  • 0xF8, FooData 3
  • \ n
  • ID из базы данных

, который просто не имеет смысла ...

, также трудно понять, правило синтаксического анализатора info дает:

  • InfoFromDb
  • <missing INFO_INTERMEDIATE>
  • : 0xF8, FooData 3
  • \ n

что здесь происходит? Правила lexer как-то необязательны и игнорируются? Я неправильно использую материал mode?

1 Ответ

0 голосов
/ 07 марта 2020

Ваш ввод:

InfoFromDb: 0xF8, FooData 3
ID from database: 0x3, Blah ID: 0, Meta ID: 0, MetaB: 1

маркируется следующим образом:

INFO              -> `InfoFromDb`
INFO_INTERMEDIATE -> `: `
INFO_DATA         -> `0xF8, FooData 3`
INFO_END          -> `\n`
ID                -> `ID from database`
ID_DATA           -> `: 0x3, Blah ID: 0, Meta ID: 0, MetaB: 1`

независимо от правил синтаксического анализатора, которые вы вызываете. Лексер всегда применяет следующие правила:

  1. соответствует максимально возможному количеству символов
  2. в случае, если 2 (или более) правила лексера соответствуют одинаковому количеству символов, правило, определенное первым " wins "

РЕДАКТИРОВАТЬ

почему ID_INTERMEDIATE не распознается? Он упорядочен правильно (ваш случай № 2). Есть ли способ заставить токены быть необязательными?

Нет, ID_INTERMEDIATE не соответствует, потому что ID_DATA соответствует большему количеству (правило 1 применимо здесь). Лексер смотрит на правило 2 только тогда, когда 2 правила совпадают с одинаковыми символами (это не так, ID_INTERMEDIATE соответствует ": " и ID_DATA соответствует ": 0x3, Blah ID: 0, Meta ID: 0, MetaB: 1")

, если я добавлю общее правило нового синтаксического анализатора: (the_id | info) * EOF; и проверьте это ... the_id не показывает ошибку ... но он все еще не анализирует промежуточный токен

Я не совсем понимаю, что вы имеете в виду. Если я посмотрю на ваше правило синтаксического анализатора the_id: ID ID_DATA;, то оно не выдаст ошибку, потому что нет ID_INTERMEDIATE. выдает ошибку, когда вы делаете: the_id: ID ID_INTERMEDIATE ID_DATA;

Я понимаю, что ~ [\ r \ n] + соответствует большему количеству символов ... но мне нужно пропустить / Откажитесь от: потому что я не хочу соответствовать всей правой части этой входной строки

Тогда вам нужно сделать ID_DATA менее жадным, чем сейчас. Может быть, не давайте начать с :?

...