feat: 增加结构体定义解析并优化模块解析逻辑

- 添加 StructParser 解析器,支持结构体定义解析
- 重构 ModuleParser 解析逻辑,提高代码可读性和可维护性
- 优化模块解析流程,支持空行和灵活的语法结构
- 增加异常处理,提升错误提示的准确性和可读性
This commit is contained in:
Luke 2025-08-29 18:05:53 +08:00
parent fea8e14245
commit 17b078b6f3

View File

@ -1,10 +1,7 @@
package org.jcnc.snow.compiler.parser.module;
import org.jcnc.snow.compiler.lexer.token.TokenType;
import org.jcnc.snow.compiler.parser.ast.DeclarationNode;
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
import org.jcnc.snow.compiler.parser.ast.ImportNode;
import org.jcnc.snow.compiler.parser.ast.ModuleNode;
import org.jcnc.snow.compiler.parser.ast.*;
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
import org.jcnc.snow.compiler.parser.base.TopLevelParser;
import org.jcnc.snow.compiler.parser.context.ParserContext;
@ -12,47 +9,33 @@ import org.jcnc.snow.compiler.parser.context.TokenStream;
import org.jcnc.snow.compiler.parser.context.UnexpectedToken;
import org.jcnc.snow.compiler.parser.function.FunctionParser;
import org.jcnc.snow.compiler.parser.statement.DeclarationStatementParser;
import org.jcnc.snow.compiler.parser.struct.StructParser;
import java.util.ArrayList;
import java.util.List;
/**
* {@code ModuleParser} 负责解析源码中的模块结构是顶层结构解析器实现之一
* {@code ModuleParser}
* <p>
* 模块定义可包含多个导入import语句globals 全局声明和函数定义function
* 导入语句可在模块中任意位置出现且允许模块体中穿插任意数量的空行空行会被自动忽略不影响语法结构
* </p>
*
* <p>
* 典型模块语法结构:
* <pre>
* module: mymod
* import ...
* globals:
* declare ...
* function ...
* ...
* end module
* </pre>
* 顶层结构解析器负责解析整个源码模块module ... end module
* <ul>
* <li>支持模块声明导入(import)全局变量(globals)结构体(struct)函数(function)等顶层语法</li>
* <li>允许模块体中出现任意数量的空行自动跳过顺序自由</li>
* <li>遇到非法顶层语句或区块会抛出 {@link UnexpectedToken}提示具体位置和原因</li>
* </ul>
* </p>
*/
public class ModuleParser implements TopLevelParser {
/**
* 解析一个模块定义块返回完整的 {@link ModuleNode} 语法树节点
* 解析一个完整的模块定义块返回 AST {@link ModuleNode}
* <p>
* 解析过程包括:
* <ol>
* <li>匹配模块声明起始 {@code module: IDENTIFIER}</li>
* <li>收集模块体内所有 importglobals function 语句允许穿插空行</li>
* <li>匹配模块结束 {@code end module}</li>
* </ol>
* 若遇到未识别的语句将抛出 {@link UnexpectedToken} 异常定位错误位置和原因
* 支持空行允许导入全局结构体函数等多种区块混排
* </p>
*
* @param ctx 当前解析上下文包含词法流等状态
* @return 解析得到的 {@link ModuleNode} 实例
* @throws UnexpectedToken 当模块体中出现未识别的顶层语句时抛出
* @param ctx 解析上下文包含 TokenStream文件名等信息
* @return 解析生成的 ModuleNode
* @throws UnexpectedToken 当模块体中遇到不支持的顶层语句时抛出
*/
@Override
public ModuleNode parse(ParserContext ctx) {
@ -62,37 +45,53 @@ public class ModuleParser implements TopLevelParser {
int column = ts.peek().getCol();
String file = ctx.getSourceName();
// 1) 解析模块声明头部
ts.expect("module");
ts.expect(":");
String name = ts.expectType(TokenType.IDENTIFIER).getLexeme();
ts.expectType(TokenType.NEWLINE);
// 2) 初始化各类节点容器
List<StructNode> structs = new ArrayList<>();
List<ImportNode> imports = new ArrayList<>();
List<DeclarationNode> globals = new ArrayList<>();
List<FunctionNode> functions = new ArrayList<>();
// 3) 各子区块的专用解析器
StructParser structParser = new StructParser();
ImportParser importParser = new ImportParser();
FunctionParser funcParser = new FunctionParser();
DeclarationStatementParser globalsParser = new DeclarationStatementParser();
// 4) 进入主循环直到 end module
while (true) {
// 跳过空行
if (ts.peek().getType() == TokenType.NEWLINE) {
ts.next();
continue;
}
// 到达模块结尾
if ("end".equals(ts.peek().getLexeme())) {
break;
}
String lex = ts.peek().getLexeme();
switch (lex) {
// 解析 import 语句可多次出现支持 import 多个模块
case "import" -> imports.addAll(importParser.parse(ctx));
// 解析 struct 结构体定义块
case "struct" -> structs.add(structParser.parse(ctx));
// 解析 function 顶层函数定义
case "function" -> functions.add(funcParser.parse(ctx));
// 解析全局变量声明区块
case "globals" -> {
ts.expect("globals");
ts.expect(":");
ts.expectType(TokenType.NEWLINE);
while (true) {
// 跳过空行
if (ts.peek().getType() == TokenType.NEWLINE) {
ts.next();
continue;
@ -100,9 +99,13 @@ public class ModuleParser implements TopLevelParser {
String innerLex = ts.peek().getLexeme();
if ("declare".equals(innerLex)) {
globals.add(globalsParser.parse(ctx));
} else if ("function".equals(innerLex) || "import".equals(innerLex) || "end".equals(innerLex)) {
}
// 下一个 function/import/end 开头则结束 globals 区块
else if ("function".equals(innerLex) || "import".equals(innerLex) || "end".equals(innerLex)) {
break;
} else {
}
// 其余标记为非法内容抛出异常
else {
throw new UnexpectedToken(
"globals 区块中不支持的内容: " + innerLex,
ts.peek().getLine(),
@ -111,6 +114,7 @@ public class ModuleParser implements TopLevelParser {
}
}
}
// 未知或非法顶层内容
case null, default -> throw new UnexpectedToken(
"Unexpected token in module: " + lex,
ts.peek().getLine(),
@ -119,9 +123,11 @@ public class ModuleParser implements TopLevelParser {
}
}
// 5) 匹配模块结尾 "end module"
ts.expect("end");
ts.expect("module");
return new ModuleNode(name, imports, globals, functions, new NodeContext(line, column, file));
// 6) 构造并返回 ModuleNode
return new ModuleNode(name, imports, globals, structs, functions, new NodeContext(line, column, file));
}
}