我正在开发一个词法和语法分析器,我使用 ANTLR 实现语义分析和中间表示生成,并且我在访问者实现中遇到了问题。具体来说,我无法在 EvalVisitor 类中成功输入访问ExpressFrag 方法。这种方法对于处理我的语言中的表达式至关重要。
这是我的问题的简化版本:
在我的 EvalVisitor.java 中,我有以下方法:
@Override
public Integer visitAddMinusOp(CCALParser.AddMinusOpContext ctx) {
Integer left = visit(ctx.expression_fragment(0));
Integer right = visit(ctx.expression_fragment(1));
if (left == null || right == null) {
throw new RuntimeException("Left or right operand is null in AddMinusOp");
}
System.out.println("visitAddMinusOp - Left: " + left + ", Right: " + right);
// ...
}
@Override
public Integer visitExpressFrag(CCALParser.ExpressFragContext ctx) {
if (ctx.expression_fragment() == null) {
System.out.println("visitExpressFrag - Expression fragment context is null.");
} else {
System.out.println("visitExpressFrag - Expression Fragment Text: " + ctx.expression_fragment().getText());
}
// ...
}
但是,当运行我的代码时,visitExpressFrag方法似乎没有按预期被调用。我添加了打印语句进行调试,但它们没有被执行,表明该方法没有被输入。
我尝试像这样直接调用visitExpressFrag:
@Override
public Integer visitAddMinusOp(CCALParser.AddMinusOpContext ctx) {
Integer left = visitExpressFrag(0);
// ...
}
但这会导致编译错误:
EvalVisitor.java:297: error: incompatible types: int cannot be converted to ExpressFragContext
Integer left = visitExpressFrag(0);
^
这是我的 CCALParser.java 的相关部分(我不完全确定这是否相关):
// ExpressFragContext definition
public static class ExpressFragContext extends ExpressionContext {
public Expression_fragmentContext expression_fragment() {
return getRuleContext(Expression_fragmentContext.class,0);
}
// ...
}
我的 CCAL.g4 看起来像这样:
expression : expression_fragment binary_arith_op expression_fragment #AddMinusOp
| LPAREN expression RPAREN #Parens
| ID LPAREN arg_list RPAREN #FunctionCallOp
| expression_fragment #ExpressFrag
;
binary_arith_op : PLUS | MINUS;
expression_fragment
: ID #ID
| MINUS ID #NegatedVariable
| NUMBER #NumberLiteral
| TRUE #TrueLiteral
| FALSE #FalseLiteral
| LPAREN expression RPAREN #NestedExpression
;
我不确定如何正确调用visitExpressFrag或者为什么它没有按预期被调用。任何有关如何解决此问题的见解或建议将不胜感激。
visitExpressFrag(0)
不正确,因为它需要 ParserRuleContext
作为参数,但您提供了 int
作为参数。
但是,当运行我的代码时,visitExpressFrag方法似乎没有被调用
对我来说也是如此。像这样使用访问者:
class EvalVisitor extends CCALBaseVisitor<Integer> {
@Override
public Integer visitParse(CCALParser.ParseContext ctx) {
return visit(ctx.expression());
}
@Override
public Integer visitAddMinusOp(CCALParser.AddMinusOpContext ctx) {
Integer left = visit(ctx.expression_fragment(0));
Integer right = visit(ctx.expression_fragment(1));
Integer operator = visit(ctx.binary_arith_op());
return left + (operator * right);
}
@Override
public Integer visitParens(CCALParser.ParensContext ctx) {
return visit(ctx.expression());
}
@Override
public Integer visitFunctionCallOp(CCALParser.FunctionCallOpContext ctx) {
return 42; // TODO
}
@Override
public Integer visitExpressFrag(CCALParser.ExpressFragContext ctx) {
return visit(ctx.expression_fragment());
}
@Override
public Integer visitBinary_arith_op(CCALParser.Binary_arith_opContext ctx) {
return ctx.PLUS() == null ? -1 : 1; // + returns 1, - returns -1
}
@Override
public Integer visitID(CCALParser.IDContext ctx) {
return 42; // TODO
}
@Override
public Integer visitNegatedVariable(CCALParser.NegatedVariableContext ctx) {
return 42; // TODO
}
@Override
public Integer visitNumberLiteral(CCALParser.NumberLiteralContext ctx) {
return Integer.valueOf(ctx.NUMBER().getText());
}
@Override
public Integer visitTrueLiteral(CCALParser.TrueLiteralContext ctx) {
return 1;
}
@Override
public Integer visitFalseLiteral(CCALParser.FalseLiteralContext ctx) {
return 0;
}
@Override
public Integer visitNestedExpression(CCALParser.NestedExpressionContext ctx) {
return visit(ctx.expression());
}
@Override
public Integer visitArg_list(CCALParser.Arg_listContext ctx) {
return visitChildren(ctx);
}
}
还有小司机班:
public class CCALDemo {
public static void main(String[] args) {
CCALLexer lexer = new CCALLexer(CharStreams.fromString("8 - 3"));
CCALParser parser = new CCALParser(new CommonTokenStream(lexer));
Integer answer = new EvalVisitor().visit(parser.parse());
System.out.println(answer);
}
}
将按预期打印
5
。