Convert ANTLR parse tree to JSON

前端 未结 1 1084
没有蜡笔的小新
没有蜡笔的小新 2020-12-19 21:24

I have a working grammar and have implemented a listener (in Java). I can display the parse tree in the console with indentation however what I would like is to export it to

相关标签:
1条回答
  • 2020-12-19 21:51

    Is there an already made method that can do this or will I have to create the json file absolutely from scratch somehow?

    As already mentioned in the comments: no, there is no such method in the core API of ANTLR. You will have to roll your own.

    I have a utility method for debugging purposes that transfers an ANTLR ParseTree into a java.util.Map which can easily be transformed into a JSON object. I'm happy to share it here.

    Given the following grammar:

    grammar Expression;
    
    parse
     : expr EOF
     ;
    
    expr
     : '(' expr ')'                          #nestedExpr
     | '-' expr                              #unartyMinusExpr
     | expr ( '*' | '/' | '%' ) expr         #multExpr
     | expr ( '+' | '-' ) expr               #addExpr
     | expr ( '>' | '>=' | '<' | '<=' ) expr #compareExpr
     | expr ( '=' | '!=' ) expr              #eqExpr
     | expr AND expr                         #andExpr
     | expr OR expr                          #orExpr
     | function_call                         #functionCallExpr
     | ID                                    #idExpr
     | NUMBER                                #numberExpr
     | STRING                                #stringExpr
     ;
    
    function_call
     : ID args
     ;
    
    args
     : '(' ( expr ( ',' expr )* )? ')'
     ;
    
    ADD    : '+';
    MINUS  : '-';
    MULT   : '*';
    DIV    : '/';
    MOD    : '%';
    OPAR   : '(';
    CPAR   : ')';
    LTE    : '<=';
    LT     : '<';
    GTE    : '>=';
    GT     : '>';
    EQ     : '=';
    NEQ    : '!=';
    AND    : 'and';
    OR     : 'or';
    NUMBER : ( [0-9]* '.' )? [0-9]+;
    ID     : [a-zA-Z_] [a-zA-Z_0-9]*;
    STRING : '"' ~["\r\n]* '"';
    NL     : '\r'? '\n' | '\r';
    SPACE  : [ \t] -> skip;
    

    and the following Main class, which handles the input (1 + 2) * 3:

    public class Examples {
    
      private static final Gson PRETTY_PRINT_GSON = new GsonBuilder().setPrettyPrinting().create();
      private static final Gson GSON = new Gson();
    
      public static String toJson(ParseTree tree) {
        return toJson(tree, true);
      }
    
      public static String toJson(ParseTree tree, boolean prettyPrint) {
        return prettyPrint ? PRETTY_PRINT_GSON.toJson(toMap(tree)) : GSON.toJson(toMap(tree));
      }
    
      public static Map<String, Object> toMap(ParseTree tree) {
        Map<String, Object> map = new LinkedHashMap<>();
        traverse(tree, map);
        return map;
      }
    
      public static void traverse(ParseTree tree, Map<String, Object> map) {
    
        if (tree instanceof TerminalNodeImpl) {
          Token token = ((TerminalNodeImpl) tree).getSymbol();
          map.put("type", token.getType());
          map.put("text", token.getText());
        }
        else {
          List<Map<String, Object>> children = new ArrayList<>();
          String name = tree.getClass().getSimpleName().replaceAll("Context$", "");
          map.put(Character.toLowerCase(name.charAt(0)) + name.substring(1), children);
    
          for (int i = 0; i < tree.getChildCount(); i++) {
            Map<String, Object> nested = new LinkedHashMap<>();
            children.add(nested);
            traverse(tree.getChild(i), nested);
          }
        }
      }
    
      public static void main(String[] args) {
        String source = "(1 + 2) * 3";
        ExpressionLexer lexer = new ExpressionLexer(CharStreams.fromString(source));
        ExpressionParser parser = new ExpressionParser(new CommonTokenStream(lexer));
        System.out.println(toJson(parser.parse()));
      }
    }
    

    you will see the following printed to your console:

    {
      "parse": [
        {
          "multExpr": [
            {
              "nestedExpr": [
                {
                  "type": 7,
                  "text": "("
                },
                {
                  "addExpr": [
                    {
                      "numberExpr": [
                        {
                          "type": 17,
                          "text": "1"
                        }
                      ]
                    },
                    {
                      "type": 2,
                      "text": "+"
                    },
                    {
                      "numberExpr": [
                        {
                          "type": 17,
                          "text": "2"
                        }
                      ]
                    }
                  ]
                },
                {
                  "type": 8,
                  "text": ")"
                }
              ]
            },
            {
              "type": 4,
              "text": "*"
            },
            {
              "numberExpr": [
                {
                  "type": 17,
                  "text": "3"
                }
              ]
            }
          ]
        },
        {
          "type": -1,
          "text": "\u003cEOF\u003e"
        }
      ]
    }
    
    0 讨论(0)
提交回复
热议问题