Skip to main content

syntaqlite_syntax/
lib.rs

1// Copyright 2025 The syntaqlite Authors. All rights reserved.
2// Licensed under the Apache License, Version 2.0.
3
4#![cfg_attr(test, allow(clippy::unwrap_used, clippy::similar_names))]
5
6//! Low-level tokenizer and parser for `SQLite` SQL.
7//!
8//! This crate is split from `syntaqlite` for internal build reasons — it is
9//! **not** a separate user-facing library. All public types are re-exported by
10//! [`syntaqlite`](https://docs.rs/syntaqlite). **Depend on `syntaqlite`
11//! directly.** If you only need parsing (no formatting or validation), disable
12//! the default features and enable just `sqlite`:
13//!
14//! ```toml
15//! [dependencies]
16//! syntaqlite = { version = "0.0.30", default-features = false, features = ["sqlite"] }
17//! ```
18
19// ==== Public API ====
20
21// Top level parser types.
22#[doc(inline)]
23pub use parser::ParserConfig;
24#[cfg(feature = "sqlite")]
25#[doc(inline)]
26pub use parser::{
27    ParseError, ParseErrorKind, ParseOutcome, ParseSession, ParsedStatement, Parser, ParserToken,
28};
29
30// Token/comment data types shared across grammars.
31#[doc(inline)]
32pub use parser::{Comment, CommentKind, CommentSpan, CompletionContext, ParserTokenFlags};
33
34// Top-level tokenizer types.
35// TokenType is always available — ordinals are stable across all dialects.
36#[doc(inline)]
37pub use sqlite::tokens::TokenType;
38#[cfg(feature = "sqlite")]
39#[doc(inline)]
40pub use tokenizer::{Token, Tokenizer};
41
42/// Cross-cutting utilities for grammar configuration and compatibility.
43///
44/// Reach for this module when you need to pin parser behavior to a target
45/// `SQLite` release or inspect feature-flag state.
46pub mod util;
47
48/// Type-erased variants of every parser and tokenizer type.
49///
50/// **Most code should not need this module.** If you are working with the
51/// `SQLite` grammar — which is the common case — use the top-level
52/// [`Parser`], [`ParseSession`], [`Tokenizer`], and [`Token`] types instead.
53///
54/// ## When to use `any`
55///
56/// Reach for this module only when you need to work with grammars generically,
57/// without knowing the grammar at compile time. The primary use cases are:
58///
59/// - **Multi-grammar infrastructure** — tools that accept an [`any::AnyGrammar`]
60///   from the caller and operate on whichever grammar is handed in (e.g. a
61///   generic formatter, a language-server host, or a test harness that runs
62///   against several grammars).
63/// - **Storage without a lifetime parameter** — [`any::AnyNodeId`] identifies a
64///   node in a parse arena and can be stored freely; typed node references
65///   borrow the arena and cannot outlive it.
66/// - **FFI and plugin boundaries** — [`any::AnyGrammar`] is `Copy + Send + Sync`
67///   and is the natural unit to pass across crate boundaries or plugin APIs.
68///
69/// ## Caveats
70///
71/// The `Any*` types erase the grammar's token and node enums, replacing them
72/// with raw `u32` ordinals. You lose exhaustive `match` on token kinds and
73/// the typed accessor methods on AST nodes. Prefer the typed API whenever the
74/// grammar is known statically.
75pub mod any {
76    #[doc(inline)]
77    pub use crate::ast::{AnyNode, AnyNodeId, AnyNodeTag, AnyTokenType, FieldValue, NodeFields};
78    #[doc(inline)]
79    pub use crate::grammar::{AnyGrammar, FieldKind, FieldMeta, KeywordEntry, TokenCategory};
80    #[doc(inline)]
81    pub use crate::parser::{
82        AnyIncrementalParseSession, AnyParseError, AnyParseSession, AnyParsedStatement, AnyParser,
83        AnyParserToken, MacroRegion, ParseOutcome,
84    };
85    #[doc(inline)]
86    pub use crate::tokenizer::{AnyToken, AnyTokenizer};
87}
88
89/// Generic, grammar-parameterized variants of parser/tokenizer types.
90///
91/// **Most code should not need this module.** Application code working with
92/// the `SQLite` grammar should use the top-level [`Parser`], [`ParseSession`],
93/// [`Tokenizer`], and [`Token`] types, which are thin wrappers over the typed
94/// internals already instantiated for `SQLite`.
95///
96/// ## When to use `typed`
97///
98/// In practice, you will rarely import from this module directly. Its contents
99/// are primarily consumed by the grammar generator: the traits
100/// [`GrammarNodeType`](typed::GrammarNodeType),
101/// [`GrammarTokenType`](typed::GrammarTokenType), and
102/// [`TypedNodeId`](typed::TypedNodeId) are implemented automatically for each
103/// grammar's generated node and token enums. The generator produces correct
104/// implementations — you do not implement or import these manually.
105///
106/// If you need to write code that works across grammars without grammar-specific
107/// types, use [`any`] instead, which provides type-erased equivalents that are
108/// far easier to work with.
109pub mod typed {
110    #[doc(inline)]
111    pub use crate::ast::{GrammarNodeType, GrammarTokenType, TypedNodeId, TypedNodeList};
112    #[doc(inline)]
113    pub use crate::grammar::TypedGrammar;
114    #[doc(inline)]
115    pub use crate::parser::{
116        ParseOutcome, TypedIncrementalParseSession, TypedParseError, TypedParseSession,
117        TypedParsedStatement, TypedParser, TypedParserToken,
118    };
119    #[doc(inline)]
120    pub use crate::tokenizer::{TypedToken, TypedTokenizer};
121
122    // Only exposed for use in generated code, not public API.
123    #[doc(hidden)]
124    pub use crate::grammar::ffi::CGrammar;
125
126    /// Top-level grammar handle for the `SQLite` grammar.
127    ///
128    /// Most code should not need to call `grammar()` directly; the top-level [`crate::Parser`]
129    /// and [`crate::Tokenizer`] types construct it internally. However, if you need to
130    /// work with the grammar directly — for example, to inspect its token and node
131    /// metadata, or to construct a parser or tokenizer manually — you can obtain a
132    /// handle with `grammar()`.
133    /// Top-level typed grammar handle type for the `SQLite` grammar.
134    ///
135    /// Useful when you need to name the type parameter in `TypedDialect<Grammar>`.
136    #[cfg(feature = "sqlite")]
137    pub use crate::sqlite::grammar::Grammar;
138    #[cfg(feature = "sqlite")]
139    pub use crate::sqlite::grammar::grammar;
140}
141
142/// Generated typed AST for the built-in `SQLite` grammar.
143///
144/// Re-exports every generated node struct, enum, and accessor type for the
145/// `SQLite` grammar. Import from here when you need to name concrete node
146/// types — for example, when pattern-matching on a [`ParsedStatement`] or
147/// traversing the parse tree.
148#[cfg(feature = "sqlite")]
149pub mod nodes {
150    pub use crate::sqlite::ast::*;
151}
152
153// Top-level incremental parse session type (SQLite grammar).
154#[cfg(feature = "sqlite")]
155#[doc(inline)]
156pub use parser::IncrementalParseSession;
157
158// ==== Internal modules ====
159
160pub(crate) mod ast;
161mod grammar;
162pub(crate) mod parser;
163pub(crate) mod tokenizer;
164
165// `sqlite` module is always present; individual sub-modules are gated inside it.
166pub(crate) mod sqlite;