diff --git a/src/main/java/org/jcnc/snow/compiler/JsonFormatter.java b/src/main/java/org/jcnc/snow/compiler/JsonFormatter.java
index 4ae2e3c..5c1a41f 100644
--- a/src/main/java/org/jcnc/snow/compiler/JsonFormatter.java
+++ b/src/main/java/org/jcnc/snow/compiler/JsonFormatter.java
@@ -1,26 +1,44 @@
package org.jcnc.snow.compiler;
+/**
+ * JSON 格式化工具类。
+ * 提供将紧凑 JSON 字符串美化为带缩进和换行的易读格式的方法。
+ */
public class JsonFormatter {
+
/**
* 对一个紧凑的 JSON 字符串进行缩进美化。
- * @param json 紧凑的 JSON
- * @return 带换行和缩进的 JSON
+ * 例如:
+ *
{@code
+ * {"a":1,"b":[2,3]} →
+ * {
+ * "a": 1,
+ * "b": [
+ * 2,
+ * 3
+ * ]
+ * }
+ * }
+ *
+ * @param json 紧凑的 JSON 字符串。
+ * @return 格式化后的 JSON 字符串,带有缩进与换行。
*/
public static String prettyPrint(String json) {
StringBuilder sb = new StringBuilder();
int indent = 0;
boolean inQuotes = false;
+
for (int i = 0; i < json.length(); i++) {
char c = json.charAt(i);
- // 切换引号状态(忽略转义的 \")
+
+ // 检查是否进入或退出字符串(忽略转义的引号)
if (c == '"' && (i == 0 || json.charAt(i - 1) != '\\')) {
inQuotes = !inQuotes;
sb.append(c);
} else if (!inQuotes) {
switch (c) {
case '{', '[':
- sb.append(c)
- .append('\n');
+ sb.append(c).append('\n');
indent++;
appendIndent(sb, indent);
break;
@@ -31,8 +49,7 @@ public class JsonFormatter {
sb.append(c);
break;
case ',':
- sb.append(c)
- .append('\n');
+ sb.append(c).append('\n');
appendIndent(sb, indent);
break;
case ':':
@@ -44,14 +61,21 @@ public class JsonFormatter {
}
}
} else {
- // 在字符串内原样输出
+ // 字符串内部原样输出
sb.append(c);
}
}
+
return sb.toString();
}
+ /**
+ * 向字符串构建器追加指定层级的缩进。
+ *
+ * @param sb 输出目标。
+ * @param indent 缩进层级(每层为两个空格)。
+ */
private static void appendIndent(StringBuilder sb, int indent) {
- sb.append(" ".repeat(Math.max(0, indent))); // 两个空格
+ sb.append(" ".repeat(Math.max(0, indent)));
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ParserEngine.java b/src/main/java/org/jcnc/snow/compiler/parser/ParserEngine.java
index 2dca672..fe6ee54 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ParserEngine.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ParserEngine.java
@@ -10,31 +10,48 @@ import java.util.ArrayList;
import java.util.List;
/**
- * 解析引擎入口:循环读取顶层块直到 EOF,自动跳过空行(NEWLINE)。
+ * 解析器主引擎,负责驱动顶层结构(如 module)解析。
+ * 它会循环处理每个顶层语法块,直到遇到 EOF。
+ * 同时自动跳过空行(NEWLINE)以增强容错性。
*/
public class ParserEngine {
private final ParserContext ctx;
+ /**
+ * 构造解析器引擎。
+ *
+ * @param ctx 解析上下文,封装了 Token 流等解析状态。
+ */
public ParserEngine(ParserContext ctx) {
this.ctx = ctx;
}
+ /**
+ * 启动解析流程,返回顶层节点列表(模块、导入等)。
+ *
+ * @return 所有解析出的 AST 顶层节点。
+ */
public List parse() {
List nodes = new ArrayList<>();
TokenStream ts = ctx.getTokens();
+
while (ts.isAtEnd()) {
- // 跳过空行(NEWLINE)
+ // 跳过空行
if (ts.peek().getType() == TokenType.NEWLINE) {
ts.next();
continue;
}
+
+ // 根据当前关键字分发顶层解析器
String lex = ts.peek().getLexeme();
- TopLevelParser p = TopLevelParserFactory.get(lex);
- if (p == null) {
+ TopLevelParser parser = TopLevelParserFactory.get(lex);
+ if (parser == null) {
throw new IllegalStateException("Unexpected top-level token: " + lex);
}
- nodes.add(p.parse(ctx));
+
+ nodes.add(parser.parse(ctx));
}
+
return nodes;
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/TopLevelParser.java b/src/main/java/org/jcnc/snow/compiler/parser/TopLevelParser.java
index 926394c..1e3de17 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/TopLevelParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/TopLevelParser.java
@@ -4,8 +4,16 @@ import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.ast.Node;
/**
- * 顶层解析器接口,如 module、import 等。
+ * 顶层结构解析器接口,用于解析模块级别的语法结构,如 {@code module}、{@code import} 等。
+ * 所有顶层解析器应实现该接口。
*/
public interface TopLevelParser {
+
+ /**
+ * 从解析上下文中解析一个顶层语法结构。
+ *
+ * @param ctx 当前解析上下文。
+ * @return 表示顶层结构的 AST 节点。
+ */
Node parse(ParserContext ctx);
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ASTJsonSerializer.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ASTJsonSerializer.java
index 65920f5..31a3595 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ASTJsonSerializer.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ASTJsonSerializer.java
@@ -2,8 +2,19 @@ package org.jcnc.snow.compiler.parser.ast;
import java.util.List;
+
+/**
+ * ASTJsonSerializer 是一个用于将抽象语法树(AST)序列化为 JSON 字符串的工具类。
+ * 该类通过访问不同类型的语法树节点,将其结构以标准 JSON 格式输出,适用于调试、可视化或进一步处理。
+ */
public class ASTJsonSerializer {
+ /**
+ * 将语法树节点列表序列化为 JSON 字符串。
+ *
+ * @param ast 抽象语法树的节点列表。
+ * @return 表示整个 AST 的 JSON 字符串。
+ */
public static String toJsonString(List ast) {
StringBuilder sb = new StringBuilder();
sb.append("[");
@@ -189,8 +200,12 @@ public class ASTJsonSerializer {
+ "}";
}
- /** 把 Java 字符串内容转成 JSON 字符串常量(加双引号并转义) */
- private static String quote(String s) {
+ /**
+ * 将字符串转换为合法的 JSON 字符串常量(添加双引号并进行必要的转义)。
+ *
+ * @param s 原始字符串。
+ * @return 转义并加双引号的 JSON 字符串。
+ */ private static String quote(String s) {
StringBuilder sb = new StringBuilder();
sb.append("\"");
for (char c : s.toCharArray()) {
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ASTPrinter.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ASTPrinter.java
index 8ca04d1..df2018b 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ASTPrinter.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ASTPrinter.java
@@ -3,17 +3,30 @@ package org.jcnc.snow.compiler.parser.ast;
import java.util.List;
/**
- * 一个简单的 AST 打印器,将所有节点格式化成可读的多行文本。
+ * AST 打印器,用于将抽象语法树(AST)中的节点打印为可读的、格式化的多行文本。
+ * 每个节点根据其类型和结构打印相应的缩进层级,便于人类阅读和调试。
*/
public class ASTPrinter {
+
+ /**
+ * 打印整个语法树的节点列表。
+ *
+ * @param nodes 要打印的 AST 节点列表,通常是顶层模块或语句。
+ */
public static void print(List nodes) {
for (Node n : nodes) {
print(n, 0);
}
}
+ /**
+ * 打印单个节点及其子节点,带有缩进格式。
+ *
+ * @param n 要打印的节点。
+ * @param indent 当前的缩进层级(每层两个空格)。
+ */
private static void print(Node n, int indent) {
- String pad = " ".repeat(indent);
+ String pad = " ".repeat(indent); // 缩进字符串
switch (n) {
case ModuleNode m -> {
@@ -65,9 +78,10 @@ public class ASTPrinter {
}
case ReturnNode r -> System.out.println(pad + "return" +
r.getExpression().map(e -> " " + e).orElse(""));
- case ExpressionStatementNode(ExpressionNode expression) -> System.out.println(pad + expression);
+ case ExpressionStatementNode(ExpressionNode expression) ->
+ System.out.println(pad + expression);
case null, default ->
- // 回退:直接调用 toString()
+ // 回退:如果节点类型不在上述范围内,则使用 toString()
System.out.println(pad + n);
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java
index 734b375..c65aea0 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/AssignmentNode.java
@@ -1,10 +1,18 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * 赋值语句节点,例如 x = expr。
+ * 表示赋值语句的 AST(抽象语法树)节点,例如 {@code x = expr}。
+ *
+ * @param variable 赋值语句左侧的变量名。
+ * @param value 赋值语句右侧的表达式节点,表示要赋给变量的值。
*/
public record AssignmentNode(String variable, ExpressionNode value) implements StatementNode {
+ /**
+ * 返回赋值语句的字符串表示形式,例如 {@code x = y + 1}。
+ *
+ * @return 表示赋值语句的字符串。
+ */
@Override
public String toString() {
return variable + " = " + value;
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java
index bba717e..fef5cd2 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/BinaryExpressionNode.java
@@ -1,11 +1,21 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * 二元运算表达式节点,如 a + b。
+ * 表示二元运算表达式的 AST 节点,例如 {@code a + b}。
+ * 该节点包含一个左操作数、一个操作符字符串和一个右操作数。
+ *
+ * @param left 表达式左侧的子表达式。
+ * @param operator 运算符字符串,例如 "+"、"-"、"*"、"/" 等。
+ * @param right 表达式右侧的子表达式。
*/
public record BinaryExpressionNode(ExpressionNode left, String operator,
ExpressionNode right) implements ExpressionNode {
+ /**
+ * 返回该二元表达式的字符串表示形式,例如 {@code a + b}。
+ *
+ * @return 表达式的字符串形式。
+ */
@Override
public String toString() {
return left + " " + operator + " " + right;
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java
index d567fa6..d9a908f 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/CallExpressionNode.java
@@ -3,10 +3,19 @@ package org.jcnc.snow.compiler.parser.ast;
import java.util.List;
/**
- * 函数调用表达式节点:callee(args…)。
+ * 表示函数调用表达式的 AST 节点,例如 {@code foo(arg1, arg2)}。
+ * 包含一个被调用的表达式(callee)和一个参数列表(arguments)。
+ *
+ * @param callee 被调用的表达式,通常是一个标识符或成员访问表达式。
+ * @param arguments 函数调用的参数列表,每个参数都是一个表达式节点。
*/
public record CallExpressionNode(ExpressionNode callee, List arguments) implements ExpressionNode {
+ /**
+ * 返回函数调用表达式的字符串表示形式,例如 {@code foo(x, y)}。
+ *
+ * @return 表达式的字符串形式。
+ */
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java
index aab840c..82b7be7 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/DeclarationNode.java
@@ -3,20 +3,45 @@ package org.jcnc.snow.compiler.parser.ast;
import java.util.Optional;
/**
- * declare 语句节点:声明变量,可选初始化表达式。
+ * 表示变量声明语句的 AST 节点,例如 {@code int x = 5;}。
+ * 该节点包含变量名称、类型,以及可选的初始化表达式。
*/
public class DeclarationNode implements StatementNode {
private final String name;
private final String type;
private final Optional initializer;
+ /**
+ * 构造一个变量声明节点。
+ *
+ * @param name 变量的名称。
+ * @param type 变量的类型(例如 "int", "string")。
+ * @param initializer 可选的初始化表达式,若为 null 表示未初始化。
+ */
public DeclarationNode(String name, String type, ExpressionNode initializer) {
this.name = name;
this.type = type;
this.initializer = Optional.ofNullable(initializer);
}
+ /**
+ * 获取变量名称。
+ *
+ * @return 变量名字符串。
+ */
public String getName() { return name; }
+
+ /**
+ * 获取变量类型。
+ *
+ * @return 变量类型字符串。
+ */
public String getType() { return type; }
+
+ /**
+ * 获取可选的初始化表达式。
+ *
+ * @return 包含初始化表达式的 Optional 对象,可能为空。
+ */
public Optional getInitializer() { return initializer; }
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionNode.java
index 5aceece..62ebab1 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionNode.java
@@ -1,6 +1,8 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * 标记所有表达式节点。
+ * 表示抽象语法树中的表达式节点类型。
+ * 所有具体的表达式(如常量、变量、运算、函数调用等)都应实现该接口。
+ * 这是一个标记接口(marker interface),用于统一处理所有表达式节点。
*/
public interface ExpressionNode extends Node {}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java
index c5b7eb7..e446a82 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ExpressionStatementNode.java
@@ -1,7 +1,10 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * 单独的表达式语句节点(如函数调用、赋值等)。
+ * 表示一条独立的表达式语句,例如 {@code foo();} 或 {@code x = 1;}。
+ * 该节点将一个表达式作为语句出现。
+ *
+ * @param expression 表达式内容,通常是函数调用或赋值操作。
*/
public record ExpressionStatementNode(ExpressionNode expression) implements StatementNode {
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java
index cf36cf0..f213345 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/FunctionNode.java
@@ -3,7 +3,13 @@ package org.jcnc.snow.compiler.parser.ast;
import java.util.List;
/**
- * 函数定义节点:包含函数名、参数列表、返回类型和函数体语句列表。
+ * 表示函数定义的 AST 节点,包含函数名、参数、返回类型和函数体。
+ * 示例:{@code int add(int a, int b) { return a + b; }}
+ *
+ * @param name 函数名称。
+ * @param parameters 参数列表,每个参数是一个 {@link ParameterNode}。
+ * @param returnType 返回值类型,表示函数的返回类型(例如 "int"、"void")。
+ * @param body 函数体,由若干语句组成的列表。
*/
public record FunctionNode(String name, List parameters, String returnType,
List body) implements Node {
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java
index 4f3af86..e50f8e5 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/IdentifierNode.java
@@ -1,9 +1,17 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * 标识符表达式节点。
+ * 表示标识符的表达式节点,例如变量名 {@code x}、函数名 {@code foo} 等。
+ *
+ * @param name 标识符的名称。
*/
public record IdentifierNode(String name) implements ExpressionNode {
+
+ /**
+ * 返回标识符的字符串表示形式,即其名称。
+ *
+ * @return 标识符名称字符串。
+ */
@Override
public String toString() {
return name;
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java
index 5f993e5..351537d 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/IfNode.java
@@ -3,7 +3,12 @@ package org.jcnc.snow.compiler.parser.ast;
import java.util.List;
/**
- * if 语句节点:包含条件表达式和 then 分支语句列表。
+ * 表示 if 语句的 AST 节点。
+ * 包含一个条件表达式和一个 then 分支的语句列表,不包含 else 分支。
+ * 示例:{@code if (x > 0) { print(x); }}
+ *
+ * @param condition 条件表达式,控制是否执行 then 分支。
+ * @param thenBranch 条件为真时执行的语句列表。
*/
public record IfNode(ExpressionNode condition, List thenBranch) implements StatementNode {
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java
index fca6340..865ee00 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ImportNode.java
@@ -1,7 +1,11 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * import 语句节点:仅保存被导入模块名。
+ * 表示 import 语句的 AST 节点。
+ * 该节点仅包含被导入模块的名称。
+ * 示例:{@code import my.module;}
+ *
+ * @param moduleName 被导入的模块名称。
*/
public record ImportNode(String moduleName) implements Node {
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java
index 42e3d2f..4d7548f 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/LoopNode.java
@@ -3,7 +3,19 @@ package org.jcnc.snow.compiler.parser.ast;
import java.util.List;
/**
- * loop 语句节点:包含初始化语句、条件表达式、更新语句和循环体。
+ * 表示循环语句(loop)的 AST 节点,结构类似于传统的 for 循环。
+ * 包含初始化语句、循环条件、更新语句和循环体。
+ * 示例:
+ * {@code
+ * for (int i = 0; i < 10; i++) {
+ * print(i);
+ * }
+ * }
+ *
+ * @param initializer 循环开始前执行的初始化语句。
+ * @param condition 每次迭代前都会评估的条件表达式。
+ * @param update 每次迭代结束时执行的更新语句。
+ * @param body 循环体内的语句列表。
*/
public record LoopNode(StatementNode initializer, ExpressionNode condition, StatementNode update,
List body) implements StatementNode {
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java
index 3846a30..14c2277 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/MemberExpressionNode.java
@@ -1,9 +1,19 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * 成员访问表达式节点,如 obj.prop。
+ * 表示成员访问的表达式节点,例如 {@code obj.prop}。
+ * 包含一个对象表达式和成员名称。
+ *
+ * @param object 表达式左侧的对象部分,通常是一个标识符或更复杂的表达式。
+ * @param member 成员名称,表示要访问的字段或方法。
*/
public record MemberExpressionNode(ExpressionNode object, String member) implements ExpressionNode {
+
+ /**
+ * 返回成员访问表达式的字符串表示形式,例如 {@code obj.prop}。
+ *
+ * @return 成员访问表达式的字符串形式。
+ */
@Override
public String toString() {
return object + "." + member;
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java
index 8bfa9e2..9e44581 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java
@@ -1,16 +1,29 @@
-// File: src/main/java/org/jcnc/snow/compiler/parser/ast/ModuleNode.java
package org.jcnc.snow.compiler.parser.ast;
import java.util.List;
import java.util.StringJoiner;
/**
- * 模块定义节点:包含模块名、import 列表和函数列表。
+ * 表示模块定义的 AST 节点。
+ * 一个模块通常由模块名、导入语句列表和函数定义列表组成。
+ * 示例结构:
+ * {@code
+ * module my.module {
+ * import other.module;
+ * fun foo() { ... }
+ * }
+ * }
+ *
+ * @param name 模块名称。
+ * @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。
+ * @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。
*/
public record ModuleNode(String name, List imports, List functions) implements Node {
/**
- * 返回模块的字符串表示,便于调试和打印。
+ * 返回模块节点的字符串表示形式,包含模块名、导入模块列表和函数列表。
+ *
+ * @return 模块的简洁字符串表示,用于调试和日志输出。
*/
@Override
public String toString() {
@@ -23,7 +36,7 @@ public record ModuleNode(String name, List imports, List
+ * {@code return;}
+ * {@code return x + 1;}
+ *
*/
public class ReturnNode implements StatementNode {
private final Optional expression;
+ /**
+ * 构造一个 return 语句节点。
+ *
+ * @param expression 可选的返回表达式,若为 null 则表示无返回值。
+ */
public ReturnNode(ExpressionNode expression) {
this.expression = Optional.ofNullable(expression);
}
- public Optional getExpression() { return expression; }
+ /**
+ * 获取返回表达式。
+ *
+ * @return 表示返回值的可选表达式,如果没有则为 {@code Optional.empty()}。
+ */
+ public Optional getExpression() {
+ return expression;
+ }
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/StatementNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/StatementNode.java
index 0ee1141..0cbea88 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/StatementNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/StatementNode.java
@@ -1,6 +1,8 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * 标记所有语句节点。
+ * 表示语法树中的语句节点类型。
+ * 所有语句类(如声明、赋值、if、loop、return 等)都应实现该接口。
+ * 这是一个标记接口(marker interface),用于统一处理所有语句节点。
*/
public interface StatementNode extends Node {}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java
index 01d7b5e..2a13739 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/StringLiteralNode.java
@@ -1,15 +1,18 @@
package org.jcnc.snow.compiler.parser.ast;
/**
- * 字符串字面量表达式节点,如 "hello"。
+ * 表示字符串字面量的表达式节点,例如 {@code "hello"}。
+ * 字面量值不包含引号,仅在打印时添加。
*
- * @param value 不包含引号的字符串内容
+ * @param value 字符串内容,不包括两端引号。
*/
public record StringLiteralNode(String value) implements ExpressionNode {
/**
- * 打印时在两端加上引号,
- * 例如 value = Result:,则 toString() 返回 "Result:"。
+ * 返回带引号的字符串表示形式,适用于调试和打印。
+ * 例如:如果 {@code value = Result:},则 {@code toString()} 返回 {@code "Result:"}。
+ *
+ * @return 添加双引号后的字符串字面量。
*/
@Override
public String toString() {
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java b/src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java
index ebdb0d3..bc382d3 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/context/ParseException.java
@@ -1,9 +1,16 @@
package org.jcnc.snow.compiler.parser.context;
/**
- * 解析时抛出的异常,用于语法错误报告。
+ * 表示解析过程中发生的异常,通常用于报告语法错误。
+ * 在语法分析器发现非法语法或无法处理的结构时抛出。
*/
public class ParseException extends RuntimeException {
+
+ /**
+ * 构造一个解析异常实例,并提供错误消息。
+ *
+ * @param message 错误描述信息,用于指出语法错误的详情。
+ */
public ParseException(String message) {
super(message);
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/context/ParserContext.java b/src/main/java/org/jcnc/snow/compiler/parser/context/ParserContext.java
index 1c9bf75..90384a2 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/context/ParserContext.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/context/ParserContext.java
@@ -4,15 +4,26 @@ import org.jcnc.snow.compiler.lexer.token.Token;
import java.util.List;
/**
- * Parser 共享上下文,包含 TokenStream,可扩展错误收集、符号表等功能。
+ * 表示解析器的共享上下文,封装了当前的 {@link TokenStream}。
+ * 后续还可以扩展为包含错误收集器、符号表、作用域信息等。
*/
public class ParserContext {
private final TokenStream tokens;
+ /**
+ * 构造解析上下文,并包装传入的词法单元列表为 {@link TokenStream}。
+ *
+ * @param tokens 词法分析器生成的 token 列表。
+ */
public ParserContext(List tokens) {
this.tokens = new TokenStream(tokens);
}
+ /**
+ * 获取当前的 Token 流,用于驱动语法解析过程。
+ *
+ * @return token 流实例。
+ */
public TokenStream getTokens() {
return tokens;
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/context/TokenStream.java b/src/main/java/org/jcnc/snow/compiler/parser/context/TokenStream.java
index ac76751..a8066b6 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/context/TokenStream.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/context/TokenStream.java
@@ -6,18 +6,29 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
import java.util.List;
/**
- * 封装 Token 列表并维护当前位置,提供 peek/next/match/expect 等操作,
- * 现在新增 peek(offset) 以便在解析赋值时向前看一个 Token。
+ * 封装 Token 列表并维护当前位置,用于解析器消费 Token 的工具类。
+ * 提供常见的操作如 {@code peek}(查看)、{@code next}(消费)、{@code match}(匹配)、
+ * {@code expect}(断言)等,支持向前查看多个 Token 以实现前瞻解析。
*/
public class TokenStream {
private final List tokens;
private int pos = 0;
+ /**
+ * 构造 Token 流对象。
+ *
+ * @param tokens 从词法分析器生成的 Token 列表。
+ */
public TokenStream(List tokens) {
this.tokens = tokens;
}
- /** 向前 offset 个位置的 Token,不消费 */
+ /**
+ * 向前查看指定偏移量的 Token(不消费)。
+ *
+ * @param offset 相对于当前位置的偏移量(例如 0 表示当前位置)。
+ * @return 对应位置的 Token,如果越界则返回 EOF Token。
+ */
public Token peek(int offset) {
int idx = pos + offset;
if (idx >= tokens.size()) {
@@ -26,19 +37,32 @@ public class TokenStream {
return tokens.get(idx);
}
- /** 默认 peek(0) */
+ /**
+ * 查看当前位置的 Token,等价于 {@code peek(0)}。
+ *
+ * @return 当前 Token。
+ */
public Token peek() {
return peek(0);
}
- /** 消费并返回当前 Token */
+ /**
+ * 消费并返回当前位置的 Token,内部位置前移。
+ *
+ * @return 当前的 Token。
+ */
public Token next() {
Token t = peek();
pos++;
return t;
}
- /** 如果当前词素等于 lexeme,则消费并返回 true */
+ /**
+ * 如果当前 Token 的词素等于指定字符串,则消费该 Token 并返回 true。
+ *
+ * @param lexeme 要匹配的词素。
+ * @return 是否成功匹配。
+ */
public boolean match(String lexeme) {
if (peek().getLexeme().equals(lexeme)) {
next();
@@ -47,7 +71,13 @@ public class TokenStream {
return false;
}
- /** 断言 lexeme,否则抛错 */
+ /**
+ * 断言当前 Token 的词素等于指定字符串,否则抛出 {@link ParseException}。
+ *
+ * @param lexeme 期望的词素。
+ * @return 匹配的 Token。
+ * @throws ParseException 如果词素不匹配。
+ */
public Token expect(String lexeme) {
Token t = peek();
if (!t.getLexeme().equals(lexeme)) {
@@ -59,7 +89,13 @@ public class TokenStream {
return next();
}
- /** 断言类型,否则抛错 */
+ /**
+ * 断言当前 Token 的类型等于指定类型,否则抛出 {@link ParseException}。
+ *
+ * @param type 期望的 Token 类型。
+ * @return 匹配的 Token。
+ * @throws ParseException 如果类型不匹配。
+ */
public Token expectType(TokenType type) {
Token t = peek();
if (t.getType() != type) {
@@ -71,6 +107,11 @@ public class TokenStream {
return next();
}
+ /**
+ * 判断是否还未到达文件结尾(EOF)。
+ *
+ * @return 如果当前位置的 Token 不是 EOF,则返回 true。
+ */
public boolean isAtEnd() {
return peek().getType() != TokenType.EOF;
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java
index 77142df..13a8f06 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/BinaryOperatorParselet.java
@@ -6,29 +6,48 @@ import org.jcnc.snow.compiler.lexer.token.Token;
import org.jcnc.snow.compiler.parser.context.ParserContext;
/**
- * 解析二元运算符表达式,支持左/右结合。
+ * 表示中缀二元运算符的解析规则(parselet),用于解析如 {@code a + b} 的表达式结构。
+ * 支持设置运算符的优先级和结合性(左结合或右结合)。
*/
public class BinaryOperatorParselet implements InfixParselet {
private final Precedence precedence;
private final boolean leftAssoc;
+ /**
+ * 构造二元运算符的解析器。
+ *
+ * @param precedence 运算符的优先级。
+ * @param leftAssoc 是否是左结合(true 表示左结合,false 表示右结合)。
+ */
public BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) {
this.precedence = precedence;
this.leftAssoc = leftAssoc;
}
+ /**
+ * 解析一个中缀表达式。
+ *
+ * @param ctx 解析上下文,包含 Token 流等信息。
+ * @param left 当前已解析出的左表达式。
+ * @return 一个新的 {@link BinaryExpressionNode} 表达式节点。
+ */
@Override
public ExpressionNode parse(ParserContext ctx, ExpressionNode left) {
- Token op = ctx.getTokens().next();
+ Token op = ctx.getTokens().next(); // 获取当前运算符 Token
int prec = precedence.ordinal();
- // 若左结合,则右侧优先级减一
+ // 如果是左结合运算符,右表达式的优先级应减一(右边绑定更紧)
ExpressionNode right = new PrattExpressionParser().parseExpression(
- ctx,
- leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]
+ ctx,
+ leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]
);
return new BinaryExpressionNode(left, op.getLexeme(), right);
}
+ /**
+ * 返回该运算符的优先级。
+ *
+ * @return 当前运算符的优先级枚举。
+ */
@Override
public Precedence getPrecedence() {
return precedence;
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java
index 965862c..8a90214 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/CallParselet.java
@@ -8,23 +8,40 @@ import java.util.ArrayList;
import java.util.List;
/**
- * 解析函数调用:left ( args… )
+ * 表示函数调用的解析规则(parselet),用于解析形如 {@code foo(arg1, arg2)} 的调用表达式。
+ * 函数调用的结构为:已解析的 callee 表达式后接一对圆括号和参数列表。
*/
public class CallParselet implements InfixParselet {
+
+ /**
+ * 解析函数调用表达式,形如 {@code callee(args...)}。
+ *
+ * @param ctx 解析上下文,包含 Token 流等信息。
+ * @param left 已解析的函数名或调用目标(即 callee 表达式)。
+ * @return 生成的 {@link CallExpressionNode} 表达式节点。
+ */
@Override
public ExpressionNode parse(ParserContext ctx, ExpressionNode left) {
- // 已知 peek 是 "("
- ctx.getTokens().next(); // consume "("
+ ctx.getTokens().next(); // 消费 "("
+
List args = new ArrayList<>();
+
+ // 如果不是空参数列表
if (!ctx.getTokens().peek().getLexeme().equals(")")) {
do {
args.add(new PrattExpressionParser().parse(ctx));
- } while (ctx.getTokens().match(","));
+ } while (ctx.getTokens().match(",")); // 支持多个参数,用逗号分隔
}
- ctx.getTokens().expect(")");
+
+ ctx.getTokens().expect(")"); // 消费并校验 ")"
return new CallExpressionNode(left, args);
}
+ /**
+ * 获取函数调用的优先级,通常是最高级别之一。
+ *
+ * @return {@link Precedence#CALL} 表示函数调用的绑定紧密度。
+ */
@Override
public Precedence getPrecedence() {
return Precedence.CALL;
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/ExpressionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/ExpressionParser.java
index 7bf554c..fa8138f 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/ExpressionParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/ExpressionParser.java
@@ -4,8 +4,16 @@ import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
import org.jcnc.snow.compiler.parser.context.ParserContext;
/**
- * 表达式解析接口。
+ * 表达式解析器接口,用于从 {@link ParserContext} 中解析出一个完整的 {@link ExpressionNode} 表达式。
+ * 不同的解析器实现可以支持不同的解析策略(如 Pratt 解析、递归下降等)。
*/
public interface ExpressionParser {
+
+ /**
+ * 从解析上下文中解析一个表达式。
+ *
+ * @param ctx 当前的解析上下文。
+ * @return 解析后的表达式节点。
+ */
ExpressionNode parse(ParserContext ctx);
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/GroupingParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/GroupingParselet.java
index d7dbc7d..2db4d4a 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/GroupingParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/GroupingParselet.java
@@ -5,9 +5,18 @@ import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
import org.jcnc.snow.compiler.parser.context.ParserContext;
/**
- * 解析括号表达式: ( expr )
+ * 解析圆括号包裹的表达式,例如 {@code (a + b)}。
+ * 用于提升子表达式的优先级,使其在整体表达式中优先计算。
*/
public class GroupingParselet implements PrefixParselet {
+
+ /**
+ * 解析括号表达式。假定当前 token 是左括号 "(",解析中间的表达式并消费右括号 ")"。
+ *
+ * @param ctx 当前解析上下文。
+ * @param token 当前起始 token(应为 "(")。
+ * @return 被括号包围的表达式节点。
+ */
@Override
public ExpressionNode parse(ParserContext ctx, Token token) {
ExpressionNode expr = new PrattExpressionParser().parse(ctx);
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java
index 790d31e..af6fd9f 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/IdentifierParselet.java
@@ -6,9 +6,18 @@ import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
import org.jcnc.snow.compiler.parser.context.ParserContext;
/**
- * 解析标识符。
+ * 用于解析标识符(identifier)的前缀解析器。
+ * 例如:变量名、函数名等单词形式的表达式,如 {@code x}、{@code count}、{@code isValid} 等。
*/
public class IdentifierParselet implements PrefixParselet {
+
+ /**
+ * 将当前的标识符 Token 解析为 {@link IdentifierNode} 表达式节点。
+ *
+ * @param ctx 当前解析上下文(未使用)。
+ * @param token 当前的标识符 Token。
+ * @return 一个表示标识符的表达式节点。
+ */
@Override
public ExpressionNode parse(ParserContext ctx, Token token) {
return new IdentifierNode(token.getLexeme());
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/InfixParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/InfixParselet.java
index 3b9a430..42c30ce 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/InfixParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/InfixParselet.java
@@ -4,9 +4,26 @@ import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
import org.jcnc.snow.compiler.parser.context.ParserContext;
/**
- * 中缀解析器接口:处理二元运算、函数调用、成员访问等。
+ * 中缀解析器接口(InfixParselet),用于处理中缀表达式的解析逻辑。
+ * 例如二元运算符(如 {@code a + b})、函数调用(如 {@code f(x)})或成员访问(如 {@code obj.prop})。
+ * 实现类需提供解析方法及该表达式的优先级。
*/
public interface InfixParselet {
+
+ /**
+ * 解析一个中缀表达式。
+ *
+ * @param ctx 解析上下文。
+ * @param left 当前已解析的左侧表达式。
+ * @return 组合后的完整表达式节点。
+ */
ExpressionNode parse(ParserContext ctx, ExpressionNode left);
+
+ /**
+ * 获取当前中缀表达式的优先级。
+ * 优先级用于决定运算符的绑定顺序。
+ *
+ * @return 表达式的优先级。
+ */
Precedence getPrecedence();
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java
index 9e24470..6fc405e 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/MemberParselet.java
@@ -7,21 +7,35 @@ import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.context.TokenStream;
/**
- * 解析成员访问表达式: left . IDENTIFIER
+ * 用于解析成员访问表达式的中缀解析器,例如 {@code object.property}。
+ * 成员访问是一种紧绑定表达式,常用于访问对象的字段或方法。
*/
public class MemberParselet implements InfixParselet {
+
+ /**
+ * 解析成员访问表达式,形如 {@code left.member}。
+ *
+ * @param ctx 解析上下文。
+ * @param left 已解析的左侧表达式(对象)。
+ * @return 一个 {@link MemberExpressionNode} 表示成员访问的表达式。
+ */
@Override
public ExpressionNode parse(ParserContext ctx, ExpressionNode left) {
TokenStream ts = ctx.getTokens();
- // 消费掉 "."
- ts.expect(".");
- // 现在下一个一定是标识符
+ ts.expect("."); // 消费点号
+ // 接下来应为标识符
String member = ts
.expectType(TokenType.IDENTIFIER)
.getLexeme();
return new MemberExpressionNode(left, member);
}
+ /**
+ * 获取成员访问表达式的优先级。
+ * 与函数调用一样,通常具有较高的优先级。
+ *
+ * @return {@link Precedence#CALL},表示高优先级。
+ */
@Override
public Precedence getPrecedence() {
return Precedence.CALL;
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java
index 5077f63..68403b2 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/NumberLiteralParselet.java
@@ -6,9 +6,18 @@ import org.jcnc.snow.compiler.parser.ast.ExpressionNode;
import org.jcnc.snow.compiler.parser.context.ParserContext;
/**
- * 解析数字字面量。
+ * 用于解析数字字面量的前缀解析器。
+ * 例如 {@code 42}、{@code 3.14} 等常量数值表达式。
*/
public class NumberLiteralParselet implements PrefixParselet {
+
+ /**
+ * 解析一个数字字面量 Token,转换为 {@link NumberLiteralNode} 表达式节点。
+ *
+ * @param ctx 当前解析上下文(未使用)。
+ * @param token 当前的数字 Token。
+ * @return 表示数字字面量的表达式节点。
+ */
@Override
public ExpressionNode parse(ParserContext ctx, Token token) {
return new NumberLiteralNode(token.getLexeme());
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java
index dd0d740..de7af9f 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java
@@ -9,45 +9,61 @@ import java.util.HashMap;
import java.util.Map;
/**
- * Pratt 算法实现的表达式解析器,支持算术、比较、调用、成员访问、字面量等。
+ * 基于 Pratt 算法的表达式解析器,实现灵活优雅的运算符优先级与结合性处理。
+ * 支持数字、字符串、标识符、分组表达式、二元运算、函数调用、成员访问等。
*/
public class PrattExpressionParser implements ExpressionParser {
+
private static final Map prefixes = new HashMap<>();
private static final Map infixes = new HashMap<>();
static {
- // 注册前缀 parselet
+ // 注册前缀解析器(PrefixParselet)
prefixes.put(TokenType.NUMBER_LITERAL.name(), new NumberLiteralParselet());
prefixes.put(TokenType.IDENTIFIER.name(), new IdentifierParselet());
prefixes.put(TokenType.LPAREN.name(), new GroupingParselet());
- prefixes.put(TokenType.STRING_LITERAL.name(), new StringLiteralParselet()); // 新增
+ prefixes.put(TokenType.STRING_LITERAL.name(), new StringLiteralParselet()); // 字符串字面量支持
- // 注册中缀 parselet(略,保持原样)
- infixes.put("+", new BinaryOperatorParselet(Precedence.SUM, true));
- infixes.put("-", new BinaryOperatorParselet(Precedence.SUM, true));
- infixes.put("*", new BinaryOperatorParselet(Precedence.PRODUCT, true));
- infixes.put("/", new BinaryOperatorParselet(Precedence.PRODUCT, true));
+ // 注册中缀解析器(InfixParselet)
+ infixes.put("+", new BinaryOperatorParselet(Precedence.SUM, true));
+ infixes.put("-", new BinaryOperatorParselet(Precedence.SUM, true));
+ infixes.put("*", new BinaryOperatorParselet(Precedence.PRODUCT, true));
+ infixes.put("/", new BinaryOperatorParselet(Precedence.PRODUCT, true));
infixes.put(">", new BinaryOperatorParselet(Precedence.SUM, true));
infixes.put("<", new BinaryOperatorParselet(Precedence.SUM, true));
infixes.put("==", new BinaryOperatorParselet(Precedence.SUM, true));
infixes.put("!=", new BinaryOperatorParselet(Precedence.SUM, true));
infixes.put(">=", new BinaryOperatorParselet(Precedence.SUM, true));
infixes.put("<=", new BinaryOperatorParselet(Precedence.SUM, true));
- infixes.put("(", new CallParselet());
- infixes.put(".", new MemberParselet());
+ infixes.put("(", new CallParselet());
+ infixes.put(".", new MemberParselet());
}
+ /**
+ * 解析完整表达式,入口方法,使用最低优先级启动解析。
+ *
+ * @param ctx 解析上下文。
+ * @return 表达式节点。
+ */
@Override
public ExpressionNode parse(ParserContext ctx) {
return parseExpression(ctx, Precedence.LOWEST);
}
+ /**
+ * 根据当前优先级解析表达式。
+ *
+ * @param ctx 解析上下文。
+ * @param prec 当前解析优先级。
+ * @return 表达式节点。
+ */
ExpressionNode parseExpression(ParserContext ctx, Precedence prec) {
Token token = ctx.getTokens().next();
PrefixParselet prefix = prefixes.get(token.getType().name());
if (prefix == null) {
- throw new IllegalStateException("No prefix for " + token.getType());
+ throw new IllegalStateException("No prefix parselet registered for token type: " + token.getType());
}
+
ExpressionNode left = prefix.parse(ctx, token);
while (ctx.getTokens().isAtEnd() &&
@@ -55,11 +71,19 @@ public class PrattExpressionParser implements ExpressionParser {
String lex = ctx.getTokens().peek().getLexeme();
InfixParselet infix = infixes.get(lex);
if (infix == null) break;
+
left = infix.parse(ctx, left);
}
+
return left;
}
+ /**
+ * 获取下一个中缀运算符的优先级。
+ *
+ * @param ctx 当前解析上下文。
+ * @return 若存在下一个中缀解析器,则返回其优先级 ordinal;否则返回 -1。
+ */
private int nextPrecedence(ParserContext ctx) {
InfixParselet infix = infixes.get(ctx.getTokens().peek().getLexeme());
return infix != null ? infix.getPrecedence().ordinal() : -1;
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java
index a706e19..5b53746 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/Precedence.java
@@ -1,11 +1,27 @@
package org.jcnc.snow.compiler.parser.expression;
/**
- * 运算符优先级枚举,用于 Pratt 算法比较。
+ * 表示运算符优先级的枚举类型,用于 Pratt 解析算法中比较不同运算符的绑定紧密度。
+ * 数值越大,优先级越高。
*/
public enum Precedence {
- LOWEST, // 最低
- SUM, // + -
- PRODUCT, // * /
- CALL // 函数调用、成员访问
+ /**
+ * 最低优先级,通常用于解析入口。
+ */
+ LOWEST,
+
+ /**
+ * 加法、减法等二元运算(+,-)。
+ */
+ SUM,
+
+ /**
+ * 乘法、除法等优先级更高的二元运算(*,/)。
+ */
+ PRODUCT,
+
+ /**
+ * 函数调用、成员访问(例如 {@code foo()}、{@code obj.prop}),绑定最紧密。
+ */
+ CALL
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrefixParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrefixParselet.java
index 444f07c..dc2a3e8 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrefixParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrefixParselet.java
@@ -5,8 +5,17 @@ import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.lexer.token.Token;
/**
- * 前缀解析器接口:处理数字字面量、标识符、括号等前缀。
+ * 前缀解析器接口(PrefixParselet),用于解析以当前 Token 开头的前缀表达式。
+ * 典型的前缀表达式包括数字字面量、标识符、括号表达式、前缀运算符等。
*/
public interface PrefixParselet {
+
+ /**
+ * 解析一个前缀表达式。
+ *
+ * @param ctx 当前的解析上下文。
+ * @param token 当前的前缀 Token。
+ * @return 解析得到的表达式节点。
+ */
ExpressionNode parse(ParserContext ctx, Token token);
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java
index 2f0b2dc..e020981 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/StringLiteralParselet.java
@@ -6,15 +6,23 @@ import org.jcnc.snow.compiler.parser.ast.StringLiteralNode;
import org.jcnc.snow.compiler.parser.context.ParserContext;
/**
- * 解析字符串字面量前缀,并去掉两端的引号。
+ * 用于解析字符串字面量的前缀解析器。
+ * 会从原始 Token 中提取内容,并去除两端的引号。
+ * 例如,Token 为 {@code "\"hello\""},则解析为 {@code StringLiteralNode("hello")}。
*/
public class StringLiteralParselet implements PrefixParselet {
+
+ /**
+ * 解析字符串字面量 Token,去除包裹的引号,生成 {@link StringLiteralNode}。
+ *
+ * @param ctx 当前解析上下文(未使用)。
+ * @param token 当前字符串字面量 Token,包含带引号的原始文本。
+ * @return 解析后的字符串字面量表达式节点。
+ */
@Override
public ExpressionNode parse(ParserContext ctx, Token token) {
- // token.getRaw() 包含原始 "\"Result:\""
- String raw = token.getRaw();
- // 去掉首尾引号
- String content = raw.substring(1, raw.length() - 1);
+ String raw = token.getRaw(); // 包含引号的原始字符串,例如 "\"Result:\""
+ String content = raw.substring(1, raw.length() - 1); // 去除前后引号
return new StringLiteralNode(content);
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java b/src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java
index 9e62c54..bc12474 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/factory/StatementParserFactory.java
@@ -1,24 +1,34 @@
package org.jcnc.snow.compiler.parser.factory;
import org.jcnc.snow.compiler.parser.statement.*;
+
import java.util.Map;
import java.util.HashMap;
/**
- * 语句解析器工厂:关键字 → 对应 StatementParser。
+ * 语句解析器工厂类,用于根据关键字(如 "if"、"loop")返回对应的 {@link StatementParser} 实例。
+ * 所有语句解析器在静态代码块中预先注册。
+ * 若关键字未注册,则默认返回 {@link ExpressionStatementParser}(空字符串对应)。
*/
public class StatementParserFactory {
private static final Map registry = new HashMap<>();
static {
+ // 注册各类语句解析器
registry.put("declare", new DeclarationStatementParser());
registry.put("if", new IfStatementParser());
registry.put("loop", new LoopStatementParser());
registry.put("return", new ReturnStatementParser());
- // 默认使用表达式语句
+ // 默认解析器:表达式语句
registry.put("", new ExpressionStatementParser());
}
+ /**
+ * 根据语句关键字获取对应的语句解析器。
+ *
+ * @param keyword 语句开头的关键字,例如 "if"、"loop"、"declare"。
+ * @return 对应的 {@link StatementParser} 实例,若无匹配则返回默认解析器。
+ */
public static StatementParser get(String keyword) {
return registry.getOrDefault(keyword, registry.get(""));
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java b/src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java
index 71c68b8..99b7d35 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/factory/TopLevelParserFactory.java
@@ -7,16 +7,25 @@ import java.util.Map;
import java.util.HashMap;
/**
- * 顶层解析器工厂:根据首个关键字(如 module)分发对应解析器。
+ * 顶层解析器工厂类,用于根据文件开头的关键字(如 {@code module})分发对应的顶层结构解析器。
+ * 每种顶层结构(模块、导入等)应有一个专门的 {@link TopLevelParser} 实现类。
*/
public class TopLevelParserFactory {
private static final Map registry = new HashMap<>();
static {
+ // 注册模块解析器
registry.put("module", new ModuleParser());
- // 如需支持 standalone import,可在此注册
+
+ // import、package 在此添加注册项
}
+ /**
+ * 根据顶层关键字获取对应的解析器。
+ *
+ * @param keyword 顶层结构的关键字(如 "module")。
+ * @return 对应的 {@link TopLevelParser} 实例;若未注册,则返回 null。
+ */
public static TopLevelParser get(String keyword) {
return registry.get(keyword);
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java
index 03476b8..8d6de5d 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java
@@ -11,14 +11,29 @@ import java.util.ArrayList;
import java.util.List;
/**
- * 解析 function 块:
- * function: NAME NEWLINE
- * parameter: (declare name:type | name:type)*
- * return_type: TYPE NEWLINE
- * body: ... end body
- * end function NEWLINE
+ * 用于解析函数定义块(function),包括函数名、参数列表、返回类型、函数体等。
+ * 支持的语法结构示例:
+ * {@code
+ * function: myFunc
+ * parameter:
+ * declare a:int
+ * b:int
+ * return_type: int
+ * body:
+ * declare x:int = 10
+ * return x
+ * end body
+ * end function
+ * }
*/
public class FunctionParser implements TopLevelParser {
+
+ /**
+ * 解析一个函数定义并返回对应的 {@link FunctionNode}。
+ *
+ * @param ctx 解析上下文。
+ * @return 解析生成的函数节点。
+ */
@Override
public FunctionNode parse(ParserContext ctx) {
TokenStream ts = ctx.getTokens();
@@ -27,7 +42,7 @@ public class FunctionParser implements TopLevelParser {
String name = ts.expectType(TokenType.IDENTIFIER).getLexeme();
ts.expectType(TokenType.NEWLINE);
- // 参数列表
+ // 解析参数列表
ts.expect("parameter");
ts.expect(":");
ts.expectType(TokenType.NEWLINE);
@@ -41,7 +56,7 @@ public class FunctionParser implements TopLevelParser {
break;
}
if ("declare".equals(ts.peek().getLexeme())) {
- ts.next(); // consume 'declare'
+ ts.next(); // 支持 declare 前缀
}
String paramName = ts.expectType(TokenType.IDENTIFIER).getLexeme();
ts.expect(":");
@@ -50,25 +65,25 @@ public class FunctionParser implements TopLevelParser {
params.add(new ParameterNode(paramName, paramType));
}
- // 返回类型
+ // 解析返回类型
ts.expect("return_type");
ts.expect(":");
String returnType = ts.expectType(TokenType.TYPE).getLexeme();
ts.expectType(TokenType.NEWLINE);
- // 函数体解析
+ // 解析函数体
ts.expect("body");
ts.expect(":");
ts.expectType(TokenType.NEWLINE);
List body = new ArrayList<>();
parseBody(ctx, body);
- // end body
+ // 解析函数体结束标识
ts.expect("end");
ts.expect("body");
ts.expectType(TokenType.NEWLINE);
- // end function
+ // 解析函数定义结束标识
ts.expect("end");
ts.expect("function");
ts.expectType(TokenType.NEWLINE);
@@ -77,7 +92,10 @@ public class FunctionParser implements TopLevelParser {
}
/**
- * 辅助方法:根据 ParserContext 解析函数体中所有语句,直到遇到 end
+ * 辅助方法:从上下文中解析函数体,直到遇到 "end"。
+ *
+ * @param ctx 当前解析上下文。
+ * @param body 存放解析出的语句节点的列表。
*/
private void parseBody(ParserContext ctx, List body) {
TokenStream ts = ctx.getTokens();
@@ -90,7 +108,8 @@ public class FunctionParser implements TopLevelParser {
break;
}
String key = ts.peek().getLexeme();
- body.add(StatementParserFactory.get(key).parse(ctx));
+ StatementNode stmt = StatementParserFactory.get(key).parse(ctx);
+ body.add(stmt);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java b/src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java
index 6f0465b..2b6ead4 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/module/ImportParser.java
@@ -8,27 +8,36 @@ import java.util.ArrayList;
import java.util.List;
/**
- * 解析 import 语句:import: MOD1, MOD2, ... NEWLINE
- * 可以在一行声明多个模块,用逗号分隔。
+ * 负责解析 import 语句的解析器。
+ * 支持在一行中导入多个模块,格式如:
+ * {@code import: mod1, mod2, mod3}
*/
public class ImportParser {
+
/**
- * 读取一行 import 声明,返回多个 ImportNode
+ * 解析一条 import 声明语句,返回对应的 {@link ImportNode} 列表。
+ * 格式必须为:{@code import: MODULE[, MODULE]* NEWLINE}
+ *
+ * @param ctx 当前的解析上下文。
+ * @return 所有被导入模块的节点列表。
*/
public List parse(ParserContext ctx) {
ctx.getTokens().expect("import");
ctx.getTokens().expect(":");
+
List imports = new ArrayList<>();
- // 读取第一个模块名
- // 继续读取逗号分隔的模块名
+
+ // 读取第一个模块名,然后继续读取逗号分隔的模块名
do {
String mod = ctx.getTokens()
.expectType(TokenType.IDENTIFIER)
.getLexeme();
imports.add(new ImportNode(mod));
} while (ctx.getTokens().match(","));
- // 消费行尾
+
+ // 消费行尾换行符
ctx.getTokens().expectType(TokenType.NEWLINE);
+
return imports;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java b/src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java
index 8a469e2..5a8a018 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/module/ModuleParser.java
@@ -13,12 +13,24 @@ import java.util.ArrayList;
import java.util.List;
/**
- * 解析 module 块:
- * module: NAME NEWLINE
- * (import… | function… )*
- * end module NEWLINE
+ * 模块解析器,用于解析形如 module 块的顶层结构。
+ * 语法示例:
+ * {@code
+ * module: my.module
+ * import: mod1, mod2
+ * function: ...
+ * end module
+ * }
+ * 支持导入语句和多个函数定义,允许中间包含空行。
*/
public class ModuleParser implements TopLevelParser {
+
+ /**
+ * 解析模块定义块,返回 {@link ModuleNode} 表示模块结构。
+ *
+ * @param ctx 解析上下文。
+ * @return 模块节点,包含模块名、导入列表和函数列表。
+ */
@Override
public ModuleNode parse(ParserContext ctx) {
TokenStream ts = ctx.getTokens();
@@ -32,17 +44,18 @@ public class ModuleParser implements TopLevelParser {
ImportParser importParser = new ImportParser();
FunctionParser funcParser = new FunctionParser();
- // 解析导入和函数,支持空行
+ // 解析模块体:包含 import 和 function 语句
while (true) {
// 跳过空行
if (ts.peek().getType() == TokenType.NEWLINE) {
ts.next();
continue;
}
- // 如果遇到 end,跳出循环
+ // 遇到 "end" 表示模块结束
if ("end".equals(ts.peek().getLexeme())) {
break;
}
+
String lex = ts.peek().getLexeme();
if ("import".equals(lex)) {
imports.addAll(importParser.parse(ctx));
@@ -53,9 +66,11 @@ public class ModuleParser implements TopLevelParser {
}
}
+ // 结束模块块结构
ts.expect("end");
ts.expect("module");
ts.expectType(TokenType.NEWLINE);
+
return new ModuleNode(name, imports, functions);
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java
index 38e13f6..ce6c816 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/DeclarationStatementParser.java
@@ -7,24 +7,47 @@ import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
/**
- * 解析 declare 语句: declare name:type (= expr)? NEWLINE
+ * 解析变量声明语句的解析器。
+ * 支持语法格式:
+ * {@code
+ * declare name:type
+ * declare name:type = expression
+ * }
+ * 每条语句必须以换行(NEWLINE)结束。
*/
public class DeclarationStatementParser implements StatementParser {
+
+ /**
+ * 解析一条 declare 声明语句。
+ *
+ * @param ctx 当前解析上下文。
+ * @return 构造好的 {@link DeclarationNode} AST 节点。
+ */
@Override
public DeclarationNode parse(ParserContext ctx) {
ctx.getTokens().expect("declare");
+
+ // 获取变量名
String name = ctx.getTokens()
- .expectType(TokenType.IDENTIFIER)
- .getLexeme();
+ .expectType(TokenType.IDENTIFIER)
+ .getLexeme();
+
ctx.getTokens().expect(":");
+
+ // 获取变量类型
String type = ctx.getTokens()
- .expectType(TokenType.TYPE)
- .getLexeme();
+ .expectType(TokenType.TYPE)
+ .getLexeme();
+
+ // 可选初始化表达式
ExpressionNode init = null;
if (ctx.getTokens().match("=")) {
init = new PrattExpressionParser().parse(ctx);
}
+
+ // 声明语句必须以 NEWLINE 结束
ctx.getTokens().expectType(TokenType.NEWLINE);
+
return new DeclarationNode(name, type, init);
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java
index c0fdca6..128b7b9 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/ExpressionStatementParser.java
@@ -10,27 +10,38 @@ import org.jcnc.snow.compiler.parser.context.TokenStream;
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
/**
- * 将任意表达式或赋值当作语句:
- * identifier = expr NEWLINE
- * expr NEWLINE
+ * 表达式语句解析器:将赋值表达式或任意表达式作为语句进行解析。
+ * 支持的形式包括:
+ *
+ * identifier = expression
+ * expression
+ *
+ * 两者都必须以换行(NEWLINE)结尾。
*/
public class ExpressionStatementParser implements StatementParser {
+
+ /**
+ * 解析一个表达式语句,可能是赋值语句或普通表达式。
+ *
+ * @param ctx 当前的解析上下文。
+ * @return 表达式语句节点或赋值语句节点。
+ */
@Override
public StatementNode parse(ParserContext ctx) {
TokenStream ts = ctx.getTokens();
- // 先检测赋值语句:IDENTIFIER '=' ...
+ // 检查是否是赋值形式(identifier = expr)
if (ts.peek().getType() == TokenType.IDENTIFIER
&& ts.peek(1).getLexeme().equals("=")) {
- String varName = ts.next().getLexeme(); // consume identifier
- ts.expect("="); // consume '='
+ String varName = ts.next().getLexeme(); // 消费 identifier
+ ts.expect("="); // 消费 '='
ExpressionNode value = new PrattExpressionParser().parse(ctx);
ts.expectType(TokenType.NEWLINE);
return new AssignmentNode(varName, value);
}
- // 否则当作普通表达式语句
+ // 否则解析为普通表达式语句
ExpressionNode expr = new PrattExpressionParser().parse(ctx);
ts.expectType(TokenType.NEWLINE);
return new ExpressionStatementNode(expr);
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java
index c1e8102..64bf84a 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/IfStatementParser.java
@@ -11,23 +11,41 @@ import java.util.ArrayList;
import java.util.List;
/**
- * 解析 if 语句: if expr then NEWLINE stmts end if NEWLINE
+ * if 语句解析器,支持基本格式:
+ * {@code
+ * if condition then
+ * statements...
+ * end if
+ * }
+ * 不支持 else 分支,仅支持 then 分支。
*/
public class IfStatementParser implements StatementParser {
+
+ /**
+ * 解析 if 表达式,并构造 {@link IfNode}。
+ *
+ * @param ctx 当前解析上下文。
+ * @return 表示 if 语句的 AST 节点。
+ */
@Override
public IfNode parse(ParserContext ctx) {
ctx.getTokens().expect("if");
+
+ // 解析条件表达式
var cond = new PrattExpressionParser().parse(ctx);
+
ctx.getTokens().expect("then");
ctx.getTokens().expectType(TokenType.NEWLINE);
+ // 解析 then 分支的语句块
List thenBranch = new ArrayList<>();
while (!ctx.getTokens().peek().getLexeme().equals("end")) {
- thenBranch.add(
- StatementParserFactory.get(ctx.getTokens().peek().getLexeme()).parse(ctx)
- );
+ String keyword = ctx.getTokens().peek().getLexeme();
+ StatementNode stmt = StatementParserFactory.get(keyword).parse(ctx);
+ thenBranch.add(stmt);
}
+ // 匹配 end if 结束语句
ctx.getTokens().expect("end");
ctx.getTokens().expect("if");
ctx.getTokens().expectType(TokenType.NEWLINE);
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java
index 6dff091..fc855b2 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/LoopStatementParser.java
@@ -14,16 +14,29 @@ import java.util.ArrayList;
import java.util.List;
/**
- * 解析 loop 语句:
- * loop: NEWLINE
- * initializer: … NEWLINE
- * condition: … NEWLINE
- * update: … NEWLINE
- * body: … NEWLINE
- * end body NEWLINE
- * end loop NEWLINE
+ * 用于解析 loop 语句块,支持以下结构:
+ * {@code
+ * loop:
+ * initializer:
+ * declare i:int = 0
+ * condition:
+ * i < 10
+ * update:
+ * i = i + 1
+ * body:
+ * ...语句...
+ * end body
+ * end loop
+ * }
*/
public class LoopStatementParser implements StatementParser {
+
+ /**
+ * 解析一个完整的 loop 语句块,返回 {@link LoopNode}。
+ *
+ * @param ctx 当前的解析上下文。
+ * @return 表示 loop 结构的 AST 节点。
+ */
@Override
public LoopNode parse(ParserContext ctx) {
TokenStream ts = ctx.getTokens();
@@ -53,7 +66,7 @@ public class LoopStatementParser implements StatementParser {
ts.expectType(TokenType.NEWLINE);
skipNewlines(ts);
- // update (专用赋值解析):
+ // update:
ts.expect("update");
ts.expect(":");
ts.expectType(TokenType.NEWLINE);
@@ -90,7 +103,11 @@ public class LoopStatementParser implements StatementParser {
return new LoopNode(initializer, condition, update, body);
}
- /** 连续跳过所有空行(NEWLINE) */
+ /**
+ * 跳过连续的 NEWLINE token,用于容错和格式整洁。
+ *
+ * @param ts 当前的 Token 流。
+ */
private void skipNewlines(TokenStream ts) {
while (ts.peek().getType() == TokenType.NEWLINE) {
ts.next();
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java
index 5f34b02..286ca36 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/ReturnStatementParser.java
@@ -7,19 +7,35 @@ import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
/**
- * 解析 return 语句: return expr? NEWLINE
+ * 用于解析 return 语句。
+ * 支持有无返回值两种形式:
+ * {@code
+ * return
+ * return expression
+ * }
+ * 语句必须以换行符(NEWLINE)结束。
*/
public class ReturnStatementParser implements StatementParser {
+
+ /**
+ * 解析 return 语句并构建 {@link ReturnNode}。
+ *
+ * @param ctx 当前解析上下文。
+ * @return 表示 return 语句的 AST 节点。
+ */
@Override
public ReturnNode parse(ParserContext ctx) {
ctx.getTokens().expect("return");
+
ExpressionNode expr = null;
- // 如果下一个不是换行,就解析表达式
+
+ // 如果不是换行,说明有返回值
if (ctx.getTokens().peek().getType() != TokenType.NEWLINE) {
expr = new PrattExpressionParser().parse(ctx);
}
- // 用 expectType 来消费真正的 NEWLINE token
+
ctx.getTokens().expectType(TokenType.NEWLINE);
+
return new ReturnNode(expr);
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java b/src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java
index 20e6388..cb78a3e 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/statement/StatementParser.java
@@ -4,8 +4,16 @@ import org.jcnc.snow.compiler.parser.context.ParserContext;
import org.jcnc.snow.compiler.parser.ast.StatementNode;
/**
- * 语句解析器接口。
+ * 语句解析器接口,用于将解析上下文中的 Token 转换为 {@link StatementNode}。
+ * 各类语句(如声明、赋值、条件、循环、返回等)均应实现该接口。
*/
public interface StatementParser {
+
+ /**
+ * 从给定的解析上下文中解析出一个语句节点。
+ *
+ * @param ctx 当前的解析上下文。
+ * @return 表示语句的 AST 节点。
+ */
StatementNode parse(ParserContext ctx);
}