sqruff_lib_core/parser/grammar/
delimited.rs1use std::ops::{Deref, DerefMut};
2
3use ahash::AHashSet;
4
5use super::anyof::{AnyNumberOf, one_of};
6use crate::dialects::syntax::SyntaxSet;
7use crate::errors::SQLParseError;
8use crate::helpers::ToMatchable;
9use crate::parser::context::ParseContext;
10use crate::parser::grammar::Ref;
11use crate::parser::grammar::noncode::NonCodeMatcher;
12use crate::parser::match_algorithms::{longest_match, skip_start_index_forward_to_code};
13use crate::parser::match_result::MatchResult;
14use crate::parser::matchable::{
15 Matchable, MatchableCacheKey, MatchableTrait, next_matchable_cache_key,
16};
17use crate::parser::segments::ErasedSegment;
18
19#[derive(Clone, Debug)]
24pub struct Delimited {
25 pub base: AnyNumberOf,
26 pub allow_trailing: bool,
27 pub(crate) delimiter: Matchable,
28 pub min_delimiters: usize,
29 pub optional_delimiter: bool,
30 optional: bool,
31 cache_key: MatchableCacheKey,
32}
33
34impl Delimited {
35 pub fn new(elements: Vec<Matchable>) -> Self {
36 Self {
37 base: one_of(elements),
38 allow_trailing: false,
39 delimiter: Ref::new("CommaSegment").to_matchable(),
40 min_delimiters: 0,
41 optional_delimiter: false,
42 optional: false,
43 cache_key: next_matchable_cache_key(),
44 }
45 }
46
47 pub fn allow_trailing(&mut self) {
48 self.allow_trailing = true;
49 }
50
51 pub fn optional_delimiter(&mut self) {
52 self.optional_delimiter = true;
53 }
54
55 pub fn delimiter(&mut self, delimiter: impl ToMatchable) {
56 self.delimiter = delimiter.to_matchable();
57 }
58}
59
60impl PartialEq for Delimited {
61 fn eq(&self, other: &Self) -> bool {
62 self.base == other.base
63 && self.allow_trailing == other.allow_trailing
64 && self.optional_delimiter == other.optional_delimiter
65 }
67}
68
69impl MatchableTrait for Delimited {
70 fn elements(&self) -> &[Matchable] {
71 &self.elements
72 }
73
74 fn is_optional(&self) -> bool {
75 self.optional || self.base.is_optional()
76 }
77
78 fn simple(
79 &self,
80 parse_context: &ParseContext,
81 crumbs: Option<Vec<&str>>,
82 ) -> Option<(AHashSet<String>, SyntaxSet)> {
83 super::anyof::simple(&self.elements, parse_context, crumbs)
84 }
85
86 fn match_segments(
92 &self,
93 segments: &[ErasedSegment],
94 idx: u32,
95 parse_context: &mut ParseContext,
96 ) -> Result<MatchResult, SQLParseError> {
97 let mut delimiters = 0;
98 let mut seeking_delimiter = false;
99 let max_idx = segments.len() as u32;
100 let mut working_idx = idx;
101 let mut working_match = MatchResult::empty_at(idx);
102 let mut delimiter_match = None;
103
104 let delimiter_matcher = self.delimiter.clone();
105
106 let mut terminator_matchers = self.terminators.clone();
107 terminator_matchers.extend(
108 parse_context
109 .terminators
110 .iter()
111 .filter(|&t| &delimiter_matcher != t)
112 .cloned(),
113 );
114
115 let delimiter_matchers = std::slice::from_ref(&self.delimiter);
116
117 if !self.allow_gaps {
118 terminator_matchers.push(NonCodeMatcher.to_matchable());
119 }
120
121 loop {
122 if self.allow_gaps && working_idx > idx {
123 working_idx =
124 skip_start_index_forward_to_code(segments, working_idx, segments.len() as u32);
125 }
126
127 if working_idx >= max_idx {
128 break;
129 }
130
131 let (match_result, _) = parse_context.deeper_match(false, &[], |this| {
132 longest_match(segments, &terminator_matchers, working_idx, this)
133 })?;
134
135 if match_result.has_match() {
136 break;
137 }
138
139 let mut push_terminators: &[_] = &[];
140 if !seeking_delimiter {
141 push_terminators = delimiter_matchers;
142 }
143
144 let (match_result, _) =
145 parse_context.deeper_match(false, push_terminators, |this| {
146 longest_match(
147 segments,
148 if seeking_delimiter {
149 delimiter_matchers
150 } else {
151 &self.elements
152 },
153 working_idx,
154 this,
155 )
156 })?;
157
158 if !match_result.has_match() {
159 if seeking_delimiter && self.optional_delimiter {
160 seeking_delimiter = false;
161 continue;
162 }
163 break;
164 }
165
166 working_idx = match_result.span.end;
167
168 if seeking_delimiter {
169 delimiter_match = match_result.into();
170 } else {
171 if let Some(delimiter_match) = &delimiter_match {
172 delimiters += 1;
173 working_match = working_match.append(delimiter_match);
174 }
175 working_match = working_match.append(match_result);
176 }
177
178 seeking_delimiter = !seeking_delimiter;
179 }
180
181 if let Some(delimiter_match) =
182 delimiter_match.filter(|_delimiter_match| self.allow_trailing && !seeking_delimiter)
183 {
184 delimiters += 1;
185 working_match = working_match.append(delimiter_match);
186 }
187
188 if delimiters < self.min_delimiters {
189 return Ok(MatchResult::empty_at(idx));
190 }
191
192 Ok(working_match)
193 }
194
195 fn cache_key(&self) -> MatchableCacheKey {
196 self.cache_key
197 }
198
199 #[track_caller]
200 fn copy(
201 &self,
202 insert: Option<Vec<Matchable>>,
203 at: Option<usize>,
204 before: Option<Matchable>,
205 remove: Option<Vec<Matchable>>,
206 terminators: Vec<Matchable>,
207 replace_terminators: bool,
208 ) -> Matchable {
209 let mut new_elements = self.elements.clone();
210
211 if let Some(insert_elements) = insert {
212 if let Some(before_element) = before {
213 if let Some(index) = self.elements.iter().position(|e| e == &before_element) {
214 new_elements.splice(index..index, insert_elements);
215 } else {
216 panic!("Element for insertion before not found");
217 }
218 } else if let Some(at_index) = at {
219 new_elements.splice(at_index..at_index, insert_elements);
220 } else {
221 new_elements.extend(insert_elements);
222 }
223 }
224
225 if let Some(remove_elements) = remove {
226 new_elements.retain(|elem| !remove_elements.contains(elem));
227 }
228
229 let mut new_grammar = self.clone();
230
231 new_grammar.base.elements = new_elements;
232 new_grammar.base.terminators = if replace_terminators {
233 terminators
234 } else {
235 [self.terminators.clone(), terminators].concat()
236 };
237
238 new_grammar.to_matchable()
239 }
240}
241
242impl Deref for Delimited {
243 type Target = AnyNumberOf;
244
245 fn deref(&self) -> &Self::Target {
246 &self.base
247 }
248}
249
250impl DerefMut for Delimited {
251 fn deref_mut(&mut self) -> &mut Self::Target {
252 &mut self.base
253 }
254}