pulsar_frontend/
parser.rs

1// Copyright (C) 2024 Ethan Uppal. All rights reserved.
2use super::{
3    ast::{Expr, ExprValue, Node},
4    op::{Op, Precedence},
5    token::{Token, TokenType},
6    ty::{Type, TypeCell}
7};
8use crate::{
9    ast::{NodeValue, TokenRegionProvider},
10    op::Associativity
11};
12use pulsar_utils::error::{
13    Error, ErrorBuilder, ErrorCode, ErrorManager, Level, Style
14};
15use std::{cell::RefCell, fmt::Display, rc::Rc};
16
17enum Ctx {
18    In(String),
19    Between(String),
20    For(String),
21    Begin(String),
22    End(String),
23    After(String)
24}
25
26impl Display for Ctx {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match &self {
29            Self::In(loc) => format!("in {}", loc),
30            Self::Between(values) => format!("between {}", values),
31            Self::For(purpose) => format!("for {}", purpose),
32            Self::Begin(loc) => format!("at start of {}", loc),
33            Self::End(loc) => format!("at end of {}", loc),
34            Self::After(loc) => format!("after {}", loc)
35        }
36        .fmt(f)
37    }
38}
39
40pub struct Parser {
41    pos: usize,
42    buffer: Vec<Token>,
43    error_manager: Rc<RefCell<ErrorManager>>
44}
45
46impl Parser {
47    /// Constructs a parser for the given token buffer `buffer`.
48    pub fn new(
49        buffer: Vec<Token>, error_manager: Rc<RefCell<ErrorManager>>
50    ) -> Parser {
51        Parser {
52            pos: 0,
53            buffer,
54            error_manager
55        }
56    }
57
58    fn is_eof(&self) -> bool {
59        self.pos == self.buffer.len()
60    }
61
62    fn previous(&self) -> &Token {
63        &self.buffer[self.pos - 1]
64    }
65
66    fn current(&self) -> &Token {
67        &self.buffer[self.pos]
68    }
69
70    fn current_opt(&self) -> Option<&Token> {
71        if self.is_eof() {
72            None
73        } else {
74            Some(self.current())
75        }
76    }
77
78    /// Parses the current token as an operator without consuming any tokens.
79    fn current_op_opt(&self) -> Option<Op> {
80        self.current_opt().and_then(|token| Op::from(token.ty))
81    }
82
83    fn is_at(&self, ty: TokenType) -> bool {
84        self.current_opt()
85            .map(|token| token.ty == ty)
86            .unwrap_or_default()
87    }
88
89    fn next_is(&self, ty: TokenType) -> bool {
90        if self.pos + 1 < self.buffer.len() {
91            self.buffer[self.pos + 1].ty == ty
92        } else {
93            false
94        }
95    }
96
97    fn advance(&mut self) {
98        self.pos += 1;
99    }
100
101    fn take(&mut self) -> Token {
102        let result = self.current().clone();
103        self.advance();
104        result
105    }
106
107    /// Reverts a [`Parser::advance`], returning `true` unless `self.is_eof()`.
108    fn unget(&mut self) -> bool {
109        if self.pos > 0 {
110            self.pos -= 1;
111            true
112        } else {
113            false
114        }
115    }
116
117    /// Skips past tokens that can be arbitrarily inserted, such as newlines.
118    fn consume_ignored(&mut self) {
119        while !self.is_eof() && self.current().ty == TokenType::Newline {
120            self.advance()
121        }
122    }
123
124    /// Returns the next token in the stream if it is of type `token_type` and
125    /// reports an error otherwise, returning `None`.
126    fn expect(&mut self, token_type: TokenType, context: Ctx) -> Option<Token> {
127        if self.is_eof() {
128            self.report_unexpected_eof(context);
129            None
130        } else if self.current().ty != token_type {
131            self.report_expected_token(
132                token_type,
133                &self.current().clone(),
134                &context.to_string()
135            );
136            None
137        } else {
138            Some(self.take())
139        }
140    }
141
142    /// [Reports](Parser::report): EOF is unexpectedly encountered in the
143    /// parsing context `context`.
144    ///
145    /// Requires: `!buffer.is_empty()`.
146    fn report_unexpected_eof(&mut self, context: Ctx) {
147        self.report(
148            ErrorBuilder::new()
149                .of_style(Style::Primary)
150                .at_level(Level::Error)
151                .with_code(ErrorCode::UnexpectedEOF)
152                .at_region(self.buffer.last().unwrap())
153                .explain(format!("Unexpected EOF {}", context))
154                .build()
155        );
156    }
157
158    /// [Reports](Parser::report): The token type of the found token `actual`
159    /// diverges from the expected type `expected_ty` in the parsing context
160    /// `context`.
161    fn report_expected_token(
162        &mut self, expected_ty: TokenType, actual: &Token, context: &str
163    ) {
164        self.report(
165            ErrorBuilder::new()
166                .of_style(Style::Primary)
167                .at_level(Level::Error)
168                .with_code(ErrorCode::UnexpectedToken)
169                .at_region(actual)
170                .message(format!("Expected '{:?}' {}", expected_ty, context))
171                .explain(format!("Received '{:?}' here", actual.ty))
172                .build()
173        );
174    }
175
176    /// [Reports](Parser::report): See [`Parser::report_expected_token`].
177    fn report_expected_tokens(
178        &mut self, expected_tys: &[TokenType], actual: &Token, context: Ctx
179    ) {
180        self.report(
181            ErrorBuilder::new()
182                .of_style(Style::Primary)
183                .at_level(Level::Error)
184                .with_code(ErrorCode::UnexpectedToken)
185                .at_region(actual)
186                .message(format!(
187                    "Expected one of {} {}",
188                    expected_tys
189                        .iter()
190                        .map(|ty| format!("'{:?}'", ty))
191                        .collect::<Vec<String>>()
192                        .join(", "),
193                    context
194                ))
195                .explain(format!("Received '{:?}' here", actual.ty))
196                .build()
197        );
198    }
199
200    /// Constructs a secondary-style error that refers back to a previous token
201    /// `refback` with additional explanation `explain`.
202    fn report_refback(&mut self, refback: &Token, explain: String) {
203        self.report(
204            ErrorBuilder::new()
205                .of_style(Style::Secondary)
206                .at_level(Level::Error)
207                .at_region(refback)
208                .continues()
209                .explain(explain)
210                .build()
211        );
212    }
213
214    /// [Reports](Parser::report): A construct (marked by `token`) is found at
215    /// top level that should not be. See [`Parser::report_not_top_level`].
216    fn report_top_level(&mut self, token: &Token) {
217        self.report(ErrorBuilder::new()
218            .of_style(Style::Primary)
219            .at_level(Level::Error)
220            .with_code(ErrorCode::InvalidTopLevelConstruct)
221            .at_region(token)
222            .message(format!("Unexpected {:?} at top level", token.ty))
223            .fix(
224                "Allowed constructs at top level include functions and imports"
225                    .into()
226            )
227            .build());
228    }
229
230    /// [Reports](Parser::report): A construct (marked by `token`) that belongs
231    /// only at top level is found further nested. See
232    /// [`Parser::report_top_level`].
233    fn report_not_top_level(&mut self, token: &Token) {
234        self.report(
235            ErrorBuilder::new()
236                .of_style(Style::Primary)
237                .at_level(Level::Error)
238                .with_code(ErrorCode::ConstructShouldBeTopLevel)
239                .at_region(token)
240                .message("Unexpected top-level construct".into())
241                .fix("Did you mean to place it at the top level?".into())
242                .build()
243        );
244    }
245
246    /// [Reports](Parser::report): `token` represents an invalid start to a
247    /// statement.
248    fn report_invalid_token(&mut self, token: &Token) {
249        self.report(
250            ErrorBuilder::new()
251                .of_style(Style::Primary)
252                .at_level(Level::Error)
253                .with_code(ErrorCode::InvalidTokenForStatement)
254                .at_region(token)
255                .message("Invalid token at the start of a statement".into())
256                .build()
257        );
258    }
259
260    /// [Reports](Parser::report): `token` was used incorrectly as a `usage`
261    /// operator when it is not.
262    fn report_invalid_operator(&mut self, token: &Token, usage: &str) {
263        self.report(
264            ErrorBuilder::new()
265                .of_style(Style::Primary)
266                .at_level(Level::Error)
267                .with_code(ErrorCode::InvalidOperatorSyntax)
268                .at_region(token)
269                .message(format!(
270                    "{} is not an {} operator",
271                    token.value, usage
272                ))
273                .explain(format!("Used here as an {} operator", usage))
274                .build()
275        );
276    }
277
278    fn report(&mut self, error: Error) {
279        self.error_manager.borrow_mut().record(error);
280    }
281}
282
283macro_rules! expect_n {
284    ($self:ident in [$($token_type:expr),*] => $context:expr) => {
285        if $self.is_eof() {
286            $self.report_unexpected_eof($context.into());
287            None
288        } else if ![$($token_type),*].contains(&$self.current().ty) {
289            $self.report_expected_tokens(
290                &[$($token_type),*],
291                &$self.current().clone(),
292                $context
293            );
294            None
295        } else {
296            Some($self.take())
297        }
298    };
299}
300
301/// `contained_in! { self; left_type, name, right_type; ... }` computes an
302/// expression or series of statements followed by an expression (`...`)
303/// surrounded by tokens of type `left_type` and `right_type`.
304macro_rules! contained_in {
305    ($self:ident; $open_type:expr, $loc_ctx:expr, $close_type:expr; $($action:tt)*) => {
306        {
307            let open_token = $self.expect($open_type, Ctx::Begin($loc_ctx.into()))?;
308            let result = {$($action)*};
309            let close_token = $self.expect($close_type, Ctx::End($loc_ctx.into()));
310            if close_token.is_none() {
311                $self.report_refback(
312                    &open_token,
313                    format!("{} opened here", $open_type)
314                );
315                return None;
316            }
317            Some(result)
318        }
319    };
320}
321
322/// See [`parse_full_expr!`] and [`parse_full_node!`].
323macro_rules! parse_full_abstract {
324    ($self:ident.$method:ident<$type:ty>($($arg:expr),*)) => {{
325        let start_token = $self.current().clone();
326        let value = $self.$method($($arg),*);
327        let end_token = $self.previous().clone();
328        value.map(|v| <$type>::new(v, start_token, end_token))
329    }};
330}
331
332/// `parse_full_expr!(self.method_returning_expr_value())` wraps the
333/// [`ExprValue`] as an [`Expr`] by keeping track of the surrounding tokens.
334macro_rules! parse_full_expr {
335    ($self:ident.$method:ident($($arg:expr),*)) => {
336        parse_full_abstract!($self.$method<Expr>($($arg),*))
337    };
338}
339
340/// `parse_full_node!(self.method_returning_node_value())` wraps the
341/// [`NodeValue`] as an [`Node`] by keeping track of the surrounding tokens.
342macro_rules! parse_full_node {
343    ($self:ident.$method:ident($($arg:expr),*)) => {
344        parse_full_abstract!($self.$method<Node>($($arg),*))
345    };
346}
347
348impl TokenType {
349    fn begins_top_level_construct(&self) -> bool {
350        matches!(self, Self::Func | Self::Pure) // || Self::Import
351    }
352}
353
354impl Parser {
355    /// Advances until EOF, or when specified by `current_exit`, or when a
356    /// top-level construct is potentially found.
357    fn synchronize(
358        &mut self, custom_exit: fn(&Token) -> bool, description: String
359    ) {
360        if !self.is_eof() {
361            self.report(
362                ErrorBuilder::new()
363                    .of_style(Style::Primary)
364                    .at_level(Level::Info)
365                    .with_code(ErrorCode::UnexpectedToken)
366                    .at_region(self.current())
367                    .message(
368                        "Attempting to recover understanding of code".into()
369                    )
370                    .explain(description)
371                    .build()
372            );
373        }
374        while !self.is_eof()
375            && !custom_exit(self.current())
376            && !self.current().ty.begins_top_level_construct()
377        {
378            self.advance();
379        }
380    }
381
382    /// Identical to [`Parser::synchronize`] but with no custom exit.`
383    fn attempt_restore_to_top_level(&mut self) {
384        self.synchronize(|_| false, "Seeking top-level construct".into());
385    }
386
387    fn parse_primary_type(&mut self, name: Option<&str>) -> Option<Type> {
388        let context = match name {
389            Some(name) => Ctx::In(name.into()),
390            None => Ctx::For("primary type".into())
391        };
392        let type_token = self.expect(TokenType::Identifier, context)?;
393        Some(match type_token.value.as_str() {
394            "Int64" | "Int" => Type::Int64,
395            "Unit" => Type::Unit,
396            other => Type::Name(other.into())
397        })
398    }
399
400    fn parse_array_type(&mut self, inner: Type) -> Option<Type> {
401        let size_token = contained_in! { self;
402            TokenType::LeftBracket, "array type", TokenType::RightBracket;
403            self.expect(TokenType::Integer, Ctx::For("array size".into()))?
404        }?;
405
406        let size = size_token
407            .value
408            .as_str()
409            .parse::<i64>()
410            .expect("number token can be parsed as number");
411        if size < 0 {
412            self.report(
413                ErrorBuilder::new()
414                    .of_style(Style::Primary)
415                    .at_level(Level::Error)
416                    .with_code(ErrorCode::MalformedType)
417                    .at_region(&size_token)
418                    .message("Array size cannot be negative".into())
419                    .build()
420            );
421            return None;
422        } else if size == 0 {
423            self.report(
424                ErrorBuilder::new()
425                    .of_style(Style::Primary)
426                    .at_level(Level::Warning)
427                    .with_code(ErrorCode::MalformedType)
428                    .at_region(&size_token)
429                    .message("Array size is zero".into())
430                    .build()
431            );
432        }
433
434        let result = Type::Array(TypeCell::new(inner), size as isize);
435        if self.is_at(TokenType::LeftBracket) {
436            self.parse_array_type(result)
437        } else {
438            Some(result)
439        }
440    }
441
442    fn parse_type(&mut self, name: Option<&str>) -> Option<Type> {
443        if self.is_eof() {
444            self.report_unexpected_eof(Ctx::In(
445                match name {
446                    Some(name) => name,
447                    None => "type"
448                }
449                .into()
450            ));
451            return None;
452        }
453        let primary = self.parse_primary_type(name)?;
454        if self.is_at(TokenType::LeftBracket) {
455            self.parse_array_type(primary)
456        } else {
457            Some(primary)
458        }
459    }
460
461    fn parse_array_literal_expr_value(&mut self) -> Option<ExprValue> {
462        let mut elements = vec![];
463        let mut should_continue = false;
464        let mut i = 0;
465        contained_in! { self;
466            TokenType::LeftBracket, "array literal", TokenType::RightBracket;
467
468            while !self.is_eof() && self.current().ty != TokenType::RightBracket {
469                if i > 0 {
470                    self.expect(
471                        TokenType::Comma,
472                        Ctx::Between("array elements".into())
473                    )?;
474                    self.consume_ignored();
475                }
476                match (self.current_opt().map(|token| token.ty), i) {
477                    (Some(TokenType::RightBracket), i) => {
478                        if i > 0 {
479                            break;
480                        }
481                    }
482                    (Some(TokenType::Dots), _) => {
483                        should_continue = true;
484                        self.advance();
485                        break;
486                    }
487                    _ => {}
488                }
489
490                let element_opt = self.parse_expr();
491                if let Some(element) = element_opt {
492                    elements.push(element);
493                } else {
494                    self.synchronize(|token| token.ty == TokenType::RightBrace, "Seeking end of array literal".into());
495                    return None;
496                }
497
498                i += 1;
499            }
500        };
501
502        Some(ExprValue::ArrayLiteral(elements, should_continue))
503    }
504
505    fn parse_literal_expr_value(&mut self) -> Option<ExprValue> {
506        let literal_token = expect_n! { self in
507            [TokenType::Integer, TokenType::Float, TokenType::Char, TokenType::LeftBracket, TokenType::Identifier] => Ctx::Begin("literal expression".into())
508        }?;
509        match literal_token.ty {
510            TokenType::Integer => Some(ExprValue::ConstantInt(
511                literal_token.value.parse::<i64>().unwrap()
512            )),
513            TokenType::LeftBracket => {
514                self.unget();
515                self.parse_array_literal_expr_value()
516            }
517            TokenType::Identifier => {
518                Some(ExprValue::BoundName(literal_token.clone()))
519            }
520            _ => None
521        }
522    }
523
524    fn parse_unary_prefix_expr_value(
525        &mut self, prefix_op: Op
526    ) -> Option<ExprValue> {
527        if prefix_op.is_unary_prefix() {
528            self.report_invalid_operator(&self.current().clone(), "unary");
529            return None;
530        }
531
532        let op_token = self.take();
533        let rhs = self.parse_expr()?;
534
535        Some(ExprValue::PrefixOp(op_token, Box::new(rhs)))
536    }
537
538    fn parse_postfix_binary_expr_value(
539        &mut self, mut lhs: Expr
540    ) -> Option<ExprValue> {
541        while let Some(postfix_bop) =
542            self.current_op_opt().and_then(|op| op.postfix_binary)
543        {
544            let op1 = self.take();
545            let rhs = self.parse_expr()?;
546            let op2 = self.expect(
547                postfix_bop.close_token_ty,
548                postfix_bop.name.map_or(
549                    Ctx::After(
550                        "second subexpression in postfix binary expression"
551                            .into()
552                    ),
553                    |name| Ctx::In(name)
554                )
555            )?;
556            let start_token = lhs.start_token().clone();
557            let end_token = op2.clone();
558            lhs = Expr::new(
559                ExprValue::PostfixBop(Box::new(lhs), op1, Box::new(rhs), op2),
560                start_token,
561                end_token
562            );
563        }
564        Some(lhs.value)
565    }
566
567    /// Warning: do not call this function unless it is wrapped in
568    /// [`parse_expr_full!`].
569    fn parse_call_expr_value(&mut self) -> Option<ExprValue> {
570        let name = self.expect(
571            TokenType::Identifier,
572            Ctx::Begin("call expression".into())
573        )?;
574
575        let mut args = vec![];
576        contained_in! { self;
577            TokenType::LeftPar, "call expression", TokenType::RightPar;
578            let mut i = 0;
579            while !self.is_eof() && self.current().ty != TokenType::RightPar {
580                if i > 0 {
581                    self.expect(TokenType::Comma, Ctx::Between("arguments".into()))?;
582                    self.consume_ignored();
583                }
584                if self.is_at(TokenType::RightPar) {
585                    break;
586                }
587
588                let arg_opt = self.parse_expr();
589                if let Some(arg) = arg_opt {
590                    args.push(arg);
591                } else {
592                    self.synchronize(|token| token.ty == TokenType::RightPar, "Seeking end of call arguments".into());
593                    return None;
594                }
595
596                i += 1;
597            }
598        };
599
600        Some(ExprValue::Call(name.clone(), args))
601    }
602
603    fn parse_primary_expr_value_aux(&mut self) -> Option<ExprValue> {
604        if self.is_eof() {
605            self.report_unexpected_eof(Ctx::Begin("primary expression".into()));
606            None
607        } else if let Some(prefix_op) =
608            self.current_op_opt().filter(|op| op.is_unary_prefix())
609        {
610            self.parse_unary_prefix_expr_value(prefix_op)
611        } else if self.is_at(TokenType::LeftPar) {
612            let open_paren = self.take();
613            let expr_value = self.parse_expr()?.value;
614            let closing_paren =
615                self.expect(TokenType::RightPar, Ctx::In("expression".into()));
616            if closing_paren.is_none() {
617                self.report_refback(
618                    &open_paren,
619                    "Parentheses opened here".into()
620                );
621                None
622            } else {
623                Some(expr_value)
624            }
625        } else if self.is_at(TokenType::HardwareMap) {
626            let map_token = self.expect(
627                TokenType::HardwareMap,
628                Ctx::Begin("hardware map".into())
629            )?;
630            self.expect(
631                TokenType::LeftAngle,
632                Ctx::In("hardware map expression".into())
633            )?;
634            let parallel_factor_token = self.expect(
635                TokenType::Integer,
636                Ctx::In("hardware map expression".into())
637            )?;
638            self.expect(
639                TokenType::RightAngle,
640                Ctx::In("hardware map expression".into())
641            )?;
642            self.expect(
643                TokenType::LeftPar,
644                Ctx::In("hardware map expression".into())
645            )?;
646            let f = self.expect(
647                TokenType::Identifier,
648                Ctx::In("hardware map expression".into())
649            )?;
650            self.expect(
651                TokenType::Comma,
652                Ctx::In("hardware map expression".into())
653            )?;
654            let arr = self.parse_expr()?;
655            self.expect(
656                TokenType::RightPar,
657                Ctx::In("hardware map expression".into())
658            )?;
659            // TODO: check for negatives
660            Some(ExprValue::HardwareMap(
661                map_token.clone(),
662                parallel_factor_token.value.parse::<usize>().unwrap(),
663                f,
664                Box::new(arr)
665            ))
666        } else if self.is_at(TokenType::Identifier)
667            && self.next_is(TokenType::LeftPar)
668        {
669            // TODO: allow calling expressions and more complex names with `::`
670            self.parse_call_expr_value()
671        } else {
672            self.parse_literal_expr_value()
673        }
674    }
675
676    fn parse_primary_expr_value(&mut self) -> Option<ExprValue> {
677        let primary = parse_full_expr!(self.parse_primary_expr_value_aux())?;
678        if self
679            .current_op_opt()
680            .map_or(false, |op| op.is_postfix_binary())
681        {
682            self.parse_postfix_binary_expr_value(primary)
683        } else {
684            Some(primary.value)
685        }
686    }
687
688    /// Implements [operator-precedence parsing](https://en.wikipedia.org/wiki/Operator-precedence_parser).
689    fn parse_infix_binary_expr(
690        &mut self, mut lhs: Expr, min_precedence: Precedence
691    ) -> Option<Expr> {
692        let mut lookahead = self.current().clone();
693        while !self.is_eof()
694            && Op::from(lookahead.ty)
695                .and_then(|op| op.infix_binary)
696                .map(|bop| bop.precedence >= min_precedence)
697                .unwrap_or_default()
698        {
699            let op_token = self.take();
700            let bop = Op::from(op_token.ty)
701                .and_then(|op| op.infix_binary)
702                .expect("while cond guarantees");
703
704            let mut rhs = parse_full_expr!(self.parse_primary_expr_value())?;
705            if self.is_eof() {
706                break;
707            }
708            lookahead = self.current().clone();
709            while !self.is_eof()
710                && Op::from(lookahead.ty)
711                    .and_then(|next_op| next_op.infix_binary)
712                    .map(|next_bop| {
713                        (next_bop.associativity == Associativity::Left
714                            && next_bop.precedence > bop.precedence)
715                            || (next_bop.associativity == Associativity::Right
716                                && next_bop.precedence == bop.precedence)
717                    })
718                    .unwrap_or_default()
719            {
720                let next_bop = Op::from(lookahead.ty)
721                    .and_then(|bop| bop.infix_binary)
722                    .unwrap();
723
724                let new_min_precedence = bop.precedence
725                    + if next_bop.precedence > bop.precedence {
726                        1
727                    } else {
728                        0
729                    };
730                rhs = self.parse_infix_binary_expr(rhs, new_min_precedence)?;
731                lookahead = self.current().clone();
732            }
733            let start_token = lhs.start_token().clone();
734            let end_token = rhs.end_token().clone();
735            lhs = Expr::new(
736                ExprValue::InfixBop(Box::new(lhs), op_token, Box::new(rhs)),
737                start_token,
738                end_token
739            );
740        }
741        Some(lhs)
742    }
743
744    fn parse_expr(&mut self) -> Option<Expr> {
745        self.consume_ignored();
746        let primary = parse_full_expr!(self.parse_primary_expr_value())?;
747        if let Some(op) = self.current_op_opt() {
748            if op.is_infix_binary() {
749                self.parse_infix_binary_expr(primary, -1)
750            } else {
751                self.report_invalid_operator(&self.current().clone(), "binary");
752                None
753            }
754        } else {
755            Some(primary)
756        }
757    }
758
759    fn parse_let(&mut self) -> Option<NodeValue> {
760        self.expect(TokenType::Let, Ctx::Begin("let binding".into()))?;
761
762        let name = self.expect(
763            TokenType::Identifier,
764            Ctx::For("name in let binding".into())
765        )?;
766
767        let mut hint = None;
768        if self.current().ty == TokenType::Colon {
769            self.advance();
770            hint = Some(TypeCell::new(
771                self.parse_type("let binding type hint".into())?
772            ));
773        }
774
775        self.expect(
776            TokenType::Assign,
777            Ctx::After("name in let binding".into())
778        )?;
779
780        let value = self.parse_expr()?;
781
782        Some(NodeValue::LetBinding {
783            name,
784            hint,
785            value: Box::new(value)
786        })
787    }
788
789    fn parse_return(&mut self) -> Option<NodeValue> {
790        let token = self
791            .expect(TokenType::Return, Ctx::Begin("return statement".into()))?;
792
793        let value = if self.is_at(TokenType::Newline) {
794            None
795        } else {
796            Some(Box::new(self.parse_expr()?))
797        };
798
799        Some(NodeValue::Return {
800            keyword_token: token,
801            value
802        })
803    }
804
805    /// Parses a brace-enclosed list of statements, e.g., `parse_block("function
806    /// body")`.
807    fn parse_block(&mut self, name: &str) -> Option<Vec<Node>> {
808        self.consume_ignored();
809
810        let mut nodes = vec![];
811        let mut block_failed = false;
812
813        contained_in! { self;
814            TokenType::LeftBrace, name, TokenType::RightBrace;
815            self.consume_ignored();
816            while !self.is_eof() && self.current().ty != TokenType::RightBrace {
817                let stmt_opt = self.parse_stmt(false);
818                if let Some(stmt) = stmt_opt {
819                    nodes.push(stmt);
820                } else {
821                    block_failed = true;
822                    self.synchronize(|token| token.ty == TokenType::RightBrace, format!("Seeking end of {}", name));
823                    break;
824                }
825            }
826        };
827
828        if block_failed {
829            None
830        } else {
831            Some(nodes)
832        }
833    }
834
835    fn parse_func(&mut self) -> Option<NodeValue> {
836        let mut pure_token = None;
837        if self.is_at(TokenType::Pure) {
838            pure_token = Some(self.take());
839        }
840
841        self.expect(
842            TokenType::Func,
843            Ctx::Begin("function declaration".into())
844        )?;
845
846        let name = self
847            .expect(TokenType::Identifier, Ctx::For("function name".into()))?;
848
849        let open_paren = self.expect(
850            TokenType::LeftPar,
851            Ctx::Begin(format!("function parameters in `{}`", name.value))
852        )?;
853
854        self.consume_ignored();
855
856        let mut i = 0;
857        let mut params = vec![];
858        while !self.is_eof() && self.current().ty != TokenType::RightPar {
859            if i > 0 {
860                self.expect(
861                    TokenType::Comma,
862                    Ctx::Between(format!(
863                        "function parameters in `{}`",
864                        name.value
865                    ))
866                )?;
867                self.consume_ignored();
868            }
869            if self.is_at(TokenType::RightPar) {
870                break;
871            }
872
873            let name = self.expect(
874                TokenType::Identifier,
875                Ctx::For(format!("parameter name in `{}`", name.value))
876            )?;
877            self.expect(
878                TokenType::Colon,
879                Ctx::After(format!("parameter name in `{}`", name.value))
880            )?;
881            let ty = self.parse_type("parameter type".into())?;
882            params.push((name, ty));
883
884            self.consume_ignored();
885            i += 1
886        }
887
888        let close_paren = self.expect(
889            TokenType::RightPar,
890            Ctx::End("function parameters".into())
891        );
892        if close_paren.is_none() {
893            self.report_refback(&open_paren, "Parentheses opened here".into());
894            return None;
895        }
896
897        let mut ret = Type::Unit;
898        if self.is_at(TokenType::Arrow) {
899            self.advance();
900            ret = self.parse_type("function return type".into())?;
901        }
902
903        let mut body = self.parse_block("function body")?;
904        if ret == Type::Unit {
905            body.push(
906                Node::new(
907                    NodeValue::Return {
908                        keyword_token: name.clone(),
909                        value: None
910                    },
911                    name.clone(),
912                    name.clone()
913                )
914                .mark_generated()
915            );
916        }
917
918        Some(NodeValue::Function {
919            name: name.clone(),
920            params,
921            ret,
922            pure_token,
923            body
924        })
925    }
926
927    /// Requires: a statement must have been parsed, and as consequence at least
928    /// one token has already been encountered.
929    fn end_stmt(&mut self) -> Option<Token> {
930        let ending_token = self.previous().clone();
931
932        if !self.is_eof() && self.current().ty == TokenType::RightBrace {
933            return Some(ending_token);
934        }
935
936        self.expect(TokenType::Newline, Ctx::After("statement".into()))?;
937
938        self.consume_ignored();
939
940        Some(ending_token)
941    }
942
943    /// Requires: `!self.is_eof()`.
944    fn parse_stmt_value(&mut self, top_level: bool) -> Option<NodeValue> {
945        self.consume_ignored();
946        if self.is_eof() || self.error_manager.borrow().is_full() {
947            return None;
948        }
949
950        let current_ty = self.current().ty;
951        match (current_ty, top_level) {
952            (TokenType::Func, true) | (TokenType::Pure, true) => {
953                if let Some(func) = self.parse_func() {
954                    return Some(func);
955                }
956            }
957            (TokenType::Let, false) => {
958                if let Some(let_stmt) = self.parse_let() {
959                    return Some(let_stmt);
960                }
961            }
962            (TokenType::Return, false) => {
963                if let Some(return_stmt) = self.parse_return() {
964                    return Some(return_stmt);
965                }
966            }
967            _ => {
968                if current_ty.begins_top_level_construct() && !top_level {
969                    self.report_not_top_level(&self.current().clone());
970                } else if !current_ty.begins_top_level_construct() && top_level
971                {
972                    self.report_top_level(&self.current().clone());
973                } else {
974                    self.report_invalid_token(&self.current().clone());
975                }
976                self.advance();
977            }
978        }
979
980        if top_level {
981            self.attempt_restore_to_top_level();
982            self.parse_stmt_value(true)
983        } else {
984            None
985        }
986    }
987
988    fn parse_stmt(&mut self, top_level: bool) -> Option<Node> {
989        if self.is_eof() {
990            return None;
991        }
992        let node = parse_full_node!(self.parse_stmt_value(top_level))?;
993        if self.end_stmt().is_none() {
994            self.advance();
995            return None;
996        }
997        Some(node)
998    }
999}
1000
1001impl Iterator for Parser {
1002    type Item = Node;
1003
1004    fn next(&mut self) -> Option<Node> {
1005        self.parse_stmt(true)
1006    }
1007}