2017-01-19 13 views
1

Я тестирую некоторую грамматику с grun, и я не вижу, что мои жетоны распознаются как токены. Сначала я подумал, что, возможно, я создал «неявные» токены на основе этого StackOverflow link.ANTLR4 Утренняя урна, по-видимому, не сообщает маркеры правильно ... я понимаю это?

Кроме того, при просмотре вывода grun-tokens я нашел эти ссылки: 1) Последние Change - totokens output. 2) Возможно устаревшее testrig.md Я расколол это и врылся в него.

Вот мой простой HelloTC.g4 где я исследую это:

grammar HelloTC; 
r : HELLO id; 
WS : [ \r\t\n]+ -> skip ; 
CMD: '%'; 
DIR: '%%'; 
A: 'A'; 
AA: 'AA'; 
HELLO:'hello'; 
ID : [a-z]+ ; 
id : DIR | CMD | A | AA; 

я проверить это с:

grun HelloTC r -tokens 
hello %% 
hello % 
hello A 
hello AA 
^Z 

[@0,0:4='hello',<'hello'>,1:0] 
[@1,6:7='%%',<'%%'>,1:6] 
[@2,10:14='hello',<'hello'>,2:0] 
[@3,16:16='%',<'%'>,2:6] 
[@4,19:23='hello',<'hello'>,3:0] 
[@5,25:25='A',<'A'>,3:6] 
[@6,28:32='hello',<'hello'>,4:0] 
[@7,34:35='AA',<'AA'>,4:6] 
[@8,38:37='<EOF>',<EOF>,5:0] 

Ни один из моих лексем не признаются в качестве маркеров. я ожидал:

[@0,0:4='hello',<HELLO>,1:0] 
[@1,6:7='%%',<DIR>,1:6] 
[@2,10:14='hello',<HELLO>,2:0] 
[@3,16:16='%',<CMD>,2:6] 
[@4,19:23='hello',<HELLO>,3:0] 
[@5,25:25='A',<A>,3:6] 
[@6,28:32='hello',<HELLO>,4:0] 
[@7,34:35='AA',<AA>,4:6] 
[@8,38:37='<EOF>',<EOF>,5:0] 

В моих ожидаемых результатах я заменил «символов» с именем лексемы.

Я запустил antlr4 с -Xlog, и мои токены объявлены (от второй до последней строки), так что теперь мне интересно, просто ли я неправильно понимаю, что сообщает отчет grun. Я ожидал, что данные в <> будут именем TOKEN, переданным лексером. У меня это неправильно?

Что я могу сделать с моей грамматикой, чтобы распознать токены? ИЛИ ... как отлаживать грамматик, чтобы лексер правильно идентифицировал маркеры?

Вот мой -Xlog файл:

2017-01-20 06:57:29:640 grammar LogManager.java:25 before: (COMBINED_GRAMMAR HelloTC (RULES (RULE r (BLOCK (ALT HELLO id))) (RULE WS (BLOCK (LEXER_ALT_ACTION (ALT (+ (BLOCK (ALT [ \r\t\n])))) skip))) (RULE CMD (BLOCK (ALT '%cat'))) (RULE DIR (BLOCK (ALT '%%'))) (RULE A (BLOCK (ALT 'A'))) (RULE AA (BLOCK (ALT 'AA'))) (RULE HELLO (BLOCK (ALT 'hello'))) (RULE id (BLOCK (ALT DIR) (ALT CMD) (ALT A) (ALT AA))))) 
2017-01-20 06:57:29:661 grammar LogManager.java:25 after: (COMBINED_GRAMMAR HelloTC (RULES (RULE r (BLOCK (ALT HELLO id))) (RULE WS (BLOCK (LEXER_ALT_ACTION (ALT (+ (BLOCK (ALT [ \r\t\n])))) skip))) (RULE CMD (BLOCK (ALT '%cat'))) (RULE DIR (BLOCK (ALT '%%'))) (RULE A (BLOCK (ALT 'A'))) (RULE AA (BLOCK (ALT 'AA'))) (RULE HELLO (BLOCK (ALT 'hello'))) (RULE id (BLOCK (ALT (SET DIR CMD A AA)))))) 
2017-01-20 06:57:29:694 grammar LogManager.java:25 after extract implicit lexer =(COMBINED_GRAMMAR HelloTC (RULES (RULE r (BLOCK (ALT HELLO id))) (RULE id (BLOCK (ALT (SET DIR CMD A AA)))))) 
2017-01-20 06:57:29:694 grammar LogManager.java:25 lexer =(LEXER_GRAMMAR HelloTCLexer (RULES (RULE WS (BLOCK (LEXER_ALT_ACTION (ALT (+ (BLOCK (ALT [ \r\t\n])))) skip))) (RULE CMD (BLOCK (ALT '%cat'))) (RULE DIR (BLOCK (ALT '%%'))) (RULE A (BLOCK (ALT 'A'))) (RULE AA (BLOCK (ALT 'AA'))) (RULE HELLO (BLOCK (ALT 'hello'))))) 
2017-01-20 06:57:30:040 semantics LogManager.java:25 tokens={EOF=-1, WS=1, CMD=2, DIR=3, A=4, AA=5, HELLO=6} 
2017-01-20 06:57:30:040 semantics LogManager.java:25 strings={'%cat'=2, '%%'=3, 'A'=4, 'AA'=5, 'hello'=6} 

Пример типа синтаксиса Я пытаюсь создать грамматику для ниже.

//COMMENTS 
;comments 
%%DIRECTIVEA 
%%DIRECTIVEB 
RESERVED_TOKEN(ARGS,ARGS) 
%commandA 
commandB 
commandD 
commandE 
... 
CommandH (only A-H allowed) 
// comments 
%commandB 
%%DIRECTIVEB 
%commandD 
commandE 
%commandA 
done 

Я все еще экспериментировал и экспериментировал. Надеюсь, этот вопрос, и любые ответы помогут другим.

ответ

1

Я тоже удивлен. В предыдущих версиях, имя лексемы не было даже в переводе:

[@0,0:4='hello',<6>,1:0] 
[@1,6:7='%%',<3>,1:6] 
[@2,9:13='hello',<6>,2:0] 
[@3,15:15='%',<2>,2:6] 
[@4,17:21='hello',<6>,3:0] 
[@5,23:23='A',<4>,3:6] 
[@6,25:29='hello',<6>,4:0] 
[@7,31:32='AA',<5>,4:6] 
[@8,34:33='<EOF>',<-1>,5:0] 

Несколько лет назад я написал сценарий Ruby, чтобы перевести <n> в его имени, запрашивая файл <grammar>.tokens. Теперь это сделано в 4.6.

Если определить ПРИВЕТ и идентификатор таким образом, и в этой последовательности:

HELLO 
    : [a-z]+ {getText().equals("hello")}? ; 
ID : [a-z]+ ; 

с этим входом

hello %% 
... 
    hello xyz 

у вас есть этот результат:

[@0,0:4='hello',<HELLO>,1:0] 
    [@1,6:7='%%',<'%%'>,1:6] 
... 
    [@8,34:38='hello',<HELLO>,5:0] 
    [@9,40:42='xyz',<ID>,5:6] 

вход hello является двусмысленный, он может быть согласован двумя правилами. Синтаксический предикат в правиле lexer позволяет лексеру выбирать HELLO, когда вход hello.

Мы можем заключить, что константы представлены сами по себе, а другой ввод - именем маркера. Несмотря на это любопытство, ваши жетоны правильно распознаются. Если бы это было не так, то анализатор будет жаловаться: вход hello %% 123 дает:

$ grun Question r -tokens data.txt 
line 1:9 token recognition error at: '1' 
line 1:10 token recognition error at: '2' 
line 1:11 token recognition error at: '3' 
[@0,0:4='hello',<HELLO>,1:0] 
[@1,6:7='%%',<'%%'>,1:6] 

Если добавить правило INT в грамматике

INT : [0-9]+ ; 

то новый маркер признается:

[@0,0:4='hello',<HELLO>,1:0] 
[@1,6:7='%%',<'%%'>,1:6] 
[@2,9:11='123',<INT>,1:9] 
+0

После дополнительного тестирования я смог убедить себя, что грамматика/лексер, который я определил, работает. Я заметил, что аннотация testrig TOKEN_NAME была более новой функцией в ANTLR после копания. –

0

Это не идеально. Выход grun по-прежнему не выводит мои токены ... но я могу продолжить изучение таргетинга Java, вставив действия System.out.printlin(). Недостатком является то, что после того, как я закончил, мне придется вытащить эти отладочные предложения. В конечном итоге мой целевой парсер будет основан на python. Но я все еще нахожусь на кривой обучения в Java.

В этом link показано, как использовать действия для отладки.

С этим я доработан мой HelloTC.gr к:

grammar HelloTC; 
r : HELLO id+ {System.out.println("r rule encountered");}; 
WS : [ \r\t\n]+ -> skip ; 
CMD: '%' {System.out.println("Lexer found a CMD");}; 
DIR: '%%'{System.out.println("Lexer found a DIR");}; 
A: 'A'; 
AA: 'AA'; 
HELLO:'hello'{System.out.println("Lexer found a HELLO");}; 
ID : [a-z]+ ; 
id : DIR | CMD | A | AA { System.out.println("Parser found rule match "+$text);}; 

и отладка его с Grůň выходами:

java org.antlr.v4.gui.TestRig HelloTC r -tokens 
hello%% 
hello %% 
^Z 
Lexer found a HELLO 
Lexer found a DIR 
Lexer found a HELLO 
Lexer found a DIR 
[@0,0:4='hello',<'hello'>,1:0] 
[@1,5:6='%%',<'%%'>,1:5] 
[@2,9:13='hello',<'hello'>,2:0] 
[@3,15:16='%%',<'%%'>,2:6] 
[@4,19:18='<EOF>',<EOF>,3:0] 
line 2:0 extraneous input 'hello' expecting {<EOF>, '%', '%%', 'A', 'AA'} 
r rule encountered 

Так что хорошая новость заключается в том, что правила LeXeR видятся, и У меня есть метод для анализа/отладки. Я думаю, чтобы понять/расшифровать grun больше, мне придется больше изучить источники ... thatleads, чтобы хотеть «строить/тестировать» модификации antlr, который является скользким уклоном. Я пытаюсь сосредоточиться на своей первоначальной задаче ... , которая разрабатывает парсер.