diff options
author | Aleksey Kladov <[email protected]> | 2018-01-07 07:10:35 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-01-07 07:10:35 +0000 |
commit | 50132db4c676a7dac105dba7fa966edafaa1d209 (patch) | |
tree | a0635e78b60d747228d351e67efbbc99ec785538 /src/tree/mod.rs | |
parent | 31a07da88dc9473a9f05617a98db6180e6e9e3c6 (diff) |
Store syntax errors
Diffstat (limited to 'src/tree/mod.rs')
-rw-r--r-- | src/tree/mod.rs | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 7a5d429a3..00d33cbc7 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs | |||
@@ -36,6 +36,7 @@ pub struct Token { | |||
36 | pub struct File { | 36 | pub struct File { |
37 | text: String, | 37 | text: String, |
38 | nodes: Vec<NodeData>, | 38 | nodes: Vec<NodeData>, |
39 | errors: Vec<SyntaxErrorData>, | ||
39 | } | 40 | } |
40 | 41 | ||
41 | impl File { | 42 | impl File { |
@@ -72,6 +73,14 @@ impl<'f> Node<'f> { | |||
72 | Children { next: self.as_node(self.data().first_child) } | 73 | Children { next: self.as_node(self.data().first_child) } |
73 | } | 74 | } |
74 | 75 | ||
76 | pub fn SyntaxErrors(&self) -> SyntaxErrors<'f> { | ||
77 | let pos = self.file.errors.iter().position(|e| e.node == self.idx); | ||
78 | let next = pos | ||
79 | .map(|i| ErrorIdx(i as u32)) | ||
80 | .map(|idx| SyntaxError { file: self.file, idx }); | ||
81 | SyntaxErrors { next } | ||
82 | } | ||
83 | |||
75 | fn data(&self) -> &'f NodeData { | 84 | fn data(&self) -> &'f NodeData { |
76 | &self.file.nodes[self.idx] | 85 | &self.file.nodes[self.idx] |
77 | } | 86 | } |
@@ -81,7 +90,41 @@ impl<'f> Node<'f> { | |||
81 | } | 90 | } |
82 | } | 91 | } |
83 | 92 | ||
93 | impl<'f> fmt::Debug for Node<'f> { | ||
94 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
95 | write!(fmt, "{:?}@{:?}", self.kind(), self.range()) | ||
96 | } | ||
97 | } | ||
84 | 98 | ||
99 | #[derive(Clone, Copy)] | ||
100 | pub struct SyntaxError<'f> { | ||
101 | file: &'f File, | ||
102 | idx: ErrorIdx, | ||
103 | } | ||
104 | |||
105 | impl<'f> SyntaxError<'f> { | ||
106 | pub fn message(&self) -> &'f str { | ||
107 | self.data().message.as_str() | ||
108 | } | ||
109 | |||
110 | fn data(&self) -> &'f SyntaxErrorData { | ||
111 | &self.file.errors[self.idx] | ||
112 | } | ||
113 | |||
114 | fn next(&self) -> Option<SyntaxError<'f>> { | ||
115 | if self.file.errors.len() == self.idx.0 as usize { | ||
116 | return None; | ||
117 | } | ||
118 | let result = SyntaxError { | ||
119 | file: self.file, | ||
120 | idx: ErrorIdx(self.idx.0 + 1) | ||
121 | }; | ||
122 | if result.data().node != self.data().node { | ||
123 | return None; | ||
124 | } | ||
125 | Some(result) | ||
126 | } | ||
127 | } | ||
85 | 128 | ||
86 | pub struct Children<'f> { | 129 | pub struct Children<'f> { |
87 | next: Option<Node<'f>>, | 130 | next: Option<Node<'f>>, |
@@ -97,7 +140,22 @@ impl<'f> Iterator for Children<'f> { | |||
97 | } | 140 | } |
98 | } | 141 | } |
99 | 142 | ||
100 | #[derive(Clone, Copy)] | 143 | pub struct SyntaxErrors<'f> { |
144 | next: Option<SyntaxError<'f>>, | ||
145 | } | ||
146 | |||
147 | impl<'f> Iterator for SyntaxErrors<'f> { | ||
148 | type Item = SyntaxError<'f>; | ||
149 | |||
150 | fn next(&mut self) -> Option<SyntaxError<'f>> { | ||
151 | let next = self.next; | ||
152 | self.next = next.as_ref().and_then(SyntaxError::next); | ||
153 | next | ||
154 | } | ||
155 | } | ||
156 | |||
157 | |||
158 | #[derive(Clone, Copy, PartialEq, Eq)] | ||
101 | struct NodeIdx(u32); | 159 | struct NodeIdx(u32); |
102 | 160 | ||
103 | struct NodeData { | 161 | struct NodeData { |
@@ -122,8 +180,18 @@ impl ::std::ops::IndexMut<NodeIdx> for Vec<NodeData> { | |||
122 | } | 180 | } |
123 | } | 181 | } |
124 | 182 | ||
125 | impl<'f> fmt::Debug for Node<'f> { | 183 | #[derive(Clone, Copy)] |
126 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | 184 | struct ErrorIdx(u32); |
127 | write!(fmt, "{:?}@{:?}", self.kind(), self.range()) | 185 | |
186 | struct SyntaxErrorData { | ||
187 | node: NodeIdx, | ||
188 | message: String, | ||
189 | } | ||
190 | |||
191 | impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> { | ||
192 | type Output = SyntaxErrorData; | ||
193 | |||
194 | fn index(&self, ErrorIdx(idx): ErrorIdx) -> &SyntaxErrorData { | ||
195 | &self[idx as usize] | ||
128 | } | 196 | } |
129 | } \ No newline at end of file | 197 | } |