diff options
author | Aleksey Kladov <[email protected]> | 2018-02-11 13:53:57 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-02-11 13:53:57 +0000 |
commit | 9e2c0564783aa91f6440e7cadcc1a4dfda785de0 (patch) | |
tree | 4a6ef12405bf0562f4875b48cc1c834195ce7920 /src | |
parent | 7a0ada860b57acd44b1d53e944ae621e438652da (diff) |
Separate parser API from implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/parser/event.rs | 6 | ||||
-rw-r--r-- | src/parser/grammar/mod.rs | 3 | ||||
-rw-r--r-- | src/parser/mod.rs | 37 | ||||
-rw-r--r-- | src/parser/parser.rs | 193 | ||||
-rw-r--r-- | src/parser/parser/imp.rs | 118 | ||||
-rw-r--r-- | src/parser/parser/mod.rs | 100 | ||||
-rw-r--r-- | src/parser/token_set.rs | 25 | ||||
-rw-r--r-- | src/tree/file_builder.rs | 4 |
8 files changed, 254 insertions, 232 deletions
diff --git a/src/parser/event.rs b/src/parser/event.rs index 90348398e..30fe5c6d7 100644 --- a/src/parser/event.rs +++ b/src/parser/event.rs | |||
@@ -61,7 +61,7 @@ pub(crate) enum Event { | |||
61 | }, | 61 | }, |
62 | 62 | ||
63 | Error { | 63 | Error { |
64 | message: String, | 64 | msg: String, |
65 | }, | 65 | }, |
66 | } | 66 | } |
67 | 67 | ||
@@ -140,8 +140,8 @@ pub(super) fn to_file(text: String, tokens: &[Token], events: Vec<Event>) -> Fil | |||
140 | } | 140 | } |
141 | builder.leaf(kind, len); | 141 | builder.leaf(kind, len); |
142 | } | 142 | } |
143 | &Event::Error { ref message } => builder.error(ErrorMsg { | 143 | &Event::Error { ref msg } => builder.error(ErrorMsg { |
144 | message: message.clone(), | 144 | msg: msg.clone(), |
145 | }), | 145 | }), |
146 | } | 146 | } |
147 | } | 147 | } |
diff --git a/src/parser/grammar/mod.rs b/src/parser/grammar/mod.rs index f5b63aaab..e29cf9b02 100644 --- a/src/parser/grammar/mod.rs +++ b/src/parser/grammar/mod.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | use super::parser::{Parser, TokenSet}; | 1 | use parser::parser::{Parser}; |
2 | use parser::token_set::TokenSet; | ||
2 | use SyntaxKind; | 3 | use SyntaxKind; |
3 | use syntax_kinds::*; | 4 | use syntax_kinds::*; |
4 | 5 | ||
diff --git a/src/parser/mod.rs b/src/parser/mod.rs index c23ed3349..3814837e1 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs | |||
@@ -3,19 +3,20 @@ use {File, SyntaxKind, Token}; | |||
3 | use syntax_kinds::*; | 3 | use syntax_kinds::*; |
4 | 4 | ||
5 | #[macro_use] | 5 | #[macro_use] |
6 | mod token_set; | ||
6 | mod parser; | 7 | mod parser; |
7 | mod input; | 8 | mod input; |
8 | mod event; | 9 | mod event; |
9 | mod grammar; | 10 | mod grammar; |
10 | use self::event::Event; | ||
11 | 11 | ||
12 | /// Parse a sequence of tokens into the representative node tree | 12 | /// Parse a sequence of tokens into the representative node tree |
13 | pub fn parse(text: String, tokens: &[Token]) -> File { | 13 | pub fn parse(text: String, tokens: &[Token]) -> File { |
14 | let events = { | 14 | let events = { |
15 | let input = input::ParserInput::new(&text, tokens); | 15 | let input = input::ParserInput::new(&text, tokens); |
16 | let mut parser = parser::Parser::new(&input); | 16 | let parser_impl = parser::imp::ParserImpl::new(&input); |
17 | let mut parser = parser::Parser(parser_impl); | ||
17 | grammar::file(&mut parser); | 18 | grammar::file(&mut parser); |
18 | parser.into_events() | 19 | parser.0.into_events() |
19 | }; | 20 | }; |
20 | event::to_file(text, tokens, events) | 21 | event::to_file(text, tokens, events) |
21 | } | 22 | } |
@@ -26,33 +27,3 @@ fn is_insignificant(kind: SyntaxKind) -> bool { | |||
26 | _ => false, | 27 | _ => false, |
27 | } | 28 | } |
28 | } | 29 | } |
29 | |||
30 | impl<'p> parser::Parser<'p> { | ||
31 | fn at(&self, kind: SyntaxKind) -> bool { | ||
32 | self.current() == kind | ||
33 | } | ||
34 | |||
35 | fn err_and_bump(&mut self, message: &str) { | ||
36 | let err = self.start(); | ||
37 | self.error(message); | ||
38 | self.bump(); | ||
39 | err.complete(self, ERROR); | ||
40 | } | ||
41 | |||
42 | fn expect(&mut self, kind: SyntaxKind) -> bool { | ||
43 | if self.at(kind) { | ||
44 | self.bump(); | ||
45 | true | ||
46 | } else { | ||
47 | self.error(format!("expected {:?}", kind)); | ||
48 | false | ||
49 | } | ||
50 | } | ||
51 | |||
52 | fn eat(&mut self, kind: SyntaxKind) -> bool { | ||
53 | self.at(kind) && { | ||
54 | self.bump(); | ||
55 | true | ||
56 | } | ||
57 | } | ||
58 | } | ||
diff --git a/src/parser/parser.rs b/src/parser/parser.rs deleted file mode 100644 index 7c8e47cb6..000000000 --- a/src/parser/parser.rs +++ /dev/null | |||
@@ -1,193 +0,0 @@ | |||
1 | use super::Event; | ||
2 | use super::input::{InputPosition, ParserInput}; | ||
3 | use SyntaxKind::{self, EOF, TOMBSTONE}; | ||
4 | |||
5 | pub(crate) struct Marker { | ||
6 | pos: u32, | ||
7 | } | ||
8 | |||
9 | impl Marker { | ||
10 | pub fn complete(self, p: &mut Parser, kind: SyntaxKind) -> CompleteMarker { | ||
11 | match self.event(p) { | ||
12 | &mut Event::Start { | ||
13 | kind: ref mut slot, .. | ||
14 | } => { | ||
15 | *slot = kind; | ||
16 | } | ||
17 | _ => unreachable!(), | ||
18 | } | ||
19 | p.event(Event::Finish); | ||
20 | let result = CompleteMarker { pos: self.pos }; | ||
21 | ::std::mem::forget(self); | ||
22 | result | ||
23 | } | ||
24 | |||
25 | pub fn abandon(self, p: &mut Parser) { | ||
26 | let idx = self.pos as usize; | ||
27 | if idx == p.events.len() - 1 { | ||
28 | match p.events.pop() { | ||
29 | Some(Event::Start { | ||
30 | kind: TOMBSTONE, | ||
31 | forward_parent: None, | ||
32 | }) => (), | ||
33 | _ => unreachable!(), | ||
34 | } | ||
35 | } | ||
36 | ::std::mem::forget(self); | ||
37 | } | ||
38 | |||
39 | fn event<'p>(&self, p: &'p mut Parser) -> &'p mut Event { | ||
40 | &mut p.events[self.idx()] | ||
41 | } | ||
42 | |||
43 | fn idx(&self) -> usize { | ||
44 | self.pos as usize | ||
45 | } | ||
46 | } | ||
47 | |||
48 | impl Drop for Marker { | ||
49 | fn drop(&mut self) { | ||
50 | if !::std::thread::panicking() { | ||
51 | panic!("Each marker should be eithe completed or abandoned"); | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | pub(crate) struct CompleteMarker { | ||
57 | pos: u32, | ||
58 | } | ||
59 | |||
60 | impl CompleteMarker { | ||
61 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { | ||
62 | let m = p.start(); | ||
63 | match p.events[self.pos as usize] { | ||
64 | Event::Start { | ||
65 | ref mut forward_parent, | ||
66 | .. | ||
67 | } => { | ||
68 | *forward_parent = Some(m.pos - self.pos); | ||
69 | } | ||
70 | _ => unreachable!(), | ||
71 | } | ||
72 | m | ||
73 | } | ||
74 | } | ||
75 | |||
76 | pub(crate) struct TokenSet { | ||
77 | pub tokens: &'static [SyntaxKind], | ||
78 | } | ||
79 | |||
80 | impl TokenSet { | ||
81 | pub fn contains(&self, kind: SyntaxKind) -> bool { | ||
82 | self.tokens.contains(&kind) | ||
83 | } | ||
84 | } | ||
85 | |||
86 | #[macro_export] | ||
87 | macro_rules! token_set { | ||
88 | ($($t:ident),*) => { | ||
89 | TokenSet { | ||
90 | tokens: &[$($t),*], | ||
91 | } | ||
92 | }; | ||
93 | |||
94 | ($($t:ident),* ,) => { | ||
95 | token_set!($($t),*) | ||
96 | }; | ||
97 | } | ||
98 | |||
99 | pub(crate) struct Parser<'t> { | ||
100 | inp: &'t ParserInput<'t>, | ||
101 | |||
102 | pos: InputPosition, | ||
103 | events: Vec<Event>, | ||
104 | } | ||
105 | |||
106 | impl<'t> Parser<'t> { | ||
107 | pub(crate) fn new(inp: &'t ParserInput<'t>) -> Parser<'t> { | ||
108 | Parser { | ||
109 | inp, | ||
110 | |||
111 | pos: InputPosition::new(), | ||
112 | events: Vec::new(), | ||
113 | } | ||
114 | } | ||
115 | |||
116 | pub(crate) fn into_events(self) -> Vec<Event> { | ||
117 | assert_eq!(self.current(), EOF); | ||
118 | self.events | ||
119 | } | ||
120 | |||
121 | pub(crate) fn start(&mut self) -> Marker { | ||
122 | let m = Marker { | ||
123 | pos: self.events.len() as u32, | ||
124 | }; | ||
125 | self.event(Event::Start { | ||
126 | kind: TOMBSTONE, | ||
127 | forward_parent: None, | ||
128 | }); | ||
129 | m | ||
130 | } | ||
131 | |||
132 | pub(crate) fn error<'p, T: Into<String>>(&'p mut self, msg: T) -> ErrorBuilder<'p, 't> { | ||
133 | ErrorBuilder::new(self, msg.into()) | ||
134 | } | ||
135 | |||
136 | pub(crate) fn bump(&mut self) { | ||
137 | let kind = self.current(); | ||
138 | if kind == EOF { | ||
139 | return; | ||
140 | } | ||
141 | self.pos += 1; | ||
142 | self.event(Event::Token { | ||
143 | kind, | ||
144 | n_raw_tokens: 1, | ||
145 | }); | ||
146 | } | ||
147 | |||
148 | pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) { | ||
149 | if self.current() == EOF { | ||
150 | // TODO: panic!? | ||
151 | return; | ||
152 | } | ||
153 | self.pos += 1; | ||
154 | self.event(Event::Token { | ||
155 | kind, | ||
156 | n_raw_tokens: 1, | ||
157 | }); | ||
158 | } | ||
159 | |||
160 | pub(crate) fn nth(&self, n: u32) -> SyntaxKind { | ||
161 | self.inp.kind(self.pos + n) | ||
162 | } | ||
163 | |||
164 | pub(crate) fn at_kw(&self, t: &str) -> bool { | ||
165 | self.inp.text(self.pos) == t | ||
166 | } | ||
167 | |||
168 | pub(crate) fn current(&self) -> SyntaxKind { | ||
169 | self.nth(0) | ||
170 | } | ||
171 | |||
172 | fn event(&mut self, event: Event) { | ||
173 | self.events.push(event) | ||
174 | } | ||
175 | } | ||
176 | |||
177 | pub(crate) struct ErrorBuilder<'p, 't: 'p> { | ||
178 | message: String, | ||
179 | parser: &'p mut Parser<'t>, | ||
180 | } | ||
181 | |||
182 | impl<'p, 't: 'p> Drop for ErrorBuilder<'p, 't> { | ||
183 | fn drop(&mut self) { | ||
184 | let message = ::std::mem::replace(&mut self.message, String::new()); | ||
185 | self.parser.event(Event::Error { message }); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | impl<'t, 'p> ErrorBuilder<'p, 't> { | ||
190 | fn new(parser: &'p mut Parser<'t>, message: String) -> Self { | ||
191 | ErrorBuilder { message, parser } | ||
192 | } | ||
193 | } | ||
diff --git a/src/parser/parser/imp.rs b/src/parser/parser/imp.rs new file mode 100644 index 000000000..2b16e11b9 --- /dev/null +++ b/src/parser/parser/imp.rs | |||
@@ -0,0 +1,118 @@ | |||
1 | use parser::input::{ParserInput, InputPosition}; | ||
2 | use parser::event::Event; | ||
3 | |||
4 | use SyntaxKind; | ||
5 | use syntax_kinds::{TOMBSTONE, EOF}; | ||
6 | |||
7 | pub(crate) struct ParserImpl<'t> { | ||
8 | inp: &'t ParserInput<'t>, | ||
9 | |||
10 | pos: InputPosition, | ||
11 | events: Vec<Event>, | ||
12 | } | ||
13 | |||
14 | impl<'t> ParserImpl<'t> { | ||
15 | pub(crate) fn new(inp: &'t ParserInput<'t>) -> ParserImpl<'t> { | ||
16 | ParserImpl { | ||
17 | inp, | ||
18 | |||
19 | pos: InputPosition::new(), | ||
20 | events: Vec::new(), | ||
21 | } | ||
22 | } | ||
23 | |||
24 | pub(crate) fn into_events(self) -> Vec<Event> { | ||
25 | assert_eq!(self.nth(0), EOF); | ||
26 | self.events | ||
27 | } | ||
28 | |||
29 | |||
30 | pub(super) fn nth(&self, n: u32) -> SyntaxKind { | ||
31 | self.inp.kind(self.pos + n) | ||
32 | } | ||
33 | |||
34 | pub(super) fn at_kw(&self, t: &str) -> bool { | ||
35 | self.inp.text(self.pos) == t | ||
36 | } | ||
37 | |||
38 | pub(super) fn start(&mut self) -> u32 { | ||
39 | let pos = self.events.len() as u32; | ||
40 | self.event(Event::Start { | ||
41 | kind: TOMBSTONE, | ||
42 | forward_parent: None, | ||
43 | }); | ||
44 | pos | ||
45 | } | ||
46 | |||
47 | pub(super) fn bump(&mut self) { | ||
48 | let kind = self.nth(0); | ||
49 | if kind == EOF { | ||
50 | return; | ||
51 | } | ||
52 | self.do_bump(kind); | ||
53 | } | ||
54 | |||
55 | pub(super) fn bump_remap(&mut self, kind: SyntaxKind) { | ||
56 | if self.nth(0) == EOF { | ||
57 | // TODO: panic!? | ||
58 | return; | ||
59 | } | ||
60 | self.do_bump(kind); | ||
61 | } | ||
62 | |||
63 | fn do_bump(&mut self, kind: SyntaxKind) { | ||
64 | self.pos += 1; | ||
65 | self.event(Event::Token { | ||
66 | kind, | ||
67 | n_raw_tokens: 1, | ||
68 | }); | ||
69 | } | ||
70 | |||
71 | pub(super) fn error(&mut self, msg: String) { | ||
72 | self.event(Event::Error { msg }) | ||
73 | } | ||
74 | |||
75 | pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) { | ||
76 | match self.events[pos as usize] { | ||
77 | Event::Start { | ||
78 | kind: ref mut slot, .. | ||
79 | } => { | ||
80 | *slot = kind; | ||
81 | } | ||
82 | _ => unreachable!(), | ||
83 | } | ||
84 | self.event(Event::Finish); | ||
85 | } | ||
86 | |||
87 | pub(super) fn abandon(&mut self, pos: u32) { | ||
88 | let idx = pos as usize; | ||
89 | if idx == self.events.len() - 1 { | ||
90 | match self.events.pop() { | ||
91 | Some(Event::Start { | ||
92 | kind: TOMBSTONE, | ||
93 | forward_parent: None, | ||
94 | }) => (), | ||
95 | _ => unreachable!(), | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | pub(super) fn precede(&mut self, pos: u32) -> u32 { | ||
101 | let new_pos = self.start(); | ||
102 | match self.events[pos as usize] { | ||
103 | Event::Start { | ||
104 | ref mut forward_parent, | ||
105 | .. | ||
106 | } => { | ||
107 | *forward_parent = Some(new_pos - pos); | ||
108 | } | ||
109 | _ => unreachable!(), | ||
110 | } | ||
111 | new_pos | ||
112 | } | ||
113 | |||
114 | |||
115 | fn event(&mut self, event: Event) { | ||
116 | self.events.push(event) | ||
117 | } | ||
118 | } | ||
diff --git a/src/parser/parser/mod.rs b/src/parser/parser/mod.rs new file mode 100644 index 000000000..c8db20918 --- /dev/null +++ b/src/parser/parser/mod.rs | |||
@@ -0,0 +1,100 @@ | |||
1 | use SyntaxKind; | ||
2 | use syntax_kinds::ERROR; | ||
3 | |||
4 | pub(super) mod imp; | ||
5 | use self::imp::ParserImpl; | ||
6 | |||
7 | pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>); | ||
8 | |||
9 | |||
10 | impl<'t> Parser<'t> { | ||
11 | pub(crate) fn current(&self) -> SyntaxKind { | ||
12 | self.nth(0) | ||
13 | } | ||
14 | |||
15 | pub(crate) fn nth(&self, n: u32) -> SyntaxKind { | ||
16 | self.0.nth(n) | ||
17 | } | ||
18 | |||
19 | pub(crate) fn at(&self, kind: SyntaxKind) -> bool { | ||
20 | self.current() == kind | ||
21 | } | ||
22 | |||
23 | pub(crate) fn at_kw(&self, t: &str) -> bool { | ||
24 | self.0.at_kw(t) | ||
25 | } | ||
26 | |||
27 | pub(crate) fn start(&mut self) -> Marker { | ||
28 | Marker(self.0.start()) | ||
29 | } | ||
30 | |||
31 | pub(crate) fn bump(&mut self) { | ||
32 | self.0.bump(); | ||
33 | } | ||
34 | |||
35 | pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) { | ||
36 | self.0.bump_remap(kind); | ||
37 | } | ||
38 | |||
39 | pub(crate) fn error<T: Into<String>>(&mut self, message: T) { | ||
40 | self.0.error(message.into()) | ||
41 | } | ||
42 | |||
43 | pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { | ||
44 | if self.at(kind) { | ||
45 | self.bump(); | ||
46 | return true; | ||
47 | } | ||
48 | self.error(format!("expected {:?}", kind)); | ||
49 | false | ||
50 | } | ||
51 | |||
52 | pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool { | ||
53 | if !self.at(kind) { | ||
54 | return false; | ||
55 | } | ||
56 | self.bump(); | ||
57 | true | ||
58 | } | ||
59 | |||
60 | pub(crate) fn err_and_bump(&mut self, message: &str) { | ||
61 | let m = self.start(); | ||
62 | self.error(message); | ||
63 | self.bump(); | ||
64 | m.complete(self, ERROR); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | pub(crate) struct Marker(u32); | ||
69 | |||
70 | impl Marker { | ||
71 | pub(crate) fn complete(self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { | ||
72 | let pos = self.0; | ||
73 | ::std::mem::forget(self); | ||
74 | p.0.complete(pos, kind); | ||
75 | CompletedMarker(pos) | ||
76 | } | ||
77 | |||
78 | pub(crate) fn abandon(self, p: &mut Parser) { | ||
79 | let pos = self.0; | ||
80 | ::std::mem::forget(self); | ||
81 | p.0.abandon(pos); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | impl Drop for Marker { | ||
86 | fn drop(&mut self) { | ||
87 | if !::std::thread::panicking() { | ||
88 | panic!("Marker must be either completed or abandoned"); | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | |||
94 | pub(crate) struct CompletedMarker(u32); | ||
95 | |||
96 | impl CompletedMarker { | ||
97 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { | ||
98 | Marker(p.0.precede(self.0)) | ||
99 | } | ||
100 | } | ||
diff --git a/src/parser/token_set.rs b/src/parser/token_set.rs new file mode 100644 index 000000000..82558fa2e --- /dev/null +++ b/src/parser/token_set.rs | |||
@@ -0,0 +1,25 @@ | |||
1 | use SyntaxKind; | ||
2 | |||
3 | pub(crate) struct TokenSet { | ||
4 | pub tokens: &'static [SyntaxKind], | ||
5 | } | ||
6 | |||
7 | impl TokenSet { | ||
8 | pub fn contains(&self, kind: SyntaxKind) -> bool { | ||
9 | self.tokens.contains(&kind) | ||
10 | } | ||
11 | } | ||
12 | |||
13 | #[macro_export] | ||
14 | macro_rules! token_set { | ||
15 | ($($t:ident),*) => { | ||
16 | TokenSet { | ||
17 | tokens: &[$($t),*], | ||
18 | } | ||
19 | }; | ||
20 | |||
21 | ($($t:ident),* ,) => { | ||
22 | token_set!($($t),*) | ||
23 | }; | ||
24 | } | ||
25 | |||
diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs index 3c7e2d7cf..f831676c7 100644 --- a/src/tree/file_builder.rs +++ b/src/tree/file_builder.rs | |||
@@ -70,7 +70,7 @@ impl Sink for FileBuilder { | |||
70 | let &(node, after_child) = self.in_progress.last().unwrap(); | 70 | let &(node, after_child) = self.in_progress.last().unwrap(); |
71 | self.errors.push(SyntaxErrorData { | 71 | self.errors.push(SyntaxErrorData { |
72 | node, | 72 | node, |
73 | message: err.message, | 73 | message: err.msg, |
74 | after_child, | 74 | after_child, |
75 | }) | 75 | }) |
76 | } | 76 | } |
@@ -157,5 +157,5 @@ fn grow(left: &mut TextRange, right: TextRange) { | |||
157 | 157 | ||
158 | #[derive(Default)] | 158 | #[derive(Default)] |
159 | pub(crate) struct ErrorMsg { | 159 | pub(crate) struct ErrorMsg { |
160 | pub(crate) message: String, | 160 | pub(crate) msg: String, |
161 | } | 161 | } |