Как получить доступ к токенам лексера ANTLR

#java #antlr #antlr4

#java #antlr #antlr4

Вопрос:

Я указал следующую грамматику ANTLR:

 expression: ...
          | extractor=EXTRACTOR '(' setElementDefinition ',' expression ')' #setExtractorExp
          | ... ;

EXTRACTOR: 'select'
         | 'choose' ;
  

Я хотел бы знать, с каким типом извлечения я имею дело при разборе этого выражения.
Один из способов сделать это — сравнить поле extractor со строкой, содержащей тип extractor, например:

 @Override
public Expression visitSetExtractorExp(MyParser.SetExtractorExpContext ctx) {
    if(ctx.extractor.getText().equals("select")) { ... }
}
  

Но мне не нравится дублировать имена экстракторов здесь, на случай, если я решу изменить имена экстракторов позже.
Итак, есть ли способ получить доступ к токенам лексера?

Я представляю себе что-то вроде if(ctx.extractor == MyLexer.EXTRACTOR.choose) .

Ответ №1:

Прямо сейчас у вас EXTRACTOR есть только один тип, что делает "select" и "choose" почти то же самое. Единственный способ провести различие — это сравнение строк, как вы уже делаете. Если вы этого не хотите, сделайте что-то вроде этого:

 expression
 : ...
 | extractor '(' setElementDefinition ',' expression ')' #setExtractorExp
 | ... 
 ;

extractor
 : SELECT
 | CHOOSE
 ;

SELECT : 'select';
CHOOSE : 'choose';
  

и в вашем посетителе:

 @Override
public Expression visitSetExtractorExp(MyParser.SetExtractorExpContext ctx) {
  if(ctx.extractor().start.getType() == MyLexer.SELECT) { ... }
  else if(ctx.extractor().start.getType() == MyLexer.CHOOSE) { ... }
}
  

Таким образом, вам не нужно дублировать (волшебные) строки.