增加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,217 +4,192 @@ 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) {
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(); StringBuilder sb = new StringBuilder();
sb.append("["); sb.append("[");
for (int i = 0; i < ast.size(); i++) { for (int i = 0; i < list.size(); i++) {
sb.append(nodeToJson(ast.get(i))); sb.append(mapper.apply(list.get(i)));
if (i + 1 < ast.size()) sb.append(","); if (i + 1 < list.size()) sb.append(",");
} }
sb.append("]"); sb.append("]");
return sb.toString(); return sb.toString();
} }
private static String nodeToJson(Node n) { private static String listToJsonArray(List<String> list) {
if (n instanceof ModuleNode m) return moduleToJson(m); return listToJsonArray(list, s -> s);
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 moduleToJson(ModuleNode m) { private static String quote(String s) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("{\"type\":\"Module\",") sb.append('"');
.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("\"");
for (char c : s.toCharArray()) { for (char c : s.toCharArray()) {
switch (c) { switch (c) {
case '\\': sb.append("\\\\"); break; case '\\': sb.append("\\\\"); break;
case '"': sb.append("\\\""); break; case '"': sb.append("\\\""); break;
case '\n': sb.append("\\n"); break; case '\n': sb.append("\\n"); break;
case '\r': sb.append("\\r"); break; case '\r': sb.append("\\r"); break;
case '\t': sb.append("\\t"); break; case '\t': sb.append("\\t"); break;
default: sb.append(c); default: sb.append(c);
} }
} }
sb.append("\""); sb.append('"');
return sb.toString(); return sb.toString();
} }
} }

191
test
View File

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