将 ANTLR 解析树转换为 JSON

Convert ANTLR parse tree to JSON

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

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

谢谢!

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

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

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

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

给定以下语法:

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;

和下面的 Main class,它处理输入 (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()));
  }
}

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

{
  "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"
    }
  ]
}

将 Bart 的解决方案翻译成 C#


public static Dictionary<String, Object> toMap(IParseTree tree, YOURPARSERHERE parser)
{
    Dictionary<String, Object> map = new Dictionary<String, Object>();
    traverse(tree, map);
    return map;
}

public static void traverse(IParseTree tree, Dictionary<String, Object> map)
{
    if (tree is TerminalNodeImpl) 
    {
        map.Add("type", tree.GetType());
        map.Add("text", tree.GetText());
    }
    else
    {
        List<Dictionary<String, Object>> children = new List<Dictionary<String,Object>>();
        String name = tree.GetType().Name.Replace("Context", "");
        map.Add(char.ToLower(name.ElementAt(0)) + name.Substring(1), children);

        for (int i = 0; i < tree.ChildCount; i++)
        {
            Dictionary<String, Object> nested = new Dictionary<string, object>();
            children.Add(nested);
            traverse(tree.GetChild(i), nested);
        }
    }
}