ANTLR 访问者模式出现问题 - 未进入访问ExpressFrag 方法

问题描述 投票:0回答:1

我正在开发一个词法和语法分析器,我使用 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或者为什么它没有按预期被调用。任何有关如何解决此问题的见解或建议将不胜感激。

java antlr antlr4 visitor-pattern
1个回答
0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.