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 | |
parent | 31a07da88dc9473a9f05617a98db6180e6e9e3c6 (diff) |
Store syntax errors
Diffstat (limited to 'src')
-rw-r--r-- | src/tree/file_builder.rs | 5 | ||||
-rw-r--r-- | src/tree/mod.rs | 78 |
2 files changed, 77 insertions, 6 deletions
diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs index da8b8f824..83aa4186f 100644 --- a/src/tree/file_builder.rs +++ b/src/tree/file_builder.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use {SyntaxKind, TextUnit, TextRange}; | 1 | use {SyntaxKind, TextUnit, TextRange}; |
2 | use super::{NodeData, NodeIdx, File}; | 2 | use super::{NodeData, SyntaxErrorData, NodeIdx, File}; |
3 | 3 | ||
4 | pub trait Sink { | 4 | pub trait Sink { |
5 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); | 5 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); |
@@ -11,6 +11,7 @@ pub trait Sink { | |||
11 | pub struct FileBuilder { | 11 | pub struct FileBuilder { |
12 | text: String, | 12 | text: String, |
13 | nodes: Vec<NodeData>, | 13 | nodes: Vec<NodeData>, |
14 | errors: Vec<SyntaxErrorData>, | ||
14 | in_progress: Vec<(NodeIdx, Option<NodeIdx>)>, // (parent, last_child) | 15 | in_progress: Vec<(NodeIdx, Option<NodeIdx>)>, // (parent, last_child) |
15 | pos: TextUnit, | 16 | pos: TextUnit, |
16 | } | 17 | } |
@@ -58,6 +59,7 @@ impl FileBuilder { | |||
58 | FileBuilder { | 59 | FileBuilder { |
59 | text, | 60 | text, |
60 | nodes: Vec::new(), | 61 | nodes: Vec::new(), |
62 | errors: Vec::new(), | ||
61 | in_progress: Vec::new(), | 63 | in_progress: Vec::new(), |
62 | pos: TextUnit::new(0), | 64 | pos: TextUnit::new(0), |
63 | } | 65 | } |
@@ -75,6 +77,7 @@ impl FileBuilder { | |||
75 | File { | 77 | File { |
76 | text: self.text, | 78 | text: self.text, |
77 | nodes: self.nodes, | 79 | nodes: self.nodes, |
80 | errors: self.errors, | ||
78 | } | 81 | } |
79 | } | 82 | } |
80 | 83 | ||
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 | } |