diff options
Diffstat (limited to 'src/tree/file_builder.rs')
-rw-r--r-- | src/tree/file_builder.rs | 150 |
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 | }; |
15 | use super::{File, NodeData, NodeIdx, SyntaxErrorData}; | ||
16 | use SError; | 15 | use SError; |
17 | 16 | ||
18 | pub(crate) trait Sink { | 17 | pub(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)] | ||
26 | pub(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 | |||
35 | impl 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 | |||
84 | impl 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 | |||
153 | fn fill<T>(slot: &mut Option<T>, value: T) { | ||
154 | assert!(slot.is_none()); | ||
155 | *slot = Some(value); | ||
156 | } | ||
157 | |||
158 | fn 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)] | ||
164 | pub(crate) struct ErrorMsg { | ||
165 | pub(crate) msg: String, | ||
166 | } | 22 | } |
167 | 23 | ||
168 | pub(crate) struct GreenBuilder { | 24 | pub(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 | } |
223 | impl SyntaxKind { | 79 | impl SyntaxKind { |