1use crate::ir::Nav;
7use indexmap::IndexMap;
8use rowan::TextRange;
9
10pub type NodeId = u32;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct Fragment {
19 pub entry: NodeId,
20 pub exit: NodeId,
21}
22
23impl Fragment {
24 pub fn new(entry: NodeId, exit: NodeId) -> Self {
25 Self { entry, exit }
26 }
27
28 pub fn single(node: NodeId) -> Self {
29 Self {
30 entry: node,
31 exit: node,
32 }
33 }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum ArrayMode {
39 None,
41 Simple,
43 Qis,
45}
46
47#[derive(Debug)]
52pub struct BuildGraph<'src> {
53 nodes: Vec<BuildNode<'src>>,
54 definitions: IndexMap<&'src str, NodeId>,
55}
56
57impl<'src> BuildGraph<'src> {
58 pub fn new() -> Self {
59 Self {
60 nodes: Vec::new(),
61 definitions: IndexMap::new(),
62 }
63 }
64
65 pub fn add_node(&mut self, node: BuildNode<'src>) -> NodeId {
66 let id = self.nodes.len() as NodeId;
67 self.nodes.push(node);
68 id
69 }
70
71 pub fn add_epsilon(&mut self) -> NodeId {
72 self.add_node(BuildNode::epsilon())
73 }
74
75 pub fn clone_node_with_nav(&mut self, node_id: NodeId, nav: Nav) -> NodeId {
78 let original = &self.nodes[node_id as usize];
79 let cloned = BuildNode {
80 matcher: original.matcher.clone(),
81 effects: original.effects.clone(),
82 ref_marker: original.ref_marker.clone(),
83 successors: original.successors.clone(),
84 nav,
85 ref_name: original.ref_name,
86 };
87 self.add_node(cloned)
88 }
89
90 pub fn add_matcher(&mut self, matcher: BuildMatcher<'src>) -> NodeId {
91 self.add_node(BuildNode::with_matcher(matcher))
92 }
93
94 pub fn add_definition(&mut self, name: &'src str, entry: NodeId) {
95 self.definitions.insert(name, entry);
96 }
97
98 pub fn definition(&self, name: &str) -> Option<NodeId> {
99 self.definitions.get(name).copied()
100 }
101
102 pub fn definitions(&self) -> impl Iterator<Item = (&'src str, NodeId)> + '_ {
103 self.definitions.iter().map(|(k, v)| (*k, *v))
104 }
105
106 pub fn node(&self, id: NodeId) -> &BuildNode<'src> {
107 &self.nodes[id as usize]
108 }
109
110 pub fn node_mut(&mut self, id: NodeId) -> &mut BuildNode<'src> {
111 &mut self.nodes[id as usize]
112 }
113
114 pub fn len(&self) -> usize {
115 self.nodes.len()
116 }
117
118 pub fn is_empty(&self) -> bool {
119 self.nodes.is_empty()
120 }
121
122 pub fn iter(&self) -> impl Iterator<Item = (NodeId, &BuildNode<'src>)> {
123 self.nodes.iter().enumerate().map(|(i, n)| (i as NodeId, n))
124 }
125
126 pub fn connect(&mut self, from: NodeId, to: NodeId) {
127 self.nodes[from as usize].successors.push(to);
128 }
129
130 pub fn connect_exit(&mut self, fragment: Fragment, to: NodeId) {
131 self.connect(fragment.exit, to);
132 }
133
134 pub fn matcher_fragment(&mut self, matcher: BuildMatcher<'src>) -> Fragment {
135 Fragment::single(self.add_matcher(matcher))
136 }
137
138 pub fn epsilon_fragment(&mut self) -> Fragment {
139 Fragment::single(self.add_epsilon())
140 }
141
142 pub fn sequence(&mut self, fragments: &[Fragment]) -> Fragment {
144 match fragments.len() {
145 0 => self.epsilon_fragment(),
146 1 => fragments[0],
147 _ => {
148 for window in fragments.windows(2) {
149 self.connect(window[0].exit, window[1].entry);
150 }
151 Fragment::new(fragments[0].entry, fragments[fragments.len() - 1].exit)
152 }
153 }
154 }
155
156 pub fn alternation(&mut self, fragments: &[Fragment]) -> Fragment {
158 if fragments.is_empty() {
159 return self.epsilon_fragment();
160 }
161 if fragments.len() == 1 {
162 return fragments[0];
163 }
164
165 let entry = self.add_epsilon();
166 let exit = self.add_epsilon();
167
168 for f in fragments {
169 self.connect(entry, f.entry);
170 self.connect(f.exit, exit);
171 }
172
173 Fragment::new(entry, exit)
174 }
175
176 fn build_repetition(
182 &mut self,
183 inner: Fragment,
184 at_least_one: bool,
185 greedy: bool,
186 mode: ArrayMode,
187 initial_nav: Nav,
188 ) -> Fragment {
189 let has_array = mode != ArrayMode::None;
190 let has_qis = mode == ArrayMode::Qis;
191
192 let start = if has_array {
194 let s = self.add_epsilon();
195 self.node_mut(s).add_effect(BuildEffect::StartArray {
196 is_plus: at_least_one,
197 });
198 Some(s)
199 } else {
200 None
201 };
202
203 let end = if has_array {
204 let e = self.add_epsilon();
205 self.node_mut(e).add_effect(BuildEffect::EndArray);
206 Some(e)
207 } else {
208 None
209 };
210
211 let (obj_start, obj_end) = if has_qis {
213 let os = self.add_epsilon();
214 self.node_mut(os).add_effect(BuildEffect::StartObject {
215 for_alternation: false,
216 });
217 let oe = self.add_epsilon();
218 self.node_mut(oe).add_effect(BuildEffect::EndObject);
219 (Some(os), Some(oe))
220 } else {
221 (None, None)
222 };
223
224 let push = if has_array {
226 let p = self.add_epsilon();
227 self.node_mut(p).add_effect(BuildEffect::PushElement);
228 Some(p)
229 } else {
230 None
231 };
232
233 let branch = self.add_epsilon();
235
236 let exit = if !has_array {
238 Some(self.add_epsilon())
239 } else {
240 None
241 };
242
243 let (loop_body_entry, loop_body_exit) = if has_qis {
245 self.connect(obj_start.unwrap(), inner.entry);
246 self.connect(inner.exit, obj_end.unwrap());
247 (obj_start.unwrap(), obj_end.unwrap())
248 } else {
249 (inner.entry, inner.exit)
250 };
251
252 self.node_mut(inner.entry).set_nav(initial_nav);
255
256 let try_next = self.clone_node_with_nav(inner.entry, Nav::next());
260
261 let (try_next_entry, try_next_exit) = if has_qis {
263 let os = self.add_epsilon();
264 self.node_mut(os).add_effect(BuildEffect::StartObject {
265 for_alternation: false,
266 });
267 let oe = self.add_epsilon();
268 self.node_mut(oe).add_effect(BuildEffect::EndObject);
269 self.connect(os, try_next);
270 self.connect(try_next, oe);
271 (os, oe)
272 } else {
273 (try_next, try_next)
274 };
275
276 if at_least_one {
278 let entry_point = start.unwrap_or(loop_body_entry);
281 let exit_point = end.or(exit).unwrap();
282
283 let re_entry = self.add_epsilon();
285
286 if let Some(s) = start {
287 self.connect(s, loop_body_entry);
288 }
289
290 if let Some(p) = push {
291 self.connect(loop_body_exit, p);
292 self.connect(try_next_exit, p);
294 self.connect(p, re_entry);
295 } else {
296 self.connect(loop_body_exit, re_entry);
297 self.connect(try_next_exit, re_entry);
298 }
299
300 if greedy {
303 self.connect(re_entry, try_next_entry);
304 self.connect(re_entry, exit_point);
305 } else {
306 self.connect(re_entry, exit_point);
307 self.connect(re_entry, try_next_entry);
308 }
309
310 Fragment::new(entry_point, exit_point)
311 } else {
312 let entry_point = start.unwrap_or(branch);
315 let exit_point = end.or(exit).unwrap();
316
317 let re_entry = self.add_epsilon();
319
320 if let Some(s) = start {
321 self.connect(s, branch);
322 }
323
324 if greedy {
325 self.connect(branch, loop_body_entry);
326 self.connect(branch, exit_point);
327 } else {
328 self.connect(branch, exit_point);
329 self.connect(branch, loop_body_entry);
330 }
331
332 if let Some(p) = push {
333 self.connect(loop_body_exit, p);
334 self.connect(try_next_exit, p);
336 self.connect(p, re_entry);
337 } else {
338 self.connect(loop_body_exit, re_entry);
339 self.connect(try_next_exit, re_entry);
340 }
341
342 if greedy {
345 self.connect(re_entry, try_next_entry);
346 self.connect(re_entry, exit_point);
347 } else {
348 self.connect(re_entry, exit_point);
349 self.connect(re_entry, try_next_entry);
350 }
351
352 Fragment::new(entry_point, exit_point)
353 }
354 }
355
356 fn build_optional(&mut self, inner: Fragment, greedy: bool, qis: bool) -> Fragment {
361 let branch = self.add_epsilon();
362 let exit = self.add_epsilon();
363
364 if qis {
365 let obj_start = self.add_epsilon();
366 self.node_mut(obj_start)
367 .add_effect(BuildEffect::StartObject {
368 for_alternation: false,
369 });
370
371 let obj_end = self.add_epsilon();
372 self.node_mut(obj_end).add_effect(BuildEffect::EndObject);
373
374 let skip = self.add_epsilon();
376 self.node_mut(skip).add_effect(BuildEffect::ClearCurrent);
377
378 self.connect(obj_start, inner.entry);
379 self.connect(inner.exit, obj_end);
380 self.connect(obj_end, exit);
381 self.connect(skip, exit);
382
383 if greedy {
384 self.connect(branch, obj_start);
385 self.connect(branch, skip);
386 } else {
387 self.connect(branch, skip);
388 self.connect(branch, obj_start);
389 }
390 } else {
391 let skip = self.add_epsilon();
392 self.node_mut(skip).add_effect(BuildEffect::ClearCurrent);
393
394 self.connect(skip, exit);
395 self.connect(inner.exit, exit);
396
397 if greedy {
398 self.connect(branch, inner.entry);
399 self.connect(branch, skip);
400 } else {
401 self.connect(branch, skip);
402 self.connect(branch, inner.entry);
403 }
404 }
405
406 Fragment::new(branch, exit)
407 }
408
409 pub fn zero_or_more(&mut self, inner: Fragment, nav: Nav) -> Fragment {
411 self.build_repetition(inner, false, true, ArrayMode::None, nav)
412 }
413
414 pub fn zero_or_more_lazy(&mut self, inner: Fragment, nav: Nav) -> Fragment {
416 self.build_repetition(inner, false, false, ArrayMode::None, nav)
417 }
418
419 pub fn one_or_more(&mut self, inner: Fragment, nav: Nav) -> Fragment {
421 self.build_repetition(inner, true, true, ArrayMode::None, nav)
422 }
423
424 pub fn one_or_more_lazy(&mut self, inner: Fragment, nav: Nav) -> Fragment {
426 self.build_repetition(inner, true, false, ArrayMode::None, nav)
427 }
428
429 pub fn optional(&mut self, inner: Fragment) -> Fragment {
431 self.build_optional(inner, true, false)
432 }
433
434 pub fn optional_lazy(&mut self, inner: Fragment) -> Fragment {
436 self.build_optional(inner, false, false)
437 }
438
439 pub fn zero_or_more_array(&mut self, inner: Fragment, nav: Nav) -> Fragment {
441 self.build_repetition(inner, false, true, ArrayMode::Simple, nav)
442 }
443
444 pub fn zero_or_more_array_lazy(&mut self, inner: Fragment, nav: Nav) -> Fragment {
446 self.build_repetition(inner, false, false, ArrayMode::Simple, nav)
447 }
448
449 pub fn one_or_more_array(&mut self, inner: Fragment, nav: Nav) -> Fragment {
451 self.build_repetition(inner, true, true, ArrayMode::Simple, nav)
452 }
453
454 pub fn one_or_more_array_lazy(&mut self, inner: Fragment, nav: Nav) -> Fragment {
456 self.build_repetition(inner, true, false, ArrayMode::Simple, nav)
457 }
458
459 pub fn zero_or_more_array_qis(&mut self, inner: Fragment, nav: Nav) -> Fragment {
464 self.build_repetition(inner, false, true, ArrayMode::Qis, nav)
465 }
466
467 pub fn zero_or_more_array_qis_lazy(&mut self, inner: Fragment, nav: Nav) -> Fragment {
469 self.build_repetition(inner, false, false, ArrayMode::Qis, nav)
470 }
471
472 pub fn one_or_more_array_qis(&mut self, inner: Fragment, nav: Nav) -> Fragment {
474 self.build_repetition(inner, true, true, ArrayMode::Qis, nav)
475 }
476
477 pub fn one_or_more_array_qis_lazy(&mut self, inner: Fragment, nav: Nav) -> Fragment {
479 self.build_repetition(inner, true, false, ArrayMode::Qis, nav)
480 }
481
482 pub fn optional_qis(&mut self, inner: Fragment) -> Fragment {
486 self.build_optional(inner, true, true)
487 }
488
489 pub fn optional_qis_lazy(&mut self, inner: Fragment) -> Fragment {
491 self.build_optional(inner, false, true)
492 }
493
494 pub fn wrap_definitions_with_root(&mut self, root_kind: &'src str) {
501 let def_names: Vec<&'src str> = self.definitions.keys().copied().collect();
502
503 for name in def_names {
504 let entry = self.definitions[name];
505
506 if self.entry_matches_root(entry, root_kind) {
508 continue;
509 }
510
511 let wrapper = self.add_node(BuildNode::with_matcher(BuildMatcher::node(root_kind)));
513
514 let down_nav = self.add_epsilon();
516 self.node_mut(down_nav).set_nav(Nav::down());
517
518 self.connect(wrapper, down_nav);
520 self.connect(down_nav, entry);
521
522 self.definitions.insert(name, wrapper);
524 }
525 }
526
527 fn entry_matches_root(&self, entry: NodeId, root_kind: &str) -> bool {
529 match &self.nodes[entry as usize].matcher {
530 BuildMatcher::Node { kind, .. } => *kind == root_kind,
531 BuildMatcher::Epsilon => {
532 for &target in &self.nodes[entry as usize].successors {
534 if self.entry_matches_root(target, root_kind) {
535 return true;
536 }
537 }
538 false
539 }
540 _ => false,
541 }
542 }
543}
544
545impl Default for BuildGraph<'_> {
546 fn default() -> Self {
547 Self::new()
548 }
549}
550
551#[derive(Debug, Clone)]
553pub struct BuildNode<'src> {
554 pub matcher: BuildMatcher<'src>,
555 pub effects: Vec<BuildEffect<'src>>,
556 pub ref_marker: RefMarker,
557 pub successors: Vec<NodeId>,
558 pub nav: Nav,
559 pub ref_name: Option<&'src str>,
560}
561
562impl<'src> BuildNode<'src> {
563 pub fn epsilon() -> Self {
564 Self {
565 matcher: BuildMatcher::Epsilon,
566 effects: Vec::new(),
567 ref_marker: RefMarker::None,
568 successors: Vec::new(),
569 nav: Nav::stay(),
570 ref_name: None,
571 }
572 }
573
574 pub fn with_matcher(matcher: BuildMatcher<'src>) -> Self {
575 Self {
576 matcher,
577 effects: Vec::new(),
578 ref_marker: RefMarker::None,
579 successors: Vec::new(),
580 nav: Nav::stay(),
581 ref_name: None,
582 }
583 }
584
585 pub fn add_effect(&mut self, effect: BuildEffect<'src>) {
586 self.effects.push(effect);
587 }
588
589 pub fn set_ref_marker(&mut self, marker: RefMarker) {
590 self.ref_marker = marker;
591 }
592
593 pub fn set_nav(&mut self, nav: Nav) {
594 self.nav = nav;
595 }
596
597 pub fn is_epsilon(&self) -> bool {
598 matches!(self.matcher, BuildMatcher::Epsilon)
599 }
600}
601
602#[derive(Debug, Clone, PartialEq, Eq)]
604pub enum BuildMatcher<'src> {
605 Epsilon,
606 Node {
607 kind: &'src str,
608 field: Option<&'src str>,
609 negated_fields: Vec<&'src str>,
610 },
611 Anonymous {
612 literal: &'src str,
613 field: Option<&'src str>,
614 },
615 Wildcard {
616 field: Option<&'src str>,
617 },
618}
619
620impl<'src> BuildMatcher<'src> {
621 pub fn node(kind: &'src str) -> Self {
622 Self::Node {
623 kind,
624 field: None,
625 negated_fields: Vec::new(),
626 }
627 }
628
629 pub fn anonymous(literal: &'src str) -> Self {
630 Self::Anonymous {
631 literal,
632 field: None,
633 }
634 }
635
636 pub fn wildcard() -> Self {
637 Self::Wildcard { field: None }
638 }
639
640 pub fn with_field(mut self, field: &'src str) -> Self {
641 match &mut self {
642 BuildMatcher::Node { field: f, .. } => *f = Some(field),
643 BuildMatcher::Anonymous { field: f, .. } => *f = Some(field),
644 BuildMatcher::Wildcard { field: f } => *f = Some(field),
645 BuildMatcher::Epsilon => {}
646 }
647 self
648 }
649
650 pub fn with_negated_field(mut self, field: &'src str) -> Self {
651 if let BuildMatcher::Node { negated_fields, .. } = &mut self {
652 negated_fields.push(field);
653 }
654 self
655 }
656}
657
658#[derive(Debug, Clone, PartialEq, Eq)]
660pub enum BuildEffect<'src> {
661 CaptureNode,
662 ClearCurrent,
664 StartArray {
666 is_plus: bool,
667 },
668 PushElement,
669 EndArray,
670 StartObject {
674 for_alternation: bool,
675 },
676 EndObject,
677 Field {
678 name: &'src str,
679 span: TextRange,
680 },
681 StartVariant(&'src str),
682 EndVariant,
683 ToString,
684}
685
686#[derive(Debug, Clone, PartialEq, Eq, Default)]
688pub enum RefMarker {
689 #[default]
690 None,
691 Enter {
692 ref_id: u32,
693 },
694 Exit {
695 ref_id: u32,
696 },
697}
698
699impl RefMarker {
700 pub fn enter(ref_id: u32) -> Self {
701 Self::Enter { ref_id }
702 }
703
704 pub fn exit(ref_id: u32) -> Self {
705 Self::Exit { ref_id }
706 }
707
708 pub fn is_none(&self) -> bool {
709 matches!(self, RefMarker::None)
710 }
711
712 pub fn is_some(&self) -> bool {
713 !matches!(self, RefMarker::None)
714 }
715
716 pub fn is_enter(&self) -> bool {
717 matches!(self, RefMarker::Enter { .. })
718 }
719
720 pub fn is_exit(&self) -> bool {
721 matches!(self, RefMarker::Exit { .. })
722 }
723}