1use 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 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 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 fn unget(&mut self) -> bool {
109 if self.pos > 0 {
110 self.pos -= 1;
111 true
112 } else {
113 false
114 }
115 }
116
117 fn consume_ignored(&mut self) {
119 while !self.is_eof() && self.current().ty == TokenType::Newline {
120 self.advance()
121 }
122 }
123
124 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 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 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 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 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 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 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 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 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
301macro_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
322macro_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
332macro_rules! parse_full_expr {
335 ($self:ident.$method:ident($($arg:expr),*)) => {
336 parse_full_abstract!($self.$method<Expr>($($arg),*))
337 };
338}
339
340macro_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) }
352}
353
354impl Parser {
355 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 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 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 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 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 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 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 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 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}