plotnik_lib/parser/
ast.rs1use super::cst::{SyntaxKind, SyntaxNode, SyntaxToken};
16use rowan::TextRange;
17
18pub fn token_src<'src>(token: &SyntaxToken, source: &'src str) -> &'src str {
22 let range = token.text_range();
23 &source[range.start().into()..range.end().into()]
24}
25
26macro_rules! ast_node {
27 ($name:ident, $kind:ident) => {
28 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
29 pub struct $name(SyntaxNode);
30
31 impl $name {
32 pub fn cast(node: SyntaxNode) -> Option<Self> {
33 (node.kind() == SyntaxKind::$kind).then(|| Self(node))
34 }
35
36 pub fn as_cst(&self) -> &SyntaxNode {
37 &self.0
38 }
39
40 pub fn text_range(&self) -> TextRange {
41 self.0.text_range()
42 }
43 }
44 };
45}
46
47macro_rules! define_expr {
48 ($($variant:ident),+ $(,)?) => {
49 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
51 pub enum Expr {
52 $($variant($variant)),+
53 }
54
55 impl Expr {
56 pub fn cast(node: SyntaxNode) -> Option<Self> {
57 $(if let Some(n) = $variant::cast(node.clone()) { return Some(Expr::$variant(n)); })+
58 None
59 }
60
61 pub fn as_cst(&self) -> &SyntaxNode {
62 match self { $(Expr::$variant(n) => n.as_cst()),+ }
63 }
64
65 pub fn text_range(&self) -> TextRange {
66 match self { $(Expr::$variant(n) => n.text_range()),+ }
67 }
68 }
69 };
70}
71
72impl Expr {
73 pub fn children(&self) -> Vec<Expr> {
75 match self {
76 Expr::NamedNode(n) => n.children().collect(),
77 Expr::SeqExpr(s) => s.children().collect(),
78 Expr::CapturedExpr(c) => c.inner().into_iter().collect(),
79 Expr::QuantifiedExpr(q) => q.inner().into_iter().collect(),
80 Expr::FieldExpr(f) => f.value().into_iter().collect(),
81 Expr::AltExpr(a) => a.branches().filter_map(|b| b.body()).collect(),
82 Expr::Ref(_) | Expr::AnonymousNode(_) => vec![],
83 }
84 }
85}
86
87ast_node!(Root, Root);
88ast_node!(Def, Def);
89ast_node!(NamedNode, Tree);
90ast_node!(Ref, Ref);
91ast_node!(AltExpr, Alt);
92ast_node!(Branch, Branch);
93ast_node!(SeqExpr, Seq);
94ast_node!(CapturedExpr, Capture);
95ast_node!(Type, Type);
96ast_node!(QuantifiedExpr, Quantifier);
97ast_node!(FieldExpr, Field);
98ast_node!(NegatedField, NegatedField);
99ast_node!(Anchor, Anchor);
100
101#[derive(Debug, Clone, PartialEq, Eq, Hash)]
103pub enum SeqItem {
104 Expr(Expr),
105 Anchor(Anchor),
106}
107
108impl SeqItem {
109 pub fn cast(node: SyntaxNode) -> Option<Self> {
110 if let Some(expr) = Expr::cast(node.clone()) {
111 return Some(SeqItem::Expr(expr));
112 }
113 if let Some(anchor) = Anchor::cast(node) {
114 return Some(SeqItem::Anchor(anchor));
115 }
116 None
117 }
118
119 pub fn as_anchor(&self) -> Option<&Anchor> {
120 match self {
121 SeqItem::Anchor(a) => Some(a),
122 _ => None,
123 }
124 }
125
126 pub fn as_expr(&self) -> Option<&Expr> {
127 match self {
128 SeqItem::Expr(e) => Some(e),
129 _ => None,
130 }
131 }
132}
133
134#[derive(Debug, Clone, PartialEq, Eq, Hash)]
137pub struct AnonymousNode(SyntaxNode);
138
139impl AnonymousNode {
140 pub fn cast(node: SyntaxNode) -> Option<Self> {
141 matches!(node.kind(), SyntaxKind::Str | SyntaxKind::Wildcard).then(|| Self(node))
142 }
143
144 pub fn as_cst(&self) -> &SyntaxNode {
145 &self.0
146 }
147
148 pub fn text_range(&self) -> TextRange {
149 self.0.text_range()
150 }
151
152 pub fn value(&self) -> Option<SyntaxToken> {
154 if self.0.kind() == SyntaxKind::Wildcard {
155 return None;
156 }
157 self.0
158 .children_with_tokens()
159 .filter_map(|it| it.into_token())
160 .find(|t| t.kind() == SyntaxKind::StrVal)
161 }
162
163 pub fn is_any(&self) -> bool {
165 self.0.kind() == SyntaxKind::Wildcard
166 }
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
171pub enum AltKind {
172 Tagged,
174 Untagged,
176 Mixed,
178}
179
180define_expr!(
181 NamedNode,
182 Ref,
183 AnonymousNode,
184 AltExpr,
185 SeqExpr,
186 CapturedExpr,
187 QuantifiedExpr,
188 FieldExpr,
189);
190
191impl Root {
192 pub fn defs(&self) -> impl Iterator<Item = Def> + '_ {
193 self.0.children().filter_map(Def::cast)
194 }
195
196 pub fn exprs(&self) -> impl Iterator<Item = Expr> + '_ {
197 self.0.children().filter_map(Expr::cast)
198 }
199}
200
201impl Def {
202 pub fn name(&self) -> Option<SyntaxToken> {
203 self.0
204 .children_with_tokens()
205 .filter_map(|it| it.into_token())
206 .find(|t| t.kind() == SyntaxKind::Id)
207 }
208
209 pub fn body(&self) -> Option<Expr> {
210 self.0.children().find_map(Expr::cast)
211 }
212}
213
214impl NamedNode {
215 pub fn node_type(&self) -> Option<SyntaxToken> {
216 self.0
217 .children_with_tokens()
218 .filter_map(|it| it.into_token())
219 .find(|t| {
220 matches!(
221 t.kind(),
222 SyntaxKind::Id
223 | SyntaxKind::Underscore
224 | SyntaxKind::KwError
225 | SyntaxKind::KwMissing
226 )
227 })
228 }
229
230 pub fn is_any(&self) -> bool {
232 self.node_type()
233 .map(|t| t.kind() == SyntaxKind::Underscore)
234 .unwrap_or(false)
235 }
236
237 pub fn children(&self) -> impl Iterator<Item = Expr> + '_ {
238 self.0.children().filter_map(Expr::cast)
239 }
240
241 pub fn anchors(&self) -> impl Iterator<Item = Anchor> + '_ {
243 self.0.children().filter_map(Anchor::cast)
244 }
245
246 pub fn items(&self) -> impl Iterator<Item = SeqItem> + '_ {
248 self.0.children().filter_map(SeqItem::cast)
249 }
250}
251
252impl Ref {
253 pub fn name(&self) -> Option<SyntaxToken> {
254 self.0
255 .children_with_tokens()
256 .filter_map(|it| it.into_token())
257 .find(|t| t.kind() == SyntaxKind::Id)
258 }
259}
260
261impl AltExpr {
262 pub fn kind(&self) -> AltKind {
263 let mut tagged = false;
264 let mut untagged = false;
265
266 for child in self.0.children().filter(|c| c.kind() == SyntaxKind::Branch) {
267 let has_label = child
268 .children_with_tokens()
269 .filter_map(|it| it.into_token())
270 .any(|t| t.kind() == SyntaxKind::Id);
271
272 if has_label {
273 tagged = true;
274 } else {
275 untagged = true;
276 }
277 }
278
279 match (tagged, untagged) {
280 (true, true) => AltKind::Mixed,
281 (true, false) => AltKind::Tagged,
282 _ => AltKind::Untagged,
283 }
284 }
285
286 pub fn branches(&self) -> impl Iterator<Item = Branch> + '_ {
287 self.0.children().filter_map(Branch::cast)
288 }
289
290 pub fn exprs(&self) -> impl Iterator<Item = Expr> + '_ {
291 self.0.children().filter_map(Expr::cast)
292 }
293}
294
295impl Branch {
296 pub fn label(&self) -> Option<SyntaxToken> {
297 self.0
298 .children_with_tokens()
299 .filter_map(|it| it.into_token())
300 .find(|t| t.kind() == SyntaxKind::Id)
301 }
302
303 pub fn body(&self) -> Option<Expr> {
304 self.0.children().find_map(Expr::cast)
305 }
306}
307
308impl SeqExpr {
309 pub fn children(&self) -> impl Iterator<Item = Expr> + '_ {
310 self.0.children().filter_map(Expr::cast)
311 }
312
313 pub fn anchors(&self) -> impl Iterator<Item = Anchor> + '_ {
315 self.0.children().filter_map(Anchor::cast)
316 }
317
318 pub fn items(&self) -> impl Iterator<Item = SeqItem> + '_ {
320 self.0.children().filter_map(SeqItem::cast)
321 }
322}
323
324impl CapturedExpr {
325 pub fn name(&self) -> Option<SyntaxToken> {
326 self.0
327 .children_with_tokens()
328 .filter_map(|it| it.into_token())
329 .find(|t| t.kind() == SyntaxKind::Id)
330 }
331
332 pub fn inner(&self) -> Option<Expr> {
333 self.0.children().find_map(Expr::cast)
334 }
335
336 pub fn type_annotation(&self) -> Option<Type> {
337 self.0.children().find_map(Type::cast)
338 }
339}
340
341impl Type {
342 pub fn name(&self) -> Option<SyntaxToken> {
343 self.0
344 .children_with_tokens()
345 .filter_map(|it| it.into_token())
346 .find(|t| t.kind() == SyntaxKind::Id)
347 }
348}
349
350impl QuantifiedExpr {
351 pub fn inner(&self) -> Option<Expr> {
352 self.0.children().find_map(Expr::cast)
353 }
354
355 pub fn operator(&self) -> Option<SyntaxToken> {
356 self.0
357 .children_with_tokens()
358 .filter_map(|it| it.into_token())
359 .find(|t| {
360 matches!(
361 t.kind(),
362 SyntaxKind::Star
363 | SyntaxKind::Plus
364 | SyntaxKind::Question
365 | SyntaxKind::StarQuestion
366 | SyntaxKind::PlusQuestion
367 | SyntaxKind::QuestionQuestion
368 )
369 })
370 }
371
372 pub fn is_optional(&self) -> bool {
374 self.operator()
375 .map(|op| {
376 matches!(
377 op.kind(),
378 SyntaxKind::Question
379 | SyntaxKind::Star
380 | SyntaxKind::QuestionQuestion
381 | SyntaxKind::StarQuestion
382 )
383 })
384 .unwrap_or(false)
385 }
386}
387
388impl FieldExpr {
389 pub fn name(&self) -> Option<SyntaxToken> {
390 self.0
391 .children_with_tokens()
392 .filter_map(|it| it.into_token())
393 .find(|t| t.kind() == SyntaxKind::Id)
394 }
395
396 pub fn value(&self) -> Option<Expr> {
397 self.0.children().find_map(Expr::cast)
398 }
399}
400
401impl NegatedField {
402 pub fn name(&self) -> Option<SyntaxToken> {
403 self.0
404 .children_with_tokens()
405 .filter_map(|it| it.into_token())
406 .find(|t| t.kind() == SyntaxKind::Id)
407 }
408}