sqruff_lib_core/
dialects.rs1pub mod common;
2pub mod init;
3pub mod syntax;
4
5use std::borrow::Cow;
6use std::fmt::Debug;
7
8use hashbrown::hash_map::Entry;
9use hashbrown::{HashMap, HashSet};
10
11use crate::dialects::init::DialectKind;
12use crate::dialects::syntax::SyntaxKind;
13use crate::helpers::ToMatchable;
14use crate::parser::lexer::{Lexer, Matcher};
15use crate::parser::matchable::Matchable;
16use crate::parser::parsers::StringParser;
17use crate::parser::types::DialectElementType;
18
19#[derive(Debug, Clone, Default)]
20pub struct Dialect {
21 pub name: DialectKind,
22 lexer_matchers: Vec<Matcher>,
23 library: HashMap<Cow<'static, str>, DialectElementType>,
24 sets: HashMap<&'static str, HashSet<&'static str>>,
25 pub bracket_collections: HashMap<&'static str, HashSet<BracketPair>>,
26 lexer: Option<Lexer>,
27}
28
29impl PartialEq for Dialect {
30 fn eq(&self, other: &Self) -> bool {
31 self.name == other.name
32 }
33}
34
35impl Dialect {
36 pub fn new() -> Self {
37 Dialect {
38 name: DialectKind::Ansi,
39 ..Default::default()
40 }
41 }
42
43 pub fn name(&self) -> DialectKind {
44 self.name
45 }
46
47 pub fn add(&mut self, iter: impl IntoIterator<Item = (Cow<'static, str>, DialectElementType)>) {
48 self.library.extend(iter);
49 }
50
51 pub fn grammar(&self, name: &str) -> Matchable {
52 match self
53 .library
54 .get(name)
55 .unwrap_or_else(|| panic!("not found {name}"))
56 {
57 DialectElementType::Matchable(matchable) => matchable.clone(),
58 DialectElementType::SegmentGenerator(_) => {
59 unreachable!("Attempted to fetch non grammar [{name}] with `Dialect::grammar`.")
60 }
61 }
62 }
63
64 #[track_caller]
65 pub fn replace_grammar(&mut self, name: &'static str, match_grammar: Matchable) {
66 match self.library.entry(Cow::Borrowed(name)) {
67 Entry::Occupied(entry) => {
68 let target = entry.into_mut();
69 match target {
70 DialectElementType::Matchable(matchable) => {
71 if let Some(node_matcher) = matchable.as_node_matcher() {
72 node_matcher.replace(match_grammar);
73 } else {
74 *target = DialectElementType::Matchable(match_grammar);
75 }
76 }
77 DialectElementType::SegmentGenerator(_) => {
78 *target = DialectElementType::Matchable(match_grammar);
79 }
80 }
81 }
82 Entry::Vacant(entry) => {
83 entry.insert(match_grammar.into());
84 }
85 }
86 }
87
88 pub fn lexer_matchers(&self) -> &[Matcher] {
89 &self.lexer_matchers
90 }
91
92 pub fn insert_lexer_matchers(&mut self, lexer_patch: Vec<Matcher>, before: &str) {
93 assert!(
94 !self.lexer_matchers.is_empty(),
95 "Lexer struct must be defined before it can be patched!"
96 );
97
98 let mut buff = Vec::new();
99 let mut found = false;
100
101 for elem in std::mem::take(&mut self.lexer_matchers) {
102 if elem.name() == before {
103 found = true;
104 for patch in lexer_patch.clone() {
105 buff.push(patch);
106 }
107 buff.push(elem);
108 } else {
109 buff.push(elem);
110 }
111 }
112
113 assert!(
114 found,
115 "Lexer struct insert before '{before}' failed because tag never found."
116 );
117
118 self.lexer_matchers = buff;
119 }
120
121 pub fn patch_lexer_matchers(&mut self, lexer_patch: Vec<Matcher>) {
122 assert!(
123 !self.lexer_matchers.is_empty(),
124 "Lexer struct must be defined before it can be patched!"
125 );
126
127 let mut buff = Vec::with_capacity(self.lexer_matchers.len());
128
129 let patch_dict: HashMap<&'static str, Matcher> = lexer_patch
130 .into_iter()
131 .map(|elem| (elem.name(), elem))
132 .collect();
133
134 for elem in std::mem::take(&mut self.lexer_matchers) {
135 if let Some(patch) = patch_dict.get(elem.name()) {
136 buff.push(patch.clone());
137 } else {
138 buff.push(elem);
139 }
140 }
141
142 self.lexer_matchers = buff;
143 }
144
145 pub fn set_lexer_matchers(&mut self, lexer_matchers: Vec<Matcher>) {
146 self.lexer_matchers = lexer_matchers;
147 }
148
149 pub fn sets(&self, label: &str) -> HashSet<&'static str> {
150 match label {
151 "bracket_pairs" | "angle_bracket_pairs" => {
152 panic!("Use `bracket_sets` to retrieve {label} set.");
153 }
154 _ => (),
155 }
156
157 self.sets.get(label).cloned().unwrap_or_default()
158 }
159
160 pub fn sets_mut(&mut self, label: &'static str) -> &mut HashSet<&'static str> {
161 assert!(
162 label != "bracket_pairs" && label != "angle_bracket_pairs",
163 "Use `bracket_sets` to retrieve {label} set."
164 );
165
166 match self.sets.entry(label) {
167 Entry::Occupied(entry) => entry.into_mut(),
168 Entry::Vacant(entry) => entry.insert(<_>::default()),
169 }
170 }
171
172 pub fn update_keywords_set_from_multiline_string(
173 &mut self,
174 set_label: &'static str,
175 values: &'static str,
176 ) {
177 let keywords = values.lines().map(str::trim);
178 self.sets_mut(set_label).extend(keywords);
179 }
180
181 pub fn add_keyword_to_set(&mut self, set_label: &'static str, value: &'static str) {
182 self.sets_mut(set_label).insert(value);
183 }
184
185 pub fn bracket_sets(&self, label: &str) -> HashSet<BracketPair> {
186 assert!(
187 label == "bracket_pairs" || label == "angle_bracket_pairs",
188 "Invalid bracket set. Consider using another identifier instead."
189 );
190
191 self.bracket_collections
192 .get(label)
193 .cloned()
194 .unwrap_or_default()
195 }
196
197 pub fn bracket_sets_mut(&mut self, label: &'static str) -> &mut HashSet<BracketPair> {
198 assert!(
199 label == "bracket_pairs" || label == "angle_bracket_pairs",
200 "Invalid bracket set. Consider using another identifier instead."
201 );
202
203 self.bracket_collections.entry(label).or_default()
204 }
205
206 pub fn update_bracket_sets(&mut self, label: &'static str, pairs: Vec<BracketPair>) {
207 let set = self.bracket_sets_mut(label);
208 for pair in pairs {
209 set.insert(pair);
210 }
211 }
212
213 #[track_caller]
214 pub fn r#ref(&self, name: &str) -> Matchable {
215 match self.library.get(name) {
216 Some(DialectElementType::Matchable(matchable)) => matchable.clone(),
217 Some(DialectElementType::SegmentGenerator(_)) => {
218 panic!("Unexpected SegmentGenerator while fetching '{name}'");
219 }
220 None => {
221 panic!("Grammar refers to '{name}' which was not found in the dialect.",);
222 }
223 }
224 }
225
226 pub fn expand(&mut self) {
227 let mut library = std::mem::take(&mut self.library);
230 for element in library.values_mut() {
231 if let DialectElementType::SegmentGenerator(generator) = element {
232 *element = DialectElementType::Matchable(generator.expand(self));
233 }
234 }
235 self.library = library;
236
237 for keyword_set in [
238 "unreserved_keywords",
239 "reserved_keywords",
240 "future_reserved_keywords",
241 ] {
242 if let Some(keywords) = self.sets.get(keyword_set) {
243 for &kw in keywords {
244 if !self.library.contains_key(kw) {
245 let parser = StringParser::new(kw, SyntaxKind::Keyword);
246
247 self.library.insert(
248 kw.into(),
249 DialectElementType::Matchable(parser.to_matchable()),
250 );
251 }
252 }
253 }
254 }
255
256 self.lexer = Lexer::new(self.lexer_matchers()).into();
257 }
258
259 pub fn lexer(&self) -> &Lexer {
260 self.lexer.as_ref().unwrap()
261 }
262}
263
264pub type BracketPair = (&'static str, &'static str, &'static str, bool);