优化FunctionParser,实现无序

This commit is contained in:
Luke 2025-04-24 20:25:53 +08:00
parent 0cecb5797b
commit d586c65e22
2 changed files with 142 additions and 47 deletions

View File

@ -11,17 +11,17 @@ import java.util.ArrayList;
import java.util.List;
/**
* 用于解析函数定义块function包括函数名参数列表返回类型函数体等
* 支持的语法结构示例
* FunctionParser 是用于解析函数定义的顶层解析器
* <p>
* 支持的语法结构参数返回类型函数体顺序可变
* <pre>{@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
* }</pre>
@ -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<ParameterNode> parameters = new ArrayList<>();
String[] returnType = {null}; // 使用数组模拟引用传参
List<StatementNode> 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<ParameterNode> parameters,
List<StatementNode> body,
java.util.function.Consumer<String> 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<ParameterNode> parseParameters(TokenStream ts) {
ts.expect("parameter");
ts.expect(":");
ts.expectType(TokenType.NEWLINE);
List<ParameterNode> 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<StatementNode> parseFunctionBody(ParserContext ctx, TokenStream ts) {
ts.expect("body");
ts.expect(":");
ts.expectType(TokenType.NEWLINE);
List<StatementNode> body = new ArrayList<>();
parseBody(ctx, body);
// 解析函数体结束标识
List<StatementNode> 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<StatementNode> 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);
}
}
}

7
test
View File

@ -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