merge: resolve manuscript conflicts with latest main comments

This commit is contained in:
2026-11-12 11:11:00 +08:00
123 changed files with 2699 additions and 253 deletions
+18 -2
View File
@@ -26,22 +26,26 @@ impl SourcePlan {
}
}
/// 把外部源码或属性表示转换为内部枚举/结构,并反馈不支持的输入。
/// 优先解析完整模块,否则按可完成的交互输入分段为 Script,并将 AST/诊断位置映回原文。
pub fn parse(source: &SourceUnit) -> Result<SourcePlan> {
// 完整模块优先;只有模块解析失败才退回连续交互输入模式,宿主不自行实现 Endor 语法。
if let Ok(module) = frontend::parse_source_ast(source, ParseMode::Module) {
return Ok(SourcePlan::Module(module));
}
// 一次词法分析获得原始字节 span,候选分段依赖 token 之间的实际换行而非直接按行切字符串。
let tokens = frontend::lex_source(source)?;
let mut roots = Vec::new();
let mut start = 0;
let mut depth = 0_i64;
for (index, token) in tokens.iter().enumerate() {
// 追踪圆/花括号嵌套,括号内换行不能直接结束输入;最终语法是否合法仍交给 Aster。
match token.kind {
TokenKind::LeftParen | TokenKind::LeftBrace => depth += 1,
TokenKind::RightParen | TokenKind::RightBrace => depth -= 1,
_ => {}
}
let end = token.span.end;
// 末尾 token 总是尝试解析;非末尾要求顶层换行,且下一 token 不像成员访问、调用或算术续接。
let boundary = tokens.get(index + 1).is_none_or(|next| {
depth == 0
&& source.text()[end..next.span.start].contains(['\r', '\n'])
@@ -58,25 +62,30 @@ pub fn parse(source: &SourceUnit) -> Result<SourcePlan> {
if !boundary {
continue;
}
// 当前片段从上一次成功边界 start 开始,保留期间的空白与注释;解析器看到的是片段局部字节位置。
match frontend::parse_ast(&source.text()[start..end], ParseMode::Interactive) {
Ok(mut root) => {
let AstRoot::Interactive(input) = &mut root else {
unreachable!("interactive mode");
};
// 成功后递归加回 start,把整个 AST 的局部 span 转成原文件位置,再推进下一段起点。
shift_input(input, start);
roots.push(root);
start = end;
}
// An incomplete interactive input can continue on the next line.
// Only Aster decides whether its combined syntax is valid.
// 错误恰在片段末尾且还有 token 时,视为可能未完成的交互输入,保持 start 不动继续拼接。
Err(diagnostic) if index + 1 < tokens.len() && diagnostic.span.start == end - start => {
}
Err(mut diagnostic) => {
// 其他语法错误立即恢复原始偏移,再用 SourceUnit 添加原文件来源与行列诊断。
shift_span(&mut diagnostic.span, start);
return Err(source.annotate(diagnostic).into());
}
}
}
// 空输入不能静默产生空计划;再次委托交互入口给出解析器自己的空输入诊断与来源。
if roots.is_empty() {
// Produce Aster's original empty-input diagnostic and provenance.
frontend::parse_source_ast(source, ParseMode::Interactive)?;
@@ -84,8 +93,9 @@ pub fn parse(source: &SourceUnit) -> Result<SourcePlan> {
Ok(SourcePlan::Script(roots))
}
/// 递归调整对应语法节点的源码范围,保持片段解析后的错误位置仍指向原输入。
/// 为单个半开字节范围加回片段起始偏移,不处理其所属节点的子节点。
fn shift_span(span: &mut Span, offset: usize) {
// span 采用原文本字节偏移,start/end 同增 offset 保持长度;不是按字符数或行数偏移。
span.start += offset;
span.end += offset;
}
@@ -93,6 +103,7 @@ fn shift_span(span: &mut Span, offset: usize) {
/// 递归调整对应语法节点的源码范围,保持片段解析后的错误位置仍指向原输入。
fn shift_input(input: &mut InteractiveInput, offset: usize) {
shift_span(&mut input.span, offset);
// 根范围之外,逐条语句递归处理所有内层节点,避免错误只在顶层位置正确。
for statement in &mut input.statements {
shift_statement(statement, offset);
}
@@ -134,6 +145,7 @@ fn shift_statement(statement: &mut Stmt, offset: usize) {
shift_span(&mut assignment.name.span, offset);
shift_expression(&mut assignment.value, offset);
}
// 成员赋值同时包含目标对象表达式、成员名和右值,三部分都要恢复原始位置。
StmtKind::MemberAssignment(assignment) => {
shift_span(&mut assignment.span, offset);
shift_span(&mut assignment.name.span, offset);
@@ -156,6 +168,7 @@ fn shift_declaration(declaration: &mut Decl, offset: usize) {
shift_span(&mut declaration.span, offset);
match &mut declaration.kind {
DeclKind::Function(function) => shift_function(function, offset),
// 类的名称、基类、字段类型和方法均保存独立 span,不能仅移动声明外层范围。
DeclKind::Class(class) => {
shift_span(&mut class.span, offset);
shift_span(&mut class.name.span, offset);
@@ -179,6 +192,7 @@ fn shift_function(function: &mut frontend::ast::Function, offset: usize) {
shift_span(&mut function.span, offset);
shift_span(&mut function.name.span, offset);
shift_span(&mut function.return_type.span, offset);
// 参数自身、名称、类型各有范围;函数返回类型和函数体范围也独立移动。
for parameter in &mut function.parameters {
shift_span(&mut parameter.span, offset);
shift_span(&mut parameter.name.span, offset);
@@ -194,6 +208,7 @@ fn shift_function(function: &mut frontend::ast::Function, offset: usize) {
fn shift_expression(expression: &mut Expr, offset: usize) {
shift_span(&mut expression.span, offset);
match &mut expression.kind {
// 这些叶节点只用表达式外层 span;Symbol/Member 的名称还保存额外 span,需继续调整。
ExprKind::Name(_) | ExprKind::Number(_) | ExprKind::String(_) => {}
ExprKind::Symbol(name) => shift_span(&mut name.span, offset),
ExprKind::Unary { operand, .. } | ExprKind::Await(operand) => {
@@ -207,6 +222,7 @@ fn shift_expression(expression: &mut Expr, offset: usize) {
shift_expression(object, offset);
shift_span(&mut name.span, offset);
}
// 调用目标可继续是成员/调用等复合表达式;逐个递归实参而非只改整个 Call 的范围。
ExprKind::Call { callee, arguments } => {
shift_expression(callee, offset);
for argument in arguments {