将 ANTLR 解析树转换为 JSON

blu*_*ska 4 java parsing json antlr antlr4

我有一个有效的语法并实现了一个监听器(在 Java 中)。我可以在控制台中用缩进显示解析树,但是我想将它导出为 JSON 结构,以便它可以在任何通用查看器中使用。

是否有一种已经制作的方法可以做到这一点,或者我是否必须以某种方式完全从头开始创建 json 文件?

谢谢!

PS:我还设法通过 TreeView 类在 Swing 中显示...

Bar*_*ers 8

是否有一种已经制作的方法可以做到这一点,或者我是否必须以某种方式完全从头开始创建 json 文件?

正如评论中已经提到的:不,ANTLR 的核心 API 中没有这样的方法。你将不得不推出自己的。

我有一个用于调试目的的实用方法,可以将 ANTLRParseTree转换为java.util.Map可以轻松转换为 JSON 对象的 ANTLR 。我很高兴在这里分享。

鉴于以下语法:

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;
Run Code Online (Sandbox Code Playgroud)

以及以下处理输入的 Main 类(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()));
  }
}
Run Code Online (Sandbox Code Playgroud)

您将看到以下内容打印到您的控制台:

{
  "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"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)