diff --git a/src/main/java/org/jcnc/snow/compiler/parser/struct/StructParser.java b/src/main/java/org/jcnc/snow/compiler/parser/struct/StructParser.java index b1217f8..b035c1b 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/struct/StructParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/struct/StructParser.java @@ -33,9 +33,13 @@ public class StructParser implements TopLevelParser { /** * 解析结构体声明块,并返回 AST 节点 {@link StructNode}。 + * *

- * @param ctx 解析上下文 - * @return 结构体节点 StructNode + * 该方法解析结构体声明的头部,结构体内部的字段块(fields)、构造函数块(init)、方法块(function)以及结束标记(end struct)。 + *

+ * + * @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。 *

- * 允许包含 params 和 body 两部分。严格要求 "end init" 结束。 + * 允许包含 params 和 body 两部分,顺序不限;以 "end init" 结束。 + *

* * @param ctx 解析上下文 * @param structName 结构体名称,用于构造函数唯一命名 @@ -143,7 +151,7 @@ public class StructParser implements TopLevelParser { /* -------- 初始化参数和方法体容器 -------- */ List params = new ArrayList<>(); - List body = new ArrayList<>(); + List body = new ArrayList<>(); // 主循环:支持 params/body 两块,顺序不限 while (true) { @@ -175,8 +183,11 @@ public class StructParser implements TopLevelParser { } /* ---------------- params: 参数块解析 ---------------- */ + /** * 解析 params 块,返回参数列表。 + *

+ * 且在类型位置同时接受内建类型({@link TokenType#TYPE})与自定义标识符({@link TokenType#IDENTIFIER})。 * * @param ctx 解析上下文 * @return 解析得到的参数节点列表 @@ -190,33 +201,58 @@ public class StructParser implements TopLevelParser { List 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 parseBody(ParserContext ctx) { + private List parseBody(ParserContext ctx) { TokenStream ts = ctx.getTokens(); ts.expect("body");