You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ANTLR4的两个独立语法间实现Visitor委托?

ANTLR4 跨语法Visitor调用问题解决

我正在开发一个ANTLR4项目,包含两个独立语法:

Transformation.g4

该语法包含toString、lowercase、uppercase等对象转字符串的转换规则,代码如下:

grammar Transformation;

transformation
    : toStringExpr
    | lowercaseExpr
    | uppercaseExpr
    | nestedTransformation
    ;

toStringExpr
    : 'toString' '(' object ')'
    ;
lowercaseExpr
    : 'lowercase' '(' transformation ')'
    ;

uppercaseExpr
    : 'uppercase' '(' transformation ')'
    ;

nestedTransformation
    : '(' transformation ')'
    ;

object
    : IDENTIFIER
    ;

IDENTIFIER
    : [a-zA-Z_][a-zA-Z_0-9]*
    ;

WS
    : [ \t\n\r]+ -> skip ;

Predicate.g4

该语法通过import引入Transformation,包含比较转换结果的谓词规则,代码如下:

grammar Predicate;

import Transformation;

predicate
    : transformation EQUALS transformation
    ;

EQUALS
    : '==' ;

WS
    : [ \t\n\r]+ -> skip ;

需求与问题

我需要将这些语法编译为Java并实现对应的Visitor,其中PredicateVisitorImpl需要依赖TransformationVisitorImpl计算transformation,但希望保持语法独立。

我尝试了如下实现:

public class PredicateVisitorImpl extends PredicateBaseVisitor<Boolean> {
    private final TransformationVisitor transformationVisitor = new TransformationVisitor();

    @Override
    public Boolean visitTransformationComparison(PredicateParser.TransformationComparisonContext ctx) {
        String left = transformationVisitor.visit(ctx.transformation(0));
        String right = transformationVisitor.visit(ctx.transformation(1));
        
        return left.equals(right);
    }
}

但transformationVisitor.visit调用均返回null,核心原因是:当Predicate语法import Transformation后,生成的PredicateParser.TransformationContext是Predicate自身的上下文类,并非TransformationParser.TransformationContext,直接传给Transformation的Visitor无法匹配规则,因此返回null。

我不想通过重新解析转换字符串实现,希望找到高效简洁的解决方案。


解决方案

以下两种方式均无需重新解析字符串,可直接复用上下文结构处理,同时保持语法独立性:

方式1:用工具类统一处理两种上下文

将Transformation的核心计算逻辑抽离为工具类,兼容Transformation和Predicate生成的上下文类型:

public class TransformationUtils {
    public static String evaluateTransformation(RuleContext ctx) {
        // 匹配toString表达式(兼容两种语法的上下文)
        if (ctx instanceof TransformationParser.ToStringExprContext || ctx instanceof PredicateParser.ToStringExprContext) {
            RuleContext objectCtx = (RuleContext) ctx.getChild(2);
            String identifier = objectCtx.getText();
            // 模拟业务逻辑:根据标识符获取对象并转为字符串
            return getObjectValue(identifier).toString();
        }
        // 匹配lowercase表达式
        else if (ctx instanceof TransformationParser.LowercaseExprContext || ctx instanceof PredicateParser.LowercaseExprContext) {
            RuleContext transCtx = (RuleContext) ctx.getChild(2);
            String value = evaluateTransformation(transCtx);
            return value != null ? value.toLowerCase() : null;
        }
        // 匹配uppercase表达式
        else if (ctx instanceof TransformationParser.UppercaseExprContext || ctx instanceof PredicateParser.UppercaseExprContext) {
            RuleContext transCtx = (RuleContext) ctx.getChild(2);
            String value = evaluateTransformation(transCtx);
            return value != null ? value.toUpperCase() : null;
        }
        // 匹配嵌套转换表达式
        else if (ctx instanceof TransformationParser.NestedTransformationContext || ctx instanceof PredicateParser.NestedTransformationContext) {
            RuleContext transCtx = (RuleContext) ctx.getChild(1);
            return evaluateTransformation(transCtx);
        }
        return null;
    }

    // 模拟获取对象值的业务方法
    private static Object getObjectValue(String identifier) {
        return identifier;
    }
}

修改PredicateVisitorImpl调用工具类:

public class PredicateVisitorImpl extends PredicateBaseVisitor<Boolean> {

    @Override
    public Boolean visitPredicate(PredicateParser.PredicateContext ctx) {
        String left = TransformationUtils.evaluateTransformation(ctx.transformation(0));
        String right = TransformationUtils.evaluateTransformation(ctx.transformation(1));
        return left != null && right != null && left.equals(right);
    }
}

方式2:让TransformationVisitor兼容Predicate上下文

让TransformationVisitorImpl同时实现PredicateVisitor<String>接口,处理两种语法的规则上下文:

public class TransformationVisitorImpl extends TransformationBaseVisitor<String> implements PredicateVisitor<String> {

    // 处理Transformation语法的toString表达式
    @Override
    public String visitToStringExpr(TransformationParser.ToStringExprContext ctx) {
        String identifier = ctx.object().getText();
        return getObjectValue(identifier).toString();
    }

    // 处理Predicate语法的toString表达式
    @Override
    public String visitToStringExpr(PredicateParser.ToStringExprContext ctx) {
        String identifier = ctx.object().getText();
        return getObjectValue(identifier).toString();
    }

    // 处理Transformation语法的lowercase表达式
    @Override
    public String visitLowercaseExpr(TransformationParser.LowercaseExprContext ctx) {
        String value = visit(ctx.transformation());
        return value != null ? value.toLowerCase() : null;
    }

    // 处理Predicate语法的lowercase表达式
    @Override
    public String visitLowercaseExpr(PredicateParser.LowercaseExprContext ctx) {
        String value = visit(ctx.transformation());
        return value != null ? value.toLowerCase() : null;
    }

    // 处理Transformation语法的uppercase表达式
    @Override
    public String visitUppercaseExpr(TransformationParser.UppercaseExprContext ctx) {
        String value = visit(ctx.transformation());
        return value != null ? value.toUpperCase() : null;
    }

    // 处理Predicate语法的uppercase表达式
    @Override
    public String visitUppercaseExpr(PredicateParser.UppercaseExprContext ctx) {
        String value = visit(ctx.transformation());
        return value != null ? value.toUpperCase() : null;
    }

    // 处理Transformation语法的嵌套转换
    @Override
    public String visitNestedTransformation(TransformationParser.NestedTransformationContext ctx) {
        return visit(ctx.transformation());
    }

    // 处理Predicate语法的嵌套转换
    @Override
    public String visitNestedTransformation(PredicateParser.NestedTransformationContext ctx) {
        return visit(ctx.transformation());
    }

    // PredicateVisitor默认方法,无需处理直接返回null
    @Override
    public String visitPredicate(PredicateParser.PredicateContext ctx) {
        return null;
    }

    // 模拟获取对象值的业务方法
    private Object getObjectValue(String identifier) {
        return identifier;
    }
}

修改PredicateVisitorImpl使用兼容后的Visitor:

public class PredicateVisitorImpl extends PredicateBaseVisitor<Boolean> {
    private final TransformationVisitorImpl transformationVisitor = new TransformationVisitorImpl();

    @Override
    public Boolean visitPredicate(PredicateParser.PredicateContext ctx) {
        String left = transformationVisitor.visit(ctx.transformation(0));
        String right = transformationVisitor.visit(ctx.transformation(1));
        return left != null && right != null && left.equals(right);
    }
}

内容的提问来源于stack exchange,提问作者Raúl García

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 19:25:16