From 4df44686e78e9086bac60f3eb0ccc9a8ffa33e51 Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 27 Apr 2025 11:46:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=89=93=E5=8D=B0=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parser/util/ASTJsonSerializer.java | 241 +++++++++--------- 1 file changed, 115 insertions(+), 126 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/parser/util/ASTJsonSerializer.java b/src/main/java/org/jcnc/snow/compiler/parser/util/ASTJsonSerializer.java index d3ff7cb..2d643a2 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/util/ASTJsonSerializer.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/util/ASTJsonSerializer.java @@ -5,193 +5,182 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; import org.jcnc.snow.compiler.parser.ast.base.Node; import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; -/** - * 更加健壮、完整的 AST -> JSON 序列化器。 - */ public class ASTJsonSerializer { public static String toJsonString(List ast) { - return listToJsonArray(ast.stream().map(ASTJsonSerializer::nodeToJson).toList()); + return ast.stream() + .map(ASTJsonSerializer::nodeToJson) + .collect(Collectors.joining(",", "[", "]")); } private static String nodeToJson(Node n) { - if (n instanceof ModuleNode m) return moduleToJson(m); - if (n instanceof FunctionNode f) return functionToJson(f); - if (n instanceof DeclarationNode d) return declarationToJson(d); - if (n instanceof AssignmentNode a) return assignmentToJson(a); - if (n instanceof IfNode i) return ifToJson(i); - if (n instanceof LoopNode l) return loopToJson(l); - if (n instanceof ReturnNode r) return returnToJson(r); - if (n instanceof ExpressionStatementNode e) return exprStmtToJson(e); - return simpleTypeJson(n.getClass().getSimpleName()); + return switch (n) { + case ModuleNode m -> moduleToJson(m); + case FunctionNode f -> functionToJson(f); + case DeclarationNode d -> declarationToJson(d); + case AssignmentNode a -> assignmentToJson(a); + case IfNode i -> ifToJson(i); + case LoopNode l -> loopToJson(l); + case ReturnNode r -> returnToJson(r); + case ExpressionStatementNode e -> exprStmtToJson(e); + default -> simpleTypeJson(n.getClass().getSimpleName()); + }; } private static String moduleToJson(ModuleNode m) { - return "{" + - "\"type\":\"Module\"," + - "\"name\":" + quote(m.name()) + "," + - "\"imports\":" + listToJsonArray(m.imports(), imp -> "{\"type\":\"Import\",\"module\":" + quote(imp.moduleName()) + "}") + "," + - "\"functions\":" + listToJsonArray(m.functions(), ASTJsonSerializer::functionToJson) + - "}"; + return """ + {"type":"Module","name":%1$s,"imports":%2$s,"functions":%3$s} + """.formatted( + quote(m.name()), + listToJsonArray(m.imports(), + imp -> String.format("{\"type\":\"Import\",\"module\":%s}", quote(imp.moduleName())) + ), + listToJsonArray(m.functions(), ASTJsonSerializer::functionToJson) + ); } private static String functionToJson(FunctionNode f) { - return "{" + - "\"type\":\"Function\"," + - "\"name\":" + quote(f.name()) + "," + - "\"parameters\":" + listToJsonArray(f.parameters(), p -> "{\"name\":" + quote(p.name()) + ",\"type\":" + quote(p.type()) + "}") + "," + - "\"returnType\":" + quote(f.returnType()) + "," + - "\"body\":" + listToJsonArray(f.body(), ASTJsonSerializer::nodeToJson) + - "}"; + return """ + {"type":"Function","name":%1$s,"parameters":%2$s,"returnType":%3$s,"body":%4$s} + """.formatted( + quote(f.name()), + listToJsonArray(f.parameters(), + p -> String.format("{\"name\":%s,\"type\":%s}", quote(p.name()), quote(p.type())) + ), + quote(f.returnType()), + listToJsonArray(f.body(), ASTJsonSerializer::nodeToJson) + ); } private static String declarationToJson(DeclarationNode d) { - String json = "{" + - "\"type\":\"Declaration\"," + - "\"name\":" + quote(d.getName()) + "," + - "\"varType\":" + quote(d.getType()); - if (d.getInitializer().isPresent()) { - json += ",\"initializer\":" + exprToJson(d.getInitializer().get()); - } - return json + "}"; + var base = new StringBuilder(); + base.append(""" + {"type":"Declaration","name":%1$s,"varType":%2$s + """.formatted(quote(d.getName()), quote(d.getType()))); + d.getInitializer().ifPresent(init -> + base.append(",\"initializer\":").append(exprToJson(init)) + ); + base.append("}"); + return base.toString(); } private static String assignmentToJson(AssignmentNode a) { - return "{" + - "\"type\":\"Assignment\"," + - "\"variable\":" + quote(a.variable()) + "," + - "\"value\":" + exprToJson(a.value()) + - "}"; + return """ + {"type":"Assignment","variable":%1$s,"value":%2$s} + """.formatted(quote(a.variable()), exprToJson(a.value())); } private static String ifToJson(IfNode i) { - StringBuilder sb = new StringBuilder(); - sb.append("{" + "\"type\":\"If\"," + "\"condition\":").append(exprToJson(i.condition())).append(","); - sb.append("\"then\":").append(listToJsonArray(i.thenBranch(), ASTJsonSerializer::nodeToJson)); - if (!i.elseBranch().isEmpty()) { - sb.append(",\"else\":").append(listToJsonArray(i.elseBranch(), ASTJsonSerializer::nodeToJson)); - } + var thenJson = listToJsonArray(i.thenBranch(), ASTJsonSerializer::nodeToJson); + var elseJson = i.elseBranch().isEmpty() ? "" + : ",\"else\":" + listToJsonArray(i.elseBranch(), ASTJsonSerializer::nodeToJson); + return """ + {"type":"If","condition":%1$s,"then":%2$s%3$s} + """.formatted(exprToJson(i.condition()), thenJson, elseJson); + } + + private static String loopToJson(LoopNode l) { + return """ + {"type":"Loop","initializer":%1$s,"condition":%2$s,"update":%3$s,"body":%4$s} + """.formatted( + l.initializer() != null ? nodeToJson(l.initializer()) : "null", + l.condition() != null ? exprToJson(l.condition()) : "null", + l.update() != null ? nodeToJson(l.update()) : "null", + listToJsonArray(l.body(), ASTJsonSerializer::nodeToJson) + ); + } + + private static String returnToJson(ReturnNode r) { + var sb = new StringBuilder("{\"type\":\"Return\""); + r.getExpression().ifPresent(expr -> + sb.append(",\"value\":").append(exprToJson(expr)) + ); sb.append("}"); return sb.toString(); } - private static String loopToJson(LoopNode l) { - return "{" + - "\"type\":\"Loop\"," + - "\"initializer\":" + (l.initializer() != null ? nodeToJson(l.initializer()) : "null") + "," + - "\"condition\":" + (l.condition() != null ? exprToJson(l.condition()) : "null") + "," + - "\"update\":" + (l.update() != null ? nodeToJson(l.update()) : "null") + "," + - "\"body\":" + listToJsonArray(l.body(), ASTJsonSerializer::nodeToJson) + - "}"; - } - - private static String returnToJson(ReturnNode r) { - String json = "{" + "\"type\":\"Return\""; - if (r.getExpression().isPresent()) { - json += ",\"value\":" + exprToJson(r.getExpression().get()); - } - return json + "}"; - } - private static String exprStmtToJson(ExpressionStatementNode e) { - return "{" + - "\"type\":\"ExpressionStatement\"," + - "\"expression\":" + exprToJson(e.expression()) + - "}"; + return """ + {"type":"ExpressionStatement","expression":%s} + """.formatted(exprToJson(e.expression())); } private static String exprToJson(ExpressionNode expr) { - if (expr instanceof BinaryExpressionNode b) return binaryToJson(b); - if (expr instanceof IdentifierNode id) return idToJson(id); - if (expr instanceof NumberLiteralNode n) return numToJson(n); - if (expr instanceof StringLiteralNode s) return strToJson(s); - if (expr instanceof CallExpressionNode c) return callToJson(c); - if (expr instanceof MemberExpressionNode m) return memberToJson(m); - return simpleTypeJson(expr.getClass().getSimpleName()); + return switch (expr) { + case BinaryExpressionNode b -> binaryToJson(b); + case IdentifierNode id -> idToJson(id); + case NumberLiteralNode n -> numToJson(n); + case StringLiteralNode s -> strToJson(s); + case CallExpressionNode c -> callToJson(c); + case MemberExpressionNode m -> memberToJson(m); + default -> simpleTypeJson(expr.getClass().getSimpleName()); + }; } private static String binaryToJson(BinaryExpressionNode b) { - return "{" + - "\"type\":\"BinaryExpression\"," + - "\"left\":" + exprToJson(b.left()) + "," + - "\"operator\":" + quote(b.operator()) + "," + - "\"right\":" + exprToJson(b.right()) + - "}"; + return """ + {"type":"BinaryExpression","left":%1$s,"operator":%2$s,"right":%3$s} + """.formatted(exprToJson(b.left()), quote(b.operator()), exprToJson(b.right())); } private static String idToJson(IdentifierNode id) { - return "{" + - "\"type\":\"Identifier\"," + - "\"name\":" + quote(id.name()) + - "}"; + return """ + {"type":"Identifier","name":%s} + """.formatted(quote(id.name())); } private static String numToJson(NumberLiteralNode n) { - return "{" + - "\"type\":\"NumberLiteral\"," + - "\"value\":" + quote(n.value()) + - "}"; + return """ + {"type":"NumberLiteral","value":%s} + """.formatted(quote(n.value())); } private static String strToJson(StringLiteralNode s) { - return "{" + - "\"type\":\"StringLiteral\"," + - "\"value\":" + quote(s.value()) + - "}"; + return """ + {"type":"StringLiteral","value":%s} + """.formatted(quote(s.value())); } private static String callToJson(CallExpressionNode c) { - return "{" + - "\"type\":\"CallExpression\"," + - "\"callee\":" + exprToJson(c.callee()) + "," + - "\"arguments\":" + listToJsonArray(c.arguments(), ASTJsonSerializer::exprToJson) + - "}"; + return """ + {"type":"CallExpression","callee":%1$s,"arguments":%2$s} + """.formatted(exprToJson(c.callee()), listToJsonArray(c.arguments(), ASTJsonSerializer::exprToJson)); } private static String memberToJson(MemberExpressionNode m) { - return "{" + - "\"type\":\"MemberExpression\"," + - "\"object\":" + exprToJson(m.object()) + "," + - "\"member\":" + quote(m.member()) + - "}"; + return """ + {"type":"MemberExpression","object":%1$s,"member":%2$s} + """.formatted(exprToJson(m.object()), quote(m.member())); } - // ========= 辅助函数 ========= + // ======== 通用辅助 ======== private static String simpleTypeJson(String typeName) { - return "{" + "\"type\":" + quote(typeName) + "}"; + return "{\"type\":" + quote(typeName) + "}"; } - private static String listToJsonArray(List list, java.util.function.Function mapper) { - StringBuilder sb = new StringBuilder(); - sb.append("["); - for (int i = 0; i < list.size(); i++) { - sb.append(mapper.apply(list.get(i))); - if (i + 1 < list.size()) sb.append(","); - } - sb.append("]"); - return sb.toString(); - } - - private static String listToJsonArray(List list) { - return listToJsonArray(list, s -> s); + private static String listToJsonArray(List list, Function mapper) { + return list.stream() + .map(mapper) + .collect(Collectors.joining(",", "[", "]")); } private static String quote(String s) { - StringBuilder sb = new StringBuilder(); - sb.append('"'); + var sb = new StringBuilder("\""); for (char c : s.toCharArray()) { switch (c) { - case '\\': sb.append("\\\\"); break; - case '"': sb.append("\\\""); break; - case '\n': sb.append("\\n"); break; - case '\r': sb.append("\\r"); break; - case '\t': sb.append("\\t"); break; - default: sb.append(c); + case '\\' -> sb.append("\\\\"); + case '\"' -> sb.append("\\\""); + case '\n' -> sb.append("\\n"); + case '\r' -> sb.append("\\r"); + case '\t' -> sb.append("\\t"); + default -> sb.append(c); } } sb.append('"'); return sb.toString(); } -} \ No newline at end of file +}