У меня есть грамматика запросов, над которой я работаю, и нашел один случай, который оказывается трудно решить. Ниже представлена минимальная версия грамматики для ее воспроизведения.
grammar scratch;
query : command* ; // input rule
RANGE: '..';
NUMBER: ([0-9]+ | (([0-9]+)? '.' [0-9]+));
STRING: ~([ \t\r\n] | '(' | ')' | ':' | '|' | ',' | '.' )+ ;
WS: [ \t\r\n]+ -> skip ;
command
: 'foo:' number_range # FooCommand
| 'bar:' item_list # BarCommand
;
number_range: NUMBER RANGE NUMBER # NumberRange;
item_list: '(' (NUMBER | STRING)+ ((',' | '|') (NUMBER | STRING)+)* ')' # ItemList;
При использовании этого вы можете без проблем сопоставить такие вещи, как bar:(bob, blah, 57, 4.5) foo:2..4.3
. Но если вы вставите bar:(bob.smith, blah, 57, 4.5) foo:2..4
, он пожалуется line 1:8 token recognition error at: '.s'
и разделит его на «боб» и «мит». Имеет смысл, .
игнорируется как часть строки. Хотя не уверен, почему он ест 's'.
Поэтому замените строку на STRING: ~([ \t\r\n] | '(' | ')' | ':' | '|' | ',' )+ ;
без точки. И теперь он распознает 2..4.3
как строку вместо диапазона_числов.
Я считаю, что это связано с тем, что строка соответствует большему количеству символов на одном отрезке, чем другие варианты. Но есть ли способ заставить STRING
соответствовать только в том случае, если он еще не сопоставил элементы выше в грамматике? Это означает, что это только STRING
, если он не содержит RANGE
или NUMBER
?
Я знаю, что могу добавить TERM: '"' .*? '"';
, а затем добавить TERM
в item_list, но я надеялся избежать необходимости цитировать, если это возможно. Но, похоже, это единственный способ сохранить диапазон ..
, который я нашел.
1 ответ
Вы можете разрешить только одиночные точки внутри строк, например:
STRING : ATOM+ ( '.' ATOM+ )*;
fragment ATOM : ~[ \t\r\n():|,.];
О, и NUMBER: ([0-9]+ | (([0-9]+)? '.' [0-9]+));
довольно многословен. Это делает то же самое: NUMBER : ( [0-9]* '.' )? [0-9]+;
Похожие вопросы
Новые вопросы
antlr4
Версия 4 ANother Tool для распознавания языков (ANTLR), гибкий генератор лексеров / парсеров. ANTLR4 имеет улучшенный адаптивный алгоритм синтаксического анализа LL (*), который улучшает более простой алгоритм LL (*), используемый в ANTLR3.