aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-01-07 07:10:35 +0000
committerAleksey Kladov <[email protected]>2018-01-07 07:10:35 +0000
commit50132db4c676a7dac105dba7fa966edafaa1d209 (patch)
treea0635e78b60d747228d351e67efbbc99ec785538 /src
parent31a07da88dc9473a9f05617a98db6180e6e9e3c6 (diff)
Store syntax errors
Diffstat (limited to 'src')
-rw-r--r--src/tree/file_builder.rs5
-rw-r--r--src/tree/mod.rs78
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 @@
1use {SyntaxKind, TextUnit, TextRange}; 1use {SyntaxKind, TextUnit, TextRange};
2use super::{NodeData, NodeIdx, File}; 2use super::{NodeData, SyntaxErrorData, NodeIdx, File};
3 3
4pub trait Sink { 4pub 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 {
11pub struct FileBuilder { 11pub 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 {
36pub struct File { 36pub struct File {
37 text: String, 37 text: String,
38 nodes: Vec<NodeData>, 38 nodes: Vec<NodeData>,
39 errors: Vec<SyntaxErrorData>,
39} 40}
40 41
41impl File { 42impl 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
93impl<'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)]
100pub struct SyntaxError<'f> {
101 file: &'f File,
102 idx: ErrorIdx,
103}
104
105impl<'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
86pub struct Children<'f> { 129pub 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)] 143pub struct SyntaxErrors<'f> {
144 next: Option<SyntaxError<'f>>,
145}
146
147impl<'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)]
101struct NodeIdx(u32); 159struct NodeIdx(u32);
102 160
103struct NodeData { 161struct NodeData {
@@ -122,8 +180,18 @@ impl ::std::ops::IndexMut<NodeIdx> for Vec<NodeData> {
122 } 180 }
123} 181}
124 182
125impl<'f> fmt::Debug for Node<'f> { 183#[derive(Clone, Copy)]
126 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 184struct ErrorIdx(u32);
127 write!(fmt, "{:?}@{:?}", self.kind(), self.range()) 185
186struct SyntaxErrorData {
187 node: NodeIdx,
188 message: String,
189}
190
191impl ::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}