refactor: 重构 AST节点中的位置信息表示方式
- 引入 NodeContext 类统一表示节点的上下文信息(行号、列号、文件名) - 修改相关 AST 节点的构造函数,使用 NodeContext 替代单独的行号、列号和文件名参数 - 更新解析器代码,创建 NodeContext 实例以传递给 AST节点 - 此重构简化了 AST 节点的参数列表,提高了代码的可维护性和可读性
This commit is contained in:
parent
ae0baf3e50
commit
aefa9e2dff
@ -5,6 +5,7 @@ import org.jcnc.snow.compiler.ir.core.IRProgram;
|
|||||||
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ModuleNode;
|
import org.jcnc.snow.compiler.parser.ast.ModuleNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -81,9 +82,7 @@ public final class IRProgramBuilder {
|
|||||||
null,
|
null,
|
||||||
String.valueOf(List.of()),
|
String.valueOf(List.of()),
|
||||||
List.of(stmt),
|
List.of(stmt),
|
||||||
-1,
|
new NodeContext(-1, -1, "")
|
||||||
-1,
|
|
||||||
""
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import org.jcnc.snow.compiler.ir.utils.IROpCodeUtils;
|
|||||||
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
||||||
import org.jcnc.snow.compiler.parser.ast.*;
|
import org.jcnc.snow.compiler.parser.ast.*;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -66,12 +67,12 @@ public class StatementBuilder {
|
|||||||
buildIf(ifNode);
|
buildIf(ifNode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, int _, int _, String _)) {
|
if (stmt instanceof ExpressionStatementNode(ExpressionNode exp, NodeContext _)) {
|
||||||
// 纯表达式语句,如 foo();
|
// 纯表达式语句,如 foo();
|
||||||
expr.build(exp);
|
expr.build(exp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, int _, int _, String _)) {
|
if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs, NodeContext _)) {
|
||||||
// 赋值语句,如 a = b + 1;
|
// 赋值语句,如 a = b + 1;
|
||||||
|
|
||||||
final String type = ctx.getScope().lookupType(var);
|
final String type = ctx.getScope().lookupType(var);
|
||||||
@ -209,9 +210,7 @@ public class StatementBuilder {
|
|||||||
ExpressionNode left,
|
ExpressionNode left,
|
||||||
String operator,
|
String operator,
|
||||||
ExpressionNode right,
|
ExpressionNode right,
|
||||||
_,
|
NodeContext _
|
||||||
_,
|
|
||||||
_
|
|
||||||
)
|
)
|
||||||
&& ComparisonUtils.isComparisonOperator(operator)) {
|
&& ComparisonUtils.isComparisonOperator(operator)) {
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.ir.core.IROpCode;
|
|||||||
import org.jcnc.snow.compiler.ir.core.IROpCodeMappings;
|
import org.jcnc.snow.compiler.ir.core.IROpCodeMappings;
|
||||||
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
|
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ public final class ComparisonUtils {
|
|||||||
/* ------------ 内部工具 ------------ */
|
/* ------------ 内部工具 ------------ */
|
||||||
|
|
||||||
private static boolean isLongLiteral(ExpressionNode node) {
|
private static boolean isLongLiteral(ExpressionNode node) {
|
||||||
if (node instanceof NumberLiteralNode(String value, int _, int _, String _)) {
|
if (node instanceof NumberLiteralNode(String value, NodeContext _)) {
|
||||||
return value.endsWith("L") || value.endsWith("l");
|
return value.endsWith("L") || value.endsWith("l");
|
||||||
}
|
}
|
||||||
return false; // 变量暂不处理(后续可扩展符号表查询)
|
return false; // 变量暂不处理(后续可扩展符号表查询)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import org.jcnc.snow.compiler.ir.value.IRConstant;
|
|||||||
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
|
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ public final class ExpressionUtils {
|
|||||||
|
|
||||||
/** 递归推断单个表达式节点的类型后缀(b/s/i/l/f/d)。 */
|
/** 递归推断单个表达式节点的类型后缀(b/s/i/l/f/d)。 */
|
||||||
private static char typeChar(ExpressionNode node) {
|
private static char typeChar(ExpressionNode node) {
|
||||||
if (node instanceof NumberLiteralNode(String value, int _, int _, String _)) {
|
if (node instanceof NumberLiteralNode(String value, NodeContext _)) {
|
||||||
char last = Character.toLowerCase(value.charAt(value.length() - 1));
|
char last = Character.toLowerCase(value.charAt(value.length() - 1));
|
||||||
return switch (last) {
|
return switch (last) {
|
||||||
case 'b','s','i','l','f','d' -> last;
|
case 'b','s','i','l','f','d' -> last;
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast;
|
|||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code AssignmentNode} 表示抽象语法树(AST)中的赋值语句节点。
|
* {@code AssignmentNode} 表示抽象语法树(AST)中的赋值语句节点。
|
||||||
@ -16,16 +17,12 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
|||||||
*
|
*
|
||||||
* @param variable 左值变量名(即赋值目标)
|
* @param variable 左值变量名(即赋值目标)
|
||||||
* @param value 表达式右值(即赋值来源)
|
* @param value 表达式右值(即赋值来源)
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点的上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record AssignmentNode(
|
public record AssignmentNode(
|
||||||
String variable,
|
String variable,
|
||||||
ExpressionNode value,
|
ExpressionNode value,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements StatementNode {
|
) implements StatementNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code BinaryExpressionNode} 表示抽象语法树(AST)中的二元运算表达式节点。
|
* {@code BinaryExpressionNode} 表示抽象语法树(AST)中的二元运算表达式节点。
|
||||||
@ -12,17 +13,13 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
* @param left 左操作数(子表达式)
|
* @param left 左操作数(子表达式)
|
||||||
* @param operator 运算符字符串(如 "+", "-", "*", "/" 等)
|
* @param operator 运算符字符串(如 "+", "-", "*", "/" 等)
|
||||||
* @param right 右操作数(子表达式)
|
* @param right 右操作数(子表达式)
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文(包含行号、列号等信息)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record BinaryExpressionNode(
|
public record BinaryExpressionNode(
|
||||||
ExpressionNode left,
|
ExpressionNode left,
|
||||||
String operator,
|
String operator,
|
||||||
ExpressionNode right,
|
ExpressionNode right,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements ExpressionNode {
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示布尔字面量(boolean literal)的抽象语法树(AST)节点。
|
* 表示布尔字面量(boolean literal)的抽象语法树(AST)节点。
|
||||||
@ -9,16 +10,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
* 表达布尔类型的字面量常量(如 "true" 或 "false")。
|
* 表达布尔类型的字面量常量(如 "true" 或 "false")。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param value 字面量的布尔值
|
* @param value 字面量的布尔值
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record BoolLiteralNode(
|
public record BoolLiteralNode(
|
||||||
boolean value,
|
boolean value,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements ExpressionNode {
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,10 +25,11 @@ public record BoolLiteralNode(
|
|||||||
* 如果传入的字符串为 "true"(忽略大小写),则解析结果为 {@code true};否则为 {@code false}。
|
* 如果传入的字符串为 "true"(忽略大小写),则解析结果为 {@code true};否则为 {@code false}。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param lexeme 布尔字面量的字符串表示
|
* @param lexeme 布尔字面量的字符串表示
|
||||||
|
* @param context 节点上下文信息(行号、列号等)
|
||||||
*/
|
*/
|
||||||
public BoolLiteralNode(String lexeme, int line, int column, String file) {
|
public BoolLiteralNode(String lexeme, NodeContext context) {
|
||||||
this(Boolean.parseBoolean(lexeme), line, column, file);
|
this(Boolean.parseBoolean(lexeme), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -12,16 +13,12 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @param callee 被调用的表达式节点,通常为函数标识符或成员访问表达式,表示函数名或方法名等。
|
* @param callee 被调用的表达式节点,通常为函数标识符或成员访问表达式,表示函数名或方法名等。
|
||||||
* @param arguments 参数表达式列表,表示函数调用中传递给函数的实际参数。参数的顺序与调用顺序一致。
|
* @param arguments 参数表达式列表,表示函数调用中传递给函数的实际参数。参数的顺序与调用顺序一致。
|
||||||
* @param line 当前表达式所在的行号,方便调试和错误定位。
|
* @param context 节点上下文信息(包含行号、列号等)。
|
||||||
* @param column 当前表达式所在的列号,用于精确定位错误位置。
|
|
||||||
* @param file 当前表达式所在的文件,用于错误定位。
|
|
||||||
*/
|
*/
|
||||||
public record CallExpressionNode(
|
public record CallExpressionNode(
|
||||||
ExpressionNode callee, // 被调用的表达式节点,表示函数或方法名
|
ExpressionNode callee, // 被调用的表达式节点,表示函数或方法名
|
||||||
List<ExpressionNode> arguments, // 函数调用的参数表达式列表
|
List<ExpressionNode> arguments, // 函数调用的参数表达式列表
|
||||||
int line, // 当前节点所在的行号
|
NodeContext context // 节点上下文信息(包含行号、列号等)
|
||||||
int column, // 当前节点所在的列号
|
|
||||||
String file // 当前节点所在的文件
|
|
||||||
) implements ExpressionNode {
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,31 +40,4 @@ public record CallExpressionNode(
|
|||||||
sb.append(")"); // 拼接右括号
|
sb.append(")"); // 拼接右括号
|
||||||
return sb.toString(); // 返回拼接好的字符串
|
return sb.toString(); // 返回拼接好的字符串
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的行号。
|
|
||||||
*
|
|
||||||
* @return 当前表达式的行号。
|
|
||||||
*/
|
|
||||||
public int line() {
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的列号。
|
|
||||||
*
|
|
||||||
* @return 当前表达式的列号。
|
|
||||||
*/
|
|
||||||
public int column() {
|
|
||||||
return column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的文件名。
|
|
||||||
*
|
|
||||||
* @return 当前表达式所在的文件名。
|
|
||||||
*/
|
|
||||||
public String file() {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast;
|
|||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -23,14 +24,8 @@ public class DeclarationNode implements StatementNode {
|
|||||||
/** 可选的初始化表达式 */
|
/** 可选的初始化表达式 */
|
||||||
private final Optional<ExpressionNode> initializer;
|
private final Optional<ExpressionNode> initializer;
|
||||||
|
|
||||||
/** 当前节点所在的行号 **/
|
/** 节点上下文信息(包含行号、列号等) */
|
||||||
private final int line;
|
private final NodeContext context;
|
||||||
|
|
||||||
/** 当前节点所在的列号 **/
|
|
||||||
private final int column;
|
|
||||||
|
|
||||||
/** 当前节点所在的文件 **/
|
|
||||||
private final String file;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造一个 {@code DeclarationNode} 实例。
|
* 构造一个 {@code DeclarationNode} 实例。
|
||||||
@ -38,14 +33,13 @@ public class DeclarationNode implements StatementNode {
|
|||||||
* @param name 变量名称
|
* @param name 变量名称
|
||||||
* @param type 变量类型字符串(如 "int"、"string")
|
* @param type 变量类型字符串(如 "int"、"string")
|
||||||
* @param initializer 可选初始化表达式,若为 {@code null} 表示未初始化
|
* @param initializer 可选初始化表达式,若为 {@code null} 表示未初始化
|
||||||
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
*/
|
*/
|
||||||
public DeclarationNode(String name, String type, ExpressionNode initializer, int line, int column, String file) {
|
public DeclarationNode(String name, String type, ExpressionNode initializer, NodeContext context) {
|
||||||
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.context = context;
|
||||||
this.column = column;
|
|
||||||
this.file = file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,27 +70,12 @@ public class DeclarationNode implements StatementNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前表达式所在的行号。
|
* 获取节点上下文信息(包含行号、列号等)。
|
||||||
*
|
*
|
||||||
* @return 当前表达式的行号。
|
* @return NodeContext 实例
|
||||||
*/
|
*/
|
||||||
public int line() {
|
@Override
|
||||||
return line;
|
public NodeContext context() {
|
||||||
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的列号。
|
|
||||||
*
|
|
||||||
* @return 当前表达式的列号。
|
|
||||||
*/
|
|
||||||
public int column() {
|
|
||||||
return column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的文件名。
|
|
||||||
*
|
|
||||||
* @return 当前表达式所在的文件名。
|
|
||||||
*/
|
|
||||||
public String file() { return file; }
|
|
||||||
}
|
}
|
||||||
@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast;
|
|||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code ExpressionStatementNode} 表示抽象语法树(AST)中的表达式语句节点。
|
* {@code ExpressionStatementNode} 表示抽象语法树(AST)中的表达式语句节点。
|
||||||
@ -11,14 +12,10 @@ import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param expression 表达式主体,通常为函数调用、赋值、方法链式调用等可求值表达式。
|
* @param expression 表达式主体,通常为函数调用、赋值、方法链式调用等可求值表达式。
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record ExpressionStatementNode(
|
public record ExpressionStatementNode(
|
||||||
ExpressionNode expression,
|
ExpressionNode expression,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements StatementNode {
|
) implements StatementNode {
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -17,17 +18,13 @@ 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 context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record FunctionNode(
|
public record FunctionNode(
|
||||||
String name,
|
String name,
|
||||||
List<ParameterNode> parameters,
|
List<ParameterNode> parameters,
|
||||||
String returnType,
|
String returnType,
|
||||||
List<StatementNode> body,
|
List<StatementNode> body,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements Node {
|
) implements Node {
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code IdentifierNode} 表示抽象语法树(AST)中的标识符表达式节点。
|
* {@code IdentifierNode} 表示抽象语法树(AST)中的标识符表达式节点。
|
||||||
@ -9,16 +10,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
* 在语义分析中,通常需要将此类节点绑定到其声明位置或符号表项。
|
* 在语义分析中,通常需要将此类节点绑定到其声明位置或符号表项。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param name 标识符的文本名称(如变量名 "x",函数名 "foo")
|
* @param name 标识符的文本名称(如变量名 "x",函数名 "foo")
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record IdentifierNode(
|
public record IdentifierNode(
|
||||||
String name,
|
String name,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements ExpressionNode {
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast;
|
|||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -16,29 +17,16 @@ import java.util.List;
|
|||||||
* 若 condition 为假,则执行 else 分支(如果提供)。
|
* 若 condition 为假,则执行 else 分支(如果提供)。
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* 示例语法结构:
|
|
||||||
* </p>
|
|
||||||
* <pre>{@code
|
|
||||||
* if (x > 0) {
|
|
||||||
* print("Positive");
|
|
||||||
* } else {
|
|
||||||
* print("Negative");
|
|
||||||
* }
|
|
||||||
* }</pre>
|
|
||||||
*
|
*
|
||||||
* @param condition 控制分支执行的条件表达式
|
* @param condition 控制分支执行的条件表达式
|
||||||
* @param thenBranch 条件为 true 时执行的语句块
|
* @param thenBranch 条件为 true 时执行的语句块
|
||||||
* @param elseBranch 条件为 false 时执行的语句块(可为空)
|
* @param elseBranch 条件为 false 时执行的语句块(可为空)
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @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,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements StatementNode {
|
) implements StatementNode {
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code ImportNode} 表示抽象语法树(AST)中的 import 语句节点。
|
* {@code ImportNode} 表示抽象语法树(AST)中的 import 语句节点。
|
||||||
@ -14,14 +15,10 @@ import org.jcnc.snow.compiler.parser.ast.base.Node;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param moduleName 被导入的模块名称,通常为点分层次结构(如 "core.utils")
|
* @param moduleName 被导入的模块名称,通常为点分层次结构(如 "core.utils")
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record ImportNode(
|
public record ImportNode(
|
||||||
String moduleName,
|
String moduleName,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements Node {
|
) implements Node {
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -17,17 +18,13 @@ import java.util.List;
|
|||||||
* @param condition 每次迭代前评估的条件表达式,控制循环是否继续
|
* @param condition 每次迭代前评估的条件表达式,控制循环是否继续
|
||||||
* @param update 每轮迭代完成后执行的更新语句
|
* @param update 每轮迭代完成后执行的更新语句
|
||||||
* @param body 循环体语句列表,表示循环主体执行逻辑
|
* @param body 循环体语句列表,表示循环主体执行逻辑
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点的上下文信息(包含行号、列号、文件名等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record LoopNode(
|
public record LoopNode(
|
||||||
StatementNode initializer,
|
StatementNode initializer,
|
||||||
ExpressionNode condition,
|
ExpressionNode condition,
|
||||||
StatementNode update,
|
StatementNode update,
|
||||||
List<StatementNode> body,
|
List<StatementNode> body,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements StatementNode {
|
) implements StatementNode {
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code MemberExpressionNode} 表示抽象语法树(AST)中的成员访问表达式节点。
|
* {@code MemberExpressionNode} 表示抽象语法树(AST)中的成员访问表达式节点。
|
||||||
@ -9,18 +10,14 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
* 成员访问常见于结构体、模块、对象导入等上下文中,是表达式链中常见的构件之一。
|
* 成员访问常见于结构体、模块、对象导入等上下文中,是表达式链中常见的构件之一。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param object 左侧对象表达式,表示成员所属的作用域或容器
|
* @param object 左侧对象表达式,表示成员所属的作用域或容器
|
||||||
* @param member 要访问的成员名称(字段名或方法名)
|
* @param member 要访问的成员名称(字段名或方法名)
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record MemberExpressionNode(
|
public record MemberExpressionNode(
|
||||||
ExpressionNode object,
|
ExpressionNode object,
|
||||||
String member,
|
String member,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements ExpressionNode {
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
@ -8,22 +9,17 @@ import java.util.StringJoiner;
|
|||||||
/**
|
/**
|
||||||
* 表示模块定义的 AST 节点。
|
* 表示模块定义的 AST 节点。
|
||||||
* 一个模块通常由模块名、导入语句列表和函数定义列表组成。
|
* 一个模块通常由模块名、导入语句列表和函数定义列表组成。
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* @param name 模块名称。
|
* @param name 模块名称。
|
||||||
* @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。
|
* @param imports 模块导入列表,每个导入是一个 {@link ImportNode}。
|
||||||
* @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。
|
* @param functions 模块中的函数列表,每个函数是一个 {@link FunctionNode}。
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record ModuleNode(
|
public record ModuleNode(
|
||||||
String name,
|
String name,
|
||||||
List<ImportNode> imports,
|
List<ImportNode> imports,
|
||||||
List<FunctionNode> functions,
|
List<FunctionNode> functions,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements Node {
|
) implements Node {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code NumberLiteralNode} 表示抽象语法树(AST)中的数字字面量表达式节点。
|
* {@code NumberLiteralNode} 表示抽象语法树(AST)中的数字字面量表达式节点。
|
||||||
@ -11,15 +12,11 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param value 数字字面量的原始字符串表示
|
* @param value 数字字面量的原始字符串表示
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record NumberLiteralNode(
|
public record NumberLiteralNode(
|
||||||
String value,
|
String value,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements ExpressionNode {
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code ParameterNode} 表示抽象语法树(AST)中的函数参数定义节点。
|
* {@code ParameterNode} 表示抽象语法树(AST)中的函数参数定义节点。
|
||||||
@ -9,18 +10,14 @@ import org.jcnc.snow.compiler.parser.ast.base.Node;
|
|||||||
* 用于构成函数签名并参与类型检查与函数调用匹配。
|
* 用于构成函数签名并参与类型检查与函数调用匹配。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param name 参数名称标识符
|
* @param name 参数名称标识符
|
||||||
* @param type 参数类型字符串(如 "int"、"string")
|
* @param type 参数类型字符串(如 "int"、"string")
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record ParameterNode(
|
public record ParameterNode(
|
||||||
String name,
|
String name,
|
||||||
String type,
|
String type,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements Node {
|
) implements Node {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.ast;
|
|||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -23,25 +24,18 @@ public class ReturnNode implements StatementNode {
|
|||||||
/** 可选的返回值表达式 */
|
/** 可选的返回值表达式 */
|
||||||
private final Optional<ExpressionNode> expression;
|
private final Optional<ExpressionNode> expression;
|
||||||
|
|
||||||
/** 当前节点所在的行号 **/
|
/** 节点上下文信息(包含行号、列号等) */
|
||||||
private final int line;
|
private final NodeContext context;
|
||||||
|
|
||||||
/** 当前节点所在的列号 **/
|
|
||||||
private final int column;
|
|
||||||
|
|
||||||
/** 当前节点所在的文件 **/
|
|
||||||
private final String file;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造一个 {@code ReturnNode} 实例。
|
* 构造一个 {@code ReturnNode} 实例。
|
||||||
*
|
*
|
||||||
* @param expression 返回值表达式,如果无返回值则可为 {@code null}
|
* @param expression 返回值表达式,如果无返回值则可为 {@code null}
|
||||||
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
*/
|
*/
|
||||||
public ReturnNode(ExpressionNode expression, int line, int column, String file) {
|
public ReturnNode(ExpressionNode expression, NodeContext context) {
|
||||||
this.expression = Optional.ofNullable(expression);
|
this.expression = Optional.ofNullable(expression);
|
||||||
this.line = line;
|
this.context = context;
|
||||||
this.column = column;
|
|
||||||
this.file = file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,27 +48,12 @@ public class ReturnNode implements StatementNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前表达式所在的行号。
|
* 获取节点上下文信息(包含行号、列号等)。
|
||||||
*
|
*
|
||||||
* @return 当前表达式的行号。
|
* @return NodeContext 实例
|
||||||
*/
|
*/
|
||||||
public int line() {
|
@Override
|
||||||
return line;
|
public NodeContext context() {
|
||||||
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的列号。
|
|
||||||
*
|
|
||||||
* @return 当前表达式的列号。
|
|
||||||
*/
|
|
||||||
public int column() {
|
|
||||||
return column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的文件名。
|
|
||||||
*
|
|
||||||
* @return 当前表达式所在的文件名。
|
|
||||||
*/
|
|
||||||
public String file() { return file; }
|
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code StringLiteralNode} 表示抽象语法树(AST)中的字符串字面量表达式节点。
|
* {@code StringLiteralNode} 表示抽象语法树(AST)中的字符串字面量表达式节点。
|
||||||
@ -10,15 +11,11 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param value 字符串常量的内容,原始值中不包含双引号
|
* @param value 字符串常量的内容,原始值中不包含双引号
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record StringLiteralNode(
|
public record StringLiteralNode(
|
||||||
String value,
|
String value,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements ExpressionNode {
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.ast;
|
package org.jcnc.snow.compiler.parser.ast;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code UnaryExpressionNode} —— 前缀一元运算 AST 节点。
|
* {@code UnaryExpressionNode} —— 前缀一元运算 AST 节点。
|
||||||
@ -15,16 +16,12 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
*
|
*
|
||||||
* @param operator 一元运算符(仅 "-" 或 "!")
|
* @param operator 一元运算符(仅 "-" 或 "!")
|
||||||
* @param operand 运算对象 / 右操作数
|
* @param operand 运算对象 / 右操作数
|
||||||
* @param line 当前节点所在的行号
|
* @param context 节点上下文信息(包含行号、列号等)
|
||||||
* @param column 当前节点所在的列号
|
|
||||||
* @param file 当前节点所在的文件
|
|
||||||
*/
|
*/
|
||||||
public record UnaryExpressionNode(
|
public record UnaryExpressionNode(
|
||||||
String operator,
|
String operator,
|
||||||
ExpressionNode operand,
|
ExpressionNode operand,
|
||||||
int line,
|
NodeContext context
|
||||||
int column,
|
|
||||||
String file
|
|
||||||
) implements ExpressionNode {
|
) implements ExpressionNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -17,23 +17,7 @@ package org.jcnc.snow.compiler.parser.ast.base;
|
|||||||
*/
|
*/
|
||||||
public interface Node {
|
public interface Node {
|
||||||
/**
|
/**
|
||||||
* 获取当前表达式所在的行号。
|
* 获取节点的上下文(行/列/文件等信息)。
|
||||||
*
|
|
||||||
* @return 当前表达式的行号。
|
|
||||||
*/
|
*/
|
||||||
int line();
|
NodeContext context();
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的列号。
|
|
||||||
*
|
|
||||||
* @return 当前表达式的列号。
|
|
||||||
*/
|
|
||||||
int column();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前表达式所在的文件名。
|
|
||||||
*
|
|
||||||
* @return 当前表达式所在的文件名。
|
|
||||||
*/
|
|
||||||
String file();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
package org.jcnc.snow.compiler.parser.ast.base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NodeContext 记录 AST 节点的位置信息(文件、行、列)。
|
||||||
|
*/
|
||||||
|
public record NodeContext(int line, int column, String file) {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return file + ":" + line + ":" + column;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.base.InfixParselet;
|
import org.jcnc.snow.compiler.parser.expression.base.InfixParselet;
|
||||||
|
|
||||||
@ -46,12 +47,9 @@ public record BinaryOperatorParselet(Precedence precedence, boolean leftAssoc) i
|
|||||||
int prec = precedence.ordinal();
|
int prec = precedence.ordinal();
|
||||||
|
|
||||||
// 右侧表达式根据结合性确定优先级绑定
|
// 右侧表达式根据结合性确定优先级绑定
|
||||||
ExpressionNode right = new PrattExpressionParser().parseExpression(
|
ExpressionNode right = new PrattExpressionParser().parseExpression(ctx, leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]);
|
||||||
ctx,
|
|
||||||
leftAssoc ? Precedence.values()[prec] : Precedence.values()[prec - 1]
|
|
||||||
);
|
|
||||||
|
|
||||||
return new BinaryExpressionNode(left, op.getLexeme(), right, line, column, file);
|
return new BinaryExpressionNode(left, op.getLexeme(), right, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode;
|
import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
||||||
|
|
||||||
@ -28,6 +29,6 @@ public class BoolLiteralParselet implements PrefixParselet {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode parse(ParserContext ctx, Token token) {
|
public ExpressionNode parse(ParserContext ctx, Token token) {
|
||||||
return new BoolLiteralNode(token.getLexeme(), token.getLine(), token.getCol(), ctx.getSourceName());
|
return new BoolLiteralNode(token.getLexeme(), new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.expression;
|
|||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.CallExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.CallExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.base.InfixParselet;
|
import org.jcnc.snow.compiler.parser.expression.base.InfixParselet;
|
||||||
|
|
||||||
@ -45,7 +46,8 @@ public class CallParselet implements InfixParselet {
|
|||||||
ctx.getTokens().expect(")"); // 消费并验证 ")"
|
ctx.getTokens().expect(")"); // 消费并验证 ")"
|
||||||
|
|
||||||
// 创建 CallExpressionNode 并传递位置信息
|
// 创建 CallExpressionNode 并传递位置信息
|
||||||
return new CallExpressionNode(left, args, line, column, file);
|
return new CallExpressionNode(left, args, new NodeContext(line, column, file));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.parser.ast.IdentifierNode;
|
import org.jcnc.snow.compiler.parser.ast.IdentifierNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
||||||
|
|
||||||
@ -29,6 +30,6 @@ public class IdentifierParselet implements PrefixParselet {
|
|||||||
int column = ctx.getTokens().peek(-1).getCol();
|
int column = ctx.getTokens().peek(-1).getCol();
|
||||||
String file = ctx.getSourceName();
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
return new IdentifierNode(token.getLexeme(), line, column, file);
|
return new IdentifierNode(token.getLexeme(), new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
import org.jcnc.snow.compiler.parser.ast.MemberExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.MemberExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.TokenStream;
|
import org.jcnc.snow.compiler.parser.context.TokenStream;
|
||||||
import org.jcnc.snow.compiler.parser.expression.base.InfixParselet;
|
import org.jcnc.snow.compiler.parser.expression.base.InfixParselet;
|
||||||
@ -34,7 +35,7 @@ public class MemberParselet implements InfixParselet {
|
|||||||
String file = ctx.getSourceName();
|
String file = ctx.getSourceName();
|
||||||
|
|
||||||
String member = ts.expectType(TokenType.IDENTIFIER).getLexeme();
|
String member = ts.expectType(TokenType.IDENTIFIER).getLexeme();
|
||||||
return new MemberExpressionNode(left, member, line, column, file);
|
return new MemberExpressionNode(left, member, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
|
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
||||||
|
|
||||||
@ -24,6 +25,6 @@ public class NumberLiteralParselet implements PrefixParselet {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ExpressionNode parse(ParserContext ctx, Token token) {
|
public ExpressionNode parse(ParserContext ctx, Token token) {
|
||||||
return new NumberLiteralNode(token.getLexeme(), token.getLine(), token.getCol(), ctx.getSourceName());
|
return new NumberLiteralNode(token.getLexeme(), new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.StringLiteralNode;
|
import org.jcnc.snow.compiler.parser.ast.StringLiteralNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
||||||
|
|
||||||
@ -27,6 +28,6 @@ public class StringLiteralParselet implements PrefixParselet {
|
|||||||
public ExpressionNode parse(ParserContext ctx, Token token) {
|
public ExpressionNode parse(ParserContext ctx, Token token) {
|
||||||
String raw = token.getRaw();
|
String raw = token.getRaw();
|
||||||
String content = raw.substring(1, raw.length() - 1);
|
String content = raw.substring(1, raw.length() - 1);
|
||||||
return new StringLiteralNode(content, token.getLine(), token.getCol(), ctx.getSourceName());
|
return new StringLiteralNode(content, new NodeContext(token.getLine(), token.getCol(), ctx.getSourceName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.expression;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.parser.ast.UnaryExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.UnaryExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet;
|
||||||
|
|
||||||
@ -55,6 +56,6 @@ public class UnaryOperatorParselet implements PrefixParselet {
|
|||||||
/* ------------------------------------------------------------
|
/* ------------------------------------------------------------
|
||||||
* 2. 封装成 AST 节点并返回。
|
* 2. 封装成 AST 节点并返回。
|
||||||
* ------------------------------------------------------------ */
|
* ------------------------------------------------------------ */
|
||||||
return new UnaryExpressionNode(token.getLexeme(), operand, line, column, file);
|
return new UnaryExpressionNode(token.getLexeme(), operand, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.function;
|
|||||||
import org.jcnc.snow.compiler.parser.ast.*;
|
import org.jcnc.snow.compiler.parser.ast.*;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
import org.jcnc.snow.compiler.parser.utils.ASTJsonSerializer;
|
import org.jcnc.snow.compiler.parser.utils.ASTJsonSerializer;
|
||||||
import org.jcnc.snow.compiler.parser.utils.JsonFormatter;
|
import org.jcnc.snow.compiler.parser.utils.JsonFormatter;
|
||||||
@ -66,8 +67,8 @@ public class ASTPrinter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case FunctionNode(
|
case FunctionNode(
|
||||||
String name, List<ParameterNode> parameters, String returnType, List<StatementNode> body
|
String name, List<ParameterNode> parameters, String returnType, List<StatementNode> body,
|
||||||
, int _, int _, String _
|
NodeContext _
|
||||||
) -> {
|
) -> {
|
||||||
System.out.println(pad + "function " + name
|
System.out.println(pad + "function " + name
|
||||||
+ "(params=" + parameters + ", return=" + returnType + ")");
|
+ "(params=" + parameters + ", return=" + returnType + ")");
|
||||||
@ -82,11 +83,10 @@ public class ASTPrinter {
|
|||||||
.orElse("");
|
.orElse("");
|
||||||
System.out.println(pad + "declare " + d.getName() + ":" + d.getType() + init);
|
System.out.println(pad + "declare " + d.getName() + ":" + d.getType() + init);
|
||||||
}
|
}
|
||||||
case AssignmentNode(String variable, ExpressionNode value, int _, int _, String _) ->
|
case AssignmentNode(String variable, ExpressionNode value, NodeContext _) ->
|
||||||
System.out.println(pad + variable + " = " + value);
|
System.out.println(pad + variable + " = " + value);
|
||||||
case IfNode(
|
case IfNode(
|
||||||
ExpressionNode condition, List<StatementNode> thenBranch, List<StatementNode> elseBranch, int _,
|
ExpressionNode condition, List<StatementNode> thenBranch, List<StatementNode> elseBranch, NodeContext _
|
||||||
int _, String _
|
|
||||||
) -> {
|
) -> {
|
||||||
System.out.println(pad + "if " + condition);
|
System.out.println(pad + "if " + condition);
|
||||||
for (StatementNode stmt : thenBranch) {
|
for (StatementNode stmt : thenBranch) {
|
||||||
@ -100,8 +100,8 @@ public class ASTPrinter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case LoopNode(
|
case LoopNode(
|
||||||
StatementNode initializer, ExpressionNode condition, StatementNode update, List<StatementNode> body
|
StatementNode initializer, ExpressionNode condition, StatementNode update, List<StatementNode> body,
|
||||||
, int _, int _, String _
|
NodeContext _
|
||||||
) -> {
|
) -> {
|
||||||
System.out.println(pad + "loop {");
|
System.out.println(pad + "loop {");
|
||||||
print(initializer, indent + 1);
|
print(initializer, indent + 1);
|
||||||
@ -116,7 +116,7 @@ public class ASTPrinter {
|
|||||||
}
|
}
|
||||||
case ReturnNode r -> System.out.println(pad + "return" +
|
case ReturnNode r -> System.out.println(pad + "return" +
|
||||||
r.getExpression().map(e -> " " + e).orElse(""));
|
r.getExpression().map(e -> " " + e).orElse(""));
|
||||||
case ExpressionStatementNode(ExpressionNode expression, int _, int _, String _) ->
|
case ExpressionStatementNode(ExpressionNode expression, NodeContext _) ->
|
||||||
System.out.println(pad + expression);
|
System.out.println(pad + expression);
|
||||||
case null, default -> System.out.println(pad + n); // 回退处理
|
case null, default -> System.out.println(pad + n); // 回退处理
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.parser.function;
|
|||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.base.TopLevelParser;
|
import org.jcnc.snow.compiler.parser.base.TopLevelParser;
|
||||||
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ParameterNode;
|
import org.jcnc.snow.compiler.parser.ast.ParameterNode;
|
||||||
@ -74,7 +75,7 @@ public class FunctionParser implements TopLevelParser {
|
|||||||
|
|
||||||
parseFunctionFooter(ts);
|
parseFunctionFooter(ts);
|
||||||
|
|
||||||
return new FunctionNode(functionName, parameters, returnType[0], body, line, column, file);
|
return new FunctionNode(functionName, parameters, returnType[0], body, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,7 +195,7 @@ public class FunctionParser implements TopLevelParser {
|
|||||||
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, line, column, file));
|
list.add(new ParameterNode(pname, ptype, new NodeContext(line, column, file)));
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.parser.module;
|
package org.jcnc.snow.compiler.parser.module;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ImportNode;
|
import org.jcnc.snow.compiler.parser.ast.ImportNode;
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ public class ImportParser {
|
|||||||
.getLexeme();
|
.getLexeme();
|
||||||
|
|
||||||
// 创建 ImportNode 节点并加入列表
|
// 创建 ImportNode 节点并加入列表
|
||||||
imports.add(new ImportNode(mod, line, column, file));
|
imports.add(new ImportNode(mod, new NodeContext(line, column, file)));
|
||||||
} while (ctx.getTokens().match(",")); // 如果匹配到逗号,继续解析下一个模块名
|
} while (ctx.getTokens().match(",")); // 如果匹配到逗号,继续解析下一个模块名
|
||||||
|
|
||||||
// 最后必须匹配换行符,标志 import 语句的结束
|
// 最后必须匹配换行符,标志 import 语句的结束
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
|
|||||||
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ImportNode;
|
import org.jcnc.snow.compiler.parser.ast.ImportNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ModuleNode;
|
import org.jcnc.snow.compiler.parser.ast.ModuleNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.base.TopLevelParser;
|
import org.jcnc.snow.compiler.parser.base.TopLevelParser;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.TokenStream;
|
import org.jcnc.snow.compiler.parser.context.TokenStream;
|
||||||
@ -93,6 +94,6 @@ public class ModuleParser implements TopLevelParser {
|
|||||||
ts.expect("end");
|
ts.expect("end");
|
||||||
ts.expect("module");
|
ts.expect("module");
|
||||||
|
|
||||||
return new ModuleNode(name, imports, functions, line, column, file);
|
return new ModuleNode(name, imports, functions, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
import org.jcnc.snow.compiler.parser.ast.DeclarationNode;
|
import org.jcnc.snow.compiler.parser.ast.DeclarationNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
|
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
|
||||||
|
|
||||||
@ -74,6 +75,6 @@ public class DeclarationStatementParser implements StatementParser {
|
|||||||
ctx.getTokens().expectType(TokenType.NEWLINE);
|
ctx.getTokens().expectType(TokenType.NEWLINE);
|
||||||
|
|
||||||
// 返回构建好的声明语法树节点
|
// 返回构建好的声明语法树节点
|
||||||
return new DeclarationNode(name, type, init, line, column, file);
|
return new DeclarationNode(name, type, init, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
|
|||||||
import org.jcnc.snow.compiler.parser.ast.AssignmentNode;
|
import org.jcnc.snow.compiler.parser.ast.AssignmentNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ExpressionStatementNode;
|
import org.jcnc.snow.compiler.parser.ast.ExpressionStatementNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.TokenStream;
|
import org.jcnc.snow.compiler.parser.context.TokenStream;
|
||||||
@ -56,12 +57,12 @@ 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, line, column, file);
|
return new AssignmentNode(varName, value, new NodeContext(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, line, column, file);
|
return new ExpressionStatementNode(expr, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.Token;
|
import org.jcnc.snow.compiler.lexer.token.Token;
|
||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
import org.jcnc.snow.compiler.parser.ast.IfNode;
|
import org.jcnc.snow.compiler.parser.ast.IfNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
|
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
|
||||||
@ -125,6 +126,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, line, column, file);
|
return new IfNode(condition, thenBranch, elseBranch, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import org.jcnc.snow.compiler.lexer.token.TokenType;
|
|||||||
import org.jcnc.snow.compiler.parser.ast.AssignmentNode;
|
import org.jcnc.snow.compiler.parser.ast.AssignmentNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.LoopNode;
|
import org.jcnc.snow.compiler.parser.ast.LoopNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.TokenStream;
|
import org.jcnc.snow.compiler.parser.context.TokenStream;
|
||||||
@ -116,7 +117,7 @@ public class LoopStatementParser implements StatementParser {
|
|||||||
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, line, column, file);
|
update[0] = new AssignmentNode(varName, expr, new NodeContext(line, column, file));
|
||||||
ParserUtils.skipNewlines(ts1);
|
ParserUtils.skipNewlines(ts1);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
@ -150,6 +151,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, loop_line, loop_column, file);
|
return new LoopNode(initializer[0], condition[0], update[0], body, new NodeContext(loop_line, loop_column, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.statement;
|
|||||||
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
import org.jcnc.snow.compiler.lexer.token.TokenType;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ReturnNode;
|
import org.jcnc.snow.compiler.parser.ast.ReturnNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
import org.jcnc.snow.compiler.parser.context.ParserContext;
|
||||||
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
|
import org.jcnc.snow.compiler.parser.expression.PrattExpressionParser;
|
||||||
|
|
||||||
@ -54,6 +55,6 @@ public class ReturnStatementParser implements StatementParser {
|
|||||||
ctx.getTokens().expectType(TokenType.NEWLINE);
|
ctx.getTokens().expectType(TokenType.NEWLINE);
|
||||||
|
|
||||||
// 构建并返回 ReturnNode(可能为空表达式)
|
// 构建并返回 ReturnNode(可能为空表达式)
|
||||||
return new ReturnNode(expr, line, column, file);
|
return new ReturnNode(expr, new NodeContext(line, column, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.parser.utils;
|
|||||||
import org.jcnc.snow.compiler.parser.ast.*;
|
import org.jcnc.snow.compiler.parser.ast.*;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -82,8 +83,7 @@ public class ASTJsonSerializer {
|
|||||||
return switch (n) {
|
return switch (n) {
|
||||||
// 模块节点
|
// 模块节点
|
||||||
case ModuleNode(
|
case ModuleNode(
|
||||||
String name, List<ImportNode> imports, List<FunctionNode> functions, _, int _,
|
String name, List<ImportNode> imports, List<FunctionNode> functions, NodeContext _
|
||||||
String _
|
|
||||||
) -> {
|
) -> {
|
||||||
Map<String, Object> map = newNodeMap("Module");
|
Map<String, Object> map = newNodeMap("Module");
|
||||||
map.put("name", name);
|
map.put("name", name);
|
||||||
@ -181,34 +181,34 @@ public class ASTJsonSerializer {
|
|||||||
return switch (expr) {
|
return switch (expr) {
|
||||||
// 二元表达式
|
// 二元表达式
|
||||||
case BinaryExpressionNode(
|
case BinaryExpressionNode(
|
||||||
ExpressionNode left, String operator, ExpressionNode right, int _, int _, String _
|
ExpressionNode left, String operator, ExpressionNode right, NodeContext _
|
||||||
) -> exprMap("BinaryExpression",
|
) -> exprMap("BinaryExpression",
|
||||||
"left", exprToMap(left),
|
"left", exprToMap(left),
|
||||||
"operator", operator,
|
"operator", operator,
|
||||||
"right", exprToMap(right)
|
"right", exprToMap(right)
|
||||||
);
|
);
|
||||||
// 一元表达式
|
// 一元表达式
|
||||||
case UnaryExpressionNode(String operator, ExpressionNode operand, int _, int _, String _) ->
|
case UnaryExpressionNode(String operator, ExpressionNode operand, NodeContext _) ->
|
||||||
exprMap("UnaryExpression",
|
exprMap("UnaryExpression",
|
||||||
"operator", operator,
|
"operator", operator,
|
||||||
"operand", exprToMap(operand)
|
"operand", exprToMap(operand)
|
||||||
);
|
);
|
||||||
// 布尔字面量
|
// 布尔字面量
|
||||||
case BoolLiteralNode(boolean value, int _, int _, String _) -> exprMap("BoolLiteral", "value", value);
|
case BoolLiteralNode(boolean value, NodeContext _) -> exprMap("BoolLiteral", "value", value);
|
||||||
// 标识符
|
// 标识符
|
||||||
case IdentifierNode(String name, int _, int _, String _) -> exprMap("Identifier", "name", name);
|
case IdentifierNode(String name, NodeContext _) -> exprMap("Identifier", "name", name);
|
||||||
// 数字字面量
|
// 数字字面量
|
||||||
case NumberLiteralNode(String value, int _, int _, String _) -> exprMap("NumberLiteral", "value", value);
|
case NumberLiteralNode(String value, NodeContext _) -> exprMap("NumberLiteral", "value", value);
|
||||||
// 字符串字面量
|
// 字符串字面量
|
||||||
case StringLiteralNode(String value, int _, int _, String _) -> exprMap("StringLiteral", "value", value);
|
case StringLiteralNode(String value, NodeContext _) -> exprMap("StringLiteral", "value", value);
|
||||||
// 调用表达式
|
// 调用表达式
|
||||||
case CallExpressionNode(ExpressionNode callee, List<ExpressionNode> arguments, int _, int _, String _) -> {
|
case CallExpressionNode(ExpressionNode callee, List<ExpressionNode> arguments, NodeContext _) -> {
|
||||||
List<Object> args = new ArrayList<>(arguments.size());
|
List<Object> args = new ArrayList<>(arguments.size());
|
||||||
for (ExpressionNode arg : arguments) args.add(exprToMap(arg));
|
for (ExpressionNode arg : arguments) args.add(exprToMap(arg));
|
||||||
yield exprMap("CallExpression", "callee", exprToMap(callee), "arguments", args);
|
yield exprMap("CallExpression", "callee", exprToMap(callee), "arguments", args);
|
||||||
}
|
}
|
||||||
// 成员访问表达式
|
// 成员访问表达式
|
||||||
case MemberExpressionNode(ExpressionNode object, String member, int _, int _, String _) ->
|
case MemberExpressionNode(ExpressionNode object, String member, NodeContext _) ->
|
||||||
exprMap("MemberExpression",
|
exprMap("MemberExpression",
|
||||||
"object", exprToMap(object),
|
"object", exprToMap(object),
|
||||||
"member", member
|
"member", member
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.semantic.analyzers.expression;
|
|||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.*;
|
import org.jcnc.snow.compiler.parser.ast.*;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.semantic.analyzers.base.ExpressionAnalyzer;
|
import org.jcnc.snow.compiler.semantic.analyzers.base.ExpressionAnalyzer;
|
||||||
import org.jcnc.snow.compiler.semantic.core.Context;
|
import org.jcnc.snow.compiler.semantic.core.Context;
|
||||||
import org.jcnc.snow.compiler.semantic.core.ModuleInfo;
|
import org.jcnc.snow.compiler.semantic.core.ModuleInfo;
|
||||||
@ -51,8 +52,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, int _, int _, String _)
|
if (callee instanceof MemberExpressionNode(var obj, String member, NodeContext _)
|
||||||
&& obj instanceof IdentifierNode(String mod, int _, int _, String _)) {
|
&& obj instanceof IdentifierNode(String mod, NodeContext _)) {
|
||||||
// 验证模块是否存在并已导入
|
// 验证模块是否存在并已导入
|
||||||
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 +66,7 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer<CallExpression
|
|||||||
functionName = member;
|
functionName = member;
|
||||||
|
|
||||||
// 简单函数名形式:func(...)
|
// 简单函数名形式:func(...)
|
||||||
} else if (callee instanceof IdentifierNode(String name, int _, int _, String _)) {
|
} else if (callee instanceof IdentifierNode(String name, NodeContext _)) {
|
||||||
functionName = name;
|
functionName = name;
|
||||||
|
|
||||||
// 不支持的 callee 形式
|
// 不支持的 callee 形式
|
||||||
|
|||||||
@ -42,11 +42,12 @@ public record SemanticError(Node node, String message) {
|
|||||||
String file = null;
|
String file = null;
|
||||||
|
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
line = node.line();
|
line = node.context().line();
|
||||||
col = node.column();
|
col = node.context().column();
|
||||||
file = node.file();
|
file = node.context().file();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (file != null && !file.isBlank()) sb.append(file).append(": ");
|
if (file != null && !file.isBlank()) sb.append(file).append(": ");
|
||||||
sb.append((line >= 0 && col >= 0) ? "行 " + line + ", 列 " + col : "未知位置");
|
sb.append((line >= 0 && col >= 0) ? "行 " + line + ", 列 " + col : "未知位置");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user