增加注释

This commit is contained in:
Luke 2025-04-24 17:50:57 +08:00
parent 1c0251e581
commit dc9eb925ce
4 changed files with 47 additions and 15 deletions

View File

@ -15,6 +15,7 @@ import java.util.List;
* 同时自动跳过空行NEWLINE以增强容错性
*/
public class ParserEngine {
// 解析上下文对象包含 TokenStream 及相关辅助功能
private final ParserContext ctx;
/**
@ -33,25 +34,32 @@ public class ParserEngine {
*/
public List<Node> parse() {
List<Node> nodes = new ArrayList<>();
TokenStream ts = ctx.getTokens();
TokenStream ts = ctx.getTokens(); // 获取 Token
while (ts.isAtEnd()) {
// 跳过空行
// 循环解析直到文件结束
while (!ts.isAtEnd()) {
// 跳过空行增加语法容错能力
if (ts.peek().getType() == TokenType.NEWLINE) {
ts.next();
ts.next(); // 消耗空行
continue;
}
// 根据当前关键字分发顶层解析器
// 获取当前标记 module, import, function
String lex = ts.peek().getLexeme();
// 通过工厂方法获得对应的顶层解析器
TopLevelParser parser = TopLevelParserFactory.get(lex);
// 如果找不到对应解析器说明语法结构非法或暂不支持
if (parser == null) {
throw new IllegalStateException("意外的顶级标记: " + lex);
}
// 使用解析器解析该顶层结构添加到结果列表中
nodes.add(parser.parse(ctx));
}
// 返回构建的 AST 节点集合
return nodes;
}
}

View File

@ -4,16 +4,20 @@ import org.jcnc.snow.compiler.parser.ast.Node;
import org.jcnc.snow.compiler.parser.context.ParserContext;
/**
* 顶层结构解析器接口用于解析模块级别的语法结构 {@code module}{@code import}
* 所有顶层解析器应实现该接口
* 顶层结构解析器接口用于解析模块级别的语法结构 {@code module}{@code import}{@code function}
* 所有顶层解析器应实现该接口并从 {@link ParserContext} 中读取 TokenStream 来构造 AST 节点
* <p>
* 该接口由 {@link org.jcnc.snow.compiler.parser.factory.TopLevelParserFactory} 根据当前关键字动态调度
*/
public interface TopLevelParser {
/**
* 从解析上下文中解析一个顶层语法结构
* 每个实现应从 TokenStream 中消费对应的 token并返回构建后的 AST 节点
*
* @param ctx 当前解析上下文
* @return 表示顶层结构的 AST 节点
* @param ctx 当前解析上下文包含 Token 流与状态信息
* @return 表示顶层结构的 AST 节点不应为 null
* @throws IllegalStateException 如果遇到非法语法结构
*/
Node parse(ParserContext ctx);
}

View File

@ -9,15 +9,20 @@ import java.util.HashMap;
/**
* 顶层解析器工厂类用于根据文件开头的关键字 {@code module}分发对应的顶层结构解析器
* 每种顶层结构模块导入等应有一个专门的 {@link TopLevelParser} 实现类
*
* <p>该类采用静态注册机制在类加载时将所有支持的关键字及其解析器实例注册到内部映射表中
* 外部通过 {@link #get(String)} 方法获取对应的解析器</p>
*
* <p>用于 {@link org.jcnc.snow.compiler.parser.ParserEngine} 根据关键字动态解析不同语法块</p>
*/
public class TopLevelParserFactory {
// 存储关键字 -> 解析器 实例的映射关系
private static final Map<String, TopLevelParser> registry = new HashMap<>();
static {
// 注册模块解析器
// 注册模块解析器关键字 "module" 映射到 ModuleParser 实例
registry.put("module", new ModuleParser());
// importpackage 在此添加注册项
}
/**

View File

@ -34,43 +34,58 @@ public class ModuleParser implements TopLevelParser {
@Override
public ModuleNode parse(ParserContext ctx) {
TokenStream ts = ctx.getTokens();
// 期望以 "module" 开头
ts.expect("module");
ts.expect(":");
// 读取模块名称标识符
String name = ts.expectType(TokenType.IDENTIFIER).getLexeme();
// 模块声明后的换行
ts.expectType(TokenType.NEWLINE);
// 初始化导入列表与函数列表
List<ImportNode> imports = new ArrayList<>();
List<FunctionNode> functions = new ArrayList<>();
// 创建导入语句和函数解析器
ImportParser importParser = new ImportParser();
FunctionParser funcParser = new FunctionParser();
// 解析模块包含 import function 语句
// 解析模块主体内容支持多个 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));
} else if ("function".equals(lex)) {
// 添加解析后的函数节点
functions.add(funcParser.parse(ctx));
} else {
// 非法语法抛出异常提示位置与原因
throw new IllegalStateException("Unexpected token in module: " + lex);
}
}
// 结束模块块结构
// 解析模块结尾结构确保以 "end module" 结尾
ts.expect("end");
ts.expect("module");
ts.expectType(TokenType.NEWLINE);
// 返回构建完成的模块语法树节点
return new ModuleNode(name, imports, functions);
}
}