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::{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    MetaSegment(MetaSegment),
103    MultiStringParser(MultiStringParser),
104    RegexParser(RegexParser),
105    Delimited(Delimited),
106    Anything(Anything),
107    Conditional(Conditional),
108    BracketedSegmentMatcher(BracketedSegmentMatcher),
109    LookaheadExclude(LookaheadExclude),
110}
111
112impl PartialEq for MatchableTraitImpl {
113    fn eq(&self, other: &Self) -> bool {
114        match (self, other) {
115            (Self::Ref(a), Self::Ref(b)) => {
116                a.reference == b.reference
117                    && a.optional == b.optional
118                    && a.allow_gaps == b.allow_gaps
119            }
120            (Self::Delimited(a), Self::Delimited(b)) => {
121                a.base == b.base && a.allow_trailing == b.allow_trailing
122            }
123            (Self::StringParser(a), Self::StringParser(b)) => a == b,
124            (Self::TypedParser(a), Self::TypedParser(b)) => a == b,
125            (Self::MultiStringParser(a), Self::MultiStringParser(b)) => a == b,
126            _ => {
127                std::mem::discriminant(self) == std::mem::discriminant(other)
128                    && self.is_optional() == other.is_optional()
129                    && self.elements() == other.elements()
130            }
131        }
132    }
133}
134
135#[enum_dispatch]
136pub trait MatchableTrait {
137    fn get_type(&self) -> SyntaxKind {
138        todo!()
139    }
140
141    fn match_grammar(&self, _dialect: &Dialect) -> Option<Matchable> {
142        None
143    }
144
145    fn elements(&self) -> &[Matchable];
146
147    // Return whether this element is optional.
148    fn is_optional(&self) -> bool {
149        false
150    }
151
152    // Try to obtain a simple response from the matcher.
153    // Returns a tuple of two sets of strings if simple.
154    // The first is a set of uppercase raw strings which would match.
155    // The second is a set of segment types that would match.
156    // Returns None if not simple.
157    // Note: the crumbs argument is used to detect recursion.
158    fn simple(
159        &self,
160        parse_context: &ParseContext,
161        crumbs: Option<Vec<&str>>,
162    ) -> Option<(AHashSet<String>, SyntaxSet)> {
163        let match_grammar = self.match_grammar(parse_context.dialect())?;
164
165        match_grammar.simple(parse_context, crumbs)
166    }
167
168    fn match_segments(
169        &self,
170        _segments: &[ErasedSegment],
171        _idx: u32,
172        _parse_context: &mut ParseContext,
173    ) -> Result<MatchResult, SQLParseError> {
174        todo!();
175    }
176
177    fn cache_key(&self) -> MatchableCacheKey {
178        unimplemented!("{}", std::any::type_name::<Self>())
179    }
180
181    #[track_caller]
182    fn copy(
183        &self,
184        _insert: Option<Vec<Matchable>>,
185        _at: Option<usize>,
186        _before: Option<Matchable>,
187        _remove: Option<Vec<Matchable>>,
188        _terminators: Vec<Matchable>,
189        _replace_terminators: bool,
190    ) -> Matchable {
191        unimplemented!("{}", std::any::type_name::<Self>())
192    }
193}
194
195pub type MatchableCacheKey = u32;
196
197pub fn next_matchable_cache_key() -> MatchableCacheKey {
198    // The value 0 is reserved for NonCodeMatcher. This grammar matcher is somewhat
199    // of a singleton, so we don't need a unique ID in the same way as other grammar
200    // matchers.
201    static ID: AtomicU32 = AtomicU32::new(1);
202
203    ID.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |id| id.checked_add(1))
204        .unwrap()
205}