1use eure_tree::{
2 Cst,
3 node_kind::{NonTerminalKind, TerminalKind},
4 tree::{ConcreteSyntaxTree, CstNodeData, CstNodeId, InputSpan, NonTerminalData, TerminalData},
5};
6use parol_runtime::{ParolError, Token, parser::parse_tree_type::TreeConstruct};
7
8#[derive(Debug, Clone)]
11pub struct CstBuilder {
12 tree: ConcreteSyntaxTree<TerminalKind, NonTerminalKind>,
13 node_stack: Vec<NodeStackItem>,
14 root_node: Option<CstNodeId>,
15}
16
17#[derive(Debug, Clone)]
18struct NodeStackItem {
19 node: CstNodeId,
20 span: InputSpan,
21 children: Vec<CstNodeId>,
22}
23
24impl Default for CstBuilder {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl CstBuilder {
31 pub fn new() -> Self {
32 let temp_root_data =
34 CstNodeData::new_non_terminal(NonTerminalKind::Root, NonTerminalData::Dynamic);
35 Self {
36 tree: ConcreteSyntaxTree::new(temp_root_data),
37 node_stack: Vec::new(),
38 root_node: None,
39 }
40 }
41
42 fn add_terminal_node(&mut self, kind: TerminalKind, span: InputSpan) -> CstNodeId {
44 let node = self.tree.add_node(CstNodeData::Terminal {
45 kind,
46 data: TerminalData::Input(span),
47 });
48
49 let parent = self.node_stack.last_mut().expect("node stack is empty");
50 parent.children.push(node);
51 parent.span = parent.span.merge(span);
52
53 node
54 }
55
56 fn open_non_terminal_node(&mut self, kind: NonTerminalKind) -> CstNodeId {
58 let node = self.tree.add_node(CstNodeData::NonTerminal {
60 kind,
61 data: NonTerminalData::Input(InputSpan::EMPTY),
62 });
63
64 if let Some(parent) = self.node_stack.last_mut() {
65 parent.children.push(node);
66 } else {
67 self.root_node = Some(node);
69 }
70
71 self.node_stack.push(NodeStackItem {
72 node,
73 span: InputSpan::EMPTY,
74 children: Vec::new(),
75 });
76 node
77 }
78
79 fn close_non_terminal_node(&mut self) -> Option<CstNodeId> {
81 let popped = self.node_stack.pop();
82 if let Some(item) = &popped {
83 let parent = item.node;
84
85 self.tree.update_children(parent, item.children.clone());
87
88 if let Some(CstNodeData::NonTerminal { kind, .. }) = self.tree.node_data(parent) {
90 let updated_data = CstNodeData::NonTerminal {
91 kind,
92 data: NonTerminalData::Input(item.span),
93 };
94 self.tree.update_node(parent, updated_data);
95 }
96
97 if let Some(parent_item) = self.node_stack.last_mut() {
98 parent_item.span = parent_item.span.merge(item.span);
99 }
100 }
101 popped.map(|item| item.node)
102 }
103
104 pub fn build_tree(mut self) -> Cst {
106 while !self.node_stack.is_empty() {
107 self.close_non_terminal_node();
108 }
109
110 if let Some(root_node) = self.root_node {
112 self.tree.set_root(root_node);
113 }
114
115 self.tree
116 }
117}
118
119impl<'t> TreeConstruct<'t> for CstBuilder {
120 type Error = ParolError;
121 type Tree = Cst;
122
123 fn open_non_terminal(
124 &mut self,
125 name: &'static str,
126 _size_hint: Option<usize>,
127 ) -> Result<(), Self::Error> {
128 let kind = NonTerminalKind::from_non_terminal_name(name);
129 self.open_non_terminal_node(kind);
130 Ok(())
131 }
132
133 fn close_non_terminal(&mut self) -> Result<(), Self::Error> {
134 self.close_non_terminal_node();
135 Ok(())
136 }
137
138 fn add_token(&mut self, token: &Token<'t>) -> Result<(), Self::Error> {
139 let kind = TerminalKind::from_terminal_index(token.token_type);
140 let span = InputSpan {
141 start: token.location.start,
142 end: token.location.end,
143 };
144 self.add_terminal_node(kind, span);
145 Ok(())
146 }
147
148 fn build(self) -> Result<Self::Tree, Self::Error> {
149 Ok(self.build_tree())
150 }
151}