[ArrayInitVisitorImpl的ANTLR访问者实现

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

我正在尝试构建将字符串数组转换为Unicode的访客实现。

我正在使用以下语法:

grammar ArrayInit;

init : '{' value (',' value)* '}' ;

value : init
      | INT
      ;

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

我已经做到这一点:

public class ArrayInitVisitorImpl extends ArrayInitBaseVisitor<String> {

    @Override
    public String visitInit(ArrayInitParser.InitContext ctx){
        return "\"";
    }

    @Override
    public String visitValue(ArrayInitParser.ValueContext ctx) {
        int value = Integer.parseInt(ctx.INT().getText());
        return String.format("\\u%04x", value);
    }

}

而且我不确定如何处理嵌套访问。任何帮助表示赞赏。

编辑:

感谢Bart的帮助,我能够为我的用例提出最终的解决方案。

public class Driver {

    public static void main(String[] args) {
        String stringArray = "{ 99, {1, 2, 3}, 3, 451 }";

        StringArrayToUnicodeConverter converter = new StringArrayToUnicodeConverter();
        String unicode = converter.convert(stringArray);

        System.out.println(unicode);
    }

}

public class StringArrayToUnicodeConverter {

    public String convert(String source) {
        CodePointCharStream input = CharStreams.fromString(source);
        return compile(input);
    }

    private String compile(CharStream source) {
        ArrayInitLexer lexer = new ArrayInitLexer(source);
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        ArrayInitParser parser = new ArrayInitParser(tokenStream);
        ParseTree tree = parser.init();
        ArrayInitVisitorImpl visitor = new ArrayInitVisitorImpl();
        return visitor.visit(tree);
    }

}

public class ArrayInitVisitorImpl extends ArrayInitBaseVisitor<String> {

    @Override
    public String visitInit(ArrayInitParser.InitContext ctx){
        List<String> values = new ArrayList<>();
        for (ArrayInitParser.ValueContext value : ctx.value()) {
            values.add(this.visit(value));
        }
        return "\"" + String.join(",", values) + "\"";
    }

    @Override
    public String visitValue(ArrayInitParser.ValueContext ctx) {
        if(ctx.INT() != null){
            int value = Integer.parseInt(ctx.INT().getText());
            return String.format("\\u%04x", value);
        }

        return this.visit(ctx.init());
    }

}
java design-patterns antlr antlr4 visitor-pattern
1个回答
2
投票

这样的事情应该做:

public class Main {
    public static void main(String[] args) throws Exception {
        ArrayInitLexer lexer = new ArrayInitLexer(CharStreams.fromString("{1,2,{33,44,55}}"));
        ArrayInitParser parser = new ArrayInitParser(new CommonTokenStream(lexer));
        Object[] result = (Object[]) new ArrayInitVisitorImpl().visit(parser.init());
        System.out.println(Arrays.deepToString(result));
    }
}

class ArrayInitVisitorImpl extends ArrayInitBaseVisitor<Object> {

    @Override
    public Object visitInit(ArrayInitParser.InitContext ctx){
        List<Object> values = new ArrayList<>();
        for (ArrayInitParser.ValueContext value : ctx.value()) {
            values.add(this.visit(value));
        }
        return values.toArray();
    }

    @Override
    public Object visitValue(ArrayInitParser.ValueContext ctx) {
        if (ctx.INT() != null) {
            int value = Integer.parseInt(ctx.INT().getText());
            return String.format("\\u%04x", value);
        }
        else {
            return this.visit(ctx.init());
        }
    }
}

将打印:

[\u0001, \u0002, [\u0021, \u002c, \u0037]]
© www.soinside.com 2019 - 2024. All rights reserved.