如何在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

