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 37cdea5..17597c0 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 @@ -55,39 +55,54 @@ public class FunctionParser implements TopLevelParser { */ @Override public FunctionNode parse(ParserContext ctx) { + // 获取当前解析上下文中的 token 流 TokenStream ts = ctx.getTokens(); - // 获取当前 token 的行号、列号和文件名 + // 记录当前 token 的行号、列号和源文件名,用于错误报告或生成节点上下文 int line = ctx.getTokens().peek().getLine(); int column = ctx.getTokens().peek().getCol(); String file = ctx.getSourceName(); + // 解析函数头(例如可能是 `function` 关键字等) parseFunctionHeader(ts); + + // 解析函数名 String functionName = parseFunctionName(ts); + // 用于存放解析出来的参数列表 List parameters = new ArrayList<>(); + // 用于存放返回类型,这里用数组是为了在闭包中修改其值 String[] returnType = new String[1]; + // 用于存放函数体语句列表 List body = new ArrayList<>(); + // 获取函数可以包含的可选节(如参数、返回类型、主体等)的定义映射 Map sections = getSectionDefinitions(parameters, returnType, body); + + // 调用通用的多节解析器,实际根据 sections 中注册的规则解析各部分内容 FlexibleSectionParser.parse(ctx, ts, sections); + + // 如果函数体为空且返回类型为 void,自动补充一个空的 return 语句 if (body.isEmpty() && returnType[0].equals("void")) { body.add(new ReturnNode(null, new NodeContext(line, column, file))); } + // 检查参数名称是否重复 Set set = new HashSet<>(); parameters.forEach((node) -> { final String name = node.name(); if (set.contains(name)) { + // 如果参数名重复,抛出带具体行列信息的解析异常 throw new ParseException(String.format("参数 `%s` 重定义", name), node.context().line(), node.context().column()); } - set.add(name); }); + // 解析函数的尾部(例如右大括号或者 end 标志) parseFunctionFooter(ts); + // 返回完整的函数节点,包含函数名、参数、返回类型、函数体以及源位置信息 return new FunctionNode(functionName, parameters, returnType[0], body, new NodeContext(line, column, file)); }