1use std::cell::Cell;
4
5use drop_bomb::DropBomb;
6
7use crate::{
8 Edition,
9 SyntaxKind::{self, EOF, ERROR, TOMBSTONE},
10 T, TokenSet,
11 event::Event,
12 input::Input,
13};
14
15pub(crate) struct Parser<'t> {
25 inp: &'t Input,
26 pos: usize,
27 events: Vec<Event>,
28 steps: Cell<u32>,
29}
30
31const PARSER_STEP_LIMIT: usize = if cfg!(debug_assertions) { 150_000 } else { 15_000_000 };
32
33impl<'t> Parser<'t> {
34 pub(super) fn new(inp: &'t Input) -> Parser<'t> {
35 Parser { inp, pos: 0, events: Vec::new(), steps: Cell::new(0) }
36 }
37
38 pub(crate) fn finish(self) -> Vec<Event> {
39 self.events
40 }
41
42 pub(crate) fn current(&self) -> SyntaxKind {
46 self.nth(0)
47 }
48
49 pub(crate) fn nth(&self, n: usize) -> SyntaxKind {
52 assert!(n <= 3);
53
54 let steps = self.steps.get();
55 assert!((steps as usize) < PARSER_STEP_LIMIT, "the parser seems stuck");
56 self.steps.set(steps + 1);
57
58 self.inp.kind(self.pos + n)
59 }
60
61 pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
63 self.nth_at(0, kind)
64 }
65
66 pub(crate) fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {
67 match kind {
68 T![-=] => self.at_composite2(n, T![-], T![=]),
69 T![->] => self.at_composite2(n, T![-], T![>]),
70 T![::] => self.at_composite2(n, T![:], T![:]),
71 T![!=] => self.at_composite2(n, T![!], T![=]),
72 T![..] => self.at_composite2(n, T![.], T![.]),
73 T![*=] => self.at_composite2(n, T![*], T![=]),
74 T![/=] => self.at_composite2(n, T![/], T![=]),
75 T![&&] => self.at_composite2(n, T![&], T![&]),
76 T![&=] => self.at_composite2(n, T![&], T![=]),
77 T![%=] => self.at_composite2(n, T![%], T![=]),
78 T![^=] => self.at_composite2(n, T![^], T![=]),
79 T![+=] => self.at_composite2(n, T![+], T![=]),
80 T![<<] => self.at_composite2(n, T![<], T![<]),
81 T![<=] => self.at_composite2(n, T![<], T![=]),
82 T![==] => self.at_composite2(n, T![=], T![=]),
83 T![=>] => self.at_composite2(n, T![=], T![>]),
84 T![>=] => self.at_composite2(n, T![>], T![=]),
85 T![>>] => self.at_composite2(n, T![>], T![>]),
86 T![|=] => self.at_composite2(n, T![|], T![=]),
87 T![||] => self.at_composite2(n, T![|], T![|]),
88
89 T![...] => self.at_composite3(n, T![.], T![.], T![.]),
90 T![..=] => self.at_composite3(n, T![.], T![.], T![=]),
91 T![<<=] => self.at_composite3(n, T![<], T![<], T![=]),
92 T![>>=] => self.at_composite3(n, T![>], T![>], T![=]),
93
94 _ => self.inp.kind(self.pos + n) == kind,
95 }
96 }
97
98 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
100 if !self.at(kind) {
101 return false;
102 }
103 let n_raw_tokens = match kind {
104 T![-=]
105 | T![->]
106 | T![::]
107 | T![!=]
108 | T![..]
109 | T![*=]
110 | T![/=]
111 | T![&&]
112 | T![&=]
113 | T![%=]
114 | T![^=]
115 | T![+=]
116 | T![<<]
117 | T![<=]
118 | T![==]
119 | T![=>]
120 | T![>=]
121 | T![>>]
122 | T![|=]
123 | T![||] => 2,
124
125 T![...] | T![..=] | T![<<=] | T![>>=] => 3,
126 _ => 1,
127 };
128 self.do_bump(kind, n_raw_tokens);
129 true
130 }
131
132 pub(crate) fn eat_contextual_kw(&mut self, kind: SyntaxKind) -> bool {
133 if !self.at_contextual_kw(kind) {
134 return false;
135 }
136 self.bump_remap(kind);
137 true
138 }
139
140 fn at_composite2(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind) -> bool {
141 self.inp.kind(self.pos + n) == k1
142 && self.inp.kind(self.pos + n + 1) == k2
143 && self.inp.is_joint(self.pos + n)
144 }
145
146 fn at_composite3(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind, k3: SyntaxKind) -> bool {
147 self.inp.kind(self.pos + n) == k1
148 && self.inp.kind(self.pos + n + 1) == k2
149 && self.inp.kind(self.pos + n + 2) == k3
150 && self.inp.is_joint(self.pos + n)
151 && self.inp.is_joint(self.pos + n + 1)
152 }
153
154 pub(crate) fn at_ts(&self, kinds: TokenSet) -> bool {
156 kinds.contains(self.current())
157 }
158
159 pub(crate) fn at_contextual_kw(&self, kw: SyntaxKind) -> bool {
161 self.inp.contextual_kind(self.pos) == kw
162 }
163
164 pub(crate) fn nth_at_contextual_kw(&self, n: usize, kw: SyntaxKind) -> bool {
166 self.inp.contextual_kind(self.pos + n) == kw
167 }
168
169 pub(crate) fn start(&mut self) -> Marker {
173 let pos = self.events.len() as u32;
174 self.push_event(Event::tombstone());
175 Marker::new(pos)
176 }
177
178 pub(crate) fn bump(&mut self, kind: SyntaxKind) {
180 assert!(self.eat(kind));
181 }
182
183 pub(crate) fn bump_any(&mut self) {
185 let kind = self.nth(0);
186 if kind == EOF {
187 return;
188 }
189 self.do_bump(kind, 1);
190 }
191
192 pub(crate) fn split_float(&mut self, mut marker: Marker) -> (bool, Marker) {
194 assert!(self.at(SyntaxKind::FLOAT_NUMBER));
195 let ends_in_dot = !self.inp.is_joint(self.pos);
203 if !ends_in_dot {
204 let new_marker = self.start();
205 let idx = marker.pos as usize;
206 match &mut self.events[idx] {
207 Event::Start { forward_parent, kind } => {
208 *kind = SyntaxKind::FIELD_EXPR;
209 *forward_parent = Some(new_marker.pos - marker.pos);
210 }
211 _ => unreachable!(),
212 }
213 marker.bomb.defuse();
214 marker = new_marker;
215 };
216 self.pos += 1;
217 self.push_event(Event::FloatSplitHack { ends_in_dot });
218 (ends_in_dot, marker)
219 }
220
221 pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
228 if self.nth(0) == EOF {
229 return;
231 }
232 self.do_bump(kind, 1);
233 }
234
235 pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
240 let msg = message.into();
241 self.push_event(Event::Error { msg });
242 }
243
244 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
247 if self.eat(kind) {
248 return true;
249 }
250 self.error(format!("expected {kind:?}"));
251 false
252 }
253
254 pub(crate) fn err_and_bump(&mut self, message: &str) {
256 let m = self.start();
257 self.error(message);
258 self.bump_any();
259 m.complete(self, ERROR);
260 }
261
262 pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) -> bool {
266 if matches!(self.current(), T!['{'] | T!['}']) {
267 self.error(message);
268 return true;
269 }
270
271 if self.at_ts(recovery) {
272 self.error(message);
273 return true;
274 }
275
276 let m = self.start();
277 self.error(message);
278 self.bump_any();
279 m.complete(self, ERROR);
280 false
281 }
282
283 fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) {
284 self.pos += n_raw_tokens as usize;
285 self.steps.set(0);
286 self.push_event(Event::Token { kind, n_raw_tokens });
287 }
288
289 fn push_event(&mut self, event: Event) {
290 self.events.push(event);
291 }
292
293 pub(crate) fn current_edition(&self) -> Edition {
294 self.inp.edition(self.pos)
295 }
296}
297
298pub(crate) struct Marker {
300 pos: u32,
301 bomb: DropBomb,
302}
303
304impl Marker {
305 fn new(pos: u32) -> Marker {
306 Marker { pos, bomb: DropBomb::new("Marker must be either completed or abandoned") }
307 }
308
309 pub(crate) fn complete(mut self, p: &mut Parser<'_>, kind: SyntaxKind) -> CompletedMarker {
313 self.bomb.defuse();
314 let idx = self.pos as usize;
315 match &mut p.events[idx] {
316 Event::Start { kind: slot, .. } => {
317 *slot = kind;
318 }
319 _ => unreachable!(),
320 }
321 p.push_event(Event::Finish);
322 let end_pos = p.events.len() as u32;
323 CompletedMarker::new(self.pos, end_pos, kind)
324 }
325
326 pub(crate) fn abandon(mut self, p: &mut Parser<'_>) {
329 self.bomb.defuse();
330 let idx = self.pos as usize;
331 if idx == p.events.len() - 1 {
332 assert!(matches!(
333 p.events.pop(),
334 Some(Event::Start { kind: TOMBSTONE, forward_parent: None })
335 ));
336 }
337 }
338}
339
340pub(crate) struct CompletedMarker {
341 start_pos: u32,
342 end_pos: u32,
343 kind: SyntaxKind,
344}
345
346impl CompletedMarker {
347 fn new(start_pos: u32, end_pos: u32, kind: SyntaxKind) -> Self {
348 CompletedMarker { start_pos, end_pos, kind }
349 }
350
351 pub(crate) fn precede(self, p: &mut Parser<'_>) -> Marker {
365 let new_pos = p.start();
366 let idx = self.start_pos as usize;
367 match &mut p.events[idx] {
368 Event::Start { forward_parent, .. } => {
369 *forward_parent = Some(new_pos.pos - self.start_pos);
370 }
371 _ => unreachable!(),
372 }
373 new_pos
374 }
375
376 pub(crate) fn extend_to(self, p: &mut Parser<'_>, mut m: Marker) -> CompletedMarker {
378 m.bomb.defuse();
379 let idx = m.pos as usize;
380 match &mut p.events[idx] {
381 Event::Start { forward_parent, .. } => {
382 *forward_parent = Some(self.start_pos - m.pos);
383 }
384 _ => unreachable!(),
385 }
386 self
387 }
388
389 pub(crate) fn kind(&self) -> SyntaxKind {
390 self.kind
391 }
392
393 pub(crate) fn last_token(&self, p: &Parser<'_>) -> Option<SyntaxKind> {
394 let end_pos = self.end_pos as usize;
395 debug_assert_eq!(p.events[end_pos - 1], Event::Finish);
396 p.events[..end_pos].iter().rev().find_map(|event| match event {
397 Event::Token { kind, .. } => Some(*kind),
398 _ => None,
399 })
400 }
401}