1mod span;
2
3use ahash::HashMap;
4use std::{collections::BTreeMap, convert::Infallible};
5use thiserror::Error;
6
7pub use span::*;
8
9use crate::{
10 CstConstructError,
11 node_kind::{NodeKind, NonTerminalKind, TerminalKind},
12 nodes::{BlockComment, LineComment, NewLine, RootHandle, Whitespace},
13 visitor::{BuiltinTerminalVisitor, CstVisitor},
14};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
17pub struct DynamicTokenId(pub u32);
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21pub enum CstNodeData<T, Nt> {
22 Terminal { kind: T, data: TerminalData },
24 NonTerminal { kind: Nt, data: NonTerminalData },
26}
27
28impl<T, Nt> CstNodeData<T, Nt> {
29 pub fn new_terminal(kind: T, data: TerminalData) -> Self {
30 Self::Terminal { kind, data }
31 }
32
33 pub fn new_non_terminal(kind: Nt, data: NonTerminalData) -> Self {
34 Self::NonTerminal { kind, data }
35 }
36
37 pub fn is_terminal(&self) -> bool {
38 matches!(self, CstNodeData::Terminal { .. })
39 }
40
41 pub fn is_non_terminal(&self) -> bool {
42 matches!(self, CstNodeData::NonTerminal { .. })
43 }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
47pub enum TerminalData {
48 Input(InputSpan),
49 Dynamic(DynamicTokenId),
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53pub enum NonTerminalData {
54 Input(InputSpan),
55 Dynamic,
56}
57
58impl<T, Nt> CstNodeData<T, Nt>
59where
60 T: Copy,
61 Nt: Copy,
62{
63 pub fn node_kind(&self) -> NodeKind<T, Nt> {
64 match self {
65 CstNodeData::Terminal { kind, .. } => NodeKind::Terminal(*kind),
66 CstNodeData::NonTerminal { kind, .. } => NodeKind::NonTerminal(*kind),
67 }
68 }
69}
70
71impl<T, Nt> CstNodeData<T, Nt>
72where
73 T: PartialEq + Copy,
74 Nt: PartialEq + Copy,
75{
76 pub fn expected_terminal_or_error(
77 &self,
78 node: CstNodeId,
79 expected: T,
80 ) -> Result<(T, TerminalData), ViewConstructionError<T, Nt>> {
81 match self {
82 CstNodeData::Terminal { kind, data } if *kind == expected => Ok((*kind, *data)),
83 _ => Err(ViewConstructionError::UnexpectedNode {
84 node,
85 data: *self,
86 expected_kind: NodeKind::Terminal(expected),
87 }),
88 }
89 }
90
91 pub fn expected_non_terminal_or_error(
92 &self,
93 node: CstNodeId,
94 expected: Nt,
95 ) -> Result<(Nt, NonTerminalData), ViewConstructionError<T, Nt>> {
96 match self {
97 CstNodeData::NonTerminal { kind, data } if *kind == expected => Ok((*kind, *data)),
98 _ => Err(ViewConstructionError::UnexpectedNode {
99 node,
100 data: *self,
101 expected_kind: NodeKind::NonTerminal(expected),
102 }),
103 }
104 }
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
108pub struct CstNodeId(pub usize);
109
110impl std::fmt::Display for CstNodeId {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 write!(f, "{}", self.0)
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
118pub struct ConcreteSyntaxTree<T, Nt> {
119 nodes: Vec<CstNodeData<T, Nt>>,
120 children: HashMap<CstNodeId, Vec<CstNodeId>>,
121 parent: HashMap<CstNodeId, CstNodeId>,
122 dynamic_tokens: BTreeMap<DynamicTokenId, String>,
123 next_dynamic_token_id: u32,
124 root: CstNodeId,
125}
126
127impl<T, Nt> ConcreteSyntaxTree<T, Nt>
128where
129 T: Clone,
130 Nt: Clone,
131{
132 pub fn new(root_data: CstNodeData<T, Nt>) -> Self {
133 let nodes = vec![root_data];
134 let root = CstNodeId(0);
135
136 Self {
137 nodes,
138 children: HashMap::default(),
139 parent: HashMap::default(),
140 dynamic_tokens: BTreeMap::new(),
141 next_dynamic_token_id: 0,
142 root,
143 }
144 }
145
146 pub fn root(&self) -> CstNodeId {
147 self.root
148 }
149
150 pub fn set_root(&mut self, new_root: CstNodeId) {
151 self.root = new_root;
152 }
153
154 pub fn change_parent(&mut self, id: CstNodeId, new_parent: CstNodeId) {
155 if let Some(old_parent) = self.parent.get(&id).copied()
157 && let Some(children) = self.children.get_mut(&old_parent)
158 {
159 children.retain(|&child| child != id);
160 }
161
162 self.children.entry(new_parent).or_default().push(id);
164 self.parent.insert(id, new_parent);
165 }
166
167 pub fn add_node(&mut self, data: CstNodeData<T, Nt>) -> CstNodeId {
168 let id = CstNodeId(self.nodes.len());
169 self.nodes.push(data);
170 id
171 }
172
173 pub fn add_node_with_parent(
174 &mut self,
175 data: CstNodeData<T, Nt>,
176 parent: CstNodeId,
177 ) -> CstNodeId {
178 let node = self.add_node(data);
179 self.add_child(parent, node);
180 node
181 }
182
183 pub fn add_child(&mut self, parent: CstNodeId, child: CstNodeId) {
184 self.children.entry(parent).or_default().push(child);
185 self.parent.insert(child, parent);
186 }
187
188 pub fn has_no_children(&self, node: CstNodeId) -> bool {
189 self.children
190 .get(&node)
191 .is_none_or(|children| children.is_empty())
192 }
193
194 pub fn children(&self, node: CstNodeId) -> impl DoubleEndedIterator<Item = CstNodeId> + '_ {
195 self.children
196 .get(&node)
197 .into_iter()
198 .flat_map(|children| children.iter().copied())
199 }
200
201 pub fn parent(&self, node: CstNodeId) -> Option<CstNodeId> {
202 self.parent.get(&node).copied()
203 }
204
205 pub fn get_str<'a: 'c, 'b: 'c, 'c>(
206 &'a self,
207 terminal: TerminalData,
208 input: &'b str,
209 ) -> Option<&'c str> {
210 match terminal {
211 TerminalData::Input(span) => Some(span.as_str(input)),
212 TerminalData::Dynamic(id) => self.dynamic_token(id),
213 }
214 }
215
216 pub fn dynamic_token(&self, id: DynamicTokenId) -> Option<&str> {
217 self.dynamic_tokens.get(&id).map(|s| s.as_str())
218 }
219
220 pub fn update_node(
221 &mut self,
222 id: CstNodeId,
223 data: CstNodeData<T, Nt>,
224 ) -> Option<CstNodeData<T, Nt>> {
225 if id.0 < self.nodes.len() {
226 Some(std::mem::replace(&mut self.nodes[id.0], data))
227 } else {
228 None
229 }
230 }
231
232 pub fn update_children(
233 &mut self,
234 id: CstNodeId,
235 new_children: impl IntoIterator<Item = CstNodeId>,
236 ) {
237 let new_children: Vec<_> = new_children.into_iter().collect();
238
239 if let Some(old_children) = self.children.get(&id) {
241 for &child in old_children {
242 self.parent.remove(&child);
243 }
244 }
245
246 for &child in &new_children {
248 self.parent.insert(child, id);
249 }
250
251 if new_children.is_empty() {
253 self.children.remove(&id);
254 } else {
255 self.children.insert(id, new_children);
256 }
257 }
258
259 pub fn insert_dynamic_terminal(&mut self, data: impl Into<String>) -> DynamicTokenId {
260 let id = DynamicTokenId(self.next_dynamic_token_id);
261 self.dynamic_tokens.insert(id, data.into());
262 self.next_dynamic_token_id += 1;
263 id
264 }
265}
266
267impl<T, Nt> ConcreteSyntaxTree<T, Nt>
268where
269 T: Copy,
270 Nt: Copy,
271{
272 pub fn node_data(&self, node: CstNodeId) -> Option<CstNodeData<T, Nt>> {
273 self.nodes.get(node.0).copied()
274 }
275
276 pub fn remove_node(&mut self, id: CstNodeId) {
279 if let Some(parent_id) = self.parent.remove(&id)
281 && let Some(parent_children) = self.children.get_mut(&parent_id)
282 {
283 parent_children.retain(|&child| child != id);
284 }
285
286 self.children.remove(&id);
288 }
289}
290
291impl TerminalKind {
292 fn auto_ws_is_off(&self, _index: usize) -> bool {
293 matches!(
294 self,
295 TerminalKind::Ws | TerminalKind::GrammarNewline | TerminalKind::Text
296 )
297 }
298}
299
300impl ConcreteSyntaxTree<TerminalKind, NonTerminalKind> {
301 pub fn get_non_terminal(
302 &self,
303 id: CstNodeId,
304 kind: NonTerminalKind,
305 ) -> Result<NonTerminalData, CstConstructError> {
306 let node_data = self
307 .node_data(id)
308 .ok_or(ViewConstructionError::NodeIdNotFound { node: id })?;
309 let (_, data) = node_data.expected_non_terminal_or_error(id, kind)?;
310 Ok(data)
311 }
312
313 pub fn get_terminal(
314 &self,
315 id: CstNodeId,
316 kind: TerminalKind,
317 ) -> Result<TerminalData, CstConstructError> {
318 let node_data = self
319 .node_data(id)
320 .ok_or(ViewConstructionError::NodeIdNotFound { node: id })?;
321 let (_, data) = node_data.expected_terminal_or_error(id, kind)?;
322 Ok(data)
323 }
324
325 pub fn collect_nodes<
326 'v,
327 const N: usize,
328 V: BuiltinTerminalVisitor<E, F>,
329 O,
330 E,
331 F: CstFacade,
332 >(
333 &self,
334 facade: &F,
335 parent: CstNodeId,
336 nodes: [NodeKind<TerminalKind, NonTerminalKind>; N],
337 mut visitor: impl FnMut(
338 [CstNodeId; N],
339 &'v mut V,
340 ) -> Result<(O, &'v mut V), CstConstructError<E>>,
341 visit_ignored: &'v mut V,
342 ) -> Result<O, CstConstructError<E>> {
343 let children = self.children(parent).collect::<Vec<_>>();
344 let mut children = children.into_iter();
345 let mut result = Vec::with_capacity(N);
346 let mut ignored = Vec::with_capacity(N);
347 'outer: for expected_kind in nodes {
348 'inner: for (idx, child) in children.by_ref().enumerate() {
349 let child_data = self
350 .node_data(child)
351 .ok_or(ViewConstructionError::NodeIdNotFound { node: child })?;
352 match child_data {
353 CstNodeData::Terminal { kind, data } => {
354 if NodeKind::Terminal(kind) == expected_kind {
355 result.push(child);
356 continue 'outer;
357 } else if kind.is_builtin_whitespace() || kind.is_builtin_new_line() {
358 if kind.auto_ws_is_off(idx) {
359 return Err(ViewConstructionError::UnexpectedNode {
360 node: child,
361 data: child_data,
362 expected_kind,
363 });
364 }
365 ignored.push((child, kind, data));
366 continue 'inner;
367 } else if kind.is_builtin_line_comment() || kind.is_builtin_block_comment()
368 {
369 ignored.push((child, kind, data));
370 continue 'inner;
371 } else {
372 return Err(ViewConstructionError::UnexpectedNode {
373 node: child,
374 data: child_data,
375 expected_kind,
376 });
377 }
378 }
379 CstNodeData::NonTerminal { kind, .. } => {
380 if NodeKind::NonTerminal(kind) == expected_kind {
381 result.push(child);
382 continue 'outer;
383 } else {
384 return Err(ViewConstructionError::UnexpectedNode {
385 node: child,
386 data: child_data,
387 expected_kind,
388 });
389 }
390 }
391 }
392 }
393 return Err(ViewConstructionError::UnexpectedEndOfChildren { parent });
394 }
395 for (child, kind, data) in ignored {
396 match kind {
397 TerminalKind::Whitespace => visit_ignored.visit_builtin_whitespace_terminal(
398 Whitespace(child),
399 data,
400 facade,
401 )?,
402 TerminalKind::NewLine => {
403 visit_ignored.visit_builtin_new_line_terminal(NewLine(child), data, facade)?
404 }
405 TerminalKind::LineComment => visit_ignored.visit_builtin_line_comment_terminal(
406 LineComment(child),
407 data,
408 facade,
409 )?,
410 TerminalKind::BlockComment => visit_ignored.visit_builtin_block_comment_terminal(
411 BlockComment(child),
412 data,
413 facade,
414 )?,
415 _ => unreachable!(),
416 }
417 }
418 let (result, visit_ignored) = visitor(
419 result
420 .try_into()
421 .expect("Result should have the same length as nodes"),
422 visit_ignored,
423 )?;
424 for child in children.by_ref() {
425 let child_data = self
426 .node_data(child)
427 .ok_or(ViewConstructionError::NodeIdNotFound { node: child })?;
428 match child_data {
429 CstNodeData::Terminal { kind, data } => {
430 if kind.is_builtin_terminal() {
431 match kind {
432 TerminalKind::Whitespace => visit_ignored
433 .visit_builtin_whitespace_terminal(
434 Whitespace(child),
435 data,
436 facade,
437 )?,
438 TerminalKind::NewLine => visit_ignored
439 .visit_builtin_new_line_terminal(NewLine(child), data, facade)?,
440 TerminalKind::LineComment => visit_ignored
441 .visit_builtin_line_comment_terminal(
442 LineComment(child),
443 data,
444 facade,
445 )?,
446 TerminalKind::BlockComment => visit_ignored
447 .visit_builtin_block_comment_terminal(
448 BlockComment(child),
449 data,
450 facade,
451 )?,
452 _ => unreachable!(),
453 }
454 } else {
455 return Err(ViewConstructionError::UnexpectedNode {
456 node: child,
457 data: child_data,
458 expected_kind: NodeKind::Terminal(kind),
459 });
460 }
461 }
462 CstNodeData::NonTerminal { kind, .. } => {
463 return Err(ViewConstructionError::UnexpectedNode {
464 node: child,
465 data: child_data,
466 expected_kind: NodeKind::NonTerminal(kind),
467 });
468 }
469 }
470 }
471 Ok(result)
472 }
473
474 pub fn root_handle(&self) -> RootHandle {
475 RootHandle(self.root())
476 }
477
478 pub fn visit_from_root<V: CstVisitor<Self>>(&self, visitor: &mut V) -> Result<(), V::Error> {
479 visitor.visit_root_handle(self.root_handle(), self)
480 }
481}
482
483pub trait CstFacade: Sized {
484 fn get_str<'a: 'c, 'b: 'c, 'c>(
485 &'a self,
486 terminal: TerminalData,
487 input: &'b str,
488 ) -> Option<&'c str>;
489
490 fn node_data(&self, node: CstNodeId) -> Option<CstNodeData<TerminalKind, NonTerminalKind>>;
491
492 fn has_no_children(&self, node: CstNodeId) -> bool;
493
494 fn children(&self, node: CstNodeId) -> impl DoubleEndedIterator<Item = CstNodeId>;
495
496 fn get_terminal(
497 &self,
498 node: CstNodeId,
499 kind: TerminalKind,
500 ) -> Result<TerminalData, CstConstructError>;
501
502 fn get_non_terminal(
503 &self,
504 node: CstNodeId,
505 kind: NonTerminalKind,
506 ) -> Result<NonTerminalData, CstConstructError>;
507
508 fn collect_nodes<'v, const N: usize, V: BuiltinTerminalVisitor<E, Self>, O, E>(
509 &self,
510 parent: CstNodeId,
511 nodes: [NodeKind<TerminalKind, NonTerminalKind>; N],
512 visitor: impl FnMut([CstNodeId; N], &'v mut V) -> Result<(O, &'v mut V), CstConstructError<E>>,
513 visit_ignored: &'v mut V,
514 ) -> Result<O, CstConstructError<E>>;
515
516 fn dynamic_token(&self, id: DynamicTokenId) -> Option<&str>;
517
518 fn parent(&self, node: CstNodeId) -> Option<CstNodeId>;
519
520 fn root_handle(&self) -> RootHandle;
521
522 fn get_terminal_str<'a: 'c, 'b: 'c, 'c, T: TerminalHandle>(
524 &'a self,
525 input: &'b str,
526 handle: T,
527 ) -> Result<Result<&'c str, DynamicTokenId>, CstConstructError> {
528 let data = self.get_terminal(handle.node_id(), handle.kind())?;
529 match data {
530 TerminalData::Input(input_span) => Ok(Ok(
531 &input[input_span.start as usize..input_span.end as usize]
532 )),
533 TerminalData::Dynamic(id) => Ok(self.dynamic_token(id).ok_or(id)),
534 }
535 }
536
537 fn span(&self, node_id: CstNodeId) -> Option<InputSpan> {
551 match self.node_data(node_id)? {
552 CstNodeData::Terminal { data, .. } => {
553 match data {
555 TerminalData::Input(span) => Some(span),
556 TerminalData::Dynamic(_) => None,
557 }
558 }
559 CstNodeData::NonTerminal { data, .. } => {
560 let first_span = self
562 .children(node_id)
563 .find_map(|child| self.find_first_non_trivia_span(child));
564
565 let last_span = self
567 .children(node_id)
568 .rev()
569 .find_map(|child| self.find_last_non_trivia_span(child));
570
571 match (first_span, last_span) {
572 (Some(first), Some(last)) => Some(first.merge(last)),
573 (Some(span), None) | (None, Some(span)) => Some(span),
574 (None, None) => {
575 match data {
577 NonTerminalData::Input(span) if span != InputSpan::EMPTY => Some(span),
578 _ => None,
579 }
580 }
581 }
582 }
583 }
584 }
585
586 fn concrete_span(&self, node_id: CstNodeId) -> Option<InputSpan> {
588 match self.node_data(node_id)? {
589 CstNodeData::NonTerminal {
590 data: NonTerminalData::Input(span),
591 ..
592 } => Some(span),
593 CstNodeData::Terminal { data, .. } => match data {
594 TerminalData::Input(span) => Some(span),
595 TerminalData::Dynamic(_) => None,
596 },
597 _ => None,
598 }
599 }
600
601 fn find_first_non_trivia_span(&self, node_id: CstNodeId) -> Option<InputSpan> {
603 match self.node_data(node_id)? {
604 CstNodeData::Terminal { kind, data } => {
605 if kind.is_builtin_terminal() {
606 None
607 } else {
608 match data {
609 TerminalData::Input(span) => Some(span),
610 TerminalData::Dynamic(_) => None,
611 }
612 }
613 }
614 CstNodeData::NonTerminal { .. } => self
615 .children(node_id)
616 .find_map(|child| self.find_first_non_trivia_span(child)),
617 }
618 }
619
620 fn find_last_non_trivia_span(&self, node_id: CstNodeId) -> Option<InputSpan> {
622 match self.node_data(node_id)? {
623 CstNodeData::Terminal { kind, data } => {
624 if kind.is_builtin_terminal() {
625 None
626 } else {
627 match data {
628 TerminalData::Input(span) => Some(span),
629 TerminalData::Dynamic(_) => None,
630 }
631 }
632 }
633 CstNodeData::NonTerminal { .. } => self
634 .children(node_id)
635 .rev()
636 .find_map(|child| self.find_last_non_trivia_span(child)),
637 }
638 }
639}
640
641impl CstFacade for ConcreteSyntaxTree<TerminalKind, NonTerminalKind> {
642 fn get_str<'a: 'c, 'b: 'c, 'c>(
643 &'a self,
644 terminal: TerminalData,
645 input: &'b str,
646 ) -> Option<&'c str> {
647 ConcreteSyntaxTree::get_str(self, terminal, input)
648 }
649
650 fn node_data(&self, node: CstNodeId) -> Option<CstNodeData<TerminalKind, NonTerminalKind>> {
651 ConcreteSyntaxTree::node_data(self, node)
652 }
653
654 fn has_no_children(&self, node: CstNodeId) -> bool {
655 ConcreteSyntaxTree::has_no_children(self, node)
656 }
657
658 fn children(&self, node: CstNodeId) -> impl DoubleEndedIterator<Item = CstNodeId> {
659 ConcreteSyntaxTree::children(self, node)
660 }
661
662 fn get_terminal(
663 &self,
664 node: CstNodeId,
665 kind: TerminalKind,
666 ) -> Result<TerminalData, CstConstructError> {
667 ConcreteSyntaxTree::get_terminal(self, node, kind)
668 }
669
670 fn get_non_terminal(
671 &self,
672 node: CstNodeId,
673 kind: NonTerminalKind,
674 ) -> Result<NonTerminalData, CstConstructError> {
675 ConcreteSyntaxTree::get_non_terminal(self, node, kind)
676 }
677
678 fn collect_nodes<'v, const N: usize, V: BuiltinTerminalVisitor<E, Self>, O, E>(
679 &self,
680 parent: CstNodeId,
681 nodes: [NodeKind<TerminalKind, NonTerminalKind>; N],
682 visitor: impl FnMut([CstNodeId; N], &'v mut V) -> Result<(O, &'v mut V), CstConstructError<E>>,
683 visit_ignored: &'v mut V,
684 ) -> Result<O, CstConstructError<E>> {
685 ConcreteSyntaxTree::collect_nodes(self, self, parent, nodes, visitor, visit_ignored)
686 }
687
688 fn dynamic_token(&self, id: DynamicTokenId) -> Option<&str> {
689 ConcreteSyntaxTree::dynamic_token(self, id)
690 }
691
692 fn parent(&self, node: CstNodeId) -> Option<CstNodeId> {
693 ConcreteSyntaxTree::parent(self, node)
694 }
695
696 fn root_handle(&self) -> RootHandle {
697 ConcreteSyntaxTree::root_handle(self)
698 }
699}
700
701#[derive(Debug, Clone, Error)]
702pub enum ViewConstructionError<T, Nt, E = Infallible> {
704 #[error("Unexpected node for expected kind: {expected_kind:?} but got {data:?}")]
706 UnexpectedNode {
707 node: CstNodeId,
709 data: CstNodeData<T, Nt>,
711 expected_kind: NodeKind<T, Nt>,
713 },
714 #[error("Unexpected extra node")]
716 UnexpectedExtraNode {
717 node: CstNodeId,
719 },
720 #[error("Unexpected end of children")]
722 UnexpectedEndOfChildren {
723 parent: CstNodeId,
725 },
726 #[error("Unexpected empty children for a non-terminal: {node}")]
728 UnexpectedEmptyChildren {
729 node: CstNodeId,
731 },
732 #[error("Node ID not found in the tree: {node}")]
734 NodeIdNotFound {
735 node: CstNodeId,
737 },
738 #[error(transparent)]
740 Error(#[from] E),
741}
742
743impl<T, Nt, E> ViewConstructionError<T, Nt, E> {
744 pub fn extract_error(self) -> Result<E, ViewConstructionError<T, Nt, Infallible>> {
745 match self {
746 ViewConstructionError::Error(e) => Ok(e),
747 ViewConstructionError::UnexpectedNode {
748 node,
749 data,
750 expected_kind,
751 } => Err(ViewConstructionError::UnexpectedNode {
752 node,
753 data,
754 expected_kind,
755 }),
756 ViewConstructionError::UnexpectedExtraNode { node } => {
757 Err(ViewConstructionError::UnexpectedExtraNode { node })
758 }
759 ViewConstructionError::UnexpectedEndOfChildren { parent } => {
760 Err(ViewConstructionError::UnexpectedEndOfChildren { parent })
761 }
762 ViewConstructionError::UnexpectedEmptyChildren { node } => {
763 Err(ViewConstructionError::UnexpectedEmptyChildren { node })
764 }
765 ViewConstructionError::NodeIdNotFound { node } => {
766 Err(ViewConstructionError::NodeIdNotFound { node })
767 }
768 }
769 }
770}
771
772impl<T, Nt> ViewConstructionError<T, Nt, Infallible> {
773 pub fn into_any_error<E>(self) -> ViewConstructionError<T, Nt, E> {
774 match self {
775 ViewConstructionError::UnexpectedNode {
776 node,
777 data,
778 expected_kind,
779 } => ViewConstructionError::UnexpectedNode {
780 node,
781 data,
782 expected_kind,
783 },
784 ViewConstructionError::UnexpectedExtraNode { node } => {
785 ViewConstructionError::UnexpectedExtraNode { node }
786 }
787 ViewConstructionError::UnexpectedEndOfChildren { parent } => {
788 ViewConstructionError::UnexpectedEndOfChildren { parent }
789 }
790 ViewConstructionError::UnexpectedEmptyChildren { node } => {
791 ViewConstructionError::UnexpectedEmptyChildren { node }
792 }
793 ViewConstructionError::NodeIdNotFound { node } => {
794 ViewConstructionError::NodeIdNotFound { node }
795 }
796 }
797 }
798}
799
800impl<T, Nt> ViewConstructionError<T, Nt, Infallible>
801where
802 T: Copy,
803 Nt: Copy,
804{
805 pub fn unexpected_node(&self) -> Option<UnexpectedNode<T, Nt>> {
806 match self {
807 ViewConstructionError::UnexpectedNode {
808 node,
809 data,
810 expected_kind,
811 } => Some(UnexpectedNode {
812 node: *node,
813 data: *data,
814 expected_kind: *expected_kind,
815 }),
816 _ => None,
817 }
818 }
819}
820
821#[derive(Debug, Clone, Copy, PartialEq, Eq)]
822pub struct UnexpectedNode<T, Nt> {
823 node: CstNodeId,
824 data: CstNodeData<T, Nt>,
825 expected_kind: NodeKind<T, Nt>,
826}
827
828struct DummyTerminalVisitor;
829
830impl<F: CstFacade> CstVisitor<F> for DummyTerminalVisitor {
831 type Error = Infallible;
832 fn visit_new_line_terminal(
833 &mut self,
834 _terminal: crate::nodes::NewLine,
835 _data: TerminalData,
836 _tree: &F,
837 ) -> Result<(), Self::Error> {
838 Ok(())
839 }
840
841 fn visit_whitespace_terminal(
842 &mut self,
843 _terminal: crate::nodes::Whitespace,
844 _data: TerminalData,
845 _tree: &F,
846 ) -> Result<(), Self::Error> {
847 Ok(())
848 }
849
850 fn visit_line_comment_terminal(
851 &mut self,
852 _terminal: crate::nodes::LineComment,
853 _data: TerminalData,
854 _tree: &F,
855 ) -> Result<(), Self::Error> {
856 Ok(())
857 }
858
859 fn visit_block_comment_terminal(
860 &mut self,
861 _terminal: crate::nodes::BlockComment,
862 _data: TerminalData,
863 _tree: &F,
864 ) -> Result<(), Self::Error> {
865 Ok(())
866 }
867}
868
869pub trait TerminalHandle {
870 fn node_id(&self) -> CstNodeId;
872 fn kind(&self) -> TerminalKind;
874 fn get_data<F: CstFacade>(&self, tree: &F) -> Result<TerminalData, CstConstructError> {
876 tree.get_terminal(self.node_id(), self.kind())
877 }
878}
879
880pub trait NonTerminalHandle: Sized {
882 type View;
884
885 fn node_id(&self) -> CstNodeId;
887
888 fn new<F: CstFacade>(index: CstNodeId, tree: &F) -> Result<Self, CstConstructError> {
890 Self::new_with_visit(index, tree, &mut DummyTerminalVisitor)
891 }
892
893 fn new_with_visit<F: CstFacade, E>(
894 index: CstNodeId,
895 tree: &F,
896 visit_ignored: &mut impl BuiltinTerminalVisitor<E, F>,
897 ) -> Result<Self, CstConstructError<E>>;
898
899 fn get_view<C: CstFacade>(&self, tree: &C) -> Result<Self::View, CstConstructError> {
901 self.get_view_with_visit(
902 tree,
903 |view, visit_ignored| (view, visit_ignored),
904 &mut DummyTerminalVisitor,
905 )
906 }
907
908 fn get_view_with_visit<'v, F: CstFacade, V: BuiltinTerminalVisitor<E, F>, O, E>(
910 &self,
911 tree: &F,
912 visit: impl FnMut(Self::View, &'v mut V) -> (O, &'v mut V),
913 visit_ignored: &'v mut V,
914 ) -> Result<O, CstConstructError<E>>;
915
916 fn kind(&self) -> NonTerminalKind;
918}
919
920pub trait RecursiveView<F: CstFacade> {
922 type Item;
924 fn get_all(&self, tree: &F) -> Result<Vec<Self::Item>, CstConstructError> {
925 self.get_all_with_visit(tree, &mut DummyTerminalVisitor)
926 }
927
928 fn get_all_with_visit<E>(
929 &self,
930 tree: &F,
931 visit_ignored: &mut impl BuiltinTerminalVisitor<E, F>,
932 ) -> Result<Vec<Self::Item>, CstConstructError<E>>;
933}