Сломать голову над тем, как получить положение токена с помощью правила - ANTLR4 / грамматика - PullRequest
1 голос
/ 08 апреля 2020

Я пишу небольшую грамматику, используя ANLTR, и у меня есть такое правило:

operation   : OPERATION (IDENT | EXPR) ',' (IDENT | EXPR);
...

OPERATION   : 'ADD' | 'SUB' | 'MUL' | 'DIV' ;
IDENT       : [a-z]+;
EXPR        : INTEGER | FLOAT;
INTEGER     : [0-9]+ | '-'[0-9]+
FLOAT       : [0-9]+'.'[0-9]+ | '-'[0-9]+'.'[0-9]+

Теперь в слушателе внутри Java, как мне определить в случае такого сценария где операции состоят из IDENT и EXPR в том порядке, в котором они появляются? Очевидно, что правило может соответствовать как ADD 10, d, так и ADD d, 10. Но в слушателе для правила, сгенерированного ANTLR4, если есть и IDENT(), и EXPR(), как получить их порядок, так как я хочу назначить левое и правильные операнды правильно.

Я ломал голову над этим, есть какой-то простой способ или я должен переписать само правило? ctx.getTokens () требует, чтобы я указал тип токена, который побеждает цель, поскольку я не могу получить последовательность токенов в правиле, если я укажу их тип.

1 Ответ

1 голос
/ 08 апреля 2020

Вы можете сделать это следующим образом:

operation : OPERATION lhs=(IDENT | EXPR) ',' rhs=(IDENT | EXPR);

и затем внутри слушателя сделайте следующее:

@Override
public void enterOperation(TParser.OperationContext ctx) {
  if (ctx.lhs.getType() == TParser.IDENT) {
    // left hand side is an identifier
  } else {
    // left hand side is an expression
  }

  // check `rhs` the same way
}

, где TParser происходит из файла грамматики T.g4. Измените это соответственно.

Другое решение будет выглядеть примерно так:

operation
 : OPERATION ident_or_expr ',' ident_or_expr
 ;

ident_or_expr
 : IDENT
 | EXPR
 ;

, а затем в вашем слушателе:

@Override
public void enterOperation(TParser.OperationContext ctx) {
  Double lhs = findValueFor(ctx.ident_or_expr().get(0));
  Double rhs = findValueFor(ctx.ident_or_expr().get(1));

  ...
}

private Double findValueFor(TParser.Ident_or_exprContext ctx) {
  if (ctx.IDENT() != null) {
    // it's an identifier
  } else {
    // it's an expression
  }
}
...