Skip to main content

sql_dialect_fmt_lexer/
delimiter.rs

1//! Delimiter definitions for embedded procedure/function bodies.
2//!
3//! Snowflake currently documents string literal delimiters `'` and `$$` for
4//! Snowflake Scripting procedure bodies. The lexer models `$$...$$` as a single
5//! body token because embedded JavaScript/Python/SQL can contain arbitrary SQL
6//! punctuation and semicolons. Keeping the delimiter as data makes the lexer
7//! resilient if Snowflake adds another body delimiter later.
8
9use sql_dialect_fmt_syntax::Dialect;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12pub struct BodyDelimiter {
13    pub name: &'static str,
14    pub opener: &'static str,
15    pub closer: &'static str,
16}
17
18impl BodyDelimiter {
19    pub const fn symmetric(name: &'static str, delimiter: &'static str) -> Self {
20        BodyDelimiter {
21            name,
22            opener: delimiter,
23            closer: delimiter,
24        }
25    }
26
27    pub const fn paired(name: &'static str, opener: &'static str, closer: &'static str) -> Self {
28        BodyDelimiter {
29            name,
30            opener,
31            closer,
32        }
33    }
34}
35
36pub const DOLLAR_QUOTED_BODY: BodyDelimiter = BodyDelimiter::symmetric("dollar-quoted body", "$$");
37
38pub const DEFAULT_BODY_DELIMITERS: &[BodyDelimiter] = &[DOLLAR_QUOTED_BODY];
39
40#[derive(Clone, Copy, Debug)]
41pub struct LexOptions<'cfg> {
42    pub body_delimiters: &'cfg [BodyDelimiter],
43    /// The SQL dialect being lexed. Drives quoting and special-token behavior (`$$`/`$n`, `@stage`)
44    /// so the same lexer can serve multiple dialects. Defaults to [`Dialect::Snowflake`].
45    pub dialect: Dialect,
46}
47
48impl Default for LexOptions<'static> {
49    fn default() -> Self {
50        LexOptions {
51            body_delimiters: DEFAULT_BODY_DELIMITERS,
52            dialect: Dialect::default(),
53        }
54    }
55}
56
57impl<'cfg> LexOptions<'cfg> {
58    /// [`LexOptions`] for `dialect` with the default body delimiters, returning the updated options.
59    #[must_use]
60    pub fn with_dialect(mut self, dialect: Dialect) -> Self {
61        self.dialect = dialect;
62        self
63    }
64}