diff --git a/src/main/java/org/jcnc/snow/compiler/Main.java b/src/main/java/org/jcnc/snow/compiler/Main.java index 272fbad..ab9fd7b 100644 --- a/src/main/java/org/jcnc/snow/compiler/Main.java +++ b/src/main/java/org/jcnc/snow/compiler/Main.java @@ -3,7 +3,7 @@ package org.jcnc.snow.compiler; import org.jcnc.snow.compiler.lexer.LexerEngine; import org.jcnc.snow.compiler.lexer.token.Token; import org.jcnc.snow.compiler.parser.ast.ASTModule; -import org.jcnc.snow.compiler.parser.ASTPrinter; +import org.jcnc.snow.compiler.parser.utils.ASTPrinter; import org.jcnc.snow.compiler.parser.ParserEngine; import java.io.IOException; diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ASTExpression.java b/src/main/java/org/jcnc/snow/compiler/parser/ASTExpression.java index 6633459..0a76af5 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ASTExpression.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ASTExpression.java @@ -1,8 +1,21 @@ package org.jcnc.snow.compiler.parser; /** - * 抽象的表达式节点基类,所有具体表达式都应继承此类。 + * 抽象表达式节点基类。所有具体的表达式类型(如标识符、字面量、 + * 二元运算等)都应继承此类,以便在语法树中统一表示表达式。 + * + *
子类示例: + *
在解析过程中,parseExpression 方法会创建具体的 ASTExpression 实例。 + * 后续阶段(如语义分析、代码生成)可通过 instanceof 或 Visitor 模式对 + * 不同子类进行处理。 + * */ public abstract class ASTExpression { - + // 该类仅作为标记类型,不包含公共字段或方法 } diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ASTStatement.java b/src/main/java/org/jcnc/snow/compiler/parser/ASTStatement.java index 8d3b638..57c6f28 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ASTStatement.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ASTStatement.java @@ -1,3 +1,15 @@ package org.jcnc.snow.compiler.parser; -public abstract class ASTStatement extends ASTNode {} +/** + * 抽象语句节点基类。所有语法树中的语句类型(如声明、返回、循环、条件等) + * 都应继承自此类,以便在解析器和后续处理(如语义分析、生成代码) + * 中统一识别和处理。 + * + *
ASTStatement 继承自 ASTNode,包含共通的节点属性和方法。 + * 具体子类需要实现各自的构造器及特定字段,并根据需要重写 + * Visitor 模式或其他遍历/处理逻辑。 + * + * @see ASTNode + */ +public abstract class ASTStatement extends ASTNode { +} \ No newline at end of file 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 a2777a4..2111d35 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/ParserEngine.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/ParserEngine.java @@ -8,16 +8,41 @@ import java.util.ArrayList; import java.util.List; /** - * 递归下降解析器,实现对模块、函数、语句和表达式的完整解析 + * 递归下降解析器,用于解析模块、函数、语句和表达式,并生成相应的AST节点。 + * + *
使用给定的词法分析器生成的令牌序列,对语法结构进行逐步匹配和构建。 + * 提供对模块(module)、函数(function)、参数(parameter)、声明(declare)、循环(loop)、 + * 条件(if)、返回(return)以及二元表达式的支持。 + * + *
抛出ASTBinaryOp.ParseException以报告解析错误。
*/
public class ParserEngine {
+ /** 令牌序列 */
private final List
+ * module: 模块开始标记
+ * IDENTIFIER: 模块名称
+ * end module: 模块结束标记
+ *
+ *
+ * @return 构建好的ASTModule节点
+ * @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
+ */
public ASTModule parseModule() {
match(TokenType.KEYWORD, "module");
match(TokenType.COLON);
@@ -36,6 +61,20 @@ public class ParserEngine {
return module;
}
+ /**
+ * 解析函数定义,包括参数列表、返回类型和函数体。
+ *
+ *
+ * function: 函数开始标记
+ * parameter (可选): 参数声明块
+ * return_type: 返回类型
+ * body: 函数体语句
+ * end function: 函数结束标记
+ *
+ *
+ * @return 构建好的ASTFunction节点
+ * @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
+ */
private ASTFunction parseFunction() {
match(TokenType.KEYWORD, "function");
match(TokenType.COLON);
@@ -76,6 +115,16 @@ public class ParserEngine {
return fn;
}
+ /**
+ * 解析单个参数声明。
+ *
+ *
+ * declare IDENTIFIER:type
+ *
+ *
+ * @return 构建好的ASTParameter节点
+ * @throws ASTBinaryOp.ParseException 当解析过程中出现不匹配或意外令牌时抛出
+ */
private ASTParameter parseParameter() {
match(TokenType.KEYWORD, "declare");
String name = current().getLexeme();
@@ -87,6 +136,13 @@ public class ParserEngine {
return new ASTParameter(name, type);
}
+ /**
+ * 解析一条语句,根据关键字分发到不同的解析器。
+ * 支持return、declare、loop和if语句。
+ *
+ * @return 对应的ASTStatement子类实例
+ * @throws ASTBinaryOp.ParseException 当无法识别语句类型时抛出
+ */
private ASTStatement parseStatement() {
if (peek(TokenType.KEYWORD, "return")) {
return parseReturn();
@@ -100,6 +156,11 @@ public class ParserEngine {
throw new ASTBinaryOp.ParseException("无法识别的语句:" + current());
}
+ /**
+ * 解析return语句。
+ *
+ * @return 构建好的ASTReturn节点,包含返回的表达式
+ */
private ASTReturn parseReturn() {
match(TokenType.KEYWORD, "return");
ASTExpression expr = parseExpression();
@@ -107,6 +168,11 @@ public class ParserEngine {
return new ASTReturn(expr);
}
+ /**
+ * 解析声明语句,可选带初始化表达式。
+ *
+ * @return 构建好的ASTDeclare节点,若无初始化则init为null
+ */
private ASTDeclare parseDeclare() {
match(TokenType.KEYWORD, "declare");
String name = current().getLexeme(); match(TokenType.IDENTIFIER);
@@ -123,6 +189,11 @@ public class ParserEngine {
}
}
+ /**
+ * 解析循环语句,包含初始化、条件、更新和循环体。
+ *
+ * @return 构建好的ASTLoop节点
+ */
private ASTLoop parseLoop() {
match(TokenType.KEYWORD, "loop"); match(TokenType.COLON);
match(TokenType.NEWLINE);
@@ -142,6 +213,11 @@ public class ParserEngine {
return new ASTLoop(init, cond, update, stmts);
}
+ /**
+ * 解析条件语句,仅支持单分支if。
+ *
+ * @return 构建好的ASTIf节点
+ */
private ASTIf parseIf() {
match(TokenType.KEYWORD, "if");
ASTExpression cond = parseExpression();
@@ -154,6 +230,13 @@ public class ParserEngine {
return new ASTIf(cond, thenStmts);
}
+ /**
+ * 解析表达式,支持标识符、整数字面量和加减乘除二元运算。
+ * 实现左递归消除,通过递归调用构建二元运算树。
+ *
+ * @return 构建好的ASTExpression子类实例
+ * @throws ASTBinaryOp.ParseException 当遇到意外令牌时抛出
+ */
private ASTExpression parseExpression() {
ASTExpression left;
Token t = current();
@@ -164,13 +247,13 @@ public class ParserEngine {
} else {
throw new ASTBinaryOp.ParseException("表达式解析错误,意外的令牌:" + t);
}
- // 处理二元运算
+ // 处理二元运算符
Token opTok = current();
String lex = opTok.getLexeme();
if (opTok.getType() == TokenType.PLUS
- || opTok.getType() == TokenType.MINUS
- || opTok.getType() == TokenType.MULTIPLY
- || lex.equals("/")) {
+ || opTok.getType() == TokenType.MINUS
+ || opTok.getType() == TokenType.MULTIPLY
+ || lex.equals("/")) {
String op = lex;
pos++;
ASTExpression right = parseExpression();
@@ -180,22 +263,56 @@ public class ParserEngine {
}
// 工具方法
+ /**
+ * 获取当前令牌,如果超出范围则抛出异常。
+ *
+ * @return 当前Token
+ * @throws ASTBinaryOp.ParseException 当访问越界时抛出
+ */
private Token current() {
if (pos >= tokens.size()) throw new ASTBinaryOp.ParseException("超出令牌范围");
return tokens.get(pos);
}
+
+ /**
+ * 判断当前令牌类型是否匹配。
+ *
+ * @param type 期望的TokenType
+ * @return 匹配返回true,否则false
+ */
private boolean peek(TokenType type) {
return current().getType() == type;
}
+
+ /**
+ * 判断当前令牌类型和词法是否与期望匹配。
+ *
+ * @param type 期望的TokenType
+ * @param lexeme 期望的词法串
+ * @return 匹配返回true,否则false
+ */
private boolean peek(TokenType type, String lexeme) {
return peek(type) && current().getLexeme().equals(lexeme);
}
+
+ /**
+ * 强制匹配当前令牌类型,如果不匹配则抛出异常。
+ *
+ * @param type 期望的TokenType
+ * @throws ASTBinaryOp.ParseException 当不匹配时抛出,包含错误信息
+ */
private void match(TokenType type) {
if (peek(type)) pos++; else throw new ASTBinaryOp.ParseException("期望 " + type + " 但找到 " + current());
}
+
+ /**
+ * 强制匹配当前令牌类型和词法,如果不匹配则抛出异常。
+ *
+ * @param type 期望的TokenType
+ * @param lexeme 期望的词法串
+ * @throws ASTBinaryOp.ParseException 当不匹配时抛出,包含错误信息
+ */
private void match(TokenType type, String lexeme) {
if (peek(type, lexeme)) pos++; else throw new ASTBinaryOp.ParseException("期望 '" + lexeme + "' 但找到 " + current());
}
}
-
-
diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ASTPrinter.java b/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTPrinter.java
similarity index 95%
rename from src/main/java/org/jcnc/snow/compiler/parser/ASTPrinter.java
rename to src/main/java/org/jcnc/snow/compiler/parser/utils/ASTPrinter.java
index 7ae4070..a35d564 100644
--- a/src/main/java/org/jcnc/snow/compiler/parser/ASTPrinter.java
+++ b/src/main/java/org/jcnc/snow/compiler/parser/utils/ASTPrinter.java
@@ -1,5 +1,7 @@
-package org.jcnc.snow.compiler.parser;
+package org.jcnc.snow.compiler.parser.utils;
+import org.jcnc.snow.compiler.parser.ASTExpression;
+import org.jcnc.snow.compiler.parser.ASTStatement;
import org.jcnc.snow.compiler.parser.ast.*;
// ----------------- AST 打印工具 -----------------