1use crate::{Parse, ParseToEnd, Peek};
2use core::marker::PhantomData;
3use std::cell::RefCell;
4use sway_ast::keywords::Keyword;
5use sway_ast::literal::Literal;
6use sway_ast::token::{
7 DocComment, GenericTokenTree, Group, Punct, Spacing, TokenStream, TokenTree,
8};
9use sway_ast::PubToken;
10use sway_error::error::CompileError;
11use sway_error::handler::{ErrorEmitted, Handler};
12use sway_error::parser_error::{ParseError, ParseErrorKind};
13use sway_types::{
14 ast::{Delimiter, PunctKind},
15 Ident, Span, Spanned,
16};
17
18pub struct Parser<'a, 'e> {
19 token_trees: &'a [TokenTree],
20 full_span: Span,
21 handler: &'e Handler,
22 pub check_double_underscore: bool,
23}
24
25impl<'a, 'e> Parser<'a, 'e> {
26 pub fn new(handler: &'e Handler, token_stream: &'a TokenStream) -> Parser<'a, 'e> {
27 Parser {
28 token_trees: token_stream.token_trees(),
29 full_span: token_stream.span(),
30 handler,
31 check_double_underscore: true,
32 }
33 }
34
35 pub fn emit_error(&mut self, kind: ParseErrorKind) -> ErrorEmitted {
36 let span = match self.token_trees {
37 [token_tree, ..] => token_tree.span(),
38 _ => {
39 let num_trailing_spaces =
42 self.full_span.as_str().len() - self.full_span.as_str().trim_end().len();
43 let trim_offset = if num_trailing_spaces == 0 {
44 1
45 } else {
46 num_trailing_spaces
47 };
48 Span::new(
49 self.full_span.src().clone(),
50 self.full_span.end().saturating_sub(trim_offset),
51 (self.full_span.end() + 1).saturating_sub(trim_offset),
52 self.full_span.source_id().cloned(),
53 )
54 .unwrap_or(Span::dummy())
55 }
56 };
57 self.emit_error_with_span(kind, span)
58 }
59
60 pub fn emit_error_with_span(&mut self, kind: ParseErrorKind, span: Span) -> ErrorEmitted {
61 let error = ParseError { span, kind };
62 self.handler.emit_err(CompileError::Parse { error })
63 }
64
65 pub fn take<P: Peek>(&mut self) -> Option<P> {
69 let (value, tokens) = Peeker::with(self.token_trees)?;
70 self.token_trees = tokens;
71 Some(value)
72 }
73
74 pub fn peek<P: Peek>(&self) -> Option<P> {
78 Peeker::with(self.token_trees).map(|(v, _)| v)
79 }
80
81 pub fn call_parsing_function_with_recovery<
89 'original,
90 T,
91 F: FnOnce(&mut Parser<'a, '_>) -> ParseResult<T>,
92 >(
93 &'original mut self,
94 parsing_function: F,
95 ) -> Result<T, ParseRecoveryStrategies<'original, 'a, 'e>> {
96 let handler = Handler::default();
97 let mut fork = Parser {
98 token_trees: self.token_trees,
99 full_span: self.full_span.clone(),
100 handler: &handler,
101 check_double_underscore: self.check_double_underscore,
102 };
103
104 match parsing_function(&mut fork) {
105 Ok(result) => {
106 self.token_trees = fork.token_trees;
107 self.handler.append(handler);
108 Ok(result)
109 }
110 Err(error) => {
111 let Parser {
112 token_trees,
113 full_span,
114 ..
115 } = fork;
116 Err(ParseRecoveryStrategies {
117 original: RefCell::new(self),
118 handler,
119 fork_token_trees: token_trees,
120 fork_full_span: full_span,
121 error,
122 })
123 }
124 }
125 }
126
127 pub fn parse_with_recovery<'original, T: Parse>(
135 &'original mut self,
136 ) -> Result<T, ParseRecoveryStrategies<'original, 'a, 'e>> {
137 self.call_parsing_function_with_recovery(|p| p.parse())
138 }
139
140 pub fn guarded_parse_with_recovery<'original, P: Peek, T: Parse>(
150 &'original mut self,
151 ) -> Result<Option<T>, ParseRecoveryStrategies<'original, 'a, 'e>> {
152 if self.peek::<P>().is_none() {
153 return Ok(None);
154 }
155
156 let handler = Handler::default();
157 let mut fork = Parser {
158 token_trees: self.token_trees,
159 full_span: self.full_span.clone(),
160 handler: &handler,
161 check_double_underscore: self.check_double_underscore,
162 };
163
164 match fork.parse() {
165 Ok(result) => {
166 self.token_trees = fork.token_trees;
167 self.handler.append(handler);
168 Ok(Some(result))
169 }
170 Err(error) => {
171 let Parser {
172 token_trees,
173 full_span,
174 ..
175 } = fork;
176 Err(ParseRecoveryStrategies {
177 original: RefCell::new(self),
178 handler,
179 fork_token_trees: token_trees,
180 fork_full_span: full_span,
181 error,
182 })
183 }
184 }
185 }
186
187 pub fn try_parse<T: Parse>(&mut self, append_diagnostics: bool) -> ParseResult<T> {
190 let handler = Handler::default();
191 let mut fork = Parser {
192 token_trees: self.token_trees,
193 full_span: self.full_span.clone(),
194 handler: &handler,
195 check_double_underscore: self.check_double_underscore,
196 };
197 let r = match T::parse(&mut fork) {
198 Ok(result) => {
199 self.token_trees = fork.token_trees;
200 Ok(result)
201 }
202 Err(err) => Err(err),
203 };
204 if append_diagnostics {
205 self.handler.append(handler);
206 }
207 r
208 }
209
210 pub fn try_parse_and_check_empty<T: Parse>(
212 mut self,
213 append_diagnostics: bool,
214 ) -> ParseResult<Option<(T, ParserConsumed<'a>)>> {
215 let value = self.try_parse(append_diagnostics)?;
216 match self.check_empty() {
217 Some(consumed) => Ok(Some((value, consumed))),
218 None => Ok(None),
219 }
220 }
221
222 pub fn parse<T: Parse>(&mut self) -> ParseResult<T> {
224 T::parse(self)
225 }
226
227 pub fn guarded_parse<G: Peek, T: Parse>(&mut self) -> ParseResult<Option<T>> {
231 self.peek::<G>().map(|_| self.parse()).transpose()
232 }
233
234 pub fn parse_to_end<T: ParseToEnd>(self) -> ParseResult<(T, ParserConsumed<'a>)> {
235 T::parse_to_end(self)
236 }
237
238 pub fn try_parse_to_end<T: ParseToEnd>(
240 &mut self,
241 append_diagnostics: bool,
242 ) -> ParseResult<(T, ParserConsumed<'a>)> {
243 let handler = Handler::default();
244 let fork = Parser {
245 token_trees: self.token_trees,
246 full_span: self.full_span.clone(),
247 handler: &handler,
248 check_double_underscore: self.check_double_underscore,
249 };
250 let r = T::parse_to_end(fork);
251 if append_diagnostics {
252 self.handler.append(handler);
253 }
254 r
255 }
256
257 pub fn enter_delimited(
258 &mut self,
259 expected_delimiter: Delimiter,
260 ) -> Option<(Parser<'_, '_>, Span)> {
261 match self.token_trees {
262 [TokenTree::Group(Group {
263 delimiter,
264 token_stream,
265 span,
266 }), rest @ ..]
267 if *delimiter == expected_delimiter =>
268 {
269 self.token_trees = rest;
270 let parser = Parser {
271 token_trees: token_stream.token_trees(),
272 full_span: token_stream.span(),
273 handler: self.handler,
274 check_double_underscore: self.check_double_underscore,
275 };
276 Some((parser, span.clone()))
277 }
278 _ => None,
279 }
280 }
281
282 pub fn is_empty(&self) -> bool {
283 self.token_trees.is_empty()
284 }
285
286 pub fn check_empty(&self) -> Option<ParserConsumed<'a>> {
287 self.is_empty()
288 .then_some(ParserConsumed { _priv: PhantomData })
289 }
290
291 pub fn debug_tokens(&self) -> &[TokenTree] {
292 let len = std::cmp::min(5, self.token_trees.len());
293 &self.token_trees[..len]
294 }
295
296 pub fn ban_visibility_qualifier(&mut self, vis: &Option<PubToken>) -> ParseResult<()> {
298 if let Some(token) = vis {
299 return Err(self.emit_error_with_span(
300 ParseErrorKind::UnnecessaryVisibilityQualifier {
301 visibility: token.ident(),
302 },
303 token.span(),
304 ));
305 }
306 Ok(())
307 }
308
309 pub fn full_span(&self) -> &Span {
310 &self.full_span
311 }
312 pub fn consume_while_line_equals(&mut self, line: usize) {
318 loop {
319 let Some(current_token) = self.token_trees.first() else {
320 break;
321 };
322
323 let current_span = current_token.span();
324 let current_span_line = current_span.start_pos().line_col().line;
325
326 if current_span_line != line {
327 break;
328 } else {
329 self.token_trees = &self.token_trees[1..];
330 }
331 }
332 }
333
334 pub fn has_errors(&self) -> bool {
335 self.handler.has_errors()
336 }
337
338 pub fn has_warnings(&self) -> bool {
339 self.handler.has_warnings()
340 }
341}
342
343pub struct Peeker<'a> {
344 pub token_trees: &'a [TokenTree],
345 num_tokens: &'a mut usize,
346}
347
348impl<'a> Peeker<'a> {
349 pub fn with<P: Peek>(token_trees: &'a [TokenTree]) -> Option<(P, &'a [TokenTree])> {
351 let mut num_tokens = 0;
352 let peeker = Peeker {
353 token_trees,
354 num_tokens: &mut num_tokens,
355 };
356 let value = P::peek(peeker)?;
357 Some((value, &token_trees[num_tokens..]))
358 }
359
360 pub fn peek_ident(self) -> Result<&'a Ident, Self> {
361 match self.token_trees {
362 [TokenTree::Ident(ident), ..] => {
363 *self.num_tokens = 1;
364 Ok(ident)
365 }
366 _ => Err(self),
367 }
368 }
369
370 pub fn peek_literal(self) -> Result<&'a Literal, Self> {
371 match self.token_trees {
372 [TokenTree::Literal(literal), ..] => {
373 *self.num_tokens = 1;
374 Ok(literal)
375 }
376 _ => Err(self),
377 }
378 }
379
380 pub fn peek_punct_kinds(
381 self,
382 punct_kinds: &[PunctKind],
383 not_followed_by: &[PunctKind],
384 ) -> Result<Span, Self> {
385 let (last_punct_kind, first_punct_kinds) = punct_kinds
386 .split_last()
387 .unwrap_or_else(|| panic!("peek_punct_kinds called with empty slice"));
388 if self.token_trees.len() < punct_kinds.len() {
389 return Err(self);
390 }
391 for (punct_kind, tt) in first_punct_kinds.iter().zip(self.token_trees.iter()) {
392 match tt {
393 TokenTree::Punct(Punct {
394 kind,
395 spacing: Spacing::Joint,
396 ..
397 }) if *kind == *punct_kind => {}
398 _ => return Err(self),
399 }
400 }
401 let span_end = match &self.token_trees[punct_kinds.len() - 1] {
402 TokenTree::Punct(Punct {
403 kind,
404 spacing,
405 span,
406 }) if *kind == *last_punct_kind => match spacing {
407 Spacing::Alone => span,
408 Spacing::Joint => match &self.token_trees.get(punct_kinds.len()) {
409 Some(TokenTree::Punct(Punct { kind, .. })) => {
410 if not_followed_by.contains(kind) {
411 return Err(self);
412 }
413 span
414 }
415 _ => span,
416 },
417 },
418 _ => return Err(self),
419 };
420 let span_start = match &self.token_trees[0] {
421 TokenTree::Punct(Punct { span, .. }) => span,
422 _ => unreachable!(),
423 };
424 let span = Span::join(span_start.clone(), span_end);
425 *self.num_tokens = punct_kinds.len();
426 Ok(span)
427 }
428
429 pub fn peek_delimiter(self) -> Result<Delimiter, Self> {
430 match self.token_trees {
431 [TokenTree::Group(Group { delimiter, .. }), ..] => {
432 *self.num_tokens = 1;
433 Ok(*delimiter)
434 }
435 _ => Err(self),
436 }
437 }
438
439 pub fn peek_doc_comment(self) -> Result<&'a DocComment, Self> {
440 match self.token_trees {
441 [TokenTree::DocComment(doc_comment), ..] => {
442 *self.num_tokens = 1;
443 Ok(doc_comment)
444 }
445 _ => Err(self),
446 }
447 }
448}
449
450pub struct ParseRecoveryStrategies<'original, 'a, 'e> {
456 original: RefCell<&'original mut Parser<'a, 'e>>,
457 handler: Handler,
458 fork_token_trees: &'a [TokenTree],
459 fork_full_span: Span,
460 error: ErrorEmitted,
461}
462
463impl<'a> ParseRecoveryStrategies<'_, 'a, '_> {
464 pub fn recover_at_next_line_with_fallback_error(
467 &self,
468 kind: ParseErrorKind,
469 ) -> (Box<[Span]>, ErrorEmitted) {
470 let line = if self.fork_token_trees.is_empty() {
471 None
472 } else {
473 self.last_consumed_token()
474 .map(|x| x.span())
475 .or_else(|| self.fork_token_trees.first().map(|x| x.span()))
476 .map(|x| x.start_pos().line_col().line)
477 };
478
479 self.start(|p| {
480 if let Some(line) = line {
481 p.consume_while_line_equals(line);
482 }
483 if !p.has_errors() {
484 p.emit_error_with_span(kind, self.diff_span(p));
485 }
486 })
487 }
488
489 pub fn start<'this>(
493 &'this self,
494 f: impl FnOnce(&mut Parser<'a, 'this>),
495 ) -> (Box<[Span]>, ErrorEmitted) {
496 let mut p = Parser {
497 token_trees: self.fork_token_trees,
498 full_span: self.fork_full_span.clone(),
499 handler: &self.handler,
500 check_double_underscore: self.original.borrow().check_double_underscore,
501 };
502 f(&mut p);
503 self.finish(p)
504 }
505
506 pub fn starting_token(&self) -> &GenericTokenTree<TokenStream> {
508 let original = self.original.borrow();
509 &original.token_trees[0]
510 }
511
512 pub fn last_consumed_token(&self) -> Option<&GenericTokenTree<TokenStream>> {
515 let fork_head_span = self.fork_token_trees.first()?.span();
516
517 let original = self.original.borrow();
519 let fork_pos = original
520 .token_trees
521 .iter()
522 .position(|x| x.span() == fork_head_span)?;
523
524 let before_fork_pos = fork_pos.checked_sub(1)?;
525 original.token_trees.get(before_fork_pos)
526 }
527
528 pub fn diff_span<'this>(&self, p: &Parser<'a, 'this>) -> Span {
533 let original = self.original.borrow_mut();
534
535 let qty = if let Some(first_fork_tt) = p.token_trees.first() {
537 original
538 .token_trees
539 .iter()
540 .position(|tt| tt.span() == first_fork_tt.span())
541 .expect("not finding fork head")
542 } else {
543 original.token_trees.len()
544 };
545
546 let garbage: Vec<_> = original
547 .token_trees
548 .iter()
549 .take(qty)
550 .map(|x| x.span())
551 .collect();
552
553 Span::join_all(garbage)
554 }
555
556 fn finish(&self, p: Parser<'a, '_>) -> (Box<[Span]>, ErrorEmitted) {
557 let mut original = self.original.borrow_mut();
558
559 let qty = if let Some(first_fork_tt) = p.token_trees.first() {
561 original
562 .token_trees
563 .iter()
564 .position(|tt| tt.span() == first_fork_tt.span())
565 .expect("not finding fork head")
566 } else {
567 original.token_trees.len()
568 };
569
570 let garbage: Vec<_> = original
571 .token_trees
572 .iter()
573 .take(qty)
574 .map(|x| x.span())
575 .collect();
576
577 original.token_trees = p.token_trees;
578 original.handler.append(self.handler.clone());
579
580 (garbage.into_boxed_slice(), self.error)
581 }
582}
583
584pub struct ParserConsumed<'a> {
585 _priv: PhantomData<fn(&'a ()) -> &'a ()>,
586}
587
588pub type ParseResult<T> = Result<T, ErrorEmitted>;