首页 > 解决方案 > 打破头脑如何使用规则获取令牌的位置 - ANTLR4 / 语法

问题描述

我正在使用 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 ()要求我给出令牌类型,这违背了目的,因为如果我指定它们的类型,我无法获得规则中令牌的序列。

标签: parsinglistenerantlrantlr4grammar

解决方案


你可以这样做:

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
  }
}

推荐阅读