как использовать последовательность для токенации, но не возвращается как результат - PullRequest
1 голос
/ 05 апреля 2019

Я хотел бы использовать правило или последовательность в качестве разделителя для токенизации файла, но не возвращать разделитель

Я пытался использовать -> channel(hidden), но это портит анализ

У меня есть грамматика такая, что

grammar test;

file
 : l1 l2? l3
;

l1
 : 'L1:' STRING_LITERAL '\n'
;
l2
 : 'L2:'(NUMBER)+ '\n'
;
l3
 :'L3:' WORD|NUMBER '\n'
;


NUMBER          : [0-9]+ ;
STRING_LITERAL  : '"' (~["\\\r\n] | EscapeSequence)* '"';
WORD            : ('a'..'z' | 'A'..'Z')+;
fragment EscapeSequence
    : '\\' [btnfr"'\\]
    | '\\' ([0-3]? [0-7])? [0-7]
    ;

и входной файл типа

L1: "SO LONG"
L2: 42
L3: FISH

Я бы не хотел возвращать L1: L2: и L3:, но возвращаю "ТАК ДОЛГО" 42 и FISH

Я получаю токены, которые ищу, но я также получаю \n L1: L2: и L3:

See this for results tree

Также я заметил, что если у меня установлено правило l1 как l1: (~ ["\\ r \ n]) *; я не могу найти совпадения до конца строки, но получаю каждое слово как отдельный токен. смысл для меня, но есть ли способ принять это как один токен?

1 Ответ

0 голосов
/ 05 апреля 2019

Если вы хотите использовать эти токены L1: внутри парсера, то удалить их невозможно. Во всяком случае, я не вижу реального варианта использования для этого. Но я не понимаю, почему вы не можете просто пропустить (или спрятать) эти токены во время лексера. Это, кажется, работает просто отлично:

parse
 : NL* line ( NL+ line )* NL* EOF
 ;

line
 : l1
 | l2
 | l3
 ;

l1 : STRING_LITERAL;
l2 : NUMBER+;
l3 : ( WORD | NUMBER );

NUMBER         : [0-9]+;
STRING_LITERAL : '"' ( ~["\\\r\n] | EscapeSequence )* '"';
WORD           : [a-zA-Z]+;

IGNORED
 : 'L' [0-9] ':' -> skip
 ;

SPACES
 : [ \t]+ -> skip
 ;

NL
 : '\r'? '\n'
 ;

fragment EscapeSequence
 : '\\' [btnfr"'\\]
 | '\\' ([0-3]? [0-7])? [0-7]
 ;

в результате:

enter image description here

[...] поэтому я должен иметь возможность сделать что-то вроде if (parser.l1 () == "SO LONG" "), затем сделать что-то

Это не то, как работает ANTLR. Парсер создает дерево разбора (со всеми определенными вами токенами). Это дерево разбора затем может быть использовано для извлечения значений из. Извлечение значений может быть выполнено путем обхода дерева разбора вручную или с помощью класса слушателя (или посетителя) ANTLR: https://github.com/antlr/antlr4/blob/master/doc/listeners.md

Это мое предложение для вас: не skip разрыв строки и L1: токены от лексера, а использование слушателя или посетителя для получения данных из вашего дерева разбора.

...