aboutsummaryrefslogtreecommitdiff
path: root/src/tree/file_builder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tree/file_builder.rs')
-rw-r--r--src/tree/file_builder.rs150
1 files changed, 3 insertions, 147 deletions
diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs
index 4983006cd..f5d1751f9 100644
--- a/src/tree/file_builder.rs
+++ b/src/tree/file_builder.rs
@@ -12,157 +12,13 @@ use {
12 SyntaxKind, TextRange, TextUnit, 12 SyntaxKind, TextRange, TextUnit,
13 yellow::GreenNode 13 yellow::GreenNode
14}; 14};
15use super::{File, NodeData, NodeIdx, SyntaxErrorData};
16use SError; 15use SError;
17 16
18pub(crate) trait Sink { 17pub(crate) trait Sink {
19 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); 18 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
20 fn start_internal(&mut self, kind: SyntaxKind); 19 fn start_internal(&mut self, kind: SyntaxKind);
21 fn finish_internal(&mut self); 20 fn finish_internal(&mut self);
22 fn error(&mut self, err: ErrorMsg); 21 fn error(&mut self, err: String);
23}
24
25#[derive(Debug)]
26pub(crate) struct FileBuilder {
27 text: String,
28 nodes: Vec<NodeData>,
29 errors: Vec<SyntaxErrorData>,
30 in_progress: Vec<(NodeIdx, Option<NodeIdx>)>,
31 // (parent, last_child)
32 pos: TextUnit,
33}
34
35impl Sink for FileBuilder {
36 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit) {
37 let leaf = NodeData {
38 kind,
39 range: TextRange::offset_len(self.pos, len),
40 parent: None,
41 first_child: None,
42 next_sibling: None,
43 };
44 self.pos += len;
45 let id = self.push_child(leaf);
46 self.add_len(id);
47 }
48
49 fn start_internal(&mut self, kind: SyntaxKind) {
50 let node = NodeData {
51 kind,
52 range: TextRange::offset_len(self.pos, 0.into()),
53 parent: None,
54 first_child: None,
55 next_sibling: None,
56 };
57 let id = if self.in_progress.is_empty() {
58 self.new_node(node)
59 } else {
60 self.push_child(node)
61 };
62 self.in_progress.push((id, None))
63 }
64
65 fn finish_internal(&mut self) {
66 let (id, _) = self.in_progress
67 .pop()
68 .expect("trying to complete a node, but there are no in-progress nodes");
69 if !self.in_progress.is_empty() {
70 self.add_len(id);
71 }
72 }
73
74 fn error(&mut self, err: ErrorMsg) {
75 let &(node, after_child) = self.in_progress.last().unwrap();
76 self.errors.push(SyntaxErrorData {
77 node,
78 message: err.msg,
79 after_child,
80 })
81 }
82}
83
84impl FileBuilder {
85 pub fn new(text: String) -> FileBuilder {
86 FileBuilder {
87 text,
88 nodes: Vec::new(),
89 errors: Vec::new(),
90 in_progress: Vec::new(),
91 pos: 0.into(),
92 }
93 }
94
95 pub fn finish(self) -> File {
96 assert!(
97 self.in_progress.is_empty(),
98 "some nodes in FileBuilder are unfinished: {:?}",
99 self.in_progress
100 .iter()
101 .map(|&(idx, _)| self.nodes[idx].kind)
102 .collect::<Vec<_>>()
103 );
104 assert_eq!(
105 self.pos,
106 (self.text.len() as u32).into(),
107 "nodes in FileBuilder do not cover the whole file"
108 );
109 File {
110 text: self.text,
111 nodes: self.nodes,
112 errors: self.errors,
113 }
114 }
115
116 fn new_node(&mut self, data: NodeData) -> NodeIdx {
117 let id = NodeIdx(self.nodes.len() as u32);
118 self.nodes.push(data);
119 id
120 }
121
122 fn push_child(&mut self, mut child: NodeData) -> NodeIdx {
123 child.parent = Some(self.current_id());
124 let id = self.new_node(child);
125 {
126 let (parent, sibling) = *self.in_progress.last().unwrap();
127 let slot = if let Some(idx) = sibling {
128 &mut self.nodes[idx].next_sibling
129 } else {
130 &mut self.nodes[parent].first_child
131 };
132 fill(slot, id);
133 }
134 self.in_progress.last_mut().unwrap().1 = Some(id);
135 id
136 }
137
138 fn add_len(&mut self, child: NodeIdx) {
139 let range = self.nodes[child].range;
140 grow(&mut self.current_parent().range, range);
141 }
142
143 fn current_id(&self) -> NodeIdx {
144 self.in_progress.last().unwrap().0
145 }
146
147 fn current_parent(&mut self) -> &mut NodeData {
148 let idx = self.current_id();
149 &mut self.nodes[idx]
150 }
151}
152
153fn fill<T>(slot: &mut Option<T>, value: T) {
154 assert!(slot.is_none());
155 *slot = Some(value);
156}
157
158fn grow(left: &mut TextRange, right: TextRange) {
159 assert_eq!(left.end(), right.start());
160 *left = TextRange::from_to(left.start(), right.end())
161}
162
163#[derive(Default)]
164pub(crate) struct ErrorMsg {
165 pub(crate) msg: String,
166} 22}
167 23
168pub(crate) struct GreenBuilder { 24pub(crate) struct GreenBuilder {
@@ -216,8 +72,8 @@ impl Sink for GreenBuilder {
216 } 72 }
217 } 73 }
218 74
219 fn error(&mut self, err: ErrorMsg) { 75 fn error(&mut self, message: String) {
220 self.errors.push(SError { message: err.msg, offset: self.pos }) 76 self.errors.push(SError { message, offset: self.pos })
221 } 77 }
222} 78}
223impl SyntaxKind { 79impl SyntaxKind {