Expand description
Oxc Parser for JavaScript and TypeScript
Oxc’s Parser has full support for
- The latest stable ECMAScript syntax
- TypeScript
- JSX and TSX
- Stage 3 Decorators
§Usage
The parser has a minimal API with three inputs (a memory arena, a
source string, and a SourceType) and one return struct (a ParserReturn).
ⓘ
let parser_return = Parser::new(&allocator, &source_text, source_type).parse();§Abstract Syntax Tree (AST)
Oxc’s AST is located in a separate oxc_ast crate. You can find type definitions for AST
nodes here.
§Performance
The following optimization techniques are used:
- AST is allocated in a memory arena (oxc_allocator) for fast AST drop
oxc_span::Spanoffsets usesu32instead ofusize- Scope binding, symbol resolution and complicated syntax errors are not done in the parser, they are delegated to the semantic analyzer
Because [`oxc_span::Span`] uses `u32` instead of `usize`, Oxc can only parse files up
to 4 GiB in size. This shouldn't be a limitation in almost all cases.
§Examples
https://github.com/oxc-project/oxc/blob/main/crates/oxc_parser/examples/parser.rs
ⓘ
#![expect(clippy::print_stdout)]
//! # Parser Example
//!
//! This example demonstrates how to use the Oxc parser to parse JavaScript and TypeScript files.
//!
//! ## Usage
//!
//! Create a `test.js` file and run:
//! ```bash
//! cargo run -p oxc_parser --example parser [filename] [--ast] [--estree] [--comments]
//! ```
//!
//! ## Options
//!
//! - `--ast`: Display the parsed AST structure
//! - `--estree`: Display the ESTree representation
//! - `--comments`: Display extracted comments
use std::{fs, path::Path};
use oxc_allocator::Allocator;
use oxc_ast_visit::utf8_to_utf16::Utf8ToUtf16;
use oxc_parser::{ParseOptions, Parser};
use oxc_span::SourceType;
use pico_args::Arguments;
// Instruction:
// create a `test.js`,
// run `cargo run -p oxc_parser --example parser`
// or `just watch "cargo run -p oxc_parser --example parser"`
/// Parse and display information about a JavaScript or TypeScript file
fn main() -> Result<(), String> {
let mut args = Arguments::from_env();
// Parse command line arguments
let show_ast = args.contains("--ast");
let show_estree = args.contains("--estree");
let show_comments = args.contains("--comments");
let name = args.free_from_str().unwrap_or_else(|_| "test.js".to_string());
// Read source file
let path = Path::new(&name);
let source_text = fs::read_to_string(path).map_err(|_| format!("Missing '{name}'"))?;
let source_type = SourceType::from_path(path).unwrap();
// Parse the source code
let allocator = Allocator::default();
let ret = Parser::new(&allocator, &source_text, source_type)
.with_options(ParseOptions { parse_regular_expression: true, ..ParseOptions::default() })
.parse();
let mut program = ret.program;
// Display comments if requested
if show_comments {
println!("Comments:");
for comment in &program.comments {
let s = comment.content_span().source_text(&source_text);
println!("{s}");
}
}
// Display AST if requested
if show_ast {
println!("AST:");
println!("{program:#?}");
}
// Display ESTree representation if requested
if show_estree {
Utf8ToUtf16::new(&source_text).convert_program(&mut program);
if source_type.is_javascript() {
println!("ESTree AST:");
} else {
println!("TS-ESTree AST:");
}
println!("{}", program.to_pretty_estree_json(!source_type.is_javascript(), false));
}
// Report parsing results
if ret.diagnostics.is_empty() {
println!("Parsed Successfully.");
} else {
for error in ret.diagnostics {
let error = error.with_source_code(source_text.clone());
println!("{error:?}");
}
println!("Parsed with Errors.");
}
Ok(())
}§Parsing TSX
ⓘ
//! # TypeScript JSX Parsing Example
//!
//! This example demonstrates parsing TypeScript files with JSX syntax.
//! It shows how to parse a simple React component and validate the parsing results.
//!
//! ## Usage
//!
//! ```bash
//! cargo run -p oxc_parser --example parser_tsx
//! ```
use oxc_allocator::Allocator;
use oxc_parser::{Parser, ParserReturn};
use oxc_span::SourceType;
/// Parse a TypeScript JSX file and validate the results
fn main() -> Result<(), String> {
let source_text = r"
import React from 'react';
/**
* A simple counter component
*/
export const Counter: React.FC = () => {
const [count, setCount] = React.useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
</div>
)
}";
// Memory arena where AST nodes get stored
let allocator = Allocator::default();
// Infers TypeScript + JSX + ESM modules
let source_type = SourceType::from_path("Counter.tsx").unwrap();
let ParserReturn {
program, // AST
diagnostics, // Syntax errors
panicked, // Parser encountered an error it couldn't recover from
..
} = Parser::new(&allocator, source_text, source_type).parse();
if panicked {
return Err("Parser panicked".to_string());
}
if !diagnostics.is_empty() {
return Err(format!("Parsing errors: {}", diagnostics.len()));
}
assert!(!program.body.is_empty());
assert_eq!(program.comments.len(), 1);
Ok(())
}§Visitor
§Visiting without a visitor
For ad-hoc tasks, the semantic analyzer can be used to get a parent pointing tree with untyped nodes, the nodes can be iterated through a sequential loop.
ⓘ
for node in semantic.nodes().iter() {
match node.kind() {
// check node
}
}Modules§
Structs§
- Admitted
Borrowed Expression - A root authenticated by its original embedding owner, without moving it. The root remains borrowed for the owner’s lifetime, not the arena lifetime. No caller AST, source window or replacement admission status can mint this.
- Admitted
Expression - A short private-origin borrow; raw ASTs and numeric windows cannot mint it.
- Admitted
Handler Body - A short private-origin borrow; raw ASTs and numeric windows cannot mint it.
- Admitted
Parameters - A short private-origin borrow; raw ASTs and numeric windows cannot mint it.
- Admitted
Program - A short immutable borrow minted only by a clean original observation.
- Embedding
Input - A private fixed wrapper and its original allocation/source identity. No caller AST, wrapper, options or lexer configuration can be substituted.
- Embedding
Observation - The complete ordinary result, including all diagnostics and parser fields. Shared selected syntax cannot mint a replacement admitted projection.
- Expression
Observation - An ordinarily owned complete parser observation and selected arena root.
- Handler
Body Observation - An ordinarily owned complete parser observation and selected arena root.
- Original
Default Export - The sole direct value-default export in the original parser’s ModuleRecord.
- Parameters
Observation - An ordinarily owned complete parser observation and selected arena root.
- Parse
Options - Parse options
- Parser
- Recursive Descent Parser for ECMAScript and TypeScript
- Parser
Return - Return value of
Parser::parseconsisting of AST, errors and comments - Program
Observation - The complete ordinarily owned result of one parser invocation.
- Token
Enums§
- Embedding
Goal - Embedding
Hole - Embedding
Input Error - Kind
- Lexer token kind