突破如何使用规则获取令牌的位置 - ANTLR4 /语法
Breaking head over how to get position of token with a rule - ANTLR4 / grammar
我正在使用 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里面的listener中,遇到IDENT和EXPR操作同时出现的情况,如何判断它们出现的顺序呢?
显然规则可以匹配两者
ADD 10, d
或者
ADD d, 10
但是在由 ANTLR4 生成的规则的侦听器中,如果同时存在 IDENT()
和 EXPR()
如何获得它们的顺序,因为我想正确分配左右操作数。
我一直在为这个问题烦恼,有没有简单的方法或者我应该自己重写规则? ctx.getTokens ()
要求我提供标记类型,这违背了目的,因为如果我指定它们的类型,我将无法获得规则中标记的顺序。
你可以这样做:
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
}
}
我正在使用 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里面的listener中,遇到IDENT和EXPR操作同时出现的情况,如何判断它们出现的顺序呢?
显然规则可以匹配两者
ADD 10, d
或者
ADD d, 10
但是在由 ANTLR4 生成的规则的侦听器中,如果同时存在 IDENT()
和 EXPR()
如何获得它们的顺序,因为我想正确分配左右操作数。
我一直在为这个问题烦恼,有没有简单的方法或者我应该自己重写规则? ctx.getTokens ()
要求我提供标记类型,这违背了目的,因为如果我指定它们的类型,我将无法获得规则中标记的顺序。
你可以这样做:
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
}
}