aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/parsing/parser_api.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/parsing/parser_api.rs')
-rw-r--r--crates/ra_syntax/src/parsing/parser_api.rs108
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 @@
1use std::cell::Cell;
2
1use drop_bomb::DropBomb; 3use drop_bomb::DropBomb;
2 4
3use crate::{ 5use 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.
20pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>); 24pub(crate) struct Parser<'t> {
25 token_source: &'t dyn TokenSource,
26 pos: TokenPos,
27 events: Vec<Event>,
28 steps: Cell<u32>,
29}
21 30
22impl<'t> Parser<'t> { 31impl<'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 {