From a7e2e61b10d1aa72d40d08c580ddb4205bcaab0c Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 10 May 2025 16:34:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81float32double64byte8short15fl?= =?UTF-8?q?oat32double64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ir/builder/ExpressionBuilder.java | 140 ++++++----- .../jcnc/snow/compiler/ir/core/IROpCode.java | 97 +++++--- .../parser/function/FunctionParser.java | 229 +++++++++--------- test | 6 +- 4 files changed, 263 insertions(+), 209 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java index c5b5c1f..c07aa83 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java @@ -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 指令,并返回结果寄存器。 - *

- * 功能: + * ExpressionBuilder 将 AST 中的 ExpressionNode 转换为 IR 指令,并返回结果虚拟寄存器。 + * 支持: *

    - *
  1. 处理数字字面量节点,生成加载常量指令;
  2. - *
  3. 处理标识符节点,从作用域获取对应的虚拟寄存器;
  4. - *
  5. 处理二元表达式节点,递归构建左右操作数并生成二元运算指令;
  6. + *
  7. NumberLiteralNode:根据文本后缀(b/S/L/f/d)或内容自动区分 bytke/short/int/long/float/double,并生成常量加载指令
  8. + *
  9. IdentifierNode:从作用域获取已声明的虚拟寄存器
  10. + *
  11. BinaryExpressionNode:递归构建子表达式,根据数据宽度和符号生成对应的二元运算指令
  12. *
*/ public class ExpressionBuilder { - /** - * 操作符到 IR 操作码的映射表 - */ - private static final Map OP_MAP = Map.of( - "+", IROpCode.ADD_I32, - "-", IROpCode.SUB_I32, - "*", IROpCode.MUL_I32, - "/", IROpCode.DIV_I32 - ); + // 不同位宽整数和浮点的运算码映射 + private static final Map OP_I8 = Map.of("+", IROpCode.ADD_B8, "-", IROpCode.SUB_B8, "*", IROpCode.MUL_B8, "/", IROpCode.DIV_B8); + private static final Map OP_I16 = Map.of("+", IROpCode.ADD_S16, "-", IROpCode.SUB_S16, "*", IROpCode.MUL_S16, "/", IROpCode.DIV_S16); + private static final Map OP_I32 = Map.of("+", IROpCode.ADD_I32, "-", IROpCode.SUB_I32, "*", IROpCode.MUL_I32, "/", IROpCode.DIV_I32); + private static final Map OP_L64 = Map.of("+", IROpCode.ADD_L64, "-", IROpCode.SUB_L64, "*", IROpCode.MUL_L64, "/", IROpCode.DIV_L64); + private static final Map OP_F32 = Map.of("+", IROpCode.ADD_F32, "-", IROpCode.SUB_F32, "*", IROpCode.MUL_F32, "/", IROpCode.DIV_F32); + private static final Map 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