Я думаю, вам нужно больше узнать о правилах лексера в ANTLR, правила лексера начинаются с заглавной буквы и генерируют токены для потока, на который будет смотреть парсер. Правила фрагмента Lexer не будут генерировать токен для потока, но помогут другим правилам лексера генерировать токены, посмотрите на правила лексера WORDS и LETTER (LETTER не является токеном, но помогает WORDS создать токен).
Теперь, когда текстовый литерал помещен в правило синтаксического анализатора (имя правила будет начинаться со строчной буквы), этот текстовый литерал также является допустимым токеном, который лексер будет идентифицировать и передавать (по крайней мере, когда вы используете ANTLR - у меня есть не использовал никаких других инструментов, подобных ANTLR, чтобы ответить за них).
Следующее, что я заметил, это то, что ваши правила 's' и 'местоимение' - это одно и то же. Я закомментировал правило 's' и поместил все в правило 'местоимения'
И, наконец, последнее, чтобы узнать, как поместить действия в грамматику, у вас есть некоторые в правиле 's', устанавливающие возвращаемое значение. Я заставил правило местоимения возвращать строковое значение, чтобы, если бы вы хотели действия в правиле «предложения», вы легко могли выполнить свой комментарий-ответ «-i местоимение».
Теперь, так как я не знаю, каковы ваши точные результаты, я поиграл с вашим грамматиком и сделал несколько небольших изменений и реорганизовал (переместил то, что я считал правилами синтаксического анализатора, на верх, сохранив все правила лексера внизу) и вставил некоторые действия, которые, я думаю, покажут вам, что вам нужно. Кроме того, может быть несколько разных способов сделать это, и я не думаю, что мое решение идеально подходит для любого из ваших возможных желаемых результатов, но вот грамматика, которую я смог получить, работая в ANTLRWorks:
grammar pfinder;
options {
language = Java;
}
sentence
: ((words | pronoun) SPACE)* ((words | pronoun) ('.' | '?'))
;
words
: WORDS {System.out.println($text);};
pronoun returns [String value]
: sfirst {$value = $sfirst.value; System.out.println($sfirst.text + '(' + $sfirst.value + ')');}
| ssecond {$value = $ssecond.value; System.out.println($ssecond.text + '(' + $ssecond.value + ')');}
| sthird {$value = $sthird.value; System.out.println($sthird.text + '(' + $sthird.value + ')');}
| pfirst {$value = $pfirst.value; System.out.println($pfirst.text + '(' + $pfirst.value + ')');}
| psecond {$value = $psecond.value; System.out.println($psecond.text + '(' + $psecond.value + ')');}
| pthird{$value = $pthird.value; System.out.println($pthird.text + '(' + $pthird.value + ')');};
//s returns [String value]
// : exp=sfirst {$value = "s1";}
// | exp=ssecond {$value = "s2";}
// | exp=sthird {$value = "s3";}
// | exp=pfirst {$value = "p1";}
// | exp=psecond {$value = "p2";}
// | exp=pthird {$value = "p3";}
// ;
sfirst returns [String value] : ('i' | 'me' | 'my' | 'mine') {$value = "s1";};
ssecond returns [String value] : ('you' | 'your'| 'yours'| 'yourself') {$value = "s2";};
sthird returns [String value] : ('he' | 'she' | 'it' | 'his' | 'hers' | 'its' | 'him' | 'her' | 'himself' | 'herself') {$value = "s3";};
pfirst returns [String value] : ('we' | 'us' | 'our' | 'ours') {$value = "p1";};
psecond returns [String value] : ('yourselves') {$value = "p2";};
pthird returns [String value] : ('they'| 'them'| 'their'| 'theirs' | 'themselves') {$value = "p3";};
WORDS : LETTER*;// {$channel=HIDDEN;};
SPACE : (' ')?;
fragment LETTER : ('a'..'z' | 'A'..'Z');
Я думаю, что конечным результатом является то, что этот грамматик покажет вам, как выполнить то, что вы пытаетесь сделать, и потребует модификации независимо от того, каков этот конечный результат.
Удачи.
Я думаю, вам нужно изменить только одну строку в вашем тестовом классе,
parser.pronoun ();
чтобы:
parser.sentence ();
Возможно, вы захотите изменить и некоторые другие вещи в грамматике:
ПРОСТРАНСТВО : ' ';
предложение: (слова | местоимение) (ПРОБЕЛ (слова | местоимение)) * ('.' | '?'); // тогда вы можете захотеть поместить правило между предложением и словами / местоимением.