Skip to main content

hermes_parser/
lib.rs

1//! A Rust port of the Hermes JavaScript front end — lexer and parser.
2//!
3//! Faithful 1:1 port of the C++ `JSLexer` and `JSParserImpl`, validated
4//! byte-for-byte against `hermesc -dump-ast` over a per-dialect corpus. The
5//! output is the ESTree AST of the `ast` crate. Every dialect the C++ parser
6//! supports is complete and covered by that differential gate: ECMAScript,
7//! the Flow type grammar, TypeScript, and JSX. The three non-standard ones
8//! are opt-in through the same `hermes_ast::context::Context` flags as in the C++
9//! (`parse_flow` and its four extension flags, `parse_ts`, `parse_jsx`).
10//!
11//! # Quickstart
12//!
13//! ```
14//! use hermes_parser::ast::node::Node;
15//! use hermes_parser::{parse, ParseFlags};
16//!
17//! let flags = ParseFlags::default();
18//! let mut parsed = parse("1 + 2;", flags).expect("parse error");
19//!
20//! // The AST lives in an arena owned by `parsed`; read it under a lock.
21//! let statements = parsed.with_program(|_gc, program| match program {
22//!     Node::Program(p) => p.body.iter().count(),
23//!     _ => unreachable!("the root of a parse is always a Program"),
24//! });
25//! assert_eq!(statements, 1);
26//!
27//! // Or dump it the way `hermesc -dump-ast` does.
28//! let json = parsed.to_estree_json(false);
29//! assert!(json.starts_with(r#"{"type":"Program""#));
30//! ```
31//!
32//! The pieces a consumer touches:
33//! - [`parse`] / [`parse_named`] returning [`ParsedJS`] — the convenience
34//!   façade, which assembles an [`hermes_ast::context::Context`], a
35//!   `SourceErrorManager`, a [`lexer::JSLexer`] and a [`js::JSParserImpl`]
36//!   into one call. It adds no behavior; anything it does not expose is
37//!   reachable by driving those pieces directly.
38//! - [`ast`] — the AST crate, re-exported so that depending on this crate
39//!   alone is enough to name [`hermes_ast::node::Node`], walk with
40//!   [`hermes_ast::visitor::Visitor`], or drive [`hermes_ast::dump`] by hand.
41//! - [`js::JSParserImpl`] — the recursive-descent parser; `new` + `parse`
42//!   returns the `Program` node, or `None` after a reported error.
43//! - [`lexer::JSLexer`] — the lexer, usable on its own; it reports through a
44//!   `hermes_support::manager::SourceErrorManager` and interns into an `AtomTable`.
45//! - [`token::Token`] and [`token_kinds::TokenKind`] — the token surface, the
46//!   latter generated from `include/hermes/Parser/TokenKinds.def` order.
47//! - [`js::ParserPass`] — `FullParse` (eager), plus the `PreParse`/`LazyParse`
48//!   pair that indexes function bodies in one scan and defers parsing them.
49//! - [`json`] — the separate `JSONParser` port (a distinct grammar sharing the
50//!   same lexer), with the uniquing/hidden-class `JSONFactory`.
51//!
52//! The remaining modules are the lexer's own building blocks: [`cursor`] (the
53//! scan cursor), [`number`] (numeric-literal conversion), [`utf8`] (the
54//! UTF-8/UTF-16 conversions the C++ keeps in `Support`), and
55//! [`html_entities`] (the JSX entity table generated from `HTMLEntities.def`).
56//! Only the port's internals call them, and no public signature in this crate
57//! mentions them; they are public incidentally rather than by design, and may
58//! be demoted to `pub(crate)` in a future release.
59//!
60//! See `rust/ARCHITECTURE.md` for the design rationale and
61//! doc/superpowers/specs/2026-06-06-js-parser-design.md for the port spec.
62
63#![warn(missing_docs)]
64
65pub mod cursor;
66pub mod html_entities;
67pub mod js;
68pub mod json;
69pub mod lexer;
70pub mod number;
71pub mod token;
72pub mod token_kinds;
73pub mod utf8;
74
75/// The façade module is private: its items are re-exported here so each has
76/// exactly one path in the docs.
77mod facade;
78
79pub use facade::{parse, parse_named, ParseError, ParseFlags, ParsedJS};
80
81/// The AST crate, re-exported under the short name `ast`, so the public path
82/// is `hermes_parser::ast`. Parsing hands back AST types, so a consumer needs
83/// them; re-exporting keeps this crate the only dependency they must declare.
84/// `ast::node::Node`, `ast::visitor`, `ast::context::GCLock` and `ast::dump`
85/// are the pieces the façade's signatures mention. The same items are also
86/// reachable as `hermes_ast::…` by depending on that crate directly.
87pub use hermes_ast as ast;
88
89/// One recorded diagnostic, re-exported because it appears in the façade's
90/// signatures ([`ParseError::diagnostics`], [`ParsedJS::diagnostics`]).
91/// Render one with `hermes_support::render::render_diagnostic`.
92pub use hermes_support::diag::ResolvedDiagnostic;