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 new file mode 100644 index 0000000..b1217f8 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/parser/struct/StructParser.java @@ -0,0 +1,244 @@ +package org.jcnc.snow.compiler.parser.struct; + +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.ParameterNode; +import org.jcnc.snow.compiler.parser.ast.StructNode; +import org.jcnc.snow.compiler.parser.ast.base.NodeContext; +import org.jcnc.snow.compiler.parser.ast.base.StatementNode; +import org.jcnc.snow.compiler.parser.base.TopLevelParser; +import org.jcnc.snow.compiler.parser.context.ParserContext; +import org.jcnc.snow.compiler.parser.context.TokenStream; +import org.jcnc.snow.compiler.parser.context.UnexpectedToken; +import org.jcnc.snow.compiler.parser.factory.StatementParserFactory; +import org.jcnc.snow.compiler.parser.function.FunctionParser; +import org.jcnc.snow.compiler.parser.statement.DeclarationStatementParser; + +import java.util.ArrayList; +import java.util.List; + +/** + * {@code StructParser} + *

+ * 解析 struct ... end struct 结构体声明块的顶层语法解析器。 + *

+ *

+ */ +public class StructParser implements TopLevelParser { + + /** + * 解析结构体声明块,并返回 AST 节点 {@link StructNode}。 + *

+ * @param ctx 解析上下文 + * @return 结构体节点 StructNode + */ + @Override + public StructNode parse(ParserContext ctx) { + TokenStream ts = ctx.getTokens(); + + int line = ts.peek().getLine(); + int col = ts.peek().getCol(); + String file = ctx.getSourceName(); + + /* -------- 解析头部 -------- */ + ts.expect("struct"); + ts.expect(":"); + String structName = ts.expectType(TokenType.IDENTIFIER).getLexeme(); + ts.expectType(TokenType.NEWLINE); + + /* -------- 初始化容器 -------- */ + List fields = new ArrayList<>(); + FunctionNode init = null; + List methods = new ArrayList<>(); + + DeclarationStatementParser declParser = new DeclarationStatementParser(); + FunctionParser funcParser = new FunctionParser(); + + /* -------- 主循环:依次解析 struct 块内部字段、构造、方法 -------- */ + while (true) { + /* 跳过空行 */ + if (ts.peek().getType() == TokenType.NEWLINE) { + ts.next(); + continue; + } + + String lex = ts.peek().getLexeme(); + switch (lex) { + /* ---------- fields 块 ---------- */ + case "fields" -> { + ts.expect("fields"); + ts.expect(":"); + ts.expectType(TokenType.NEWLINE); + while (true) { + if (ts.peek().getType() == TokenType.NEWLINE) { + ts.next(); + continue; + } + if ("declare".equals(ts.peek().getLexeme())) { + fields.add(declParser.parse(ctx)); + } else { // 非 declare 开头则结束 fields + break; + } + } + } + + /* ---------- 构造函数 init ---------- */ + case "init" -> { + if (init != null) { + throw new UnexpectedToken( + "重复定义 init 构造函数", + ts.peek().getLine(), ts.peek().getCol()); + } + init = parseInit(ctx, structName); + } + + /* ---------- 普通方法 function ---------- */ + case "function" -> methods.add(funcParser.parse(ctx)); + + /* ---------- struct 结束 ---------- */ + case "end" -> { + ts.expect("end"); + ts.expect("struct"); + // 返回完整结构体 AST 节点 + return new StructNode(structName, fields, init, methods, + new NodeContext(line, col, file)); + } + + /* ---------- 非法内容 ---------- */ + default -> throw new UnexpectedToken( + "struct 块内不支持的标记: " + lex, + ts.peek().getLine(), ts.peek().getCol()); + } + } + } + + /* ====================================================================== */ + /* -------------------------- 构造函数 init -------------------------- */ + /* ====================================================================== */ + + /** + * 解析结构体构造函数 init 块,返回 FunctionNode。 + *

+ * 允许包含 params 和 body 两部分。严格要求 "end init" 结束。 + * + * @param ctx 解析上下文 + * @param structName 结构体名称,用于构造函数唯一命名 + * @return 表示构造函数的 FunctionNode + */ + private FunctionNode parseInit(ParserContext ctx, String structName) { + TokenStream ts = ctx.getTokens(); + + int line = ts.peek().getLine(); + int col = ts.peek().getCol(); + String file = ctx.getSourceName(); + + ts.expect("init"); + ts.expect(":"); + ts.expectType(TokenType.NEWLINE); + + /* -------- 初始化参数和方法体容器 -------- */ + List params = new ArrayList<>(); + List body = new ArrayList<>(); + + // 主循环:支持 params/body 两块,顺序不限 + while (true) { + if (ts.peek().getType() == TokenType.NEWLINE) { + ts.next(); + continue; + } + + String lex = ts.peek().getLexeme(); + switch (lex) { + case "params" -> params.addAll(parseParams(ctx)); + case "body" -> body.addAll(parseBody(ctx)); + case "end" -> { + ts.expect("end"); + ts.expect("init"); + // 构造唯一命名的 FunctionNode + return new FunctionNode( + structName + ".__init__", // 唯一命名 + params, + "void", + body, + new NodeContext(line, col, file)); + } + default -> throw new UnexpectedToken( + "init 块内不支持的标记: " + lex, + ts.peek().getLine(), ts.peek().getCol()); + } + } + } + + /* ---------------- params: 参数块解析 ---------------- */ + /** + * 解析 params 块,返回参数列表。 + * + * @param ctx 解析上下文 + * @return 解析得到的参数节点列表 + */ + private List parseParams(ParserContext ctx) { + TokenStream ts = ctx.getTokens(); + + ts.expect("params"); + ts.expect(":"); + ts.expectType(TokenType.NEWLINE); + + List list = new ArrayList<>(); + while (true) { + if (ts.peek().getType() == TokenType.NEWLINE) { + ts.next(); + continue; + } + if (ts.peek().getType() != TokenType.IDENTIFIER) break; + + int line = ts.peek().getLine(); + int col = ts.peek().getCol(); + + String pName = ts.expectType(TokenType.IDENTIFIER).getLexeme(); + ts.expect(":"); + String pType = ts.expectType(TokenType.TYPE).getLexeme(); + ts.expectType(TokenType.NEWLINE); + list.add(new ParameterNode(pName, pType, new NodeContext(line, col, + ctx.getSourceName()))); + } + return list; + } + + /* ---------------- body: 方法体块解析 ---------------- */ + /** + * 解析 body 块,返回语句节点列表。 + * + * @param ctx 解析上下文 + * @return 解析得到的方法体语句列表 + */ + private List parseBody(ParserContext ctx) { + TokenStream ts = ctx.getTokens(); + + ts.expect("body"); + ts.expect(":"); + ts.expectType(TokenType.NEWLINE); + + List body = new ArrayList<>(); + + // 循环读取每一条语句,直到 end body + while (true) { + if (ts.peek().getType() == TokenType.NEWLINE) { + ts.next(); + continue; + } + if ("end".equals(ts.peek().getLexeme())) break; // body 块结束 + + var parser = StatementParserFactory.get(ts.peek().getLexeme()); + body.add(parser.parse(ctx)); + } + + ts.expect("end"); + ts.expect("body"); + return body; + } +}