diff options
author | Aleksey Kladov <[email protected]> | 2018-01-07 09:13:01 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-01-07 09:13:01 +0000 |
commit | f797c81155e9b7371b24801efac3fcbd236fc9ab (patch) | |
tree | 27a2fd9e640962489e07d18b6225d3d30096bb39 | |
parent | 8671a892c5169fe608d0467270a2af7797df8c36 (diff) |
Smart eof for blocks
-rw-r--r-- | src/parser/event_parser/grammar.rs | 12 | ||||
-rw-r--r-- | src/parser/event_parser/mod.rs | 5 | ||||
-rw-r--r-- | src/parser/event_parser/parser.rs | 48 | ||||
-rw-r--r-- | src/parser/mod.rs | 2 | ||||
-rw-r--r-- | src/tree/file_builder.rs | 2 | ||||
-rw-r--r-- | src/tree/mod.rs | 7 | ||||
-rw-r--r-- | tests/parser.rs | 8 |
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) { | |||
74 | fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { | 74 | fn 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 | ||
16 | pub(crate) fn parse<'t>(text: &'t str, raw_tokens: &'t [Token]) -> Vec<Event> { | 19 | pub(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 | ||
16 | impl<'t> Parser<'t> { | 18 | impl<'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 | |||
116 | pub(crate) struct ErrorBuilder<'p, 't: 'p> { | ||
117 | message: Option<String>, | ||
118 | parser: &'p mut Parser<'t> | ||
119 | } | ||
120 | |||
121 | impl<'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 | } |