feat: 增强结构体解析器功能

- 优化结构体声明块的解析逻辑,支持更灵活的语法
- 改进构造函数块的解析,允许参数块和方法体块的自由顺序
- 扩展参数块解析,支持内置类型和自定义标识符作为参数类型
- 修复了一些解析过程中的小问题,提高了代码的健壮性
This commit is contained in:
Luke 2025-08-30 17:06:42 +08:00
parent 9ac8b6166a
commit b4a0bccb66

View File

@ -33,9 +33,13 @@ public class StructParser implements TopLevelParser {
/**
* 解析结构体声明块并返回 AST 节点 {@link StructNode}
*
* <p>
* @param ctx 解析上下文
* @return 结构体节点 StructNode
* 该方法解析结构体声明的头部结构体内部的字段块fields构造函数块init方法块function以及结束标记end struct
* </p>
*
* @param ctx 解析上下文包含 TokenStream 和符号表等信息
* @return 解析得到的 {@link StructNode}包含结构体的名称字段构造函数方法等信息
*/
@Override
public StructNode parse(ParserContext ctx) {
@ -74,14 +78,17 @@ public class StructParser implements TopLevelParser {
ts.expect("fields");
ts.expect(":");
ts.expectType(TokenType.NEWLINE);
// 字段块不强制 'end fields'遇到非 declare 则退出
while (true) {
if (ts.peek().getType() == TokenType.NEWLINE) {
ts.next();
continue;
}
if ("declare".equals(ts.peek().getLexeme())) {
// 字段声明使用通用 DeclarationStatementParser其已支持 TYPE/IDENTIFIER 作为类型
fields.add(declParser.parse(ctx));
} else { // declare 开头则结束 fields
} else {
// declare 开头则结束 fields
break;
}
}
@ -124,7 +131,8 @@ public class StructParser implements TopLevelParser {
/**
* 解析结构体构造函数 init 返回 FunctionNode
* <p>
* 允许包含 params body 两部分严格要求 "end init" 结束
* 允许包含 params body 两部分顺序不限 "end init" 结束
* </p>
*
* @param ctx 解析上下文
* @param structName 结构体名称用于构造函数唯一命名
@ -143,7 +151,7 @@ public class StructParser implements TopLevelParser {
/* -------- 初始化参数和方法体容器 -------- */
List<ParameterNode> params = new ArrayList<>();
List<org.jcnc.snow.compiler.parser.ast.base.StatementNode> body = new ArrayList<>();
List<StatementNode> body = new ArrayList<>();
// 主循环支持 params/body 两块顺序不限
while (true) {
@ -175,8 +183,11 @@ public class StructParser implements TopLevelParser {
}
/* ---------------- params: 参数块解析 ---------------- */
/**
* 解析 params 返回参数列表
* <p>
* 且在类型位置同时接受内建类型{@link TokenType#TYPE}与自定义标识符{@link TokenType#IDENTIFIER}
*
* @param ctx 解析上下文
* @return 解析得到的参数节点列表
@ -190,33 +201,58 @@ public class StructParser implements TopLevelParser {
List<ParameterNode> list = new ArrayList<>();
while (true) {
// 跳过空行
if (ts.peek().getType() == TokenType.NEWLINE) {
ts.next();
continue;
}
if (ts.peek().getType() != TokenType.IDENTIFIER) break;
// 碰到 body / end / returns 等其他小节说明 params 结束
String lookaheadLex = ts.peek().getLexeme();
if ("body".equals(lookaheadLex) || "end".equals(lookaheadLex) || "returns".equals(lookaheadLex)) {
break;
}
int line = ts.peek().getLine();
int col = ts.peek().getCol();
// 支持两种前缀 declare / declare
boolean hasDeclare = "declare".equals(ts.peek().getLexeme());
if (hasDeclare) {
ts.expect("declare");
}
// 参数名
String pName = ts.expectType(TokenType.IDENTIFIER).getLexeme();
ts.expect(":");
String pType = ts.expectType(TokenType.TYPE).getLexeme();
// 参数类型既可为 TYPE内置也可为 IDENTIFIER自定义
String pType;
if (ts.peek().getType() == TokenType.TYPE || ts.peek().getType() == TokenType.IDENTIFIER) {
pType = ts.next().getLexeme();
} else {
var t = ts.peek();
throw new UnexpectedToken(
"期望的标记类型为 TYPE 或 IDENTIFIER但实际得到的是 " +
t.getType() + " ('" + t.getLexeme() + "')",
t.getLine(), t.getCol());
}
ts.expectType(TokenType.NEWLINE);
list.add(new ParameterNode(pName, pType, new NodeContext(line, col,
ctx.getSourceName())));
list.add(new ParameterNode(pName, pType, new NodeContext(line, col, ctx.getSourceName())));
}
return list;
}
/* ---------------- body: 方法体块解析 ---------------- */
/**
* 解析 body 返回语句节点列表
*
* @param ctx 解析上下文
* @return 解析得到的方法体语句列表
*/
private List<org.jcnc.snow.compiler.parser.ast.base.StatementNode> parseBody(ParserContext ctx) {
private List<StatementNode> parseBody(ParserContext ctx) {
TokenStream ts = ctx.getTokens();
ts.expect("body");