支持float32double64byte8short15float32double64
This commit is contained in:
parent
59dbafb2b6
commit
a7e2e61b10
@ -1,6 +1,9 @@
|
||||
package org.jcnc.snow.compiler.ir.builder;
|
||||
|
||||
import org.jcnc.snow.compiler.ir.core.IROpCode;
|
||||
import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction;
|
||||
import org.jcnc.snow.compiler.ir.instruction.LoadConstInstruction;
|
||||
import org.jcnc.snow.compiler.ir.value.IRConstant;
|
||||
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
||||
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
|
||||
import org.jcnc.snow.compiler.parser.ast.IdentifierNode;
|
||||
@ -10,79 +13,104 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ExpressionBuilder 负责将 AST 中的 ExpressionNode 构建为 IR 指令,并返回结果寄存器。
|
||||
* <p>
|
||||
* 功能:
|
||||
* ExpressionBuilder 将 AST 中的 ExpressionNode 转换为 IR 指令,并返回结果虚拟寄存器。
|
||||
* 支持:
|
||||
* <ol>
|
||||
* <li>处理数字字面量节点,生成加载常量指令;</li>
|
||||
* <li>处理标识符节点,从作用域获取对应的虚拟寄存器;</li>
|
||||
* <li>处理二元表达式节点,递归构建左右操作数并生成二元运算指令;</li>
|
||||
* <li>NumberLiteralNode:根据文本后缀(b/S/L/f/d)或内容自动区分 bytke/short/int/long/float/double,并生成常量加载指令</li>
|
||||
* <li>IdentifierNode:从作用域获取已声明的虚拟寄存器</li>
|
||||
* <li>BinaryExpressionNode:递归构建子表达式,根据数据宽度和符号生成对应的二元运算指令</li>
|
||||
* </ol>
|
||||
*/
|
||||
public class ExpressionBuilder {
|
||||
/**
|
||||
* 操作符到 IR 操作码的映射表
|
||||
*/
|
||||
private static final Map<String, IROpCode> OP_MAP = Map.of(
|
||||
"+", IROpCode.ADD_I32,
|
||||
"-", IROpCode.SUB_I32,
|
||||
"*", IROpCode.MUL_I32,
|
||||
"/", IROpCode.DIV_I32
|
||||
);
|
||||
// 不同位宽整数和浮点的运算码映射
|
||||
private static final Map<String, IROpCode> OP_I8 = Map.of("+", IROpCode.ADD_B8, "-", IROpCode.SUB_B8, "*", IROpCode.MUL_B8, "/", IROpCode.DIV_B8);
|
||||
private static final Map<String, IROpCode> OP_I16 = Map.of("+", IROpCode.ADD_S16, "-", IROpCode.SUB_S16, "*", IROpCode.MUL_S16, "/", IROpCode.DIV_S16);
|
||||
private static final Map<String, IROpCode> OP_I32 = Map.of("+", IROpCode.ADD_I32, "-", IROpCode.SUB_I32, "*", IROpCode.MUL_I32, "/", IROpCode.DIV_I32);
|
||||
private static final Map<String, IROpCode> OP_L64 = Map.of("+", IROpCode.ADD_L64, "-", IROpCode.SUB_L64, "*", IROpCode.MUL_L64, "/", IROpCode.DIV_L64);
|
||||
private static final Map<String, IROpCode> OP_F32 = Map.of("+", IROpCode.ADD_F32, "-", IROpCode.SUB_F32, "*", IROpCode.MUL_F32, "/", IROpCode.DIV_F32);
|
||||
private static final Map<String, IROpCode> OP_D64 = Map.of("+", IROpCode.ADD_D64, "-", IROpCode.SUB_D64, "*", IROpCode.MUL_D64, "/", IROpCode.DIV_D64);
|
||||
|
||||
/**
|
||||
* 当前 IR 构建上下文,包含 IRFunction 和 IRBuilderScope
|
||||
*/
|
||||
private final IRContext ctx;
|
||||
|
||||
/**
|
||||
* 构造方法,注入 IRContext
|
||||
*
|
||||
* @param ctx 构建 IR 所需上下文,管理函数、作用域和指令添加
|
||||
*/
|
||||
public ExpressionBuilder(IRContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将给定的表达式节点转换为 IR,并返回存放结果的虚拟寄存器。
|
||||
*
|
||||
* @param expr 要构建的表达式节点
|
||||
* @return 存放表达式计算结果的虚拟寄存器
|
||||
* @throws IllegalStateException 若遇到不支持的表达式节点或未定义变量
|
||||
*/
|
||||
public IRVirtualRegister build(ExpressionNode expr) {
|
||||
// 处理数字常量
|
||||
// 1. 常量字面量
|
||||
if (expr instanceof NumberLiteralNode(String value)) {
|
||||
int v = Integer.parseInt(value);
|
||||
// 生成加载常量指令并返回结果寄存器
|
||||
return InstructionFactory.loadConst(ctx, v);
|
||||
// 判断后缀
|
||||
char suffix = value.isEmpty() ? '\0' : Character.toLowerCase(value.charAt(value.length() - 1));
|
||||
String digits = (suffix == 'b' || suffix == 's' || suffix == 'l' || suffix == 'f' || suffix == 'd') ? value.substring(0, value.length() - 1) : value;
|
||||
|
||||
IRVirtualRegister reg = ctx.newRegister();
|
||||
switch (suffix) {
|
||||
case 'b': // byte
|
||||
byte bv = Byte.parseByte(digits);
|
||||
ctx.addInstruction(new LoadConstInstruction(reg, new IRConstant(bv)));
|
||||
break;
|
||||
case 's': // short
|
||||
short sv = Short.parseShort(digits);
|
||||
ctx.addInstruction(new LoadConstInstruction(reg, new IRConstant(sv)));
|
||||
break;
|
||||
case 'l': // long
|
||||
long lv = Long.parseLong(digits);
|
||||
ctx.addInstruction(new LoadConstInstruction(reg, new IRConstant(lv)));
|
||||
break;
|
||||
case 'f': // float
|
||||
float fv = Float.parseFloat(digits);
|
||||
ctx.addInstruction(new LoadConstInstruction(reg, new IRConstant(fv)));
|
||||
break;
|
||||
case 'd': // double
|
||||
double dv = Double.parseDouble(digits);
|
||||
ctx.addInstruction(new LoadConstInstruction(reg, new IRConstant(dv)));
|
||||
break;
|
||||
default: // 无后缀,数字中有小数点或指数 => double,否则 int
|
||||
if (digits.contains(".") || digits.matches(".*[eE].*")) {
|
||||
double dd = Double.parseDouble(digits);
|
||||
ctx.addInstruction(new LoadConstInstruction(reg, new IRConstant(dd)));
|
||||
} else {
|
||||
int iv = Integer.parseInt(digits);
|
||||
ctx.addInstruction(new LoadConstInstruction(reg, new IRConstant(iv)));
|
||||
}
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
// 处理变量引用
|
||||
|
||||
// 2. 标识符 => 作用域寄存器
|
||||
if (expr instanceof IdentifierNode(String name)) {
|
||||
// 从作用域查找已声明的寄存器
|
||||
IRVirtualRegister vr = ctx.getScope().lookup(name);
|
||||
if (vr == null) {
|
||||
throw new IllegalStateException("未定义的变量: " + name);
|
||||
}
|
||||
return vr;
|
||||
IRVirtualRegister reg = ctx.getScope().lookup(name);
|
||||
if (reg == null) throw new IllegalStateException("未定义变量: " + name);
|
||||
return reg;
|
||||
}
|
||||
// 处理二元表达式
|
||||
|
||||
// 3. 二元表达式
|
||||
if (expr instanceof BinaryExpressionNode(ExpressionNode left, String operator, ExpressionNode right)) {
|
||||
// 递归构建左、右子表达式
|
||||
IRVirtualRegister l = build(left);
|
||||
IRVirtualRegister r = build(right);
|
||||
// 根据操作符获取 IR 操作码
|
||||
IROpCode op = OP_MAP.get(operator);
|
||||
if (op == null) {
|
||||
throw new IllegalStateException("不支持的运算符: " + operator);
|
||||
}
|
||||
// 生成二元运算指令并返回结果寄存器
|
||||
return InstructionFactory.binOp(ctx, op, l, r);
|
||||
IRVirtualRegister lreg = build(left);
|
||||
IRVirtualRegister rreg = build(right);
|
||||
// 判断计算类型:检查两侧是否为 NumberLiteralNode 并提取后缀
|
||||
char leftS = (left instanceof NumberLiteralNode(
|
||||
String value
|
||||
)) ? Character.toLowerCase(value.charAt(value.length() - 1)) : '\0';
|
||||
char rightS = (right instanceof NumberLiteralNode(
|
||||
String value
|
||||
)) ? Character.toLowerCase(value.charAt(value.length() - 1)) : '\0';
|
||||
// 选择优先级: byte < short < int < long < float < double
|
||||
char suf = (leftS == 'd' || rightS == 'd') ? 'd' : (leftS == 'f' || rightS == 'f') ? 'f' : (leftS == 'l' || rightS == 'l') ? 'l' : (leftS == 's' || rightS == 's') ? 's' : (leftS == 'b' || rightS == 'b') ? 'b' : '\0';
|
||||
IROpCode code = switch (suf) {
|
||||
case 'b' -> OP_I8.get(operator);
|
||||
case 's' -> OP_I16.get(operator);
|
||||
case 'l' -> OP_L64.get(operator);
|
||||
case 'f' -> OP_F32.get(operator);
|
||||
case 'd' -> OP_D64.get(operator);
|
||||
default -> OP_I32.get(operator);
|
||||
};
|
||||
if (code == null) throw new IllegalStateException("不支持的运算符: " + operator);
|
||||
IRVirtualRegister dest = ctx.newRegister();
|
||||
ctx.addInstruction(new BinaryOperationInstruction(code, dest, lreg, rreg));
|
||||
return dest;
|
||||
}
|
||||
// 其他表达式类型暂不支持
|
||||
throw new IllegalStateException(
|
||||
"不支持的表达式类型: " + expr.getClass().getSimpleName()
|
||||
);
|
||||
|
||||
throw new IllegalStateException("不支持的表达式类型: " + expr.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,75 +4,92 @@ package org.jcnc.snow.compiler.ir.core;
|
||||
* IROpCode —— IR 层支持的操作码(Opcode)枚举类型。
|
||||
* <p>
|
||||
* 本枚举类定义了中间表示层可用的所有基本指令类型,供 {@link IRInstruction} 使用。
|
||||
* 每个枚举值代表一种语义明确的 IR 操作,涵盖常见的算术、逻辑、数据操作和控制流等指令。
|
||||
* 每个枚举值代表一种语义明确的 IR 操作,涵盖不同位宽的整数和浮点算术、逻辑、数据操作和控制流指令。
|
||||
* 可根据后续需求继续扩展。
|
||||
*/
|
||||
public enum IROpCode {
|
||||
|
||||
/* ───── 算术运算 ───── */
|
||||
/* ───── 算术运算 (8位整数: byte) ───── */
|
||||
/** 8位整型加法 (byte): a = b + c */
|
||||
ADD_B8,
|
||||
/** 8位整型减法 */
|
||||
SUB_B8,
|
||||
/** 8位整型乘法 */
|
||||
MUL_B8,
|
||||
/** 8位整型除法 */
|
||||
DIV_B8,
|
||||
/** 8位整型取负 */
|
||||
NEG_B8,
|
||||
|
||||
/** 整型加法(32位),形如:a = b + c */
|
||||
/* ───── 算术运算 (16位整数: short) ───── */
|
||||
/** 16位整型加法 (short) */
|
||||
ADD_S16,
|
||||
/** 16位整型减法 */
|
||||
SUB_S16,
|
||||
/** 16位整型乘法 */
|
||||
MUL_S16,
|
||||
/** 16位整型除法 */
|
||||
DIV_S16,
|
||||
/** 16位整型取负 */
|
||||
NEG_S16,
|
||||
|
||||
/* ───── 算术运算 (32位整数: int) ───── */
|
||||
/** 32位整型加法 (int) */
|
||||
ADD_I32,
|
||||
|
||||
/** 整型减法(32位),形如:a = b - c */
|
||||
/** 32位整型减法 */
|
||||
SUB_I32,
|
||||
|
||||
/** 整型乘法(32位),形如:a = b * c */
|
||||
/** 32位整型乘法 */
|
||||
MUL_I32,
|
||||
|
||||
/** 整型除法(32位),形如:a = b / c */
|
||||
/** 32位整型除法 */
|
||||
DIV_I32,
|
||||
|
||||
/** 整型取负(32位),形如:a = -b(一元运算) */
|
||||
/** 32位整型取负 */
|
||||
NEG_I32,
|
||||
|
||||
/* ───── 算术运算 (64位整数: long) ───── */
|
||||
/** 64位整型加法 (long) */
|
||||
ADD_L64,
|
||||
/** 64位整型减法 */
|
||||
SUB_L64,
|
||||
/** 64位整型乘法 */
|
||||
MUL_L64,
|
||||
/** 64位整型除法 */
|
||||
DIV_L64,
|
||||
/** 64位整型取负 */
|
||||
NEG_L64,
|
||||
|
||||
/* ───── 算术运算 (单精度浮点: float) ───── */
|
||||
ADD_F32,
|
||||
SUB_F32,
|
||||
MUL_F32,
|
||||
DIV_F32,
|
||||
NEG_F32,
|
||||
|
||||
/* ───── 算术运算 (双精度浮点: double) ───── */
|
||||
ADD_D64,
|
||||
SUB_D64,
|
||||
MUL_D64,
|
||||
DIV_D64,
|
||||
NEG_D64,
|
||||
|
||||
/* ───── 逻辑/比较运算 ───── */
|
||||
|
||||
/** 相等比较(==),结果为布尔值,形如:a = (b == c) */
|
||||
CMP_EQ,
|
||||
|
||||
/** 不等比较(!=),结果为布尔值,形如:a = (b != c) */
|
||||
CMP_NE,
|
||||
|
||||
/** 小于比较(<),结果为布尔值,形如:a = (b < c) */
|
||||
CMP_LT,
|
||||
|
||||
/** 大于比较(>),结果为布尔值,形如:a = (b > c) */
|
||||
CMP_GT,
|
||||
|
||||
/** 小于等于(<=),结果为布尔值,形如:a = (b <= c) */
|
||||
CMP_LE,
|
||||
|
||||
/** 大于等于(>=),结果为布尔值,形如:a = (b >= c) */
|
||||
CMP_GE,
|
||||
|
||||
/* ───── 数据搬运 ───── */
|
||||
|
||||
/** 从内存加载到寄存器(Load),形如:a = *addr */
|
||||
LOAD,
|
||||
|
||||
/** 将数据存储到内存地址(Store),形如:*addr = a */
|
||||
STORE,
|
||||
|
||||
/** 加载常量值(IRConstant)到寄存器,形如:a = 123 */
|
||||
CONST,
|
||||
|
||||
/* ───── 控制流 ───── */
|
||||
|
||||
/** 无条件跳转(Jump),直接跳转到指定标签位置 */
|
||||
JUMP,
|
||||
|
||||
/** 条件跳转(Jump if zero),如果条件为 0 则跳转 */
|
||||
JUMP_IF_ZERO,
|
||||
|
||||
/** 标签定义(Label),作为跳转目标使用 */
|
||||
LABEL,
|
||||
|
||||
/* ───── 函数调用相关 ───── */
|
||||
|
||||
/** 函数调用(Call),可能带返回值和参数 */
|
||||
CALL,
|
||||
|
||||
/** 函数返回(Return),结束当前函数执行,可返回值 */
|
||||
RET
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package org.jcnc.snow.compiler.parser.function;
|
||||
|
||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||
import org.jcnc.snow.compiler.parser.base.TopLevelParser;
|
||||
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
||||
@ -17,104 +18,97 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@code FunctionParser} 是一个顶层语法分析器,用于解析函数定义的语法结构。
|
||||
* <p>
|
||||
* 该解析器通过 {@code FlexibleSectionParser} 解析函数定义的多个部分,包括:
|
||||
* <ul>
|
||||
* <li>函数名</li>
|
||||
* <li>参数列表</li>
|
||||
* <li>返回类型</li>
|
||||
* <li>函数体</li>
|
||||
* </ul>
|
||||
* 各部分的顺序不固定,由 FlexibleSectionParser 按规则识别和处理。
|
||||
* </p>
|
||||
* 顶层的函数定义解析器。
|
||||
*
|
||||
* 通过 FlexibleSectionParser 按区块顺序解析函数的各个部分:
|
||||
* 函数头(名称)、参数列表、返回类型、函数体,并最终生成 FunctionNode。
|
||||
* 支持在参数或返回类型声明中出现注释,自动跳过注释和空行而不干扰语法解析。
|
||||
*/
|
||||
public class FunctionParser implements TopLevelParser {
|
||||
|
||||
/**
|
||||
* 解析函数定义,构建函数的抽象语法树节点。
|
||||
* <p>
|
||||
* 此方法首先解析函数的头部和名称,然后通过 FlexibleSectionParser
|
||||
* 分别解析函数的参数、返回类型和函数体,最后封装为 FunctionNode 返回。
|
||||
* </p>
|
||||
* 顶层解析入口。解析完整个函数定义,并返回 FunctionNode。
|
||||
*
|
||||
* @param ctx 解析上下文(包含 Token 流、作用域信息等)
|
||||
* @return 构建完成的 FunctionNode
|
||||
* @param ctx 解析上下文,包含 TokenStream 和作用域信息
|
||||
* @return 构建好的 FunctionNode
|
||||
*/
|
||||
@Override
|
||||
public FunctionNode parse(ParserContext ctx) {
|
||||
TokenStream tokens = ctx.getTokens();
|
||||
TokenStream ts = ctx.getTokens();
|
||||
|
||||
// 匹配并消费 "function:" 标记
|
||||
parseFunctionHeader(tokens);
|
||||
// 1. 解析函数头(function:)
|
||||
parseFunctionHeader(ts);
|
||||
// 2. 读取并消费函数名称
|
||||
String functionName = parseFunctionName(ts);
|
||||
|
||||
// 获取函数名称
|
||||
String functionName = parseFunctionName(tokens);
|
||||
|
||||
// 用于接收参数、返回类型和函数体的容器
|
||||
// 容器用于收集解析结果
|
||||
List<ParameterNode> parameters = new ArrayList<>();
|
||||
String[] returnType = {null}; // 使用数组模拟引用,以便 lambda 内修改值
|
||||
String[] returnType = new String[1]; // 用一元素数组模拟可变引用
|
||||
List<StatementNode> body = new ArrayList<>();
|
||||
|
||||
// 构建区块解析定义(参数、返回类型、函数体)
|
||||
Map<String, SectionDefinition> sectionDefinitions = getStringSectionDefinitionMap(parameters, returnType, body);
|
||||
// 3. 构建区块解析逻辑,并使用 FlexibleSectionParser 解析
|
||||
Map<String, SectionDefinition> sections = getSectionDefinitions(parameters, returnType, body);
|
||||
FlexibleSectionParser.parse(ctx, ts, sections);
|
||||
|
||||
// 使用 FlexibleSectionParser 解析区块,顺序无关
|
||||
FlexibleSectionParser.parse(ctx, tokens, sectionDefinitions);
|
||||
// 4. 解析函数尾部(end function)
|
||||
parseFunctionFooter(ts);
|
||||
|
||||
// 匹配函数结束部分(end function)
|
||||
parseFunctionFooter(tokens);
|
||||
|
||||
// 构建语法树节点并返回
|
||||
// 5. 构造并返回 AST
|
||||
return new FunctionNode(functionName, parameters, returnType[0], body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造区块定义映射,包括参数、返回类型、函数体。
|
||||
* 构造各区块的解析定义:
|
||||
* 参数(parameter)、返回类型(return_type)、函数体(body)。
|
||||
*
|
||||
* @param parameters 参数节点容器
|
||||
* @param returnType 返回类型容器(数组模拟引用)
|
||||
* @param body 函数体语句节点容器
|
||||
* @return 各关键字对应的解析逻辑映射
|
||||
* @param params 参数节点列表容器
|
||||
* @param returnType 返回类型容器
|
||||
* @param body 函数体语句列表容器
|
||||
* @return 区块关键字到解析逻辑的映射
|
||||
*/
|
||||
private Map<String, SectionDefinition> getStringSectionDefinitionMap(List<ParameterNode> parameters, String[] returnType, List<StatementNode> body) {
|
||||
Map<String, SectionDefinition> sectionDefinitions = new HashMap<>();
|
||||
private Map<String, SectionDefinition> getSectionDefinitions(
|
||||
List<ParameterNode> params,
|
||||
String[] returnType,
|
||||
List<StatementNode> body) {
|
||||
Map<String, SectionDefinition> map = new HashMap<>();
|
||||
|
||||
// 参数部分解析规则
|
||||
sectionDefinitions.put("parameter", new SectionDefinition(
|
||||
ts -> ts.peek().getLexeme().equals("parameter"),
|
||||
(_, ts1) -> parameters.addAll(parseParameters(ts1))
|
||||
// 参数区块
|
||||
map.put("parameter", new SectionDefinition(
|
||||
(TokenStream stream) -> stream.peek().getLexeme().equals("parameter"),
|
||||
(ParserContext context, TokenStream stream) -> params.addAll(parseParameters(stream))
|
||||
));
|
||||
|
||||
// 返回类型部分解析规则
|
||||
sectionDefinitions.put("return_type", new SectionDefinition(
|
||||
ts -> ts.peek().getLexeme().equals("return_type"),
|
||||
(_, ts1) -> returnType[0] = parseReturnType(ts1)
|
||||
// 返回类型区块
|
||||
map.put("return_type", new SectionDefinition(
|
||||
(TokenStream stream) -> stream.peek().getLexeme().equals("return_type"),
|
||||
(ParserContext context, TokenStream stream) -> returnType[0] = parseReturnType(stream)
|
||||
));
|
||||
|
||||
// 函数体部分解析规则
|
||||
sectionDefinitions.put("body", new SectionDefinition(
|
||||
ts -> ts.peek().getLexeme().equals("body"),
|
||||
(ctx1, ts1) -> body.addAll(parseFunctionBody(ctx1, ts1))
|
||||
// 函数体区块
|
||||
map.put("body", new SectionDefinition(
|
||||
(TokenStream stream) -> stream.peek().getLexeme().equals("body"),
|
||||
(ParserContext context, TokenStream stream) -> body.addAll(parseFunctionBody(context, stream))
|
||||
));
|
||||
|
||||
return sectionDefinitions;
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配并解析函数头部(function:)。
|
||||
* 解析函数头部:匹配 "function:",并跳过后续的注释和空行
|
||||
*
|
||||
* @param ts Token 流
|
||||
* @param ts TokenStream
|
||||
*/
|
||||
private void parseFunctionHeader(TokenStream ts) {
|
||||
ts.expect("function");
|
||||
ts.expect(":");
|
||||
skipComments(ts);
|
||||
skipNewlines(ts);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析函数名称,并跳过换行。
|
||||
* 解析函数名称:IDENTIFIER + 换行
|
||||
*
|
||||
* @param ts Token 流
|
||||
* @param ts TokenStream
|
||||
* @return 函数名称
|
||||
*/
|
||||
private String parseFunctionName(TokenStream ts) {
|
||||
@ -124,9 +118,9 @@ public class FunctionParser implements TopLevelParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配并解析函数尾部(end function)。
|
||||
* 解析函数尾部:匹配 "end function" + 换行
|
||||
*
|
||||
* @param ts Token 流
|
||||
* @param ts TokenStream
|
||||
*/
|
||||
private void parseFunctionFooter(TokenStream ts) {
|
||||
ts.expect("end");
|
||||
@ -135,108 +129,123 @@ public class FunctionParser implements TopLevelParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析函数参数部分,格式:
|
||||
* 解析参数区块参数列表,支持在声明行尾添加注释
|
||||
* 格式:
|
||||
* <pre>
|
||||
* parameter:
|
||||
* declare param1: int
|
||||
* declare param2: string
|
||||
* declare x: int // 注释
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* @param ts Token 流
|
||||
* @return 参数节点列表
|
||||
* @param ts TokenStream
|
||||
* @return ParameterNode 列表
|
||||
*/
|
||||
private List<ParameterNode> parseParameters(TokenStream ts) {
|
||||
ts.expect("parameter");
|
||||
ts.expect(":");
|
||||
skipComments(ts);
|
||||
ts.expectType(TokenType.NEWLINE);
|
||||
skipNewlines(ts);
|
||||
|
||||
List<ParameterNode> params = new ArrayList<>();
|
||||
|
||||
// 持续解析参数声明行,直到下一个区块或 "end"
|
||||
List<ParameterNode> list = new ArrayList<>();
|
||||
while (true) {
|
||||
skipComments(ts);
|
||||
if (ts.peek().getType() == TokenType.NEWLINE) {
|
||||
ts.next(); // 跳过空行
|
||||
ts.next();
|
||||
continue;
|
||||
}
|
||||
|
||||
// 到达下一个区块或函数结尾时停止
|
||||
String keyword = ts.peek().getLexeme();
|
||||
if ("return_type".equals(keyword) || "body".equals(keyword) || "end".equals(keyword)) {
|
||||
String lex = ts.peek().getLexeme();
|
||||
if (lex.equals("return_type") || lex.equals("body") || lex.equals("end")) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 匹配 "declare paramName: Type" 格式
|
||||
ts.expect("declare");
|
||||
String paramName = ts.expectType(TokenType.IDENTIFIER).getLexeme();
|
||||
String pname = ts.expectType(TokenType.IDENTIFIER).getLexeme();
|
||||
ts.expect(":");
|
||||
String paramType = ts.expectType(TokenType.TYPE).getLexeme();
|
||||
String ptype = ts.expectType(TokenType.TYPE).getLexeme();
|
||||
// 跳过行内注释
|
||||
skipComments(ts);
|
||||
ts.expectType(TokenType.NEWLINE);
|
||||
|
||||
params.add(new ParameterNode(paramName, paramType));
|
||||
list.add(new ParameterNode(pname, ptype));
|
||||
}
|
||||
|
||||
return params;
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析返回类型部分,格式如下:
|
||||
* <pre>
|
||||
* return_type: int
|
||||
* </pre>
|
||||
* 解析返回类型区块,支持在类型声明前后添加注释
|
||||
* 格式:<pre>return_type: TYPE</pre>
|
||||
*
|
||||
* @param ts Token 流
|
||||
* @param ts TokenStream
|
||||
* @return 返回类型字符串
|
||||
*/
|
||||
private String parseReturnType(TokenStream ts) {
|
||||
ts.expect("return_type");
|
||||
ts.expect(":");
|
||||
String returnType = ts.expectType(TokenType.TYPE).getLexeme();
|
||||
// 跳过块前注释
|
||||
skipComments(ts);
|
||||
// 捕获类型 token
|
||||
Token typeToken = ts.expectType(TokenType.TYPE);
|
||||
String rtype = typeToken.getLexeme();
|
||||
// 跳过行内注释
|
||||
skipComments(ts);
|
||||
// 匹配换行
|
||||
ts.expectType(TokenType.NEWLINE);
|
||||
return returnType;
|
||||
// 跳过多余空行
|
||||
skipNewlines(ts);
|
||||
return rtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析函数体部分,格式示例:
|
||||
* <pre>
|
||||
* body:
|
||||
* print "hello"
|
||||
* return x
|
||||
* end body
|
||||
* </pre>
|
||||
* 解析函数体区块,直到遇到 "end body"
|
||||
*
|
||||
* @param ctx 解析上下文
|
||||
* @param ts Token 流
|
||||
* @return 语句节点列表
|
||||
* @param ctx ParserContext
|
||||
* @param ts TokenStream
|
||||
* @return StatementNode 列表
|
||||
*/
|
||||
private List<StatementNode> parseFunctionBody(ParserContext ctx, TokenStream ts) {
|
||||
ts.expect("body");
|
||||
ts.expect(":");
|
||||
skipComments(ts);
|
||||
ts.expectType(TokenType.NEWLINE);
|
||||
skipNewlines(ts);
|
||||
|
||||
List<StatementNode> body = new ArrayList<>();
|
||||
|
||||
// 持续解析直到遇到 end
|
||||
List<StatementNode> stmts = new ArrayList<>();
|
||||
while (true) {
|
||||
skipComments(ts);
|
||||
if (ts.peek().getType() == TokenType.NEWLINE) {
|
||||
ts.next();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("end".equals(ts.peek().getLexeme())) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 获取当前语句关键字,并通过工厂选择对应的语句解析器
|
||||
String keyword = ts.peek().getLexeme();
|
||||
StatementNode statement = StatementParserFactory.get(keyword).parse(ctx);
|
||||
body.add(statement);
|
||||
stmts.add(StatementParserFactory.get(ts.peek().getLexeme()).parse(ctx));
|
||||
}
|
||||
|
||||
// 匹配 end body
|
||||
ts.expect("end");
|
||||
ts.expect("body");
|
||||
ts.expectType(TokenType.NEWLINE);
|
||||
skipNewlines(ts);
|
||||
return stmts;
|
||||
}
|
||||
|
||||
return body;
|
||||
/**
|
||||
* 跳过所有连续的注释行(COMMENT)
|
||||
*
|
||||
* @param ts TokenStream
|
||||
*/
|
||||
private void skipComments(TokenStream ts) {
|
||||
while (ts.peek().getType() == TokenType.COMMENT) {
|
||||
ts.next();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳过所有连续的空行(NEWLINE)
|
||||
*
|
||||
* @param ts TokenStream
|
||||
*/
|
||||
private void skipNewlines(TokenStream ts) {
|
||||
while (ts.peek().getType() == TokenType.NEWLINE) {
|
||||
ts.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user