1#![allow(dead_code)] use logos::Logos;
10use rowan::Language;
11
12#[derive(Logos, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
15#[repr(u16)]
16pub enum SyntaxKind {
17 #[token("(")]
18 ParenOpen = 0,
19
20 #[token(")")]
21 ParenClose,
22
23 #[token("[")]
24 BracketOpen,
25
26 #[token("]")]
27 BracketClose,
28
29 #[token("{")]
30 BraceOpen,
31
32 #[token("}")]
33 BraceClose,
34
35 #[token("::")]
37 DoubleColon,
38
39 #[token(":")]
40 Colon,
41
42 #[token("=")]
43 Equals,
44
45 #[token("!")]
46 Negation,
47
48 #[token("~")]
49 Tilde,
50
51 #[token("_")]
52 Underscore,
53
54 #[token("*")]
55 Star,
56
57 #[token("+")]
58 Plus,
59
60 #[token("?")]
61 Question,
62
63 #[token("*?")]
65 StarQuestion,
66
67 #[token("+?")]
69 PlusQuestion,
70
71 #[token("??")]
73 QuestionQuestion,
74
75 #[token("/")]
77 Slash,
78
79 #[token(",")]
81 Comma,
82
83 #[token("|")]
85 Pipe,
86
87 #[regex(r#""(?:[^"\\]|\\.)*""#)]
89 #[regex(r"'(?:[^'\\]|\\.)*'")]
90 StringLiteral,
91
92 DoubleQuote,
93 SingleQuote,
94 StrVal,
96
97 #[token("ERROR")]
98 KwError,
99
100 #[token("MISSING")]
101 KwMissing,
102
103 #[regex(r"[a-zA-Z][a-zA-Z0-9_.\-]*")]
106 Id,
107
108 #[token(".")]
109 Dot,
110
111 #[token("@")]
112 At,
113
114 #[regex(r"[ \t]+")]
115 Whitespace,
116
117 #[token("\n")]
118 #[token("\r\n")]
119 Newline,
120
121 #[regex(r"//[^\n]*", allow_greedy = true)]
122 LineComment,
123
124 #[regex(r"/\*(?:[^*]|\*[^/])*\*/")]
125 BlockComment,
126
127 #[regex(r"<[a-zA-Z_:][a-zA-Z0-9_:\.\-]*(?:\s+[^>]*)?>")]
129 #[regex(r"</[a-zA-Z_:][a-zA-Z0-9_:\.\-]*\s*>")]
130 #[regex(r"<[a-zA-Z_:][a-zA-Z0-9_:\.\-]*\s*/\s*>")]
131 XMLGarbage,
132 #[regex(r"#[a-zA-Z_][a-zA-Z0-9_]*[?!]?")]
134 Predicate,
135 Garbage,
137 Error,
138
139 Root,
141 Tree,
142 Ref,
143 Str,
144 Field,
145 Capture,
146 Type,
147 Quantifier,
148 Seq,
149 Alt,
150 Branch,
151 Wildcard,
152 Anchor,
153 NegatedField,
154 Def,
155
156 #[doc(hidden)]
158 __LAST,
159}
160
161use SyntaxKind::*;
162
163impl SyntaxKind {
164 #[inline]
165 pub fn is_trivia(self) -> bool {
166 matches!(self, Whitespace | Newline | LineComment | BlockComment)
167 }
168
169 #[inline]
170 pub fn is_error(self) -> bool {
171 matches!(self, Error | XMLGarbage | Garbage | Predicate)
172 }
173}
174
175impl From<SyntaxKind> for rowan::SyntaxKind {
176 #[inline]
177 fn from(kind: SyntaxKind) -> Self {
178 Self(kind as u16)
179 }
180}
181
182#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
184pub enum QLang {}
185
186impl Language for QLang {
187 type Kind = SyntaxKind;
188
189 fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
190 assert!(raw.0 < __LAST as u16);
191 unsafe { std::mem::transmute::<u16, SyntaxKind>(raw.0) }
193 }
194
195 fn kind_to_raw(kind: Self::Kind) -> rowan::SyntaxKind {
196 kind.into()
197 }
198}
199
200pub type SyntaxNode = rowan::SyntaxNode<QLang>;
202pub type SyntaxToken = rowan::SyntaxToken<QLang>;
203pub type SyntaxElement = rowan::NodeOrToken<SyntaxNode, SyntaxToken>;
204
205#[derive(Clone, Copy, PartialEq, Eq)]
207pub struct TokenSet(u64);
208
209impl TokenSet {
210 pub const EMPTY: TokenSet = TokenSet(0);
212
213 #[inline]
215 pub const fn new(kinds: &[SyntaxKind]) -> Self {
216 let mut bits = 0u64;
217 let mut i = 0;
218 while i < kinds.len() {
219 let kind = kinds[i] as u16;
220 assert!(kind < 64, "SyntaxKind value exceeds TokenSet capacity");
221 bits |= 1 << kind;
222 i += 1;
223 }
224 TokenSet(bits)
225 }
226
227 #[inline]
228 pub const fn single(kind: SyntaxKind) -> Self {
229 let kind = kind as u16;
230 assert!(kind < 64, "SyntaxKind value exceeds TokenSet capacity");
231 TokenSet(1 << kind)
232 }
233
234 #[inline]
235 pub const fn contains(&self, kind: SyntaxKind) -> bool {
236 let kind = kind as u16;
237 if kind >= 64 {
238 return false;
239 }
240 self.0 & (1 << kind) != 0
241 }
242
243 #[inline]
244 pub const fn union(self, other: TokenSet) -> TokenSet {
245 TokenSet(self.0 | other.0)
246 }
247}
248
249impl std::fmt::Debug for TokenSet {
250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251 let mut list = f.debug_set();
252 for i in 0..64u16 {
253 if self.0 & (1 << i) != 0 && i < __LAST as u16 {
254 let kind: SyntaxKind = unsafe { std::mem::transmute(i) };
255 list.entry(&kind);
256 }
257 }
258 list.finish()
259 }
260}
261
262pub mod token_sets {
264 use super::*;
265
266 pub const EXPR_FIRST: TokenSet = TokenSet::new(&[
268 ParenOpen,
269 BracketOpen,
270 BraceOpen,
271 Underscore,
272 Id,
273 DoubleQuote,
274 SingleQuote,
275 Dot,
276 Negation,
277 KwError,
278 KwMissing,
279 ]);
280
281 pub const ROOT_EXPR_FIRST: TokenSet = TokenSet::new(&[
283 ParenOpen,
284 BracketOpen,
285 BraceOpen,
286 Underscore,
287 Id,
288 DoubleQuote,
289 SingleQuote,
290 KwError,
291 KwMissing,
292 ]);
293
294 pub const QUANTIFIERS: TokenSet = TokenSet::new(&[
295 Star,
296 Plus,
297 Question,
298 StarQuestion,
299 PlusQuestion,
300 QuestionQuestion,
301 ]);
302
303 pub const TRIVIA: TokenSet = TokenSet::new(&[Whitespace, Newline, LineComment, BlockComment]);
304 pub const SEPARATORS: TokenSet = TokenSet::new(&[Comma, Pipe]);
305
306 pub const TREE_RECOVERY: TokenSet = TokenSet::new(&[ParenOpen, BracketOpen, BraceOpen]);
307
308 pub const ALT_RECOVERY: TokenSet = TokenSet::new(&[ParenClose]);
309
310 pub const FIELD_RECOVERY: TokenSet =
311 TokenSet::new(&[ParenClose, BracketClose, BraceClose, At, Colon]);
312
313 pub const ROOT_RECOVERY: TokenSet = TokenSet::new(&[ParenOpen, BracketOpen, BraceOpen, Id]);
314
315 pub const DEF_RECOVERY: TokenSet =
316 TokenSet::new(&[ParenOpen, BracketOpen, BraceOpen, Id, Equals]);
317
318 pub const SEQ_RECOVERY: TokenSet = TokenSet::new(&[BraceClose, ParenClose, BracketClose]);
319}