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