Files
OxideJS-New/crates/oxide_parser/src/lib.rs
T

78 lines
3.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#![doc = "OxideJS - JavaScript parser (oxc_parser re-export)"]
mod error;
mod parser_log;
mod redeclaration_filter;
/// 解析错误:消息 + 源文件字节区间(起始,结束)。
pub use error::OxideError;
/// 重导出 `oxc_allocator::Allocator`:AST 节点的 bump 分配器,解析产物生命周期由其决定。
pub use oxc_allocator::Allocator;
/// 重导出 `oxc_ast::ast` 的全部 AST 节点类型(`Program`、`Statement`、`Expression` 等)。
pub use oxc_ast::ast::*;
/// 重导出 `oxc_span::Span`:源码中的位置区间。
pub use oxc_span::Span;
/// 把 `source` 解析为 AST 根节点 `Program`,AST 分配在 `allocator` 中。
///
/// 使用 oxc 默认 `SourceType`(严格模式由语法自身决定)。返回 `Ok(program)`
/// 或 `Err`(收集全部解析错误,按源码顺序排列);若 oxc 内部 panic(不可恢复
/// 语法错误)则透传其已收集的诊断(消息 + 位置),无诊断时返回单个通用错误。
fn parse_with_source_type<'a>(
allocator: &'a Allocator, source: &'a str, source_type: oxc_span::SourceType,
) -> Result<Program<'a>, Vec<OxideError>> {
use oxc_parser::Parser;
let ret = Parser::new(allocator, source, source_type).parse();
if ret.panicked {
// 不可恢复语法错误:oxc 已为出错 token 累积诊断时,把诊断(消息 + 位置)
// 透传为 `Err`,直指真实触发点;无诊断时兜底通用文本。
if !ret.errors.is_empty() {
return Err(ret.errors.into_iter().map(OxideError::from).collect());
}
return Err(vec![OxideError {
message: "Parser panicked: unrecoverable syntax error".to_string(),
span: (0, 0),
}]);
}
if !ret.errors.is_empty() {
return Err(ret.errors.into_iter().map(OxideError::from).collect());
}
// 语法早期错误(Early Errors)检查:oxc parser 把复杂早期错误委托给
// oxc_semantic(strict 绑定标识符、重复参数、NSPL、super 位置等)。
let semantic_ret = oxc_semantic::SemanticBuilder::new()
.with_check_syntax_error(true)
.build(&ret.program);
if !semantic_ret.errors.is_empty() {
// 重名诊断先经 AST 复核剔除跨语句列合法合并的误报(须在归一化前,
// 归一化只留首标签会丢失复核所需的新声明 span);复核后无剩余
// 错误时按解析成功落回。
let filtered = redeclaration_filter::filter_semantic_diagnostics(semantic_ret.errors, &ret.program);
if !filtered.is_empty() {
return Err(filtered.into_iter().map(OxideError::from).collect());
}
}
Ok(ret.program)
}
/// 将 `source` 解析为 AST 根节点 `Program`(脚本/模块由语法内容自动判定)。
///
/// 使用 oxc 的 `unambiguous` SourceType:代码含顶层 import/export 时按模块解析,
/// 否则按脚本解析。返回 `Ok(program)` 或 `Err`(收集全部解析错误)。
pub fn parse<'a>(allocator: &'a Allocator, source: &'a str) -> Result<Program<'a>, Vec<OxideError>> {
parse_with_source_type(allocator, source, oxc_span::SourceType::unambiguous())
}
/// 将 `source` 强制按 ES module 解析为 AST 根节点 `Program`。
///
/// 与 [`parse`] 的唯一区别是 SourceType 固定为模块(`SourceType::mjs`):
/// 即使源码没有 import/export 也会按模块文法解析(如 `await` 保留字、
/// module-only early errors 等),用于 test262 `flags: [module]` 用例。
pub fn parse_module<'a>(allocator: &'a Allocator, source: &'a str) -> Result<Program<'a>, Vec<OxideError>> {
parse_with_source_type(allocator, source, oxc_span::SourceType::mjs())
}