!19 fix: 语义分析报错显示未知位置
Merge pull request !19 from zhangxun/bugfix/semantic-error-location-information
This commit is contained in:
commit
c73c72d77f
@ -76,6 +76,14 @@ public final class IRProgramBuilder {
|
|||||||
* @return 生成的 FunctionNode,用于后续 IRFunction 构建
|
* @return 生成的 FunctionNode,用于后续 IRFunction 构建
|
||||||
*/
|
*/
|
||||||
private FunctionNode wrapTopLevel(StatementNode stmt) {
|
private FunctionNode wrapTopLevel(StatementNode stmt) {
|
||||||
return new FunctionNode("_start", null, String.valueOf(List.of()), List.of(stmt));
|
return new FunctionNode(
|
||||||
|
"_start",
|
||||||
|
null,
|
||||||
|
String.valueOf(List.of()),
|
||||||
|
List.of(stmt),
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,12 +66,12 @@ public class StatementBuilder {
|
|||||||
buildIf(ifNode);
|
buildIf(ifNode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (stmt instanceof ExpressionStatementNode(ExpressionNode exp)) {
|
if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, _, _, _)) {
|
||||||
// 纯表达式语句,如 foo();
|
// 纯表达式语句,如 foo();
|
||||||
expr.build(exp);
|
expr.build(exp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs)) {
|
if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, _, _, _)) {
|
||||||
// 赋值语句,如 a = b + 1;
|
// 赋值语句,如 a = b + 1;
|
||||||
|
|
||||||
final String type = ctx.getScope().lookupType(var);
|
final String type = ctx.getScope().lookupType(var);
|
||||||
@ -208,7 +208,10 @@ public class StatementBuilder {
|
|||||||
if (cond instanceof BinaryExpressionNode(
|
if (cond instanceof BinaryExpressionNode(
|
||||||
ExpressionNode left,
|
ExpressionNode left,
|
||||||
String operator,
|
String operator,
|
||||||
ExpressionNode right
|
ExpressionNode right,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
_
|
||||||
)
|
)
|
||||||
&& ComparisonUtils.isComparisonOperator(operator)) {
|
&& ComparisonUtils.isComparisonOperator(operator)) {
|
||||||
|
|
||||||
|
|||||||
@ -16,8 +16,17 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
|||||||
*
|
*
|
||||||
* @param variable 左值变量名(即赋值目标)
|
* @param variable 左值变量名(即赋值目标)
|
||||||
* @param value 表达式右值(即赋值来源)
|
* @param value 表达式右值(即赋值来源)
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record AssignmentNode(String variable, ExpressionNode value) implements StatementNode {
|
public record AssignmentNode(
|
||||||
|
String variable,
|
||||||
|
ExpressionNode value,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements StatementNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回赋值语句的字符串形式,便于调试与日志输出。
|
* 返回赋值语句的字符串形式,便于调试与日志输出。
|
||||||
|
|||||||
@ -12,9 +12,18 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
* @param left 左操作数(子表达式)
|
* @param left 左操作数(子表达式)
|
||||||
* @param operator 运算符字符串(如 "+", "-", "*", "/" 等)
|
* @param operator 运算符字符串(如 "+", "-", "*", "/" 等)
|
||||||
* @param right 右操作数(子表达式)
|
* @param right 右操作数(子表达式)
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record BinaryExpressionNode(ExpressionNode left, String operator,
|
public record BinaryExpressionNode(
|
||||||
ExpressionNode right) implements ExpressionNode {
|
ExpressionNode left,
|
||||||
|
String operator,
|
||||||
|
ExpressionNode right,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回该二元运算表达式的字符串表示形式。
|
* 返回该二元运算表达式的字符串表示形式。
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import java.util.List;
|
|||||||
* @param arguments 参数表达式列表,表示函数调用中传递给函数的实际参数。参数的顺序与调用顺序一致。
|
* @param arguments 参数表达式列表,表示函数调用中传递给函数的实际参数。参数的顺序与调用顺序一致。
|
||||||
* @param line 当前表达式所在的行号,方便调试和错误定位。
|
* @param line 当前表达式所在的行号,方便调试和错误定位。
|
||||||
* @param column 当前表达式所在的列号,用于精确定位错误位置。
|
* @param column 当前表达式所在的列号,用于精确定位错误位置。
|
||||||
|
* @param file 当前表达式所在的文件,用于错误定位。
|
||||||
*/
|
*/
|
||||||
public record CallExpressionNode(
|
public record CallExpressionNode(
|
||||||
ExpressionNode callee, // 被调用的表达式节点,表示函数或方法名
|
ExpressionNode callee, // 被调用的表达式节点,表示函数或方法名
|
||||||
|
|||||||
@ -23,6 +23,15 @@ public class DeclarationNode implements StatementNode {
|
|||||||
/** 可选的初始化表达式 */
|
/** 可选的初始化表达式 */
|
||||||
private final Optional<ExpressionNode> initializer;
|
private final Optional<ExpressionNode> initializer;
|
||||||
|
|
||||||
|
/** 当前节点所在的行号 **/
|
||||||
|
private final int line;
|
||||||
|
|
||||||
|
/** 当前节点所在的列号 **/
|
||||||
|
private final int column;
|
||||||
|
|
||||||
|
/** 当前节点所在的文件 **/
|
||||||
|
private final String file;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造一个 {@code DeclarationNode} 实例。
|
* 构造一个 {@code DeclarationNode} 实例。
|
||||||
*
|
*
|
||||||
@ -30,10 +39,13 @@ public class DeclarationNode implements StatementNode {
|
|||||||
* @param type 变量类型字符串(如 "int"、"string")
|
* @param type 变量类型字符串(如 "int"、"string")
|
||||||
* @param initializer 可选初始化表达式,若为 {@code null} 表示未初始化
|
* @param initializer 可选初始化表达式,若为 {@code null} 表示未初始化
|
||||||
*/
|
*/
|
||||||
public DeclarationNode(String name, String type, ExpressionNode initializer) {
|
public DeclarationNode(String name, String type, ExpressionNode initializer, int line, int column, String file) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.initializer = Optional.ofNullable(initializer);
|
this.initializer = Optional.ofNullable(initializer);
|
||||||
|
this.line = line;
|
||||||
|
this.column = column;
|
||||||
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,4 +74,29 @@ public class DeclarationNode implements StatementNode {
|
|||||||
public Optional<ExpressionNode> getInitializer() {
|
public Optional<ExpressionNode> getInitializer() {
|
||||||
return initializer;
|
return initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前表达式所在的行号。
|
||||||
|
*
|
||||||
|
* @return 当前表达式的行号。
|
||||||
|
*/
|
||||||
|
public int line() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前表达式所在的列号。
|
||||||
|
*
|
||||||
|
* @return 当前表达式的列号。
|
||||||
|
*/
|
||||||
|
public int column() {
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前表达式所在的文件名。
|
||||||
|
*
|
||||||
|
* @return 当前表达式所在的文件名。
|
||||||
|
*/
|
||||||
|
public String file() { return file; }
|
||||||
}
|
}
|
||||||
@ -11,6 +11,14 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param expression 表达式主体,通常为函数调用、赋值、方法链式调用等可求值表达式。
|
* @param expression 表达式主体,通常为函数调用、赋值、方法链式调用等可求值表达式。
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record ExpressionStatementNode(ExpressionNode expression) implements StatementNode {
|
public record ExpressionStatementNode(
|
||||||
|
ExpressionNode expression,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements StatementNode {
|
||||||
}
|
}
|
||||||
@ -17,7 +17,17 @@ import java.util.List;
|
|||||||
* @param parameters 参数列表,每项为 {@link ParameterNode} 表示一个形参定义
|
* @param parameters 参数列表,每项为 {@link ParameterNode} 表示一个形参定义
|
||||||
* @param returnType 函数的返回类型(如 "int"、"void" 等)
|
* @param returnType 函数的返回类型(如 "int"、"void" 等)
|
||||||
* @param body 函数体语句块,由一组 {@link StatementNode} 构成
|
* @param body 函数体语句块,由一组 {@link StatementNode} 构成
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record FunctionNode(String name, List<ParameterNode> parameters, String returnType,
|
public record FunctionNode(
|
||||||
List<StatementNode> body) implements Node {
|
String name,
|
||||||
|
List<ParameterNode> parameters,
|
||||||
|
String returnType,
|
||||||
|
List<StatementNode> body,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements Node {
|
||||||
}
|
}
|
||||||
@ -10,8 +10,16 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param name 标识符的文本名称(如变量名 "x",函数名 "foo")
|
* @param name 标识符的文本名称(如变量名 "x",函数名 "foo")
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record IdentifierNode(String name) implements ExpressionNode {
|
public record IdentifierNode(
|
||||||
|
String name,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回标识符节点的字符串形式,通常为其名称本身。
|
* 返回标识符节点的字符串形式,通常为其名称本身。
|
||||||
|
|||||||
@ -29,10 +29,16 @@ import java.util.List;
|
|||||||
* @param condition 控制分支执行的条件表达式
|
* @param condition 控制分支执行的条件表达式
|
||||||
* @param thenBranch 条件为 true 时执行的语句块
|
* @param thenBranch 条件为 true 时执行的语句块
|
||||||
* @param elseBranch 条件为 false 时执行的语句块(可为空)
|
* @param elseBranch 条件为 false 时执行的语句块(可为空)
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record IfNode(
|
public record IfNode(
|
||||||
ExpressionNode condition,
|
ExpressionNode condition,
|
||||||
List<StatementNode> thenBranch,
|
List<StatementNode> thenBranch,
|
||||||
List<StatementNode> elseBranch
|
List<StatementNode> elseBranch,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
) implements StatementNode {
|
) implements StatementNode {
|
||||||
}
|
}
|
||||||
@ -14,6 +14,14 @@ import org.jcnc.snow.compiler.parser.ast.base.Node;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param moduleName 被导入的模块名称,通常为点分层次结构(如 "core.utils")
|
* @param moduleName 被导入的模块名称,通常为点分层次结构(如 "core.utils")
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record ImportNode(String moduleName) implements Node {
|
public record ImportNode(
|
||||||
|
String moduleName,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements Node {
|
||||||
}
|
}
|
||||||
@ -17,7 +17,17 @@ import java.util.List;
|
|||||||
* @param condition 每次迭代前评估的条件表达式,控制循环是否继续
|
* @param condition 每次迭代前评估的条件表达式,控制循环是否继续
|
||||||
* @param update 每轮迭代完成后执行的更新语句
|
* @param update 每轮迭代完成后执行的更新语句
|
||||||
* @param body 循环体语句列表,表示循环主体执行逻辑
|
* @param body 循环体语句列表,表示循环主体执行逻辑
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record LoopNode(StatementNode initializer, ExpressionNode condition, StatementNode update,
|
public record LoopNode(
|
||||||
List<StatementNode> body) implements StatementNode {
|
StatementNode initializer,
|
||||||
|
ExpressionNode condition,
|
||||||
|
StatementNode update,
|
||||||
|
List<StatementNode> body,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements StatementNode {
|
||||||
}
|
}
|
||||||
@ -11,8 +11,17 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
*
|
*
|
||||||
* @param object 左侧对象表达式,表示成员所属的作用域或容器
|
* @param object 左侧对象表达式,表示成员所属的作用域或容器
|
||||||
* @param member 要访问的成员名称(字段名或方法名)
|
* @param member 要访问的成员名称(字段名或方法名)
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record MemberExpressionNode(ExpressionNode object, String member) implements ExpressionNode {
|
public record MemberExpressionNode(
|
||||||
|
ExpressionNode object,
|
||||||
|
String member,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回成员访问表达式的字符串形式。
|
* 返回成员访问表达式的字符串形式。
|
||||||
|
|||||||
@ -13,8 +13,18 @@ import java.util.StringJoiner;
|
|||||||
* @param name 模块名称。
|
* @param name 模块名称。
|
||||||
* @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。
|
* @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。
|
||||||
* @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。
|
* @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record ModuleNode(String name, List<ImportNode> imports, List<FunctionNode> functions) implements Node {
|
public record ModuleNode(
|
||||||
|
String name,
|
||||||
|
List<ImportNode> imports,
|
||||||
|
List<FunctionNode> functions,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements Node {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回模块节点的字符串表示形式,包含模块名、导入模块列表和函数列表。
|
* 返回模块节点的字符串表示形式,包含模块名、导入模块列表和函数列表。
|
||||||
|
|||||||
@ -11,8 +11,17 @@ import org.jcnc.snow.compiler.parser.ast.base.Node;
|
|||||||
*
|
*
|
||||||
* @param name 参数名称标识符
|
* @param name 参数名称标识符
|
||||||
* @param type 参数类型字符串(如 "int"、"string")
|
* @param type 参数类型字符串(如 "int"、"string")
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record ParameterNode(String name, String type) implements Node {
|
public record ParameterNode(
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements Node {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回参数的字符串形式,格式为 {@code name:type}。
|
* 返回参数的字符串形式,格式为 {@code name:type}。
|
||||||
|
|||||||
@ -23,13 +23,25 @@ public class ReturnNode implements StatementNode {
|
|||||||
/** 可选的返回值表达式 */
|
/** 可选的返回值表达式 */
|
||||||
private final Optional<ExpressionNode> expression;
|
private final Optional<ExpressionNode> expression;
|
||||||
|
|
||||||
|
/** 当前节点所在的行号 **/
|
||||||
|
private final int line;
|
||||||
|
|
||||||
|
/** 当前节点所在的列号 **/
|
||||||
|
private final int column;
|
||||||
|
|
||||||
|
/** 当前节点所在的文件 **/
|
||||||
|
private final String file;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造一个 {@code ReturnNode} 实例。
|
* 构造一个 {@code ReturnNode} 实例。
|
||||||
*
|
*
|
||||||
* @param expression 返回值表达式,如果无返回值则可为 {@code null}
|
* @param expression 返回值表达式,如果无返回值则可为 {@code null}
|
||||||
*/
|
*/
|
||||||
public ReturnNode(ExpressionNode expression) {
|
public ReturnNode(ExpressionNode expression, int line, int column, String file) {
|
||||||
this.expression = Optional.ofNullable(expression);
|
this.expression = Optional.ofNullable(expression);
|
||||||
|
this.line = line;
|
||||||
|
this.column = column;
|
||||||
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,4 +52,29 @@ public class ReturnNode implements StatementNode {
|
|||||||
public Optional<ExpressionNode> getExpression() {
|
public Optional<ExpressionNode> getExpression() {
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前表达式所在的行号。
|
||||||
|
*
|
||||||
|
* @return 当前表达式的行号。
|
||||||
|
*/
|
||||||
|
public int line() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前表达式所在的列号。
|
||||||
|
*
|
||||||
|
* @return 当前表达式的列号。
|
||||||
|
*/
|
||||||
|
public int column() {
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前表达式所在的文件名。
|
||||||
|
*
|
||||||
|
* @return 当前表达式所在的文件名。
|
||||||
|
*/
|
||||||
|
public String file() { return file; }
|
||||||
}
|
}
|
||||||
@ -15,9 +15,17 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
*
|
*
|
||||||
* @param operator 一元运算符(仅 "-" 或 "!")
|
* @param operator 一元运算符(仅 "-" 或 "!")
|
||||||
* @param operand 运算对象 / 右操作数
|
* @param operand 运算对象 / 右操作数
|
||||||
|
* @param line 当前节点所在的行号
|
||||||
|
* @param column 当前节点所在的列号
|
||||||
|
* @param file 当前节点所在的文件
|
||||||
*/
|
*/
|
||||||
public record UnaryExpressionNode(String operator,
|
public record UnaryExpressionNode(
|
||||||
ExpressionNode operand) implements ExpressionNode {
|
String operator,
|
||||||
|
ExpressionNode operand,
|
||||||
|
int line,
|
||||||
|
int column,
|
||||||
|
String file
|
||||||
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成调试友好的字符串表示,例如 {@code "-x"} 或 {@code "!flag"}。
|
* 生成调试友好的字符串表示,例如 {@code "-x"} 或 {@code "!flag"}。
|
||||||
|
|||||||
@ -37,6 +37,11 @@ public record BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) i
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode parse(ParserContext ctx, ExpressionNode left) {
|
public ExpressionNode parse(ParserContext ctx, ExpressionNode left) {
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
Token op = ctx.getTokens().next();
|
Token op = ctx.getTokens().next();
|
||||||
int prec = precedence.ordinal();
|
int prec = precedence.ordinal();
|
||||||
|
|
||||||
@ -46,7 +51,7 @@ public record BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) i
|
|||||||
leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]
|
leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
return new BinaryExpressionNode(left, op.getLexeme(), right);
|
return new BinaryExpressionNode(left, op.getLexeme(), right, line, column, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -26,14 +26,15 @@ public class CallParselet implements InfixParselet {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode parse(ParserContext ctx, ExpressionNode left) {
|
public ExpressionNode parse(ParserContext ctx, ExpressionNode left) {
|
||||||
|
// 获取函数名 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek(-1).getLine();
|
||||||
|
int column = ctx.getTokens().peek(-1).getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
ctx.getTokens().next(); // 消费 "("
|
ctx.getTokens().next(); // 消费 "("
|
||||||
|
|
||||||
List<ExpressionNode> args = new ArrayList<>();
|
List<ExpressionNode> args = new ArrayList<>();
|
||||||
|
|
||||||
// 获取当前 token 的行号和列号
|
|
||||||
int line = ctx.getTokens().peek().getLine();
|
|
||||||
int column = ctx.getTokens().peek().getCol();
|
|
||||||
|
|
||||||
// 解析函数调用参数
|
// 解析函数调用参数
|
||||||
if (!ctx.getTokens().peek().getLexeme().equals(")")) {
|
if (!ctx.getTokens().peek().getLexeme().equals(")")) {
|
||||||
do {
|
do {
|
||||||
@ -43,8 +44,7 @@ public class CallParselet implements InfixParselet {
|
|||||||
|
|
||||||
ctx.getTokens().expect(")"); // 消费并验证 ")"
|
ctx.getTokens().expect(")"); // 消费并验证 ")"
|
||||||
|
|
||||||
// 创建 CallExpressionNode 并传递位置信息,文件名称
|
// 创建 CallExpressionNode 并传递位置信息
|
||||||
String file = ctx.getSourceName();
|
|
||||||
return new CallExpressionNode(left, args, line, column, file);
|
return new CallExpressionNode(left, args, line, column, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,11 @@ public class IdentifierParselet implements PrefixParselet {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode parse(ParserContext ctx, Token token) {
|
public ExpressionNode parse(ParserContext ctx, Token token) {
|
||||||
return new IdentifierNode(token.getLexeme());
|
// 获取标识符 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek(-1).getLine();
|
||||||
|
int column = ctx.getTokens().peek(-1).getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
|
return new IdentifierNode(token.getLexeme(), line, column, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,8 +28,13 @@ public class MemberParselet implements InfixParselet {
|
|||||||
TokenStream ts = ctx.getTokens();
|
TokenStream ts = ctx.getTokens();
|
||||||
ts.expect("."); // 消费点号
|
ts.expect("."); // 消费点号
|
||||||
|
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
String member = ts.expectType(TokenType.IDENTIFIER).getLexeme();
|
String member = ts.expectType(TokenType.IDENTIFIER).getLexeme();
|
||||||
return new MemberExpressionNode(left, member);
|
return new MemberExpressionNode(left, member, line, column, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -41,6 +41,11 @@ public class UnaryOperatorParselet implements PrefixParselet {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode parse(ParserContext ctx, Token token) {
|
public ExpressionNode parse(ParserContext ctx, Token token) {
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
/* ------------------------------------------------------------
|
/* ------------------------------------------------------------
|
||||||
* 1. 以 UNARY 优先级递归解析操作数,避免错误结合顺序。
|
* 1. 以 UNARY 优先级递归解析操作数,避免错误结合顺序。
|
||||||
* ------------------------------------------------------------ */
|
* ------------------------------------------------------------ */
|
||||||
@ -50,6 +55,6 @@ public class UnaryOperatorParselet implements PrefixParselet {
|
|||||||
/* ------------------------------------------------------------
|
/* ------------------------------------------------------------
|
||||||
* 2. 封装成 AST 节点并返回。
|
* 2. 封装成 AST 节点并返回。
|
||||||
* ------------------------------------------------------------ */
|
* ------------------------------------------------------------ */
|
||||||
return new UnaryExpressionNode(token.getLexeme(), operand);
|
return new UnaryExpressionNode(token.getLexeme(), operand, line, column, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,11 @@ public class FunctionParser implements TopLevelParser {
|
|||||||
public FunctionNode parse(ParserContext ctx) {
|
public FunctionNode parse(ParserContext ctx) {
|
||||||
TokenStream ts = ctx.getTokens();
|
TokenStream ts = ctx.getTokens();
|
||||||
|
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
parseFunctionHeader(ts);
|
parseFunctionHeader(ts);
|
||||||
String functionName = parseFunctionName(ts);
|
String functionName = parseFunctionName(ts);
|
||||||
|
|
||||||
@ -69,7 +74,7 @@ public class FunctionParser implements TopLevelParser {
|
|||||||
|
|
||||||
parseFunctionFooter(ts);
|
parseFunctionFooter(ts);
|
||||||
|
|
||||||
return new FunctionNode(functionName, parameters, returnType[0], body);
|
return new FunctionNode(functionName, parameters, returnType[0], body, line, column, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,7 +97,7 @@ public class FunctionParser implements TopLevelParser {
|
|||||||
|
|
||||||
map.put("parameter", new SectionDefinition(
|
map.put("parameter", new SectionDefinition(
|
||||||
(TokenStream stream) -> stream.peek().getLexeme().equals("parameter"),
|
(TokenStream stream) -> stream.peek().getLexeme().equals("parameter"),
|
||||||
(ParserContext context, TokenStream stream) -> params.addAll(parseParameters(stream))
|
(ParserContext context, TokenStream stream) -> params.addAll(parseParameters(context))
|
||||||
));
|
));
|
||||||
|
|
||||||
map.put("return_type", new SectionDefinition(
|
map.put("return_type", new SectionDefinition(
|
||||||
@ -154,10 +159,12 @@ public class FunctionParser implements TopLevelParser {
|
|||||||
* </pre>
|
* </pre>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param ts 当前使用的 {@link TokenStream}。
|
* @param ctx 当前解析上下文,包含 {@link TokenStream} 和符号表等作用域信息。
|
||||||
* @return 所有参数节点的列表。
|
* @return 所有参数节点的列表。
|
||||||
*/
|
*/
|
||||||
private List<ParameterNode> parseParameters(TokenStream ts) {
|
private List<ParameterNode> parseParameters(ParserContext ctx) {
|
||||||
|
TokenStream ts = ctx.getTokens();
|
||||||
|
|
||||||
ts.expect("parameter");
|
ts.expect("parameter");
|
||||||
ts.expect(":");
|
ts.expect(":");
|
||||||
skipComments(ts);
|
skipComments(ts);
|
||||||
@ -175,13 +182,19 @@ public class FunctionParser implements TopLevelParser {
|
|||||||
if (lex.equals("return_type") || lex.equals("body") || lex.equals("end")) {
|
if (lex.equals("return_type") || lex.equals("body") || lex.equals("end")) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
ts.expect("declare");
|
ts.expect("declare");
|
||||||
String pname = ts.expectType(TokenType.IDENTIFIER).getLexeme();
|
String pname = ts.expectType(TokenType.IDENTIFIER).getLexeme();
|
||||||
ts.expect(":");
|
ts.expect(":");
|
||||||
String ptype = ts.expectType(TokenType.TYPE).getLexeme();
|
String ptype = ts.expectType(TokenType.TYPE).getLexeme();
|
||||||
skipComments(ts);
|
skipComments(ts);
|
||||||
ts.expectType(TokenType.NEWLINE);
|
ts.expectType(TokenType.NEWLINE);
|
||||||
list.add(new ParameterNode(pname, ptype));
|
list.add(new ParameterNode(pname, ptype, line, column, file));
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,13 +46,18 @@ public class ImportParser {
|
|||||||
|
|
||||||
// 解析一个或多个模块名(标识符),允许使用逗号分隔多个模块
|
// 解析一个或多个模块名(标识符),允许使用逗号分隔多个模块
|
||||||
do {
|
do {
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
// 获取当前标识符类型的词法单元,并提取其原始词素
|
// 获取当前标识符类型的词法单元,并提取其原始词素
|
||||||
String mod = ctx.getTokens()
|
String mod = ctx.getTokens()
|
||||||
.expectType(TokenType.IDENTIFIER)
|
.expectType(TokenType.IDENTIFIER)
|
||||||
.getLexeme();
|
.getLexeme();
|
||||||
|
|
||||||
// 创建 ImportNode 节点并加入列表
|
// 创建 ImportNode 节点并加入列表
|
||||||
imports.add(new ImportNode(mod));
|
imports.add(new ImportNode(mod, line, column, file));
|
||||||
} while (ctx.getTokens().match(",")); // 如果匹配到逗号,继续解析下一个模块名
|
} while (ctx.getTokens().match(",")); // 如果匹配到逗号,继续解析下一个模块名
|
||||||
|
|
||||||
// 最后必须匹配换行符,标志 import 语句的结束
|
// 最后必须匹配换行符,标志 import 语句的结束
|
||||||
|
|||||||
@ -40,6 +40,11 @@ public class ModuleParser implements TopLevelParser {
|
|||||||
// 获取当前上下文中提供的词法流
|
// 获取当前上下文中提供的词法流
|
||||||
TokenStream ts = ctx.getTokens();
|
TokenStream ts = ctx.getTokens();
|
||||||
|
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
// 期望模块声明以关键字 "module:" 开始
|
// 期望模块声明以关键字 "module:" 开始
|
||||||
ts.expect("module");
|
ts.expect("module");
|
||||||
ts.expect(":");
|
ts.expect(":");
|
||||||
@ -90,6 +95,6 @@ public class ModuleParser implements TopLevelParser {
|
|||||||
ts.expect("module");
|
ts.expect("module");
|
||||||
|
|
||||||
// 构建并返回完整的模块语法树节点
|
// 构建并返回完整的模块语法树节点
|
||||||
return new ModuleNode(name, imports, functions);
|
return new ModuleNode(name, imports, functions, line, column, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,6 +43,11 @@ public class DeclarationStatementParser implements StatementParser {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public DeclarationNode parse(ParserContext ctx) {
|
public DeclarationNode parse(ParserContext ctx) {
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
// 声明语句必须以 "declare" 开头
|
// 声明语句必须以 "declare" 开头
|
||||||
ctx.getTokens().expect("declare");
|
ctx.getTokens().expect("declare");
|
||||||
|
|
||||||
@ -69,6 +74,6 @@ public class DeclarationStatementParser implements StatementParser {
|
|||||||
ctx.getTokens().expectType(TokenType.NEWLINE);
|
ctx.getTokens().expectType(TokenType.NEWLINE);
|
||||||
|
|
||||||
// 返回构建好的声明语法树节点
|
// 返回构建好的声明语法树节点
|
||||||
return new DeclarationNode(name, type, init);
|
return new DeclarationNode(name, type, init, line, column, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,11 @@ public class ExpressionStatementParser implements StatementParser {
|
|||||||
throw new IllegalStateException("Cannot parse expression starting with keyword: " + ts.peek().getLexeme());
|
throw new IllegalStateException("Cannot parse expression starting with keyword: " + ts.peek().getLexeme());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
// 处理赋值语句:格式为 identifier = expression
|
// 处理赋值语句:格式为 identifier = expression
|
||||||
if (ts.peek().getType() == TokenType.IDENTIFIER
|
if (ts.peek().getType() == TokenType.IDENTIFIER
|
||||||
&& ts.peek(1).getLexeme().equals("=")) {
|
&& ts.peek(1).getLexeme().equals("=")) {
|
||||||
@ -58,13 +63,13 @@ public class ExpressionStatementParser implements StatementParser {
|
|||||||
ts.expect("="); // 消耗等号
|
ts.expect("="); // 消耗等号
|
||||||
ExpressionNode value = new PrattExpressionParser().parse(ctx); // 解析表达式
|
ExpressionNode value = new PrattExpressionParser().parse(ctx); // 解析表达式
|
||||||
ts.expectType(TokenType.NEWLINE); // 语句必须以换行符结束
|
ts.expectType(TokenType.NEWLINE); // 语句必须以换行符结束
|
||||||
return new AssignmentNode(varName, value); // 返回赋值节点
|
return new AssignmentNode(varName, value, line, column, file); // 返回赋值节点
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理普通表达式语句,如函数调用、字面量、运算表达式等
|
// 处理普通表达式语句,如函数调用、字面量、运算表达式等
|
||||||
ExpressionNode expr = new PrattExpressionParser().parse(ctx);
|
ExpressionNode expr = new PrattExpressionParser().parse(ctx);
|
||||||
ts.expectType(TokenType.NEWLINE); // 语句必须以换行符结束
|
ts.expectType(TokenType.NEWLINE); // 语句必须以换行符结束
|
||||||
return new ExpressionStatementNode(expr); // 返回表达式语句节点
|
return new ExpressionStatementNode(expr, line, column, file); // 返回表达式语句节点
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,11 @@ public class IfStatementParser implements StatementParser {
|
|||||||
public IfNode parse(ParserContext ctx) {
|
public IfNode parse(ParserContext ctx) {
|
||||||
var ts = ctx.getTokens(); // 获取 token 流引用
|
var ts = ctx.getTokens(); // 获取 token 流引用
|
||||||
|
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
// 消耗起始关键字 "if"
|
// 消耗起始关键字 "if"
|
||||||
ts.expect("if");
|
ts.expect("if");
|
||||||
|
|
||||||
@ -120,6 +125,6 @@ public class IfStatementParser implements StatementParser {
|
|||||||
ts.expectType(TokenType.NEWLINE);
|
ts.expectType(TokenType.NEWLINE);
|
||||||
|
|
||||||
// 构建并返回 IfNode,包含条件、then 分支和 else 分支
|
// 构建并返回 IfNode,包含条件、then 分支和 else 分支
|
||||||
return new IfNode(condition, thenBranch, elseBranch);
|
return new IfNode(condition, thenBranch, elseBranch, line, column, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,6 +64,12 @@ public class LoopStatementParser implements StatementParser {
|
|||||||
public LoopNode parse(ParserContext ctx) {
|
public LoopNode parse(ParserContext ctx) {
|
||||||
TokenStream ts = ctx.getTokens();
|
TokenStream ts = ctx.getTokens();
|
||||||
|
|
||||||
|
// 获取当前 token 的行号、列号
|
||||||
|
int loop_line = ctx.getTokens().peek().getLine();
|
||||||
|
int loop_column = ctx.getTokens().peek().getCol();
|
||||||
|
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
// 匹配 loop: 起始语法
|
// 匹配 loop: 起始语法
|
||||||
ParserUtils.matchHeader(ts, "loop");
|
ParserUtils.matchHeader(ts, "loop");
|
||||||
|
|
||||||
@ -101,12 +107,16 @@ public class LoopStatementParser implements StatementParser {
|
|||||||
sections.put("update", new FlexibleSectionParser.SectionDefinition(
|
sections.put("update", new FlexibleSectionParser.SectionDefinition(
|
||||||
ts1 -> ts1.peek().getLexeme().equals("update"),
|
ts1 -> ts1.peek().getLexeme().equals("update"),
|
||||||
(ctx1, ts1) -> {
|
(ctx1, ts1) -> {
|
||||||
|
// 获取当前 token 的行号、列号
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
|
||||||
ParserUtils.matchHeader(ts1, "update");
|
ParserUtils.matchHeader(ts1, "update");
|
||||||
String varName = ts1.expectType(TokenType.IDENTIFIER).getLexeme();
|
String varName = ts1.expectType(TokenType.IDENTIFIER).getLexeme();
|
||||||
ts1.expect("=");
|
ts1.expect("=");
|
||||||
ExpressionNode expr = new PrattExpressionParser().parse(ctx1);
|
ExpressionNode expr = new PrattExpressionParser().parse(ctx1);
|
||||||
ts1.expectType(TokenType.NEWLINE);
|
ts1.expectType(TokenType.NEWLINE);
|
||||||
update[0] = new AssignmentNode(varName, expr);
|
update[0] = new AssignmentNode(varName, expr, line, column, file);
|
||||||
ParserUtils.skipNewlines(ts1);
|
ParserUtils.skipNewlines(ts1);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
@ -140,6 +150,6 @@ public class LoopStatementParser implements StatementParser {
|
|||||||
ParserUtils.matchFooter(ts, "loop");
|
ParserUtils.matchFooter(ts, "loop");
|
||||||
|
|
||||||
// 返回构造完成的 LoopNode
|
// 返回构造完成的 LoopNode
|
||||||
return new LoopNode(initializer[0], condition[0], update[0], body);
|
return new LoopNode(initializer[0], condition[0], update[0], body, loop_line, loop_column, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,11 @@ public class ReturnStatementParser implements StatementParser {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ReturnNode parse(ParserContext ctx) {
|
public ReturnNode parse(ParserContext ctx) {
|
||||||
|
// 获取当前 token 的行号、列号和文件名
|
||||||
|
int line = ctx.getTokens().peek().getLine();
|
||||||
|
int column = ctx.getTokens().peek().getCol();
|
||||||
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
// 消耗 "return" 关键字
|
// 消耗 "return" 关键字
|
||||||
ctx.getTokens().expect("return");
|
ctx.getTokens().expect("return");
|
||||||
|
|
||||||
@ -49,6 +54,6 @@ public class ReturnStatementParser implements StatementParser {
|
|||||||
ctx.getTokens().expectType(TokenType.NEWLINE);
|
ctx.getTokens().expectType(TokenType.NEWLINE);
|
||||||
|
|
||||||
// 构建并返回 ReturnNode(可能为空表达式)
|
// 构建并返回 ReturnNode(可能为空表达式)
|
||||||
return new ReturnNode(expr);
|
return new ReturnNode(expr, line, column, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,8 +51,8 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer<CallExpression
|
|||||||
ExpressionNode callee = call.callee();
|
ExpressionNode callee = call.callee();
|
||||||
|
|
||||||
// 支持模块调用形式:ModuleName.FunctionName(...)
|
// 支持模块调用形式:ModuleName.FunctionName(...)
|
||||||
if (callee instanceof MemberExpressionNode(var obj, String member)
|
if (callee instanceof MemberExpressionNode(var obj, String member, _, _, _)
|
||||||
&& obj instanceof IdentifierNode(String mod)) {
|
&& obj instanceof IdentifierNode(String mod, _, _, _)) {
|
||||||
// 验证模块是否存在并已导入
|
// 验证模块是否存在并已导入
|
||||||
if (!ctx.getModules().containsKey(mod)
|
if (!ctx.getModules().containsKey(mod)
|
||||||
|| (!mi.getImports().contains(mod) && !mi.getName().equals(mod))) {
|
|| (!mi.getImports().contains(mod) && !mi.getName().equals(mod))) {
|
||||||
@ -65,7 +65,7 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer<CallExpression
|
|||||||
functionName = member;
|
functionName = member;
|
||||||
|
|
||||||
// 简单函数名形式:func(...)
|
// 简单函数名形式:func(...)
|
||||||
} else if (callee instanceof IdentifierNode(String name)) {
|
} else if (callee instanceof IdentifierNode(String name, _, _, _)) {
|
||||||
functionName = name;
|
functionName = name;
|
||||||
|
|
||||||
// 不支持的 callee 形式
|
// 不支持的 callee 形式
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package org.jcnc.snow.pkg.tasks;
|
package org.jcnc.snow.pkg.tasks;
|
||||||
|
|
||||||
import org.jcnc.snow.cli.commands.CompileCommand;
|
import org.jcnc.snow.cli.commands.CompileCommand;
|
||||||
import org.jcnc.snow.compiler.backend.util.OpHelper;
|
import org.jcnc.snow.compiler.backend.utils.OpHelper;
|
||||||
import org.jcnc.snow.compiler.backend.alloc.RegisterAllocator;
|
import org.jcnc.snow.compiler.backend.alloc.RegisterAllocator;
|
||||||
import org.jcnc.snow.compiler.backend.builder.VMCodeGenerator;
|
import org.jcnc.snow.compiler.backend.builder.VMCodeGenerator;
|
||||||
import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder;
|
import org.jcnc.snow.compiler.backend.builder.VMProgramBuilder;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user