aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-01-07 09:13:01 +0000
committerAleksey Kladov <[email protected]>2018-01-07 09:13:01 +0000
commitf797c81155e9b7371b24801efac3fcbd236fc9ab (patch)
tree27a2fd9e640962489e07d18b6225d3d30096bb39
parent8671a892c5169fe608d0467270a2af7797df8c36 (diff)
Smart eof for blocks
-rw-r--r--src/parser/event_parser/grammar.rs12
-rw-r--r--src/parser/event_parser/mod.rs5
-rw-r--r--src/parser/event_parser/parser.rs48
-rw-r--r--src/parser/mod.rs2
-rw-r--r--src/tree/file_builder.rs2
-rw-r--r--src/tree/mod.rs7
-rw-r--r--tests/parser.rs8
7 files changed, 70 insertions, 14 deletions
diff --git a/src/parser/event_parser/grammar.rs b/src/parser/event_parser/grammar.rs
index d09579881..7425526ef 100644
--- a/src/parser/event_parser/grammar.rs
+++ b/src/parser/event_parser/grammar.rs
@@ -74,7 +74,7 @@ fn many<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) {
74fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { 74fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) {
75 many(p, |p| { 75 many(p, |p| {
76 f(p); 76 f(p);
77 p.expect(COMMA) 77 p.is_eof() || p.expect(COMMA)
78 }) 78 })
79} 79}
80 80
@@ -101,6 +101,14 @@ impl<'p> Parser<'p> {
101 } 101 }
102 102
103 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { 103 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
104 self.current_is(kind) && { self.bump(); true } 104 if self.current_is(kind) {
105 self.bump();
106 true
107 } else {
108 self.error()
109 .message(format!("expected {:?}", kind))
110 .emit();
111 false
112 }
105 } 113 }
106} \ No newline at end of file 114} \ No newline at end of file
diff --git a/src/parser/event_parser/mod.rs b/src/parser/event_parser/mod.rs
index 3c3654b6b..87b317c84 100644
--- a/src/parser/event_parser/mod.rs
+++ b/src/parser/event_parser/mod.rs
@@ -10,7 +10,10 @@ pub(crate) enum Event {
10 Token { 10 Token {
11 kind: SyntaxKind, 11 kind: SyntaxKind,
12 n_raw_tokens: u8, 12 n_raw_tokens: u8,
13 } 13 },
14 Error {
15 message: String,
16 },
14} 17}
15 18
16pub(crate) fn parse<'t>(text: &'t str, raw_tokens: &'t [Token]) -> Vec<Event> { 19pub(crate) fn parse<'t>(text: &'t str, raw_tokens: &'t [Token]) -> Vec<Event> {
diff --git a/src/parser/event_parser/parser.rs b/src/parser/event_parser/parser.rs
index 07e3ccc23..eafa03521 100644
--- a/src/parser/event_parser/parser.rs
+++ b/src/parser/event_parser/parser.rs
@@ -10,7 +10,9 @@ pub struct Parser<'t> {
10 10
11 pos: usize, 11 pos: usize,
12 events: Vec<Event>, 12 events: Vec<Event>,
13
13 curly_level: i32, 14 curly_level: i32,
15 curly_limit: Option<i32>,
14} 16}
15 17
16impl<'t> Parser<'t> { 18impl<'t> Parser<'t> {
@@ -32,6 +34,7 @@ impl<'t> Parser<'t> {
32 pos: 0, 34 pos: 0,
33 events: Vec::new(), 35 events: Vec::new(),
34 curly_level: 0, 36 curly_level: 0,
37 curly_limit: None,
35 } 38 }
36 } 39 }
37 40
@@ -41,7 +44,14 @@ impl<'t> Parser<'t> {
41 } 44 }
42 45
43 pub(crate) fn is_eof(&self) -> bool { 46 pub(crate) fn is_eof(&self) -> bool {
44 self.pos == self.non_ws_tokens.len() 47 if self.pos == self.non_ws_tokens.len() {
48 return true
49 }
50 if let Some(limit) = self.curly_limit {
51 let idx = self.non_ws_tokens[self.pos].0;
52 return limit == self.curly_level && self.raw_tokens[idx].kind == R_CURLY;
53 }
54 false
45 } 55 }
46 56
47 pub(crate) fn start(&mut self, kind: SyntaxKind) { 57 pub(crate) fn start(&mut self, kind: SyntaxKind) {
@@ -52,6 +62,10 @@ impl<'t> Parser<'t> {
52 self.event(Event::Finish); 62 self.event(Event::Finish);
53 } 63 }
54 64
65 pub(crate) fn error<'p>(&'p mut self) -> ErrorBuilder<'p, 't> {
66 ErrorBuilder::new(self)
67 }
68
55 pub(crate) fn current(&self) -> Option<SyntaxKind> { 69 pub(crate) fn current(&self) -> Option<SyntaxKind> {
56 if self.is_eof() { 70 if self.is_eof() {
57 return None; 71 return None;
@@ -73,15 +87,18 @@ impl<'t> Parser<'t> {
73 } 87 }
74 88
75 pub(crate) fn curly_block<F: FnOnce(&mut Parser)>(&mut self, f: F) -> bool { 89 pub(crate) fn curly_block<F: FnOnce(&mut Parser)>(&mut self, f: F) -> bool {
76 let level = self.curly_level; 90 let old_level = self.curly_level;
91 let old_limit = self.curly_limit;
77 if !self.expect(L_CURLY) { 92 if !self.expect(L_CURLY) {
78 return false 93 return false
79 } 94 }
95 self.curly_limit = Some(self.curly_level);
80 f(self); 96 f(self);
81 assert!(self.curly_level > level); 97 assert!(self.curly_level > old_level);
98 self.curly_limit = old_limit;
82 if !self.expect(R_CURLY) { 99 if !self.expect(R_CURLY) {
83 self.start(ERROR); 100 self.start(ERROR);
84 while self.curly_level > level { 101 while self.curly_level > old_level {
85 if self.bump().is_none() { 102 if self.bump().is_none() {
86 break; 103 break;
87 } 104 }
@@ -94,4 +111,25 @@ impl<'t> Parser<'t> {
94 fn event(&mut self, event: Event) { 111 fn event(&mut self, event: Event) {
95 self.events.push(event) 112 self.events.push(event)
96 } 113 }
97} \ No newline at end of file 114}
115
116pub(crate) struct ErrorBuilder<'p, 't: 'p> {
117 message: Option<String>,
118 parser: &'p mut Parser<'t>
119}
120
121impl<'t, 'p> ErrorBuilder<'p, 't> {
122 fn new(parser: &'p mut Parser<'t>) -> Self {
123 ErrorBuilder { message: None, parser }
124 }
125
126 pub fn message<M: Into<String>>(mut self, m: M) -> Self {
127 self.message = Some(m.into());
128 self
129 }
130
131 pub fn emit(self) {
132 let message = self.message.expect("Error message not set");
133 self.parser.event(Event::Error { message });
134 }
135}
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index a632fbc01..a76356eb5 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -44,6 +44,8 @@ fn from_events_to_file(
44 break; 44 break;
45 } 45 }
46 }, 46 },
47 Event::Error { message } => builder.error().message(message).emit(),
48
47 } 49 }
48 } 50 }
49 builder.finish() 51 builder.finish()
diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs
index a1b004892..ddb29a6b9 100644
--- a/src/tree/file_builder.rs
+++ b/src/tree/file_builder.rs
@@ -154,7 +154,7 @@ impl<'f> ErrorBuilder<'f> {
154 self 154 self
155 } 155 }
156 156
157 pub fn build(self) { 157 pub fn emit(self) {
158 let message = self.message.expect("Error message not set"); 158 let message = self.message.expect("Error message not set");
159 let node = self.builder.current_id(); 159 let node = self.builder.current_id();
160 self.builder.errors.push(SyntaxErrorData { node, message }) 160 self.builder.errors.push(SyntaxErrorData { node, message })
diff --git a/src/tree/mod.rs b/src/tree/mod.rs
index 00d33cbc7..3980b23ce 100644
--- a/src/tree/mod.rs
+++ b/src/tree/mod.rs
@@ -73,7 +73,7 @@ impl<'f> Node<'f> {
73 Children { next: self.as_node(self.data().first_child) } 73 Children { next: self.as_node(self.data().first_child) }
74 } 74 }
75 75
76 pub fn SyntaxErrors(&self) -> SyntaxErrors<'f> { 76 pub fn errors(&self) -> SyntaxErrors<'f> {
77 let pos = self.file.errors.iter().position(|e| e.node == self.idx); 77 let pos = self.file.errors.iter().position(|e| e.node == self.idx);
78 let next = pos 78 let next = pos
79 .map(|i| ErrorIdx(i as u32)) 79 .map(|i| ErrorIdx(i as u32))
@@ -112,12 +112,13 @@ impl<'f> SyntaxError<'f> {
112 } 112 }
113 113
114 fn next(&self) -> Option<SyntaxError<'f>> { 114 fn next(&self) -> Option<SyntaxError<'f>> {
115 if self.file.errors.len() == self.idx.0 as usize { 115 let next_idx = self.idx.0 + 1;
116 if !((next_idx as usize) < self.file.errors.len()) {
116 return None; 117 return None;
117 } 118 }
118 let result = SyntaxError { 119 let result = SyntaxError {
119 file: self.file, 120 file: self.file,
120 idx: ErrorIdx(self.idx.0 + 1) 121 idx: ErrorIdx(next_idx)
121 }; 122 };
122 if result.data().node != self.data().node { 123 if result.data().node != self.data().node {
123 return None; 124 return None;
diff --git a/tests/parser.rs b/tests/parser.rs
index 6c31463ad..7fde365c9 100644
--- a/tests/parser.rs
+++ b/tests/parser.rs
@@ -61,8 +61,12 @@ fn dump_tree(file: &File) -> String {
61 61
62 fn go(node: Node, buff: &mut String, level: usize) { 62 fn go(node: Node, buff: &mut String, level: usize) {
63 buff.push_str(&String::from(" ").repeat(level)); 63 buff.push_str(&String::from(" ").repeat(level));
64 write!(buff, "{:?}\n", node) 64 write!(buff, "{:?}", node).unwrap();
65 .unwrap(); 65 for err in node.errors() {
66 write!(buff, " err: `{}`", err.message()).unwrap();
67 }
68 write!(buff, "\n").unwrap();
69
66 for child in node.children() { 70 for child in node.children() {
67 go(child, buff, level + 1) 71 go(child, buff, level + 1)
68 } 72 }