diff options
author | Aleksey Kladov <[email protected]> | 2019-02-20 19:44:06 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-02-20 19:44:06 +0000 |
commit | 2acb21e8f72896c7a2855ca6042d0ee1870d8643 (patch) | |
tree | 7c297534569dcf2b69d6e7af9032318aa7c8cc23 /crates/ra_syntax/src/parsing/parser_api.rs | |
parent | e72ad0a2faac98972544dd42316ccf8090717102 (diff) |
merge parse_impl and parser_api
Diffstat (limited to 'crates/ra_syntax/src/parsing/parser_api.rs')
-rw-r--r-- | crates/ra_syntax/src/parsing/parser_api.rs | 108 |
1 files changed, 92 insertions, 16 deletions
diff --git a/crates/ra_syntax/src/parsing/parser_api.rs b/crates/ra_syntax/src/parsing/parser_api.rs index aed23a6a4..92d7895d3 100644 --- a/crates/ra_syntax/src/parsing/parser_api.rs +++ b/crates/ra_syntax/src/parsing/parser_api.rs | |||
@@ -1,10 +1,14 @@ | |||
1 | use std::cell::Cell; | ||
2 | |||
1 | use drop_bomb::DropBomb; | 3 | use drop_bomb::DropBomb; |
2 | 4 | ||
3 | use crate::{ | 5 | use crate::{ |
4 | SyntaxKind::{self, ERROR}, | 6 | syntax_error::ParseError, |
7 | SyntaxKind::{self, ERROR, EOF, TOMBSTONE}, | ||
5 | parsing::{ | 8 | parsing::{ |
9 | TokenSource, TokenPos, | ||
6 | token_set::TokenSet, | 10 | token_set::TokenSet, |
7 | parser_impl::ParserImpl, | 11 | parser_impl::event::Event, |
8 | }, | 12 | }, |
9 | }; | 13 | }; |
10 | 14 | ||
@@ -17,9 +21,22 @@ use crate::{ | |||
17 | /// tree, but rather a flat stream of events of the form | 21 | /// tree, but rather a flat stream of events of the form |
18 | /// "start expression, consume number literal, | 22 | /// "start expression, consume number literal, |
19 | /// finish expression". See `Event` docs for more. | 23 | /// finish expression". See `Event` docs for more. |
20 | pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>); | 24 | pub(crate) struct Parser<'t> { |
25 | token_source: &'t dyn TokenSource, | ||
26 | pos: TokenPos, | ||
27 | events: Vec<Event>, | ||
28 | steps: Cell<u32>, | ||
29 | } | ||
21 | 30 | ||
22 | impl<'t> Parser<'t> { | 31 | impl<'t> Parser<'t> { |
32 | pub(super) fn new(token_source: &'t dyn TokenSource) -> Parser<'t> { | ||
33 | Parser { token_source, pos: TokenPos::default(), events: Vec::new(), steps: Cell::new(0) } | ||
34 | } | ||
35 | |||
36 | pub(crate) fn finish(self) -> Vec<Event> { | ||
37 | self.events | ||
38 | } | ||
39 | |||
23 | /// Returns the kind of the current token. | 40 | /// Returns the kind of the current token. |
24 | /// If parser has already reached the end of input, | 41 | /// If parser has already reached the end of input, |
25 | /// the special `EOF` kind is returned. | 42 | /// the special `EOF` kind is returned. |
@@ -32,7 +49,13 @@ impl<'t> Parser<'t> { | |||
32 | /// | 49 | /// |
33 | /// Useful for parsing things like `>>`. | 50 | /// Useful for parsing things like `>>`. |
34 | pub(crate) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> { | 51 | pub(crate) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> { |
35 | self.0.current2() | 52 | let c1 = self.token_source.token_kind(self.pos); |
53 | let c2 = self.token_source.token_kind(self.pos + 1); | ||
54 | if self.token_source.is_token_joint_to_next(self.pos) { | ||
55 | Some((c1, c2)) | ||
56 | } else { | ||
57 | None | ||
58 | } | ||
36 | } | 59 | } |
37 | 60 | ||
38 | /// Returns the kinds of the current three tokens, if they are not separated | 61 | /// Returns the kinds of the current three tokens, if they are not separated |
@@ -40,13 +63,25 @@ impl<'t> Parser<'t> { | |||
40 | /// | 63 | /// |
41 | /// Useful for parsing things like `=>>`. | 64 | /// Useful for parsing things like `=>>`. |
42 | pub(crate) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> { | 65 | pub(crate) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> { |
43 | self.0.current3() | 66 | let c1 = self.token_source.token_kind(self.pos); |
67 | let c2 = self.token_source.token_kind(self.pos + 1); | ||
68 | let c3 = self.token_source.token_kind(self.pos + 2); | ||
69 | if self.token_source.is_token_joint_to_next(self.pos) | ||
70 | && self.token_source.is_token_joint_to_next(self.pos + 1) | ||
71 | { | ||
72 | Some((c1, c2, c3)) | ||
73 | } else { | ||
74 | None | ||
75 | } | ||
44 | } | 76 | } |
45 | 77 | ||
46 | /// Lookahead operation: returns the kind of the next nth | 78 | /// Lookahead operation: returns the kind of the next nth |
47 | /// token. | 79 | /// token. |
48 | pub(crate) fn nth(&self, n: u32) -> SyntaxKind { | 80 | pub(crate) fn nth(&self, n: u32) -> SyntaxKind { |
49 | self.0.nth(n) | 81 | let steps = self.steps.get(); |
82 | assert!(steps <= 10_000_000, "the parser seems stuck"); | ||
83 | self.steps.set(steps + 1); | ||
84 | self.token_source.token_kind(self.pos + n) | ||
50 | } | 85 | } |
51 | 86 | ||
52 | /// Checks if the current token is `kind`. | 87 | /// Checks if the current token is `kind`. |
@@ -60,20 +95,26 @@ impl<'t> Parser<'t> { | |||
60 | } | 95 | } |
61 | 96 | ||
62 | /// Checks if the current token is contextual keyword with text `t`. | 97 | /// Checks if the current token is contextual keyword with text `t`. |
63 | pub(crate) fn at_contextual_kw(&self, t: &str) -> bool { | 98 | pub(crate) fn at_contextual_kw(&self, kw: &str) -> bool { |
64 | self.0.at_kw(t) | 99 | self.token_source.is_keyword(self.pos, kw) |
65 | } | 100 | } |
66 | 101 | ||
67 | /// Starts a new node in the syntax tree. All nodes and tokens | 102 | /// Starts a new node in the syntax tree. All nodes and tokens |
68 | /// consumed between the `start` and the corresponding `Marker::complete` | 103 | /// consumed between the `start` and the corresponding `Marker::complete` |
69 | /// belong to the same node. | 104 | /// belong to the same node. |
70 | pub(crate) fn start(&mut self) -> Marker { | 105 | pub(crate) fn start(&mut self) -> Marker { |
71 | Marker::new(self.0.start()) | 106 | let pos = self.events.len() as u32; |
107 | self.push_event(Event::tombstone()); | ||
108 | Marker::new(pos) | ||
72 | } | 109 | } |
73 | 110 | ||
74 | /// Advances the parser by one token unconditionally. | 111 | /// Advances the parser by one token unconditionally. |
75 | pub(crate) fn bump(&mut self) { | 112 | pub(crate) fn bump(&mut self) { |
76 | self.0.bump(); | 113 | let kind = self.nth(0); |
114 | if kind == EOF { | ||
115 | return; | ||
116 | } | ||
117 | self.do_bump(kind, 1); | ||
77 | } | 118 | } |
78 | 119 | ||
79 | /// Advances the parser by one token, remapping its kind. | 120 | /// Advances the parser by one token, remapping its kind. |
@@ -83,14 +124,18 @@ impl<'t> Parser<'t> { | |||
83 | /// `union` keyword, and keyword is what ends up in the | 124 | /// `union` keyword, and keyword is what ends up in the |
84 | /// final tree. | 125 | /// final tree. |
85 | pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) { | 126 | pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) { |
86 | self.0.bump_remap(kind); | 127 | if self.nth(0) == EOF { |
128 | // TODO: panic!? | ||
129 | return; | ||
130 | } | ||
131 | self.do_bump(kind, 1); | ||
87 | } | 132 | } |
88 | 133 | ||
89 | /// Advances the parser by `n` tokens, remapping its kind. | 134 | /// Advances the parser by `n` tokens, remapping its kind. |
90 | /// This is useful to create compound tokens from parts. For | 135 | /// This is useful to create compound tokens from parts. For |
91 | /// example, an `<<` token is two consecutive remapped `<` tokens | 136 | /// example, an `<<` token is two consecutive remapped `<` tokens |
92 | pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) { | 137 | pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) { |
93 | self.0.bump_compound(kind, n); | 138 | self.do_bump(kind, n); |
94 | } | 139 | } |
95 | 140 | ||
96 | /// Emit error with the `message` | 141 | /// Emit error with the `message` |
@@ -98,7 +143,8 @@ impl<'t> Parser<'t> { | |||
98 | /// structured errors with spans and notes, like rustc | 143 | /// structured errors with spans and notes, like rustc |
99 | /// does. | 144 | /// does. |
100 | pub(crate) fn error<T: Into<String>>(&mut self, message: T) { | 145 | pub(crate) fn error<T: Into<String>>(&mut self, message: T) { |
101 | self.0.error(message.into()) | 146 | let msg = ParseError(message.into()); |
147 | self.push_event(Event::Error { msg }) | ||
102 | } | 148 | } |
103 | 149 | ||
104 | /// Consume the next token if `kind` matches. | 150 | /// Consume the next token if `kind` matches. |
@@ -136,6 +182,15 @@ impl<'t> Parser<'t> { | |||
136 | m.complete(self, ERROR); | 182 | m.complete(self, ERROR); |
137 | }; | 183 | }; |
138 | } | 184 | } |
185 | |||
186 | fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) { | ||
187 | self.pos += u32::from(n_raw_tokens); | ||
188 | self.push_event(Event::Token { kind, n_raw_tokens }); | ||
189 | } | ||
190 | |||
191 | fn push_event(&mut self, event: Event) { | ||
192 | self.events.push(event) | ||
193 | } | ||
139 | } | 194 | } |
140 | 195 | ||
141 | /// See `Parser::start`. | 196 | /// See `Parser::start`. |
@@ -154,7 +209,14 @@ impl Marker { | |||
154 | /// operation like `.precede()` to deal with forward_parent. | 209 | /// operation like `.precede()` to deal with forward_parent. |
155 | pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { | 210 | pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { |
156 | self.bomb.defuse(); | 211 | self.bomb.defuse(); |
157 | p.0.complete(self.pos, kind); | 212 | let idx = self.pos as usize; |
213 | match p.events[idx] { | ||
214 | Event::Start { kind: ref mut slot, .. } => { | ||
215 | *slot = kind; | ||
216 | } | ||
217 | _ => unreachable!(), | ||
218 | } | ||
219 | p.push_event(Event::Finish); | ||
158 | CompletedMarker::new(self.pos, kind) | 220 | CompletedMarker::new(self.pos, kind) |
159 | } | 221 | } |
160 | 222 | ||
@@ -162,7 +224,13 @@ impl Marker { | |||
162 | /// are attached to its parent instead. | 224 | /// are attached to its parent instead. |
163 | pub(crate) fn abandon(mut self, p: &mut Parser) { | 225 | pub(crate) fn abandon(mut self, p: &mut Parser) { |
164 | self.bomb.defuse(); | 226 | self.bomb.defuse(); |
165 | p.0.abandon(self.pos); | 227 | let idx = self.pos as usize; |
228 | if idx == p.events.len() - 1 { | ||
229 | match p.events.pop() { | ||
230 | Some(Event::Start { kind: TOMBSTONE, forward_parent: None }) => (), | ||
231 | _ => unreachable!(), | ||
232 | } | ||
233 | } | ||
166 | } | 234 | } |
167 | } | 235 | } |
168 | 236 | ||
@@ -186,7 +254,15 @@ impl CompletedMarker { | |||
186 | /// then mark `NEWSTART` as `START`'s parent with saving its relative | 254 | /// then mark `NEWSTART` as `START`'s parent with saving its relative |
187 | /// distance to `NEWSTART` into forward_parent(=2 in this case); | 255 | /// distance to `NEWSTART` into forward_parent(=2 in this case); |
188 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { | 256 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { |
189 | Marker::new(p.0.precede(self.0)) | 257 | let new_pos = p.start(); |
258 | let idx = self.0 as usize; | ||
259 | match p.events[idx] { | ||
260 | Event::Start { ref mut forward_parent, .. } => { | ||
261 | *forward_parent = Some(new_pos.pos - self.0); | ||
262 | } | ||
263 | _ => unreachable!(), | ||
264 | } | ||
265 | new_pos | ||
190 | } | 266 | } |
191 | 267 | ||
192 | pub(crate) fn kind(&self) -> SyntaxKind { | 268 | pub(crate) fn kind(&self) -> SyntaxKind { |