优化打印逻辑

This commit is contained in:
Luke 2025-04-27 11:46:42 +08:00
parent fd38c94b3d
commit 4df44686e7

View File

@ -5,190 +5,179 @@ 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<Node> 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 <T> String listToJsonArray(List<T> list, java.util.function.Function<T, String> 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<String> list) {
return listToJsonArray(list, s -> s);
private static <T> String listToJsonArray(List<T> list, Function<T, String> 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('"');