Skip to content

Parser 架构

Oxc 维护自建 AST 与 Parser,目前是 Rust 生态里速度与一致性表现最好的 JS/TS(含 JSX、TSX)解析器。

由于 Parser 经常是 JS 工具性能瓶颈, 任何微调都可能放大到下游链路;自研也让我们能系统性地尝试成熟性能手段。

AST 设计理念

诸多工具沿用 estree 形态,但它的节点往往含糊不清,开发时也更容易困惑。

Oxc AST 通过删除歧义节点、引入更清晰类型来改善这一点。 例如在 Identifier 上进一步拆成 BindingIdentifierIdentifierReferenceIdentifierName 等不同用途。

从而让 AST 语义更贴近 ECMAScript 条文,也方便工具作者理解。

AST 节点示例

rust
// Instead of generic Identifier
pub struct BindingIdentifier<'a> {
    pub span: Span,
    pub name: Atom<'a>,
}

pub struct IdentifierReference<'a> {
    pub span: Span,
    pub name: Atom<'a>,
    pub reference_id: Cell<Option<ReferenceId>>,
}

pub struct IdentifierName<'a> {
    pub span: Span,
    pub name: Atom<'a>,
}

语义清晰

三类用途区分如下:

  • BindingIdentifier:声明位置(如 let x = 1
  • IdentifierReference:引用位置(如 console.log(x)
  • IdentifierName:属性名写法(如 obj.property

性能架构

为什么快

  • 内存池:AST 存放在 memory arena(bumpalo) 以实现快速批量分配/回收。
  • 字符串:短串通过 CompactString 内联。
  • 堆分配:除了上述两类外尽量避免额外 malloc。
  • 职责拆分:Scope、符号绑定与部分语法检查交给语义层处理,Parser 本体保持精炼。

Arena

rust
use oxc_allocator::Allocator;

// All AST nodes are allocated in this arena
let allocator = Allocator::default();
let ast_node = allocator.alloc(Expression::NumericLiteral(
    allocator.alloc(NumericLiteral { value: 42.0, span: SPAN })
));

优势:

  • O(1) 分配:连续 bump pointer。
  • O(1) 释放:整池释放即可。
  • 缓存友好:连续内存布局、碎片少。

CompactString

rust
// Strings ≤ 24 bytes are stored inline (no heap allocation)
let short_name = CompactString::from("variableName");  // Stack allocated
let long_name = CompactString::from("a_very_long_variable_name_that_exceeds_limit");  // Heap allocated

可显著减少对常见标识符/字面量的堆占用。

Parser 组成

两阶段流水线

  1. 解析阶段:只做结构建树,语义分析降到最低。
  2. 语义阶段:Scope/Symbol,以及更深入语法错误校验。
rust
// Phase 1: Parse to AST
let parser_result = Parser::new(&allocator, &source_text, source_type).parse();

// Phase 2: Semantic analysis
let semantic_result = SemanticBuilder::new()
    .with_check_syntax_error(true)
    .build(&parser_result.program);

组件

Lexer

  • 生成 Token
  • SIMD 跳过空白提速
  • 区分 / 正则字面量与普通除法运算符

递归下降 Parser

  • 手写实现以掌控性能上限
  • 错误恢复并提供可读诊断
  • 严格对齐 ECMAScript 条文

AST Builder

  • 借用 Rust type system 守卫正确性
  • 直接写入 arena
  • Builder API 方便构造常用节点

兼容性策略

  • Test262:ECMAScript 一致性通过率 100%
  • Babel parser tests:≥99.6%
  • TypeScript compiler tests:≥99.8%

诊断哲学

rust
pub struct OxcDiagnostic {
    pub message: String,
    pub span: Span,
    pub severity: Severity,
    pub help: Option<String>,
}

目标是 精确定位容错继续解析,以及给出 可行动的修复提示

进阶特性概览

  • TypeScript:type stripping、experimental decorators、命名空间、*.tsx
  • 持续研究 SIMD 文本、Zero-copy 解析、缓存布局等方向。