ktrs_parser/builder/mod.rs
1//! Re-implementation of IntelliJ's `PsiBuilderImpl` (platform 251.27812.49, the one bundled with
2//! Kotlin 2.4.20) and the Kotlin builder wrappers on top of it.
3//!
4//! Semantics kept exactly:
5//! - Whitespace/comments (`WHITE_SPACE`, `EOL/BLOCK/SHEBANG_COMMENT`, `DOC_COMMENT`) are skipped
6//! lazily: by `eof()`/`get_token_type()` and by `mark()` (except for the very first marker),
7//! never by `advance_lexer()`, `error()` or `done()`. Positions are fixed up afterwards by
8//! `balanceWhiteSpaces` using each edge's [`EdgeBinder`] (defaults: start markers skip leading
9//! trivia, done markers and error items exclude trailing trivia; an *empty* marker of a
10//! left-bound type — `ERROR_ELEMENT`, `CONSTRUCTOR_DELEGATION_*` — binds to the left).
11//! - `builder.error()` adds an empty error item at the current raw lexeme, ignored if the last
12//! production entry is an error item at the same lexeme; when building, only the first error item
13//! per lexeme (in production order) survives.
14//! - Collapsed markers become one leaf; leaves of lazy-parseable kinds are reparsed with a fresh
15//! builder into the same [`TreeSink`] (see `tree.rs`), so the tree equals the compiler's fully
16//! expanded PSI.
17//! - Token remaps survive `rollback_to`.
18//!
19//! Deviations: offsets are UTF-8 byte offsets (IntelliJ: UTF-16 units) — only compared with each
20//! other, so behaviour is identical. No debug-mode checks, no `ITokenTypeRemapper`,
21//! `WhitespaceSkippedCallback`, incremental reparse or recursive binders (Kotlin uses none).
22//! Tokens outside the root marker are dropped (upstream logs an error).
23//!
24//! Performance (none of it observable): builders take their vectors from a per-thread pool
25//! (`pool.rs`), chameleons reuse the outer builder's lexemes instead of re-lexing (`LazyLeaf`), and
26//! a caller re-parsing similar text can reuse expanded chameleons (`ChameleonCache`). Measure with
27//! `cargo run -p ktrs-parser --release --example bench`.
28
29mod binders;
30mod chameleon_cache;
31mod layers;
32mod marker;
33mod pool;
34mod production;
35mod psi_builder;
36mod semantic;
37mod sink;
38mod tree;
39
40#[cfg(test)]
41mod tests;
42
43pub use binders::{EdgeBinder, GREEDY_LEFT_BINDER, GREEDY_RIGHT_BINDER};
44pub use chameleon_cache::ChameleonCache;
45pub use marker::{Marker, MarkerHost};
46pub use psi_builder::PsiBuilder;
47pub use layers::Layer;
48pub use semantic::SemanticWhitespaceAwarePsiBuilder;
49pub use sink::TreeSink;
50pub use tree::{LazyLeaf, LazyReparse};