Skip to main content

surrealguard_syntax/ast/
mod.rs

1//! Typed, span-carrying SurrealQL AST.
2//!
3//! Produced by [`crate::lower`] from the tree-sitter CST; consumed by
4//! analyzers. The contract:
5//!
6//! - **Purely syntactic.** No name resolution, no schema, no environment.
7//! - **Spans on everything.** Every node carries the byte range of the CST
8//!   node it came from; nothing holds a `tree_sitter::Node` or a lifetime.
9//! - **Partiality is explicit.** Enums carry a `Partial(PartialNode)` variant
10//!   for positions that failed to lower; statement structs carry an
11//!   `unhandled` bucket for CST children the lowering did not consume.
12//!   Nothing is silently dropped.
13//! - **Normalized.** Keywords are case-folded, function paths canonicalized,
14//!   grammar quirks flattened — before analyzers ever see the tree.
15
16mod clause;
17mod expr;
18mod statement;
19mod ty;
20
21pub use clause::*;
22pub use expr::*;
23pub use statement::*;
24pub use ty::*;
25
26use crate::span::ByteRange;
27
28/// A syntax node paired with the byte range it was lowered from.
29///
30/// `SourceId` travels separately (analysis knows which source it is
31/// working on); spans are plain `Copy` byte ranges so the AST is `'static`.
32#[derive(Clone, Debug, PartialEq)]
33pub struct Spanned<T> {
34    /// The wrapped syntax node.
35    pub node: T,
36    /// Byte range in the source the node was lowered from.
37    pub span: ByteRange,
38}
39
40impl<T> Spanned<T> {
41    /// Pairs a node with the span it was lowered from.
42    pub fn new(node: T, span: ByteRange) -> Self {
43        Self { node, span }
44    }
45
46    /// Maps the inner node, keeping the span.
47    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanned<U> {
48        Spanned {
49            node: f(self.node),
50            span: self.span,
51        }
52    }
53}
54
55/// A region of syntax the lowering could not (or does not) model:
56/// a CST `ERROR`/`MISSING` node, or a construct outside the modeled tier.
57///
58/// Analyzers translate these into explicit partial analysis facts — they
59/// must never be ignored.
60#[derive(Clone, Debug, PartialEq, Eq)]
61pub struct PartialNode {
62    /// Byte range of the unmodeled region.
63    pub span: ByteRange,
64    /// The CST node kind this region had (`"ERROR"`, `"MISSING Ident"`, or
65    /// the named kind of an unmodeled construct).
66    pub cst_kind: String,
67}