I am trying to build a visitor implementation that will convert a string array to unicode.
I am using the following grammar:
grammar ArrayInit; init : '{' value (',' value)* '}' ; value : init | INT ; INT : [0-9]+ ; WS : [ trn]+ -> skip ;
I have gotten as far as this:
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); } }
and I’m not sure how to handle the nested visiting. Any assistance is appreciated.
Edit:
Thank to help from Bart, I was able to come up with a final solution for my use case.
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()); } }
Advertisement
Answer
Something like this should do it:
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()); } } }
which will print:
[u0001, u0002, [u0021, u002c, u0037]]