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}