2013-11-16 2 views
3

Этот вопрос касается того, как отличать необязательные токены при посещении правила antlr.Различают дополнительные маркеры при посещении правила Antlr

У меня есть правило парсера, которое я определил в грамматике antlr4 под названием 'assign', которая пытается присвоить результат выражения тегу, представленному INT, например 215 = «FOO». Он также позволяет присваивать тегу индекс, например 215 [2] = "FOO". Мой вопрос в том, как я могу отличить INTs формы 215 от формы 215 [2], посмотрев объекты, предоставленные antlr, во время оценки правила назначения?

assign : INT '=' expr ; 
INT  : '-'? DIGIT+ ('[' DIGIT+ ']')?; 
DIGIT : [0-9] ; 

Я определил метод посетителя, чтобы захватить оценку парсера правила "назначить" для потока токенов:

215 [2] = "Foo"

@Override 
public String visitAssign(@NotNull FixRulesParser.AssignContext ctx) { 
String left = ctx.getStart().getText(); 
String right = ctx.getStop().getText(); 
... 

В этом point left = "215 [2]" и right = "FOO"

Предлагает ли ctx-объект способ определить, содержит ли левая часть задания (215 [2]) необязательный параметр '[2]' определяемый INT? Я хочу отличить INTs формы 215 [2] против 215. Я использую регулярное выражение Java для анализа «left» (см. Ниже), чтобы сделать определение, но мне интересно, могу ли я получить ответ напрямую из antlr.

Pattern p = Pattern.compile("(-?\\d+)((\\[)(\\d+)(\\]))?"); 

ответ

3

Одно решение, которое я нашел после прочтения "The Antlr Reference - Chapter 12" было определить индекс «[2]» в качестве лексического анализатора знак его собственной и разместить его на отдельном канале.

assign : INT '=' expr ; 
INT : '-'? DIGIT+ ; 
IDX : '[' DIGIT+ ']' -> channel(TAG_INDEX); 
DIGIT : [0-9] ; 

Тогда я могу сделать определение в visitAssign():

@Override 
public String visitAssign(@NotNull FixRulesParser.AssignContext ctx) { 
    BufferedTokenStream tokens = tokenStream; // passed in to the constructor as arg 
    Token t = tokens.get(1); 
    int type = t.getType(); 
    if (type == FixRulesParser.IDX) { 
     System.out.println("YES"); 
    } else { 
     System.out.println("NO"); 
    } 

Я думаю, что урок здесь в том, что IDX не следует комбинировать с любыми другими лексемами, если вам нужно обратиться к нему индивидуально ,

Одна вещь, которая до сих пор меня смущает, если я удалю TAG_INDEX канал:

IDX : '[' DIGIT+ ']'; 

я получаю: линия 1: 4 нет жизнеспособной альтернативы на входе '215 [2]

Would хорошо знать, почему, но, по крайней мере, у меня есть решение.

Смежные вопросы