sqruff_lib_core/parser/
matchable.rs

1use std::ops::Deref;
2use std::sync::Arc;
3use std::sync::atomic::{AtomicU32, Ordering};
4
5use ahash::AHashSet;
6use enum_dispatch::enum_dispatch;
7
8use super::context::ParseContext;
9use super::grammar::anyof::AnyNumberOf;
10use super::grammar::base::{Anything, Nothing, Ref};
11use super::grammar::conditional::Conditional;
12use super::grammar::delimited::Delimited;
13use super::grammar::noncode::NonCodeMatcher;
14use super::grammar::sequence::{Bracketed, Sequence};
15use super::match_result::MatchResult;
16use super::node_matcher::NodeMatcher;
17use super::parsers::{MultiStringParser, RegexParser, StringParser, TypedParser};
18use super::segments::base::ErasedSegment;
19use super::segments::bracketed::BracketedSegmentMatcher;
20use super::segments::meta::MetaSegment;
21use crate::dialects::syntax::{SyntaxKind, SyntaxSet};
22use crate::errors::SQLParseError;
23
24#[derive(Clone, Debug, PartialEq)]
25pub struct Matchable {
26    inner: Arc<MatchableTraitImpl>,
27}
28
29impl Deref for Matchable {
30    type Target = MatchableTraitImpl;
31
32    fn deref(&self) -> &Self::Target {
33        &self.inner
34    }
35}
36
37impl Matchable {
38    pub fn new(matchable: MatchableTraitImpl) -> Self {
39        Self {
40            inner: Arc::new(matchable),
41        }
42    }
43
44    pub fn get_mut(&mut self) -> &mut MatchableTraitImpl {
45        Arc::get_mut(&mut self.inner).unwrap()
46    }
47
48    pub fn make_mut(&mut self) -> &mut MatchableTraitImpl {
49        Arc::make_mut(&mut self.inner)
50    }
51
52    pub fn as_conditional(&self) -> Option<&Conditional> {
53        match self.inner.as_ref() {
54            MatchableTraitImpl::Conditional(parser) => Some(parser),
55            _ => None,
56        }
57    }
58
59    pub fn as_indent(&self) -> Option<&MetaSegment> {
60        match self.inner.as_ref() {
61            MatchableTraitImpl::MetaSegment(parser) => Some(parser),
62            _ => None,
63        }
64    }
65
66    pub fn as_regex(&self) -> Option<&RegexParser> {
67        match self.inner.as_ref() {
68            MatchableTraitImpl::RegexParser(parser) => Some(parser),
69            _ => None,
70        }
71    }
72
73    pub fn as_ref(&self) -> Option<&Ref> {
74        match self.inner.as_ref() {
75            MatchableTraitImpl::Ref(parser) => Some(parser),
76            _ => None,
77        }
78    }
79
80    pub fn as_node_matcher(&mut self) -> Option<&mut NodeMatcher> {
81        match Arc::make_mut(&mut self.inner) {
82            MatchableTraitImpl::NodeMatcher(parser) => Some(parser),
83            _ => None,
84        }
85    }
86}
87
88#[enum_dispatch(MatchableTrait)]
89#[derive(Clone, Debug)]
90pub enum MatchableTraitImpl {
91    AnyNumberOf(AnyNumberOf),
92    Bracketed(Bracketed),
93    NodeMatcher(NodeMatcher),
94    NonCodeMatcher(NonCodeMatcher),
95    Nothing(Nothing),
96    Ref(Ref),
97    Sequence(Sequence),
98    StringParser(StringParser),
99    TypedParser(TypedParser),
100    MetaSegment(MetaSegment),
101    MultiStringParser(MultiStringParser),
102    RegexParser(RegexParser),
103    Delimited(Delimited),
104    Anything(Anything),
105    Conditional(Conditional),
106    BracketedSegmentMatcher(BracketedSegmentMatcher),
107}
108
109impl PartialEq for MatchableTraitImpl {
110    fn eq(&self, other: &Self) -> bool {
111        match (self, other) {
112            (Self::Ref(a), Self::Ref(b)) => {
113                a.reference == b.reference
114                    && a.optional == b.optional
115                    && a.allow_gaps == b.allow_gaps
116            }
117            (Self::Delimited(a), Self::Delimited(b)) => {
118                a.base == b.base && a.allow_trailing == b.allow_trailing
119            }
120            (Self::StringParser(a), Self::StringParser(b)) => a == b,
121            (Self::TypedParser(a), Self::TypedParser(b)) => a == b,
122            (Self::MultiStringParser(a), Self::MultiStringParser(b)) => a == b,
123            _ => {
124                std::mem::discriminant(self) == std::mem::discriminant(other)
125                    && self.is_optional() == other.is_optional()
126                    && self.elements() == other.elements()
127            }
128        }
129    }
130}
131
132#[enum_dispatch]
133pub trait MatchableTrait {
134    fn get_type(&self) -> SyntaxKind {
135        todo!()
136    }
137
138    fn match_grammar(&self) -> Option<Matchable> {
139        None
140    }
141
142    fn elements(&self) -> &[Matchable];
143
144    // Return whether this element is optional.
145    fn is_optional(&self) -> bool {
146        false
147    }
148
149    // Try to obtain a simple response from the matcher.
150    // Returns a tuple of two sets of strings if simple.
151    // The first is a set of uppercase raw strings which would match.
152    // The second is a set of segment types that would match.
153    // Returns None if not simple.
154    // Note: the crumbs argument is used to detect recursion.
155    fn simple(
156        &self,
157        parse_context: &ParseContext,
158        crumbs: Option<Vec<&str>>,
159    ) -> Option<(AHashSet<String>, SyntaxSet)> {
160        let match_grammar = self.match_grammar()?;
161
162        match_grammar.simple(parse_context, crumbs)
163    }
164
165    fn match_segments(
166        &self,
167        _segments: &[ErasedSegment],
168        _idx: u32,
169        _parse_context: &mut ParseContext,
170    ) -> Result<MatchResult, SQLParseError> {
171        todo!();
172    }
173
174    fn cache_key(&self) -> MatchableCacheKey {
175        unimplemented!("{}", std::any::type_name::<Self>())
176    }
177
178    #[track_caller]
179    fn copy(
180        &self,
181        _insert: Option<Vec<Matchable>>,
182        _at: Option<usize>,
183        _before: Option<Matchable>,
184        _remove: Option<Vec<Matchable>>,
185        _terminators: Vec<Matchable>,
186        _replace_terminators: bool,
187    ) -> Matchable {
188        unimplemented!("{}", std::any::type_name::<Self>())
189    }
190}
191
192pub type MatchableCacheKey = u32;
193
194pub fn next_matchable_cache_key() -> MatchableCacheKey {
195    // The value 0 is reserved for NonCodeMatcher. This grammar matcher is somewhat
196    // of a singleton, so we don't need a unique ID in the same way as other grammar
197    // matchers.
198    static ID: AtomicU32 = AtomicU32::new(1);
199
200    ID.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |id| id.checked_add(1))
201        .unwrap()
202}