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]]