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());
}
}
diff --git a/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCode.java b/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCode.java
index bec7a69..14fd198 100644
--- a/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCode.java
+++ b/src/main/java/org/jcnc/snow/compiler/ir/core/IROpCode.java
@@ -4,75 +4,92 @@ package org.jcnc.snow.compiler.ir.core;
* IROpCode —— IR 层支持的操作码(Opcode)枚举类型。
*
* 本枚举类定义了中间表示层可用的所有基本指令类型,供 {@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
-}
+}
\ No newline at end of file
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 f142b5a..d8fabd9 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
@@ -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} 是一个顶层语法分析器,用于解析函数定义的语法结构。
- *
- * 该解析器通过 {@code FlexibleSectionParser} 解析函数定义的多个部分,包括:
- *
- * - 函数名
- * - 参数列表
- * - 返回类型
- * - 函数体
- *
- * 各部分的顺序不固定,由 FlexibleSectionParser 按规则识别和处理。
- *
+ * 顶层的函数定义解析器。
+ *
+ * 通过 FlexibleSectionParser 按区块顺序解析函数的各个部分:
+ * 函数头(名称)、参数列表、返回类型、函数体,并最终生成 FunctionNode。
+ * 支持在参数或返回类型声明中出现注释,自动跳过注释和空行而不干扰语法解析。
*/
public class FunctionParser implements TopLevelParser {
/**
- * 解析函数定义,构建函数的抽象语法树节点。
- *
- * 此方法首先解析函数的头部和名称,然后通过 FlexibleSectionParser
- * 分别解析函数的参数、返回类型和函数体,最后封装为 FunctionNode 返回。
- *
+ * 顶层解析入口。解析完整个函数定义,并返回 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 parameters = new ArrayList<>();
- String[] returnType = {null}; // 使用数组模拟引用,以便 lambda 内修改值
+ String[] returnType = new String[1]; // 用一元素数组模拟可变引用
List body = new ArrayList<>();
- // 构建区块解析定义(参数、返回类型、函数体)
- Map sectionDefinitions = getStringSectionDefinitionMap(parameters, returnType, body);
+ // 3. 构建区块解析逻辑,并使用 FlexibleSectionParser 解析
+ Map 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 getStringSectionDefinitionMap(List parameters, String[] returnType, List body) {
- Map sectionDefinitions = new HashMap<>();
+ private Map getSectionDefinitions(
+ List params,
+ String[] returnType,
+ List body) {
+ Map 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 {
}
/**
- * 解析函数参数部分,格式:
+ * 解析参数区块参数列表,支持在声明行尾添加注释
+ * 格式:
*
* parameter:
- * declare param1: int
- * declare param2: string
+ * declare x: int // 注释
+ * ...
*
*
- * @param ts Token 流
- * @return 参数节点列表
+ * @param ts TokenStream
+ * @return ParameterNode 列表
*/
private List parseParameters(TokenStream ts) {
ts.expect("parameter");
ts.expect(":");
+ skipComments(ts);
ts.expectType(TokenType.NEWLINE);
+ skipNewlines(ts);
- List params = new ArrayList<>();
-
- // 持续解析参数声明行,直到下一个区块或 "end"
+ List 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;
}
/**
- * 解析返回类型部分,格式如下:
- *
- * return_type: int
- *
+ * 解析返回类型区块,支持在类型声明前后添加注释
+ * 格式:return_type: TYPE
*
- * @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;
}
/**
- * 解析函数体部分,格式示例:
- *
- * body:
- * print "hello"
- * return x
- * end body
- *
+ * 解析函数体区块,直到遇到 "end body"
*
- * @param ctx 解析上下文
- * @param ts Token 流
- * @return 语句节点列表
+ * @param ctx ParserContext
+ * @param ts TokenStream
+ * @return StatementNode 列表
*/
private List parseFunctionBody(ParserContext ctx, TokenStream ts) {
ts.expect("body");
ts.expect(":");
+ skipComments(ts);
ts.expectType(TokenType.NEWLINE);
+ skipNewlines(ts);
- List body = new ArrayList<>();
-
- // 持续解析直到遇到 end
+ List 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();
+ }
}
}
diff --git a/test b/test
index a816f71..ae71d59 100644
--- a/test
+++ b/test
@@ -2,13 +2,13 @@ module: CommonTasks
function: main1
parameter:
declare num1: int
- declare num2: int // 1
+ declare num2: int
return_type:int
-
body:
num1 = 10
- return num1
+ num2=1
+ return num1 +num2
end body
end function
end module