增加ast的else打印

This commit is contained in:
Luke 2025-04-27 11:09:44 +08:00
parent e3bc1a99e7
commit 60eaedb6b0
3 changed files with 215 additions and 349 deletions

View File

@ -7,6 +7,8 @@ import org.jcnc.snow.compiler.parser.ParserEngine;
import org.jcnc.snow.compiler.parser.context.ParserContext; import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.ast.Node; import org.jcnc.snow.compiler.parser.ast.Node;
import org.jcnc.snow.compiler.parser.function.ASTPrinter; import org.jcnc.snow.compiler.parser.function.ASTPrinter;
import org.jcnc.snow.compiler.parser.util.ASTJsonSerializer;
import org.jcnc.snow.compiler.parser.util.JsonFormatter;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -32,14 +34,14 @@ public class Main {
// 3. 可读地打印 AST // 3. 可读地打印 AST
ASTPrinter.print(ast); ASTPrinter.print(ast);
// // 1) 输出紧凑 JSON // 1) 输出紧凑 JSON
// String compact = ASTJsonSerializer.toJsonString(ast); String compact = ASTJsonSerializer.toJsonString(ast);
// System.out.println("=== Compact JSON ==="); // System.out.println("=== Compact JSON ===");
// System.out.println(compact); // System.out.println(compact);
//
// // 2) 输出美化后的 JSON // 2) 输出美化后的 JSON
// System.out.println("=== Pretty JSON ==="); System.out.println("=== Pretty JSON ===");
// System.out.println(JsonFormatter.prettyPrint(compact)); System.out.println(JsonFormatter.prettyPrint(compact));
} }
} }

View File

@ -4,28 +4,13 @@ import org.jcnc.snow.compiler.parser.ast.*;
import java.util.List; import java.util.List;
/** /**
* ASTJsonSerializer 是一个用于将抽象语法树AST序列化为 JSON 字符串的工具类 * 更加健壮完整的 AST -> JSON 序列化器
* 该类通过访问不同类型的语法树节点将其结构以标准 JSON 格式输出适用于调试可视化或进一步处理
*/ */
public class ASTJsonSerializer { public class ASTJsonSerializer {
/**
* 将语法树节点列表序列化为 JSON 字符串
*
* @param ast 抽象语法树的节点列表
* @return 表示整个 AST JSON 字符串
*/
public static String toJsonString(List<Node> ast) { public static String toJsonString(List<Node> ast) {
StringBuilder sb = new StringBuilder(); return listToJsonArray(ast.stream().map(ASTJsonSerializer::nodeToJson).toList());
sb.append("[");
for (int i = 0; i < ast.size(); i++) {
sb.append(nodeToJson(ast.get(i)));
if (i + 1 < ast.size()) sb.append(",");
}
sb.append("]");
return sb.toString();
} }
private static String nodeToJson(Node n) { private static String nodeToJson(Node n) {
@ -36,174 +21,164 @@ public class ASTJsonSerializer {
if (n instanceof IfNode i) return ifToJson(i); if (n instanceof IfNode i) return ifToJson(i);
if (n instanceof LoopNode l) return loopToJson(l); if (n instanceof LoopNode l) return loopToJson(l);
if (n instanceof ReturnNode r) return returnToJson(r); if (n instanceof ReturnNode r) return returnToJson(r);
if (n instanceof ExpressionStatementNode es) if (n instanceof ExpressionStatementNode e) return exprStmtToJson(e);
return exprStmtToJson(es); return simpleTypeJson(n.getClass().getSimpleName());
// fallback仅输出类型名
return "{\"type\":\"" + n.getClass().getSimpleName() + "\"}";
} }
private static String moduleToJson(ModuleNode m) { private static String moduleToJson(ModuleNode m) {
StringBuilder sb = new StringBuilder(); return "{" +
sb.append("{\"type\":\"Module\",") "\"type\":\"Module\"," +
.append("\"name\":").append(quote(m.name())).append(","); "\"name\":" + quote(m.name()) + "," +
// imports "\"imports\":" + listToJsonArray(m.imports(), imp -> "{\"type\":\"Import\",\"module\":" + quote(imp.moduleName()) + "}") + "," +
sb.append("\"imports\":["); "\"functions\":" + listToJsonArray(m.functions(), ASTJsonSerializer::functionToJson) +
for (int i = 0; i < m.imports().size(); i++) { "}";
ImportNode imp = m.imports().get(i);
sb.append("{\"type\":\"Import\",\"module\":")
.append(quote(imp.moduleName())).append("}");
if (i + 1 < m.imports().size()) sb.append(",");
}
sb.append("],");
// functions
sb.append("\"functions\":[");
for (int i = 0; i < m.functions().size(); i++) {
sb.append(functionToJson(m.functions().get(i)));
if (i + 1 < m.functions().size()) sb.append(",");
}
sb.append("]}");
return sb.toString();
} }
private static String functionToJson(FunctionNode f) { private static String functionToJson(FunctionNode f) {
StringBuilder sb = new StringBuilder(); return "{" +
sb.append("{\"type\":\"Function\",") "\"type\":\"Function\"," +
.append("\"name\":").append(quote(f.name())).append(","); "\"name\":" + quote(f.name()) + "," +
// parameters "\"parameters\":" + listToJsonArray(f.parameters(), p -> "{\"name\":" + quote(p.name()) + ",\"type\":" + quote(p.type()) + "}") + "," +
sb.append("\"parameters\":["); "\"returnType\":" + quote(f.returnType()) + "," +
for (int i = 0; i < f.parameters().size(); i++) { "\"body\":" + listToJsonArray(f.body(), ASTJsonSerializer::nodeToJson) +
ParameterNode p = f.parameters().get(i); "}";
sb.append("{\"name\":").append(quote(p.name()))
.append(",\"type\":").append(quote(p.type())).append("}");
if (i + 1 < f.parameters().size()) sb.append(",");
}
sb.append("],");
sb.append("\"returnType\":").append(quote(f.returnType())).append(",");
// body
sb.append("\"body\":[");
List<StatementNode> body = f.body();
return getString(sb, body);
} }
private static String declarationToJson(DeclarationNode d) { private static String declarationToJson(DeclarationNode d) {
StringBuilder sb = new StringBuilder(); String json = "{" +
sb.append("{\"type\":\"Declaration\",") "\"type\":\"Declaration\"," +
.append("\"name\":").append(quote(d.getName())).append(",") "\"name\":" + quote(d.getName()) + "," +
.append("\"varType\":").append(quote(d.getType())); "\"varType\":" + quote(d.getType());
d.getInitializer().ifPresent(init -> if (d.getInitializer().isPresent()) {
sb.append(",\"initializer\":").append(exprToJson(init)) json += ",\"initializer\":" + exprToJson(d.getInitializer().get());
); }
sb.append("}"); return json + "}";
return sb.toString();
} }
private static String assignmentToJson(AssignmentNode a) { private static String assignmentToJson(AssignmentNode a) {
return "{\"type\":\"Assignment\",\"variable\":" return "{" +
+ quote(a.variable()) "\"type\":\"Assignment\"," +
+ ",\"value\":" "\"variable\":" + quote(a.variable()) + "," +
+ exprToJson(a.value()) "\"value\":" + exprToJson(a.value()) +
+ "}"; "}";
} }
private static String ifToJson(IfNode i) { private static String ifToJson(IfNode i) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("{\"type\":\"If\",\"condition\":") sb.append("{" + "\"type\":\"If\"," + "\"condition\":").append(exprToJson(i.condition())).append(",");
.append(exprToJson(i.condition())).append(","); sb.append("\"then\":").append(listToJsonArray(i.thenBranch(), ASTJsonSerializer::nodeToJson));
sb.append("\"then\":["); if (!i.elseBranch().isEmpty()) {
List<StatementNode> thenBranch = i.thenBranch(); sb.append(",\"else\":").append(listToJsonArray(i.elseBranch(), ASTJsonSerializer::nodeToJson));
return getString(sb, thenBranch);
} }
private static String getString(StringBuilder sb, List<StatementNode> thenBranch) {
for (int j = 0; j < thenBranch.size(); j++) {
sb.append(nodeToJson(thenBranch.get(j)));
if (j + 1 < thenBranch.size()) sb.append(",");
}
sb.append("]}");
return sb.toString();
}
private static String loopToJson(LoopNode l) {
StringBuilder sb = new StringBuilder();
sb.append("{\"type\":\"Loop\",")
.append("\"initializer\":").append(nodeToJson(l.initializer())).append(",")
.append("\"condition\":").append(exprToJson(l.condition())).append(",")
.append("\"update\":").append(nodeToJson(l.update())).append(",")
.append("\"body\":[");
List<StatementNode> body = l.body();
return getString(sb, body);
}
private static String returnToJson(ReturnNode r) {
StringBuilder sb = new StringBuilder();
sb.append("{\"type\":\"Return\"");
r.getExpression().ifPresent(expr ->
sb.append(",\"value\":").append(exprToJson(expr))
);
sb.append("}"); sb.append("}");
return sb.toString(); return sb.toString();
} }
private static String exprStmtToJson(ExpressionStatementNode es) { private static String loopToJson(LoopNode l) {
return "{\"type\":\"ExpressionStatement\",\"expression\":" return "{" +
+ exprToJson(es.expression()) "\"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()) +
"}";
} }
private static String exprToJson(ExpressionNode expr) { private static String exprToJson(ExpressionNode expr) {
if (expr instanceof BinaryExpressionNode b) return binaryToJson(b); if (expr instanceof BinaryExpressionNode b) return binaryToJson(b);
if (expr instanceof IdentifierNode id) return idToJson(id); if (expr instanceof IdentifierNode id) return idToJson(id);
if (expr instanceof NumberLiteralNode num) return numToJson(num); if (expr instanceof NumberLiteralNode n) return numToJson(n);
if (expr instanceof StringLiteralNode str) return strToJson(str); if (expr instanceof StringLiteralNode s) return strToJson(s);
if (expr instanceof CallExpressionNode c) return callToJson(c); if (expr instanceof CallExpressionNode c) return callToJson(c);
if (expr instanceof MemberExpressionNode m) return memberToJson(m); if (expr instanceof MemberExpressionNode m) return memberToJson(m);
// fallback return simpleTypeJson(expr.getClass().getSimpleName());
return "{\"type\":\"" + expr.getClass().getSimpleName() + "\"}";
} }
private static String binaryToJson(BinaryExpressionNode b) { private static String binaryToJson(BinaryExpressionNode b) {
return "{\"type\":\"BinaryExpression\"," return "{" +
+ "\"left\":" + exprToJson(b.left()) + "," "\"type\":\"BinaryExpression\"," +
+ "\"operator\":" + quote(b.operator()) + "," "\"left\":" + exprToJson(b.left()) + "," +
+ "\"right\":" + exprToJson(b.right()) "\"operator\":" + quote(b.operator()) + "," +
+ "}"; "\"right\":" + exprToJson(b.right()) +
} "}";
private static String idToJson(IdentifierNode id) {
return "{\"type\":\"Identifier\",\"name\":" + quote(id.name()) + "}";
}
private static String numToJson(NumberLiteralNode num) {
return "{\"type\":\"NumberLiteral\",\"value\":" + quote(num.value()) + "}";
}
private static String strToJson(StringLiteralNode str) {
return "{\"type\":\"StringLiteral\",\"value\":" + quote(str.value()) + "}";
}
private static String callToJson(CallExpressionNode c) {
StringBuilder sb = new StringBuilder();
sb.append("{\"type\":\"CallExpression\",\"callee\":")
.append(exprToJson(c.callee())).append(",")
.append("\"arguments\":[");
for (int i = 0; i < c.arguments().size(); i++) {
sb.append(exprToJson(c.arguments().get(i)));
if (i + 1 < c.arguments().size()) sb.append(",");
}
sb.append("]}");
return sb.toString();
}
private static String memberToJson(MemberExpressionNode m) {
return "{\"type\":\"MemberExpression\",\"object\":"
+ exprToJson(m.object())
+ ",\"member\":" + quote(m.member())
+ "}";
} }
/** private static String idToJson(IdentifierNode id) {
* 将字符串转换为合法的 JSON 字符串常量添加双引号并进行必要的转义 return "{" +
* "\"type\":\"Identifier\"," +
* @param s 原始字符串 "\"name\":" + quote(id.name()) +
* @return 转义并加双引号的 JSON 字符串 "}";
*/ private static String quote(String s) { }
private static String numToJson(NumberLiteralNode n) {
return "{" +
"\"type\":\"NumberLiteral\"," +
"\"value\":" + quote(n.value()) +
"}";
}
private static String strToJson(StringLiteralNode s) {
return "{" +
"\"type\":\"StringLiteral\"," +
"\"value\":" + quote(s.value()) +
"}";
}
private static String callToJson(CallExpressionNode c) {
return "{" +
"\"type\":\"CallExpression\"," +
"\"callee\":" + exprToJson(c.callee()) + "," +
"\"arguments\":" + listToJsonArray(c.arguments(), ASTJsonSerializer::exprToJson) +
"}";
}
private static String memberToJson(MemberExpressionNode m) {
return "{" +
"\"type\":\"MemberExpression\"," +
"\"object\":" + exprToJson(m.object()) + "," +
"\"member\":" + quote(m.member()) +
"}";
}
// ========= 辅助函数 =========
private static String simpleTypeJson(String typeName) {
return "{" + "\"type\":" + quote(typeName) + "}";
}
private static <T> String listToJsonArray(List<T> list, java.util.function.Function<T, String> mapper) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("\""); 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 String quote(String s) {
StringBuilder sb = new StringBuilder();
sb.append('"');
for (char c : s.toCharArray()) { for (char c : s.toCharArray()) {
switch (c) { switch (c) {
case '\\': sb.append("\\\\"); break; case '\\': sb.append("\\\\"); break;
@ -214,7 +189,7 @@ public class ASTJsonSerializer {
default: sb.append(c); default: sb.append(c);
} }
} }
sb.append("\""); sb.append('"');
return sb.toString(); return sb.toString();
} }
} }

121
test
View File

@ -52,6 +52,7 @@ module: MainModule
end body end body
end function end function
function: main function: main
parameter: parameter:
declare args: string declare args: string
@ -73,63 +74,6 @@ module: MainModule
body: body:
if i % 2 == 0 then if i % 2 == 0 then
BuiltinUtils.print("i is even: " + BuiltinUtils.to_string(i)) BuiltinUtils.print("i is even: " + BuiltinUtils.to_string(i))
if i > 2 then
BuiltinUtils.print("i is greater than 2")
loop:
initializer:
declare k: int = 0
condition:
k < 3
update:
k = k + 1
body:
BuiltinUtils.print("k = " + BuiltinUtils.to_string(k))
if k == 2 then
BuiltinUtils.print("k is two")
loop:
initializer:
declare n: int = 0
condition:
n < 2
update:
n = n + 1
body:
BuiltinUtils.print("n = " + BuiltinUtils.to_string(n))
if n == 1 then
BuiltinUtils.print("n is one")
if i > 3 then
BuiltinUtils.print("deep i > 3 block")
loop:
initializer:
declare x: int = 0
condition:
x < 2
update:
x = x + 1
body:
if x == 1 then
BuiltinUtils.print("x is one at depth")
else
BuiltinUtils.print("x is zero at depth")
end if
end body
end loop
end if
end if
end body
end loop
end if
end body
end loop
end if
else else
BuiltinUtils.print("i is odd: " + BuiltinUtils.to_string(i)) BuiltinUtils.print("i is odd: " + BuiltinUtils.to_string(i))
@ -142,64 +86,12 @@ module: MainModule
j = j + 1 j = j + 1
body: body:
if j == 1 then if j == 1 then
BuiltinUtils.print("first inner") BuiltinUtils.print(" first inner")
else else
if j % 2 == 0 then if j % 2 == 0 then
BuiltinUtils.print("j even") BuiltinUtils.print(" j even")
if j > 2 then
BuiltinUtils.print("j > 2, deeper if")
loop:
initializer:
declare y: int = 0
condition:
y < 2
update:
y = y + 1
body:
BuiltinUtils.print("y in deep even j loop: " + BuiltinUtils.to_string(y))
if y == 1 then
BuiltinUtils.print("y is one")
end if
end body
end loop
end if
else else
BuiltinUtils.print("j odd") BuiltinUtils.print(" j odd")
loop:
initializer:
declare m: int = 0
condition:
m < 2
update:
m = m + 1
body:
BuiltinUtils.print("m = " + BuiltinUtils.to_string(m))
if m == 1 then
BuiltinUtils.print("m is one")
if j > 3 then
BuiltinUtils.print("j > 3, going deeper")
loop:
initializer:
declare z: int = 0
condition:
z < 2
update:
z = z + 1
body:
BuiltinUtils.print("z = " + BuiltinUtils.to_string(z))
end body
end loop
end if
end if
end body
end loop
end if end if
end if end if
end body end body
@ -208,7 +100,7 @@ module: MainModule
declare sum: int = CommonTasks.add_numbers(i, 10) declare sum: int = CommonTasks.add_numbers(i, 10)
declare squared: int = MathUtils.square_number(sum) declare squared: int = MathUtils.square_number(sum)
BuiltinUtils.print("i+10 squared = " + BuiltinUtils.to_string(squared)) BuiltinUtils.print(" i+10 squared = " + BuiltinUtils.to_string(squared))
end body end body
end loop end loop
@ -217,7 +109,4 @@ module: MainModule
end body end body
end function end function
end module end module