squonk_ast/lib.rs
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 Moderately AI Inc.
3
4// docs.rs feature-gate banners (ticket docs-rs-feature-gate-banners): turn on rustdoc's `doc_cfg` for the nightly docs.rs build only — gated by the `docsrs` cfg docs.rs sets — so feature-gated items render an "Available on crate feature X" banner; auto_cfg is on by default at crate level once `doc_cfg` is enabled (the old `doc_auto_cfg` gate was merged into `doc_cfg` and removed in Rust 1.92), and the whole thing is inert on the pinned stable toolchain (the cfg is never set there).
5#![cfg_attr(docsrs, feature(doc_cfg))]
6#![deny(missing_docs)]
7// Compiler-enforced, uncappable: the pure AST vocabulary has no perf hatch to reserve,
8// so it takes the stronger `forbid` where the workspace-wide lint only `deny`s
9// unsafe_code (`Cargo.toml`, `[workspace.lints.rust]`) to leave the parser a reviewed
10// opt-in. A green build of this crate is the proof no unsafe slips in.
11#![forbid(unsafe_code)]
12//! Abstract syntax tree for `squonk`.
13//!
14//! This crate holds the dialect-agnostic SQL AST: the node vocabulary ([`vocab`]),
15//! node types ([`ast`]), dialect data ([`dialect`]), and precedence data
16//! ([`precedence`]). It deliberately depends on nothing in the parser, so
17//! downstream tooling (rewriters, linters, formatters) can build on the AST
18//! without pulling in the tokenizer/parser. To *parse* SQL into these nodes, depend
19//! on the `squonk` crate, which re-exports this one as `squonk::ast` and
20//! carries the end-to-end parse → inspect → render examples.
21//!
22//! # Design records
23//!
24//! The architectural decisions behind this AST — the owned tree, byte-range spans,
25//! interned identifiers, and the canonical-shape-plus-tag policy among them — are
26//! recorded as ADRs in the repository's
27//! [`docs/adr`](https://github.com/moderately-ai/squonk/tree/main/docs/adr)
28//! directory.
29//!
30//! # Rendering
31//!
32//! Rendering is configured by [`render::RenderConfig`]: a [`mode`](render::RenderMode)
33//! (canonical, fully parenthesized, or redacted) and a
34//! [`spelling`](render::RenderSpelling) (source-preserving or target-dialect). The
35//! `squonk` crate threads these through a [`render::RenderCtx`] over a parsed
36//! tree; see that crate for the runnable parse → render flows.
37//!
38//! ```
39//! use squonk_ast::render::{RenderConfig, RenderMode, RenderSpelling};
40//!
41//! let config = RenderConfig::default();
42//! assert_eq!(config.mode, RenderMode::Canonical);
43//! assert_eq!(config.spelling, RenderSpelling::PreserveSource);
44//! ```
45
46pub mod ast;
47pub mod dialect;
48pub mod generated;
49pub mod precedence;
50pub mod render;
51pub mod vocab;
52
53/// Deserialization recursion-depth guard, available only under the `serde` feature.
54#[cfg(feature = "serde-deserialize")]
55pub mod serde_depth;
56
57pub use ast::*;
58pub use dialect::{
59 Keyword, KeywordSet, RESERVED_BARE_ALIAS, RESERVED_COLUMN_NAME, RESERVED_FUNCTION_NAME,
60 RESERVED_TYPE_NAME, lookup_keyword,
61};
62pub use vocab::{FoldedSymbol, LineIndex, Meta, NodeId, Resolver, SourceStore, Span, Symbol};