sqruff_lib_core/parser/
matchable.rs1use 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 fn is_optional(&self) -> bool {
150 false
151 }
152
153 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 static ID: AtomicU32 = AtomicU32::new(1);
203
204 ID.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |id| id.checked_add(1))
205 .unwrap()
206}