merge: resolve manuscript conflicts with latest main comments
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user