aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/parser.rs')
-rw-r--r--crates/ra_parser/src/parser.rs267
1 files changed, 267 insertions, 0 deletions
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
new file mode 100644
index 000000000..a18458148
--- /dev/null
+++ b/crates/ra_parser/src/parser.rs
@@ -0,0 +1,267 @@
1use std::cell::Cell;
2
3use drop_bomb::DropBomb;
4
5use crate::{
6 SyntaxKind::{self, ERROR, EOF, TOMBSTONE},
7 TokenSource, ParseError, TokenSet,
8 event::Event,
9};
10
11/// `Parser` struct provides the low-level API for
12/// navigating through the stream of tokens and
13/// constructing the parse tree. The actual parsing
14/// happens in the `grammar` module.
15///
16/// However, the result of this `Parser` is not a real
17/// tree, but rather a flat stream of events of the form
18/// "start expression, consume number literal,
19/// finish expression". See `Event` docs for more.
20pub(crate) struct Parser<'t> {
21 token_source: &'t dyn TokenSource,
22 token_pos: usize,
23 events: Vec<Event>,
24 steps: Cell<u32>,
25}
26
27impl<'t> Parser<'t> {
28 pub(super) fn new(token_source: &'t dyn TokenSource) -> Parser<'t> {
29 Parser { token_source, token_pos: 0, events: Vec::new(), steps: Cell::new(0) }
30 }
31
32 pub(crate) fn finish(self) -> Vec<Event> {
33 self.events
34 }
35
36 /// Returns the kind of the current token.
37 /// If parser has already reached the end of input,
38 /// the special `EOF` kind is returned.
39 pub(crate) fn current(&self) -> SyntaxKind {
40 self.nth(0)
41 }
42
43 /// Returns the kinds of the current two tokens, if they are not separated
44 /// by trivia.
45 ///
46 /// Useful for parsing things like `>>`.
47 pub(crate) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> {
48 let c1 = self.token_source.token_kind(self.token_pos);
49 let c2 = self.token_source.token_kind(self.token_pos + 1);
50 if self.token_source.is_token_joint_to_next(self.token_pos) {
51 Some((c1, c2))
52 } else {
53 None
54 }
55 }
56
57 /// Returns the kinds of the current three tokens, if they are not separated
58 /// by trivia.
59 ///
60 /// Useful for parsing things like `=>>`.
61 pub(crate) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> {
62 let c1 = self.token_source.token_kind(self.token_pos);
63 let c2 = self.token_source.token_kind(self.token_pos + 1);
64 let c3 = self.token_source.token_kind(self.token_pos + 2);
65 if self.token_source.is_token_joint_to_next(self.token_pos)
66 && self.token_source.is_token_joint_to_next(self.token_pos + 1)
67 {
68 Some((c1, c2, c3))
69 } else {
70 None
71 }
72 }
73
74 /// Lookahead operation: returns the kind of the next nth
75 /// token.
76 pub(crate) fn nth(&self, n: usize) -> SyntaxKind {
77 let steps = self.steps.get();
78 assert!(steps <= 10_000_000, "the parser seems stuck");
79 self.steps.set(steps + 1);
80 self.token_source.token_kind(self.token_pos + n)
81 }
82
83 /// Checks if the current token is `kind`.
84 pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
85 self.current() == kind
86 }
87
88 /// Checks if the current token is in `kinds`.
89 pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool {
90 kinds.contains(self.current())
91 }
92
93 /// Checks if the current token is contextual keyword with text `t`.
94 pub(crate) fn at_contextual_kw(&self, kw: &str) -> bool {
95 self.token_source.is_keyword(self.token_pos, kw)
96 }
97
98 /// Starts a new node in the syntax tree. All nodes and tokens
99 /// consumed between the `start` and the corresponding `Marker::complete`
100 /// belong to the same node.
101 pub(crate) fn start(&mut self) -> Marker {
102 let pos = self.events.len() as u32;
103 self.push_event(Event::tombstone());
104 Marker::new(pos)
105 }
106
107 /// Advances the parser by one token unconditionally.
108 pub(crate) fn bump(&mut self) {
109 let kind = self.nth(0);
110 if kind == EOF {
111 return;
112 }
113 self.do_bump(kind, 1);
114 }
115
116 /// Advances the parser by one token, remapping its kind.
117 /// This is useful to create contextual keywords from
118 /// identifiers. For example, the lexer creates an `union`
119 /// *identifier* token, but the parser remaps it to the
120 /// `union` keyword, and keyword is what ends up in the
121 /// final tree.
122 pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
123 if self.nth(0) == EOF {
124 // TODO: panic!?
125 return;
126 }
127 self.do_bump(kind, 1);
128 }
129
130 /// Advances the parser by `n` tokens, remapping its kind.
131 /// This is useful to create compound tokens from parts. For
132 /// example, an `<<` token is two consecutive remapped `<` tokens
133 pub(crate) fn bump_compound(&mut self, kind: SyntaxKind, n: u8) {
134 self.do_bump(kind, n);
135 }
136
137 /// Emit error with the `message`
138 /// TODO: this should be much more fancy and support
139 /// structured errors with spans and notes, like rustc
140 /// does.
141 pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
142 let msg = ParseError(message.into());
143 self.push_event(Event::Error { msg })
144 }
145
146 /// Consume the next token if `kind` matches.
147 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
148 if !self.at(kind) {
149 return false;
150 }
151 self.bump();
152 true
153 }
154
155 /// Consume the next token if it is `kind` or emit an error
156 /// otherwise.
157 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
158 if self.eat(kind) {
159 return true;
160 }
161 self.error(format!("expected {:?}", kind));
162 false
163 }
164
165 /// Create an error node and consume the next token.
166 pub(crate) fn err_and_bump(&mut self, message: &str) {
167 self.err_recover(message, TokenSet::empty());
168 }
169
170 /// Create an error node and consume the next token.
171 pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
172 if self.at(SyntaxKind::L_CURLY) || self.at(SyntaxKind::R_CURLY) || self.at_ts(recovery) {
173 self.error(message);
174 } else {
175 let m = self.start();
176 self.error(message);
177 self.bump();
178 m.complete(self, ERROR);
179 };
180 }
181
182 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) {
183 self.token_pos += usize::from(n_raw_tokens);
184 self.push_event(Event::Token { kind, n_raw_tokens });
185 }
186
187 fn push_event(&mut self, event: Event) {
188 self.events.push(event)
189 }
190}
191
192/// See `Parser::start`.
193pub(crate) struct Marker {
194 pos: u32,
195 bomb: DropBomb,
196}
197
198impl Marker {
199 fn new(pos: u32) -> Marker {
200 Marker { pos, bomb: DropBomb::new("Marker must be either completed or abandoned") }
201 }
202
203 /// Finishes the syntax tree node and assigns `kind` to it,
204 /// and mark the create a `CompletedMarker` for possible future
205 /// operation like `.precede()` to deal with forward_parent.
206 pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
207 self.bomb.defuse();
208 let idx = self.pos as usize;
209 match p.events[idx] {
210 Event::Start { kind: ref mut slot, .. } => {
211 *slot = kind;
212 }
213 _ => unreachable!(),
214 }
215 p.push_event(Event::Finish);
216 CompletedMarker::new(self.pos, kind)
217 }
218
219 /// Abandons the syntax tree node. All its children
220 /// are attached to its parent instead.
221 pub(crate) fn abandon(mut self, p: &mut Parser) {
222 self.bomb.defuse();
223 let idx = self.pos as usize;
224 if idx == p.events.len() - 1 {
225 match p.events.pop() {
226 Some(Event::Start { kind: TOMBSTONE, forward_parent: None }) => (),
227 _ => unreachable!(),
228 }
229 }
230 }
231}
232
233pub(crate) struct CompletedMarker(u32, SyntaxKind);
234
235impl CompletedMarker {
236 fn new(pos: u32, kind: SyntaxKind) -> Self {
237 CompletedMarker(pos, kind)
238 }
239
240 /// This method allows to create a new node which starts
241 /// *before* the current one. That is, parser could start
242 /// node `A`, then complete it, and then after parsing the
243 /// whole `A`, decide that it should have started some node
244 /// `B` before starting `A`. `precede` allows to do exactly
245 /// that. See also docs about `forward_parent` in `Event::Start`.
246 ///
247 /// Given completed events `[START, FINISH]` and its corresponding
248 /// `CompletedMarker(pos: 0, _)`.
249 /// Append a new `START` events as `[START, FINISH, NEWSTART]`,
250 /// then mark `NEWSTART` as `START`'s parent with saving its relative
251 /// distance to `NEWSTART` into forward_parent(=2 in this case);
252 pub(crate) fn precede(self, p: &mut Parser) -> Marker {
253 let new_pos = p.start();
254 let idx = self.0 as usize;
255 match p.events[idx] {
256 Event::Start { ref mut forward_parent, .. } => {
257 *forward_parent = Some(new_pos.pos - self.0);
258 }
259 _ => unreachable!(),
260 }
261 new_pos
262 }
263
264 pub(crate) fn kind(&self) -> SyntaxKind {
265 self.1
266 }
267}