diff --git a/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java index 8d6de5d..13883ec 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/function/FunctionParser.java @@ -11,17 +11,17 @@ import java.util.ArrayList; import java.util.List; /** - * 用于解析函数定义块(function),包括函数名、参数列表、返回类型、函数体等。 - * 支持的语法结构示例: + * FunctionParser 是用于解析函数定义的顶层解析器。 + *

+ * 支持的语法结构(参数、返回类型、函数体顺序可变): *

{@code
  * function: myFunc
+ * return_type: int
  * parameter:
  *   declare a:int
  *   b:int
- * return_type: int
  * body:
- *   declare x:int = 10
- *   return x
+ *   return a + b
  * end body
  * end function
  * }
@@ -29,87 +29,181 @@ import java.util.List; public class FunctionParser implements TopLevelParser { /** - * 解析一个函数定义并返回对应的 {@link FunctionNode}。 + * 解析函数定义,包括函数名、参数列表、返回类型、函数体等部分,顺序不限。 * - * @param ctx 解析上下文。 - * @return 解析生成的函数节点。 + * @param ctx 解析上下文 + * @return 生成的函数语法树节点 */ @Override public FunctionNode parse(ParserContext ctx) { - TokenStream ts = ctx.getTokens(); + TokenStream tokens = ctx.getTokens(); + + // 解析 function: 标识符 + parseFunctionHeader(tokens); + + // 解析函数名 + String functionName = parseFunctionName(tokens); + + // 初始化各部分容器 + List parameters = new ArrayList<>(); + String[] returnType = {null}; // 使用数组模拟引用传参 + List body = new ArrayList<>(); + + // 解析 parameter / return_type / body 的任意顺序区块 + parseFlexibleSections(ctx, tokens, parameters, body, type -> returnType[0] = type); + + // 匹配函数定义结束 + parseFunctionFooter(tokens); + + return new FunctionNode(functionName, parameters, returnType[0], body); + } + + /** 匹配 function: 起始标记 */ + private void parseFunctionHeader(TokenStream ts) { ts.expect("function"); ts.expect(":"); + + + } + + /** 获取函数名称标识符 */ + private String parseFunctionName(TokenStream ts) { + // “function:”后必然是函数名所以可以“expectType”断言 String name = ts.expectType(TokenType.IDENTIFIER).getLexeme(); ts.expectType(TokenType.NEWLINE); + return name; + } - // 解析参数列表 + /** + * 支持顺序无关的函数区块解析逻辑。 + * + * @param ctx 解析上下文 + * @param tokens token 流 + * @param parameters 参数节点收集容器 + * @param body 函数体语句节点容器 + * @param returnTypeSetter 设置返回类型的 Lambda(引用模拟) + */ + private void parseFlexibleSections(ParserContext ctx, + TokenStream tokens, + List parameters, + List body, + java.util.function.Consumer returnTypeSetter) { + boolean parsedParam = false; + boolean parsedReturn = false; + boolean parsedBody = false; + + while (true) { + // 跳过空行 + while (tokens.peek().getType() == TokenType.NEWLINE) { + tokens.next(); + } + + String keyword = tokens.peek().getLexeme(); + + switch (keyword) { + case "parameter": + if (parsedParam) throw new RuntimeException("重复的“参数”部分。"); + parameters.addAll(parseParameters(tokens)); + parsedParam = true; + break; + + case "return_type": + if (parsedReturn) throw new RuntimeException("重复的'return_type'部分。"); + returnTypeSetter.accept(parseReturnType(tokens)); + parsedReturn = true; + break; + + case "body": + if (parsedBody) throw new RuntimeException("重复的“body”部分。"); + body.addAll(parseFunctionBody(ctx, tokens)); + parsedBody = true; + break; + + case "end": + return; // 退出循环,进入函数尾部匹配 + + default: + throw new RuntimeException("函数中出现意外部分: " + keyword); + } + } + } + + /** 解析 parameter: 部分 */ + private List parseParameters(TokenStream ts) { ts.expect("parameter"); ts.expect(":"); ts.expectType(TokenType.NEWLINE); + List params = new ArrayList<>(); + while (true) { if (ts.peek().getType() == TokenType.NEWLINE) { - ts.next(); + ts.next(); // 忽略空行 continue; } - if ("return_type".equals(ts.peek().getLexeme())) { - break; + + if ("return_type".equals(ts.peek().getLexeme()) || "body".equals(ts.peek().getLexeme()) || "end".equals(ts.peek().getLexeme())) { + break; // 退出 parameter 区块 } + if ("declare".equals(ts.peek().getLexeme())) { - ts.next(); // 支持 declare 前缀 + ts.next(); // 可选 declare } + String paramName = ts.expectType(TokenType.IDENTIFIER).getLexeme(); ts.expect(":"); String paramType = ts.expectType(TokenType.TYPE).getLexeme(); ts.expectType(TokenType.NEWLINE); + params.add(new ParameterNode(paramName, paramType)); } - // 解析返回类型 + return params; + } + + /** 解析 return_type: 部分 */ + private String parseReturnType(TokenStream ts) { ts.expect("return_type"); ts.expect(":"); String returnType = ts.expectType(TokenType.TYPE).getLexeme(); ts.expectType(TokenType.NEWLINE); + return returnType; + } - // 解析函数体 + /** 解析 body: ... end body 部分 */ + private List parseFunctionBody(ParserContext ctx, TokenStream ts) { ts.expect("body"); ts.expect(":"); ts.expectType(TokenType.NEWLINE); - List body = new ArrayList<>(); - parseBody(ctx, body); - // 解析函数体结束标识 + List body = new ArrayList<>(); + + while (true) { + if (ts.peek().getType() == TokenType.NEWLINE) { + ts.next(); // 跳过空行 + continue; + } + + if ("end".equals(ts.peek().getLexeme())) { + break; // body 结束 + } + + String keyword = ts.peek().getLexeme(); + StatementNode statement = StatementParserFactory.get(keyword).parse(ctx); + body.add(statement); + } + ts.expect("end"); ts.expect("body"); ts.expectType(TokenType.NEWLINE); - // 解析函数定义结束标识 + return body; + } + + /** 匹配函数结束标志 end function */ + private void parseFunctionFooter(TokenStream ts) { ts.expect("end"); ts.expect("function"); ts.expectType(TokenType.NEWLINE); - - return new FunctionNode(name, params, returnType, body); - } - - /** - * 辅助方法:从上下文中解析函数体,直到遇到 "end"。 - * - * @param ctx 当前解析上下文。 - * @param body 存放解析出的语句节点的列表。 - */ - private void parseBody(ParserContext ctx, List body) { - TokenStream ts = ctx.getTokens(); - while (true) { - if (ts.peek().getType() == TokenType.NEWLINE) { - ts.next(); - continue; - } - if ("end".equals(ts.peek().getLexeme())) { - break; - } - String key = ts.peek().getLexeme(); - StatementNode stmt = StatementParserFactory.get(key).parse(ctx); - body.add(stmt); - } } } diff --git a/test b/test index 1185bf0..d7319c6 100644 --- a/test +++ b/test @@ -1,12 +1,13 @@ module: CommonTasks function: add_numbers + body: + return num1 + num2 + end body parameter: declare num1: int declare num2: int return_type: int - body: - return num1 + num2 - end body + end function end module