增加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.ast.Node;
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.nio.charset.StandardCharsets;
@ -32,14 +34,14 @@ public class Main {
// 3. 可读地打印 AST
ASTPrinter.print(ast);
// // 1) 输出紧凑 JSON
// String compact = ASTJsonSerializer.toJsonString(ast);
// 1) 输出紧凑 JSON
String compact = ASTJsonSerializer.toJsonString(ast);
// System.out.println("=== Compact JSON ===");
// System.out.println(compact);
//
// // 2) 输出美化后的 JSON
// System.out.println("=== Pretty JSON ===");
// System.out.println(JsonFormatter.prettyPrint(compact));
// 2) 输出美化后的 JSON
System.out.println("=== Pretty JSON ===");
System.out.println(JsonFormatter.prettyPrint(compact));
}
}

View File

@ -4,217 +4,192 @@ import org.jcnc.snow.compiler.parser.ast.*;
import java.util.List;
/**
* ASTJsonSerializer 是一个用于将抽象语法树AST序列化为 JSON 字符串的工具类
* 该类通过访问不同类型的语法树节点将其结构以标准 JSON 格式输出适用于调试可视化或进一步处理
* 更加健壮完整的 AST -> JSON 序列化器
*/
public class ASTJsonSerializer {
/**
* 将语法树节点列表序列化为 JSON 字符串
*
* @param ast 抽象语法树的节点列表
* @return 表示整个 AST JSON 字符串
*/
public static String toJsonString(List<Node> ast) {
return listToJsonArray(ast.stream().map(ASTJsonSerializer::nodeToJson).toList());
}
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());
}
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) +
"}";
}
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) +
"}";
}
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 + "}";
}
private static String assignmentToJson(AssignmentNode a) {
return "{" +
"\"type\":\"Assignment\"," +
"\"variable\":" + quote(a.variable()) + "," +
"\"value\":" + 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));
}
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()) +
"}";
}
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());
}
private static String binaryToJson(BinaryExpressionNode b) {
return "{" +
"\"type\":\"BinaryExpression\"," +
"\"left\":" + exprToJson(b.left()) + "," +
"\"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 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();
sb.append("[");
for (int i = 0; i < ast.size(); i++) {
sb.append(nodeToJson(ast.get(i)));
if (i + 1 < ast.size()) 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 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 es)
return exprStmtToJson(es);
// fallback仅输出类型名
return "{\"type\":\"" + n.getClass().getSimpleName() + "\"}";
private static String listToJsonArray(List<String> list) {
return listToJsonArray(list, s -> s);
}
private static String moduleToJson(ModuleNode m) {
private static String quote(String s) {
StringBuilder sb = new StringBuilder();
sb.append("{\"type\":\"Module\",")
.append("\"name\":").append(quote(m.name())).append(",");
// imports
sb.append("\"imports\":[");
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) {
StringBuilder sb = new StringBuilder();
sb.append("{\"type\":\"Function\",")
.append("\"name\":").append(quote(f.name())).append(",");
// parameters
sb.append("\"parameters\":[");
for (int i = 0; i < f.parameters().size(); i++) {
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) {
StringBuilder sb = new StringBuilder();
sb.append("{\"type\":\"Declaration\",")
.append("\"name\":").append(quote(d.getName())).append(",")
.append("\"varType\":").append(quote(d.getType()));
d.getInitializer().ifPresent(init ->
sb.append(",\"initializer\":").append(exprToJson(init))
);
sb.append("}");
return sb.toString();
}
private static String assignmentToJson(AssignmentNode a) {
return "{\"type\":\"Assignment\",\"variable\":"
+ quote(a.variable())
+ ",\"value\":"
+ 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\":[");
List<StatementNode> thenBranch = i.thenBranch();
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("}");
return sb.toString();
}
private static String exprStmtToJson(ExpressionStatementNode es) {
return "{\"type\":\"ExpressionStatement\",\"expression\":"
+ exprToJson(es.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 num) return numToJson(num);
if (expr instanceof StringLiteralNode str) return strToJson(str);
if (expr instanceof CallExpressionNode c) return callToJson(c);
if (expr instanceof MemberExpressionNode m) return memberToJson(m);
// fallback
return "{\"type\":\"" + expr.getClass().getSimpleName() + "\"}";
}
private static String binaryToJson(BinaryExpressionNode b) {
return "{\"type\":\"BinaryExpression\","
+ "\"left\":" + exprToJson(b.left()) + ","
+ "\"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())
+ "}";
}
/**
* 将字符串转换为合法的 JSON 字符串常量添加双引号并进行必要的转义
*
* @param s 原始字符串
* @return 转义并加双引号的 JSON 字符串
*/ private static String quote(String s) {
StringBuilder sb = new StringBuilder();
sb.append("\"");
sb.append('"');
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("\\\""); break;
case '\n': sb.append("\\n"); break;
case '\r': sb.append("\\r"); break;
case '\t': sb.append("\\t"); break;
default: sb.append(c);
}
}
sb.append("\"");
sb.append('"');
return sb.toString();
}
}

191
test
View File

@ -52,172 +52,61 @@ module: MainModule
end body
end function
function: main
parameter:
declare args: string
return_type: void
body:
declare input_number: int = BuiltinUtils.to_int(args)
if input_number <= 0 then
input_number = 5
end if
function: main
parameter:
declare args: string
return_type: void
body:
declare input_number: int = BuiltinUtils.to_int(args)
loop:
initializer:
declare i: int = 0
condition:
i < input_number
update:
i = i + 1
body:
if i % 2 == 0 then
BuiltinUtils.print("i is even: " + BuiltinUtils.to_string(i))
if input_number <= 0 then
input_number = 5
end if
if i > 2 then
BuiltinUtils.print("i is greater than 2")
loop:
initializer:
declare i: int = 0
condition:
i < input_number
update:
i = i + 1
body:
if i % 2 == 0 then
BuiltinUtils.print("i is even: " + BuiltinUtils.to_string(i))
else
BuiltinUtils.print("i is odd: " + BuiltinUtils.to_string(i))
loop:
initializer:
declare k: int = 0
declare j: int = 0
condition:
k < 3
j < i
update:
k = k + 1
j = j + 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
if j == 1 then
BuiltinUtils.print(" first inner")
else
if j % 2 == 0 then
BuiltinUtils.print(" j even")
else
BuiltinUtils.print(" j odd")
end if
end if
end body
end loop
end if
else
BuiltinUtils.print("i is odd: " + BuiltinUtils.to_string(i))
declare sum: int = CommonTasks.add_numbers(i, 10)
declare squared: int = MathUtils.square_number(sum)
BuiltinUtils.print(" i+10 squared = " + BuiltinUtils.to_string(squared))
end body
end loop
loop:
initializer:
declare j: int = 0
condition:
j < i
update:
j = j + 1
body:
if j == 1 then
BuiltinUtils.print("first inner")
else
if j % 2 == 0 then
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
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 body
end loop
end if
declare sum: int = CommonTasks.add_numbers(i, 10)
declare squared: int = MathUtils.square_number(sum)
BuiltinUtils.print("i+10 squared = " + BuiltinUtils.to_string(squared))
end body
end loop
declare final_message: string = StringUtils.concatenate("Finished with input: ", BuiltinUtils.to_string(input_number))
BuiltinUtils.print(final_message)
end body
declare final_message: string = StringUtils.concatenate("Finished with input: ", BuiltinUtils.to_string(input_number))
BuiltinUtils.print(final_message)
end body
end function
end module