aplang_lib/parser/
parser.rs

1use crate::lexer::token::LiteralValue;
2use crate::lexer::token::TokenType::{Eof, LeftParen, RightParen};
3use crate::lexer::token::{Token, TokenType};
4use crate::parser::ast::Break as BreakStatement;
5use crate::parser::ast::Continue as ContinueStatement;
6use crate::parser::ast::Import as ImportStatement;
7use crate::parser::ast::Return as ReturnValue;
8use crate::parser::ast::*;
9use miette::{miette, LabeledSpan, NamedSource, Report, SourceSpan};
10use std::sync::Arc;
11
12use crate::lexer::token::TokenType::*;
13use crate::parser::ast::If as IfStmt;
14
15pub struct Parser {
16    tokens: Vec<Token>,
17    source: Arc<str>,
18    named_source: NamedSource<Arc<str>>,
19    current: usize,
20    in_function_scope: bool,
21    _warnings: Vec<Report>,
22    in_loop_scope: bool,
23}
24
25impl Parser {
26    pub(crate) fn new(tokens: Vec<Token>, source: Arc<str>, file_name: &str) -> Self {
27        Self {
28            tokens,
29            source: source.clone(),
30            in_function_scope: false,
31            in_loop_scope: false,
32            named_source: NamedSource::new(file_name, source),
33            current: 0,
34            _warnings: vec![],
35        }
36    }
37
38    pub(crate) fn parse(&mut self) -> Result<Ast, Vec<Report>> {
39        let mut statements = vec![];
40        let mut reports = vec![];
41
42        while !self.is_at_end() {
43            if self.match_token(&SoftSemi) {
44                continue;
45            }
46
47            match self.declaration() {
48                Ok(stmt) => statements.push(stmt),
49                Err(report) => {
50                    let report = report;
51                    reports.push(report);
52                    self.synchronize();
53                }
54            }
55        }
56
57        if !reports.is_empty() {
58            return Err(reports);
59        }
60
61        Ok(Ast {
62            source: self.source.clone(),
63            program: statements,
64        })
65    }
66}
67
68/// parse expression
69impl Parser {
70    fn declaration(&mut self) -> miette::Result<Stmt> {
71        // Procedure might start with export.
72        // If it needs special treatment
73        if self.match_tokens(&[Export, Procedure]) {
74            return self.procedure();
75        }
76        self.statement()
77    }
78
79    fn procedure(&mut self) -> miette::Result<Stmt> {
80        let export_or_procedure = self.previous().clone();
81
82        let (proc_token, exported) = if export_or_procedure.token_type == Export {
83            let proc_token = self
84                .consume(&Procedure, |token| {
85                    let labels = vec![
86                        LabeledSpan::at(token.span(), "expected keyword 'PROCEDURE' here"),
87                        LabeledSpan::at(token.span(), "'EXPORT' cannot exist alone"),
88                    ];
89
90                    miette!(
91                        labels = labels,
92                        code = "standalone_export",
93                        help = "you can only export a procedure from a module",
94                        "expected 'PROCEDURE' following 'EXPORT' found {}",
95                        token.lexeme,
96                    )
97                })?
98                .clone();
99
100            (proc_token, true)
101        } else {
102            (export_or_procedure, false)
103        };
104
105        let name_token = self
106            .consume(&Identifier, |token| {
107                let labels = vec![
108                    LabeledSpan::at(proc_token.span(), "this procedure requires a name"),
109                    LabeledSpan::at(token.span(), "name goes here"),
110                ];
111
112                miette!(
113                    labels = labels,
114                    code = "unnamed_procedure",
115                    help = "name the PROCEDURE with an IDENT",
116                    "expected `IDENT` found `{}`",
117                    token.lexeme
118                )
119            })?
120            .clone();
121
122        // self.ident_warning(&name_token);
123
124        let name = name_token.lexeme.clone();
125
126        let _lp_token = self
127            .consume(&LeftParen, |token| {
128                let labels = vec![
129                    LabeledSpan::at(token.span(), "expected a `(`"),
130                    LabeledSpan::at(
131                        name_token.span(),
132                        format!("{} requires `(..)` argument list", name_token.lexeme),
133                    ),
134                ];
135                miette!(
136                    labels = labels,
137                    code = "missing_lp",
138                    help = "a PROCEDURE requires a argument list in `()` after its name",
139                    "expected `(` found `{}`",
140                    token.lexeme
141                )
142            })?
143            .clone();
144
145        let mut params = vec![];
146        if !self.check(&RightParen) {
147            loop {
148                if params.len() > 255 {
149                    let _peeked = self.peek();
150                    return Err(miette! {
151                        "todo: params cannot exceed 255, why the f**k do you need so many?"
152                    });
153                }
154
155                // we expect there to be parameters
156                let token = self
157                    .consume(&Identifier, |_token| miette!("hello"))?
158                    .clone();
159
160                params.push(Variable {
161                    ident: token.lexeme.clone(),
162                    token,
163                });
164
165                if !self.match_token(&Comma) {
166                    break;
167                }
168            }
169        }
170
171        let _rp_token = self
172            .consume(&RightParen, |token| {
173                let labels = vec![LabeledSpan::at(token.span(), "expected a `)`")];
174
175                miette!(
176                    labels = labels,
177                    code = "missing_rp",
178                    help = "mismatched `(`, it seems you missed a `)`.",
179                    "expected `)`, found `{}`",
180                    token.lexeme
181                )
182            })?
183            .clone();
184
185        // cache previous function state and set to true temporarily, since we're in a
186        let function_scope_state_cache = self.in_function_scope;
187        self.in_function_scope = true;
188
189        // parse the body of the function
190        let body = self.statement()?;
191        // restore the previous function scope state
192        self.in_function_scope = function_scope_state_cache;
193
194        Ok(Stmt::ProcDeclaration(Arc::new(ProcDeclaration {
195            name,
196            params,
197            body,
198            exported,
199            proc_token,
200            name_token,
201        })))
202    }
203
204    fn statement(&mut self) -> miette::Result<Stmt> {
205        // import statement
206        if self.match_token(&Import) {
207            let import_token = self.previous().clone();
208            return self.import_statement(import_token);
209        }
210
211        // IF (condition)
212        if self.match_token(&If) {
213            let if_token = self.previous().clone();
214            return self.if_statement(if_token);
215        }
216
217        // REPEAT UNTIL (condition)
218        if self.match_token(&Repeat) {
219            let repeat_token = self.previous().clone();
220
221            // we're now in a loop
222            let cache_loop_state = self.in_loop_scope;
223            self.in_loop_scope = true;
224
225            // this is a repeat until block
226            let result = if self.check(&Until) {
227                self.repeat_until(repeat_token)
228            } else {
229                self.repeat_times(repeat_token)
230            };
231
232            // we *might* not be in a loop anymore
233            self.in_loop_scope = cache_loop_state;
234
235            // finish
236            return result;
237        }
238
239        if self.match_token(&For) {
240            let for_token = self.previous().clone();
241
242            // we're now in a loop
243            let cache_loop_state = self.in_loop_scope;
244            self.in_loop_scope = true;
245            
246            // parse FOR EACH loop
247            let result = self.for_each(for_token);
248
249            // we *might* not be in a loop anymore
250            self.in_loop_scope = cache_loop_state;
251            
252            return result
253        }
254
255        // { expr }
256        if self.match_token(&LeftBrace) {
257            let lb_token = self.previous().clone();
258
259            return self.block(lb_token);
260        }
261
262        if self.match_token(&Continue) {
263            let cont_token = self.previous().clone();
264            return self.continue_statement(cont_token);
265        }
266
267        if self.match_token(&Break) {
268            let brk_token = self.previous().clone();
269            return self.break_statement(brk_token);
270        }
271
272        if self.match_token(&Return) {
273            let return_token = self.previous().clone();
274            return self.return_statement(return_token);
275        }
276
277        self.expression_statement()
278    }
279
280    fn block(&mut self, lb_token: Token) -> miette::Result<Stmt> {
281        let mut statements = vec![];
282
283        while !self.check(&LeftBrace) && !self.is_at_end() {
284            // evil code that took 6 hours to figure out
285            if self.match_token(&SoftSemi) {
286                continue;
287            }
288
289            // evil code that took 6 hours to figure out
290            if self.check(&RightBrace) {
291                break;
292            }
293
294            statements.push(self.declaration()?);
295        }
296
297        let rb_token = self
298            .consume(&RightBrace, |_token| {
299                let labels = vec![LabeledSpan::at(
300                    lb_token.span(),
301                    "this delimiter requires a closing `}`",
302                )];
303                // todo: span the next `}` token
304
305                miette!(
306                    labels = labels,
307                    code = "missing_rb",
308                    help = "mismatched `{`, it seems you missed a `}`",
309                    "this block has an unclosed delimiter"
310                )
311            })?
312            .clone();
313
314        Ok(Stmt::Block(
315            Block {
316                lb_token,
317                statements,
318                rb_token,
319            }
320            .into(),
321        ))
322    }
323
324    fn break_statement(&mut self, break_token: Token) -> miette::Result<Stmt> {
325        if !self.in_loop_scope {
326            // todo improve this message
327            return Err(miette! {
328                "BREAK can only be called in a loop"
329            });
330        }
331
332        Ok(Stmt::Break(Arc::new(BreakStatement { token: break_token })))
333    }
334
335    fn continue_statement(&mut self, continue_token: Token) -> miette::Result<Stmt> {
336        if !self.in_loop_scope {
337            // todo: make this error bearable
338            return Err(miette! {
339                "CONTINUE can only be called in a loop",
340            });
341        }
342
343        Ok(Stmt::Continue(Arc::new(ContinueStatement {
344            token: continue_token,
345        })))
346    }
347
348    fn return_statement(&mut self, return_token: Token) -> miette::Result<Stmt> {
349        if !self.in_function_scope {
350            // todo make this error better
351            return Err(miette! {
352                "RETURN can only be called in a PROCEDURE"
353            });
354        }
355
356        let maybe_value = if !self.match_token(&SoftSemi) {
357            Some(self.expression()?)
358        } else {
359            None
360        };
361
362        if maybe_value.is_some() {
363            self.consume(&SoftSemi, |_token| {
364                miette! {
365                    "todo: expected semicolon after return statement"
366                }
367            })?;
368        }
369
370        Ok(Stmt::Return(Arc::new(ReturnValue {
371            token: return_token,
372            data: maybe_value,
373        })))
374    }
375
376    fn import_statement(&mut self, import_token: Token) -> miette::Result<Stmt> {
377        // get the specific function imports
378        let only_functions = if self.match_token(&LeftBracket) {
379            // matching import ["f1", "f2", "f3"] from mod
380            let lbracket = self.previous().clone();
381
382            let mut specific_functions: Vec<Token> = vec![];
383            loop {
384                // todo: consider making this an argument because arbitrary
385                // todo: like max param limits or something
386                // set an arbitrary limit for number of specific functions
387                const MAX_SPECIFIC_FUNCTIONS: usize = 63;
388                if specific_functions.len() >= MAX_SPECIFIC_FUNCTIONS {
389                    let correct_span =
390                        lbracket.span_until_token(specific_functions.last().unwrap());
391                    let labels = vec![LabeledSpan::at(
392                        correct_span,
393                        "just import the entire module",
394                    )];
395                    let _s = 2.0;
396
397                    return Err(miette!(
398                        labels = labels,
399                        help = "what the freak dude. are you okay?",
400                        "cannot have more than {} specific imports",
401                        MAX_SPECIFIC_FUNCTIONS
402                    ));
403                }
404
405                let specific_function = self.consume(&StringLiteral, |found| {
406                    miette!("expected a specific function instead found {}", found)
407                })?;
408
409                specific_functions.push(specific_function.clone());
410
411                // we've reached the end of the specific functions
412                if !self.match_token(&Comma) {
413                    break;
414                }
415            }
416
417            println!("debug: specific functions: {:?}", specific_functions);
418
419            // close off the specific functions
420            let _rbracket = self.consume(&RightBracket, |_found| {
421                miette! {
422                    ""
423                }
424            })?;
425
426            Some(specific_functions)
427        } else if self.match_token(&StringLiteral) {
428            // matching single specific function ("string literal")
429            let one_specific_function = self.previous().clone();
430            Some(vec![one_specific_function])
431        } else {
432            None
433        };
434
435        let maybe_from_token =
436            if only_functions.is_some() {
437                Some(self.consume(&From, |found| miette! {
438                "(todo) Expected from following specific imports, found {}", found.lexeme
439            })?.clone())
440            } else {
441                None
442            };
443
444        let mod_token = self
445            .consume(&Mod, |_token| {
446                miette! {
447                    "todo: expected a mod token following import. could also be a specific function" // todo make this better
448                }
449            })?
450            .clone();
451
452        let module_name = self
453            .consume(&StringLiteral, |_token| {
454                miette! {
455                    "todo: expected a string literal specifying the type of import"
456                }
457            })?
458            .clone();
459
460        self.consume(&SoftSemi, |_token| {
461            miette! {
462                "todo: expected a semicolon following import statement"
463            }
464        })?;
465
466        Ok(Stmt::Import(Arc::new(ImportStatement {
467            import_token,
468            mod_token,
469            maybe_from_token,
470
471            only_functions,
472            module_name,
473        })))
474    }
475
476    fn if_statement(&mut self, if_token: Token) -> miette::Result<Stmt> {
477        // todo: improve this report
478        let _lp_token = self
479            .consume(&LeftParen, |token| {
480                // miette!("expected lp_token")
481                let labels = vec![
482                    LabeledSpan::at(token.span(), "expected a `(`"),
483                    LabeledSpan::at(if_token.span(), "IF requires `(..)` condition"),
484                ];
485
486                miette!(
487                    labels = labels,
488                    code = "missing_lp",
489                    help = "an IF statement requires a condition in `()` after the `IF` keyword",
490                    "expected `(` found `{}`",
491                    token.lexeme
492                )
493            })?
494            .clone();
495
496        let condition = self.expression()?;
497
498        let _rp_token = self
499            .consume(&RightParen, |token| {
500                // miette!("Expected `)` found {}", token)
501                let labels = vec![LabeledSpan::at(token.span(), "expected a `)`")];
502
503                miette!(
504                    labels = labels,
505                    code = "missing_rp",
506                    help = "mismatched `(`, it seems you missed a `)`.",
507                    "expected `)`, found `{}`",
508                    token.lexeme
509                )
510            })?
511            .clone();
512
513        let then_branch = self.statement()?;
514
515        let (else_branch, else_token) = if self.match_token(&Else) {
516            // there is an ELSE branch
517            let else_token = self.previous().clone();
518            let else_branch = self.statement()?;
519
520            (Some(else_branch), Some(else_token))
521        } else {
522            (None, None)
523        };
524
525        Ok(Stmt::If(Arc::new(IfStmt {
526            condition,
527            then_branch,
528            else_branch,
529            if_token,
530            else_token,
531        })))
532    }
533
534    fn repeat_times(&mut self, repeat_token: Token) -> miette::Result<Stmt> {
535        // confirm that the repeat token was consumed
536        self.confirm(&Repeat)?;
537
538        // expected expression
539        let count = self.expression()?;
540
541        let count_token = self.previous().clone();
542
543        let times_token = self.consume(&Times, |token| {
544            // todo improve this message
545            // miette!("expected times token")
546            let labels = vec![
547                LabeledSpan::at(token.span(), "expected a `TIMES`"),
548            ];
549
550            miette!(
551                labels = labels,
552                code = "missing_times",
553                help = "a REPEAT block requires a `TIMES` keyword after the number of times to repeat",
554                "expected `TIMES` found `{}`", token.lexeme
555            )
556        })?.clone();
557
558        let body = self.statement()?;
559
560        Ok(Stmt::RepeatTimes(
561            RepeatTimes {
562                count,
563                body,
564                repeat_token,
565                times_token,
566                count_token,
567            }
568            .into(),
569        ))
570    }
571
572    fn repeat_until(&mut self, repeat_token: Token) -> miette::Result<Stmt> {
573        // confirm that the repeat token has been consumed
574        self.confirm(&Repeat)?;
575
576        let until_token = self
577            .consume(&Until, |_token| {
578                // todo: improve this error
579                // miette!(
580                //     "expected until token after repeat token"
581                // )
582                // let labels = vec![
583                //     LabeledSpan::at(token.span(), "expected an `UNTIL`"),
584                // ];
585
586                // miette!(
587                //     labels = labels,
588                //     code = "missing_times",
589                //     help = "a REPEAT block requires an `UNTIL` keyword with a condition",
590                //     "expected `UNTIL` found {}", token.lexeme
591                // )
592                // todo consider making this advance instead of consume
593                // this should never error
594                miette!("how tf do i trigger this")
595            })?
596            .clone();
597
598        let _lp_token = self.consume(&LeftParen, |token| {
599            // todo: improve this error
600            let labels = vec![
601                LabeledSpan::at(token.span(), "expected a `(`"),
602                LabeledSpan::at(until_token.span(), "REPEAT UNTIL requires `(..)` condition")
603            ];
604
605            miette!(
606                labels = labels,
607                code = "missing_lp",
608                help = "a REPEAT UNTIL block requires a condition in `()` after the `UNTIL` keyword",
609                "expected `(` found `{}`", token.lexeme
610            )
611        })?.clone();
612
613        let condition = self.expression()?;
614
615        let _rp_token = self
616            .consume(&RightParen, |token| {
617                // todo: improve this error
618                let labels = vec![LabeledSpan::at(token.span(), "expected a `)`")];
619
620                miette!(
621                    labels = labels,
622                    code = "missing_rp",
623                    help = "mismatched `(`, it seems you missed a `)`.",
624                    "expected `)`, found `{}`",
625                    token.lexeme
626                )
627            })?
628            .clone();
629
630        let body = self.statement()?;
631
632        Ok(Stmt::RepeatUntil(
633            RepeatUntil {
634                condition,
635                body,
636                repeat_token,
637                until_token,
638            }
639            .into(),
640        ))
641    }
642
643    fn for_each(&mut self, for_token: Token) -> miette::Result<Stmt> {
644        self.confirm(&For)?;
645
646        let each_token = self
647            .consume(&Each, |token| {
648                // todo improve this message
649                // miette!("expected each token")
650                let labels = vec![LabeledSpan::at(token.span(), "expected an `EACH`")];
651
652                miette!(
653                    labels = labels,
654                    code = "missing_each",
655                    help = "a FOR block requires an `EACH` keyword after the `FOR` keyword",
656                    "expected `EACH` found `{}`",
657                    token.lexeme
658                )
659            })?
660            .clone();
661
662        let item_token = self
663            .consume(&Identifier, |token| {
664                // todo improve this message
665                // miette!("expected an ident")
666                let labels = vec![
667                    LabeledSpan::at(each_token.span(), "expected an identifier after `EACH`"),
668                    LabeledSpan::at(token.span(), "identifier goes here"),
669                ];
670
671                miette!(
672                    labels = labels,
673                    code = "missing_ident",
674                    help = "a FOR EACH block requires an identifier after the `EACH` keyword",
675                    "expected `IDENTIFIER` found `{}`",
676                    token.lexeme
677                )
678            })?
679            .clone();
680        // let item = item_token.lexeme.clone();
681        let item = Variable {
682            ident: item_token.lexeme.to_string(),
683            token: item_token.clone(),
684        };
685
686        // this is sus?
687        let in_token = self
688            .consume(&In, |token| {
689                // miette!("expected in token")
690                let labels = vec![
691                    LabeledSpan::at(item_token.span(), "expected an `IN` after identifier"),
692                    LabeledSpan::at(token.span(), "`IN` goes here"),
693                ];
694
695                miette!(
696                    labels = labels,
697                    code = "missing_in",
698                    help = "a FOR EACH block requires an `IN` keyword after the identifier",
699                    "expected `IN` found `{}`",
700                    token.lexeme
701                )
702            })?
703            .clone();
704
705        let list = self.expression()?;
706
707        let list_token = self.previous().clone();
708
709        let body = self.statement()?;
710
711        Ok(Stmt::ForEach(
712            ForEach {
713                item,
714                list,
715                body,
716                item_token,
717                for_token,
718                each_token,
719                in_token,
720                list_token,
721            }
722            .into(),
723        ))
724    }
725
726    fn expression_statement(&mut self) -> miette::Result<Stmt> {
727        let expr = self.expression()?;
728        if self.is_at_end() {
729            return Ok(Stmt::Expr(Arc::new(expr)));
730        }
731
732        if self.check(&RightBrace) {
733            return Ok(Stmt::Expr(Arc::new(expr)));
734        }
735
736        self.consume(&SoftSemi, |token| {
737            // miette!("Expected EOL or semi found {}", token)
738            let labels = vec![LabeledSpan::at(
739                token.span(),
740                "missing End Of Line indicator",
741            )];
742            miette!(
743                labels = labels,
744                code = "missing_eol",
745                help = "try manually placing a semicolon",
746                "expected `End Of Line` found `{}`",
747                token.lexeme
748            )
749        })?;
750        Ok(Stmt::Expr(Arc::new(expr)))
751    }
752
753    pub(crate) fn expression(&mut self) -> miette::Result<Expr> {
754        self.assignment()
755    }
756
757    fn assignment(&mut self) -> miette::Result<Expr> {
758        let expr = self.or()?;
759        let expr_token = self.previous().clone();
760
761        if self.match_token(&Arrow) {
762            let arrow_token = self.previous().clone();
763            let value = self.assignment()?; // Recursively parse the assignment value to handle chained assignments
764
765            match expr {
766                Expr::Variable(ref variable) => Ok(Expr::Assign(
767                    Assignment {
768                        target: variable.clone(),
769                        value,
770                        ident_token: variable.token.clone(),
771                        arrow_token,
772                    }
773                    .into(),
774                )),
775
776                // Handling set assignment for complex expressions like array[index] = value
777                Expr::Access(ref access) => Ok(Expr::Set(
778                    Set {
779                        target: Expr::Access(
780                            Access {
781                                list: access.list.clone(),
782                                list_token: access.list_token.clone(),
783                                key: access.key.clone(),
784                                brackets: access.brackets.clone(),
785                            }
786                            .into(),
787                        ),
788                        list: access.list.clone(),
789                        idx: access.key.clone(),
790                        value,
791                        list_token: access.list_token.clone(),
792                        brackets: access.brackets.clone(),
793                        arrow_token,
794                    }
795                    .into(),
796                )),
797
798                // Error for invalid assignment target
799                // todo: add better error here
800                // _ => Err({
801                //     miette!("Invalid assignment target.")
802                // })
803                _ => {
804                    let labels = vec![
805                        LabeledSpan::at(arrow_token.span(), "expected an assignment target"),
806                        LabeledSpan::at(expr_token.span(), "target goes here"),
807                    ];
808
809                    Err(miette!(
810                        labels = labels,
811                        code = "invalid_assignment_target",
812                        help = "an assignment target must be a variable or an access expression (array[index] type)",
813                        "expected an assignment target found {}", expr
814                    ).with_source_code(self.named_source.clone()))
815                }
816            }
817        } else {
818            Ok(expr)
819        }
820    }
821
822    // and ( "OR" and )*
823    fn or(&mut self) -> miette::Result<Expr> {
824        let mut expr = self.and()?;
825
826        while self.match_token(&Or) {
827            // get or token for spanning
828            let token = self.previous().clone();
829
830            let right = self.and()?;
831            expr = Expr::Logical(Arc::new(Logical {
832                left: expr,
833                operator: LogicalOp::Or,
834                right,
835
836                token,
837            }))
838        }
839
840        Ok(expr)
841    }
842
843    // logical_and → equality ( "AND" equality )*
844    fn and(&mut self) -> miette::Result<Expr> {
845        let mut expr = self.equality()?;
846
847        while self.match_token(&And) {
848            // get the token for spanning
849            let token = self.previous().clone();
850
851            let right = self.and()?;
852            expr = Expr::Logical(Arc::new(Logical {
853                left: expr,
854                operator: LogicalOp::And,
855                right,
856
857                token,
858            }))
859        }
860
861        Ok(expr)
862    }
863
864    fn equality(&mut self) -> miette::Result<Expr> {
865        let mut expr = self.comparison()?;
866
867        while self.match_tokens(&[BangEqual, EqualEqual]) {
868            // get equality token
869            let token = self.previous().clone();
870            let right = self.comparison()?;
871            let operator = token.to_binary_op()?;
872            let left = expr;
873            expr = Expr::Binary(
874                Binary {
875                    left,
876                    operator,
877                    right,
878                    token,
879                }
880                .into(),
881            )
882        }
883
884        Ok(expr)
885    }
886
887    fn comparison(&mut self) -> miette::Result<Expr> {
888        let mut expr = self.addition()?;
889
890        while self.match_tokens(&[Greater, GreaterEqual, Less, LessEqual]) {
891            // get comparison token
892            let token = self.previous().clone();
893            let right = self.addition()?;
894            let operator = token.to_binary_op()?;
895            let left = expr;
896            expr = Expr::Binary(
897                Binary {
898                    left,
899                    operator,
900                    right,
901                    token,
902                }
903                .into(),
904            )
905        }
906
907        Ok(expr)
908    }
909
910    fn addition(&mut self) -> miette::Result<Expr> {
911        let mut expr = self.multiplication()?;
912
913        while self.match_tokens(&[Plus, Minus]) {
914            // get addition token
915            let token = self.previous().clone();
916            let right = self.multiplication()?;
917            let operator = token.to_binary_op()?;
918            let left = expr;
919            expr = Expr::Binary(
920                Binary {
921                    left,
922                    operator,
923                    right,
924                    token,
925                }
926                .into(),
927            )
928        }
929
930        Ok(expr)
931    }
932
933    fn multiplication(&mut self) -> miette::Result<Expr> {
934        let mut expr = self.unary()?;
935
936        while self.match_tokens(&[Star, Slash, Mod]) {
937            // get multiplication token
938            let token = self.previous().clone();
939            let right = self.unary()?;
940            let operator = token.to_binary_op()?;
941            let left = expr;
942            expr = Expr::Binary(
943                Binary {
944                    left,
945                    operator,
946                    right,
947                    token,
948                }
949                .into(),
950            )
951        }
952
953        Ok(expr)
954    }
955
956    fn unary(&mut self) -> miette::Result<Expr> {
957        if self.match_tokens(&[Not, Minus]) {
958            let token = self.previous().clone();
959            let right = self.unary()?;
960            let operator = token.to_unary_op()?;
961
962            let expr = Expr::Unary(
963                Unary {
964                    operator,
965                    right,
966                    token,
967                }
968                .into(),
969            );
970
971            Ok(expr)
972        } else {
973            self.access()
974        }
975    }
976
977    fn access(&mut self) -> miette::Result<Expr> {
978        let mut expr = self.primary()?;
979        let expr_token = self.previous().clone();
980
981        loop {
982            if self.match_token(&LeftBracket) {
983                let lb_token = self.previous().clone();
984
985                let index = self.expression()?;
986                let rb_token = self.consume(&RightBracket, |token| {
987                    let labels = vec![
988                        // todo: make expression span
989                        // LabeledSpan::at(index.span(), "expression"),
990                        LabeledSpan::at(token.span(), "requires closing `]`")
991                    ];
992
993                    miette!(
994                        labels = labels,
995                        code = "missing_rbracket",
996                        help = "when indexing an array you must have a closing `]` bracket following the expression",
997                        "expected ']' found {}", token.lexeme
998                    )
999                })?.clone();
1000
1001                expr = Expr::Access(Arc::new(Access {
1002                    list: expr,
1003                    list_token: expr_token.clone(),
1004                    key: index,
1005                    brackets: (lb_token, rb_token),
1006                }));
1007            } else {
1008                break;
1009            }
1010        }
1011
1012        Ok(expr)
1013    }
1014
1015    // todo: add access "[" expr "]"
1016    fn primary(&mut self) -> miette::Result<Expr> {
1017        // TRUE
1018        if self.match_token(&True) {
1019            let token = self.previous().clone();
1020            return Ok(Expr::Literal(Arc::new(ExprLiteral {
1021                value: Literal::True,
1022                token,
1023            })));
1024        }
1025        // FALSE
1026        if self.match_token(&False) {
1027            let token = self.previous().clone();
1028            return Ok(Expr::Literal(Arc::new(ExprLiteral {
1029                value: Literal::False,
1030                token,
1031            })));
1032        }
1033        // NULL
1034        if self.match_token(&Null) {
1035            let token = self.previous().clone();
1036            return Ok(Expr::Literal(Arc::new(ExprLiteral {
1037                value: Literal::Null,
1038                token,
1039            })));
1040        }
1041        // string
1042        if self.match_token(&StringLiteral) {
1043            let token = self.previous().clone();
1044
1045            // todo improve this message
1046            let literal = token
1047                .literal
1048                .clone()
1049                .miette_expect(|| miette!("internal parser error. could not find literal"));
1050
1051            // if it is not string
1052            let LiteralValue::String(literal) = literal else {
1053                let report = miette!("internal parser error literal is not a string");
1054                panic!("{:?}", report)
1055            };
1056
1057            return Ok(Expr::Literal(
1058                ExprLiteral {
1059                    value: Literal::String(literal),
1060                    token,
1061                }
1062                .into(),
1063            ));
1064        }
1065
1066        // number
1067        if self.match_token(&Number) {
1068            let token = self.previous().clone();
1069
1070            // todo improve this message
1071            let literal = token
1072                .literal
1073                .clone()
1074                .miette_expect(|| miette!("internal parser error. could not find literal"));
1075
1076            // if it is not number
1077            let LiteralValue::Number(literal) = literal else {
1078                let report = miette!("internal parser error literal is not a number");
1079                panic!("{:?}", report)
1080            };
1081
1082            return Ok(Expr::Literal(
1083                ExprLiteral {
1084                    value: Literal::Number(literal),
1085                    token,
1086                }
1087                .into(),
1088            ));
1089        }
1090        // done parsing literals
1091
1092        // IDENT
1093        if self.match_token(&Identifier) {
1094            let token = self.previous().clone();
1095            // add possible ident warnings
1096            // self.ident_warning(&token);
1097
1098            let ident = token.lexeme.clone();
1099
1100            // function call
1101            // IDENT "(" ( expr ),* ")"
1102            if self.match_token(&LeftParen) {
1103                let lp_token = self.previous().clone();
1104
1105                let mut arguments = vec![];
1106                let mut arguments_tokens = vec![lp_token.clone()];
1107                if !self.check(&RightParen) {
1108                    loop {
1109                        if arguments.len() >= 255 {
1110                            // let next_token = self.peek();
1111                            // todo: improve this message
1112                            let report = miette!(
1113                                // todo: finish this
1114                                "todo: max args for function call exceeded"
1115                            );
1116                            return Err(report);
1117                        }
1118
1119                        let expr = self.expression()?;
1120                        arguments.push(expr);
1121                        arguments_tokens.push(self.peek().clone());
1122
1123                        // we've reached the end of arguments
1124                        if !self.match_token(&Comma) {
1125                            break;
1126                        }
1127                    }
1128                }
1129
1130                let rp_token = self
1131                    .consume(&RightParen, |token| {
1132                        // todo
1133                        // miette!("expected ) after argument list, found {token}")
1134                        let labels = vec![LabeledSpan::at(token.span(), "expected a `)`")];
1135
1136                        miette!(
1137                            labels = labels,
1138                            code = "missing_rp",
1139                            help = "mismatched `(`, it seems you missed a `)`.",
1140                            "expected `)`, found `{}`",
1141                            token.lexeme
1142                        )
1143                    })?
1144                    .clone();
1145
1146                let arguments_spans: Vec<SourceSpan> = arguments_tokens
1147                    .windows(2)
1148                    .map(|tok| tok[0].span_until_token(&tok[1]))
1149                    .collect();
1150
1151                return Ok(Expr::ProcCall(Arc::new(ProcCall {
1152                    ident,
1153                    arguments,
1154                    arguments_spans,
1155                    token,
1156                    parens: (lp_token, rp_token),
1157                })));
1158            }
1159
1160            // ident token
1161            return Ok(Expr::Variable(Arc::new(Variable { ident, token })));
1162        }
1163
1164        // "(" expr ")"
1165        if self.match_token(&LeftParen) {
1166            let lp_token = self.previous().clone();
1167            let expr = self.expression()?;
1168
1169            let rp_token = self.consume(&RightParen, |token| {
1170                // todo: improve this message
1171                // miette!("expected `(` found {}", token)
1172                let labels = vec![LabeledSpan::at(token.span(), "expected a `(`")];
1173
1174                miette!(
1175                    labels = labels,
1176                    code = "missing_lp",
1177                    help = "mismatched `)`, it seems you missed a `(`.",
1178                    "expected `(` found `{}`",
1179                    token.lexeme
1180                )
1181            })?;
1182
1183            return Ok(Expr::Grouping(Arc::new(Grouping {
1184                expr,
1185                parens: (lp_token.clone(), rp_token.clone()),
1186            })));
1187        }
1188
1189        // "[" ( expr ),* "]"
1190        if self.match_token(&LeftBracket) {
1191            let lb_token = self.previous().clone();
1192
1193            let mut items = vec![];
1194            if !self.check(&RightBracket) {
1195                loop {
1196                    let expr = self.expression()?;
1197                    items.push(expr);
1198
1199                    // we've reached the end of arguments
1200                    if !self.match_token(&Comma) {
1201                        break;
1202                    }
1203                }
1204            }
1205
1206            let rb_token = self.consume(&RightBracket, |token| {
1207                // todo
1208                // miette!("expected ] after item list, found {token}")
1209                let labels = vec![LabeledSpan::at(token.span(), "expected a `]`")];
1210
1211                miette!(
1212                    labels = labels,
1213                    code = "missing_rb",
1214                    help = "mismatched `[`, it seems you missed a `]`.",
1215                    "expected `]`, found `{}`",
1216                    token.lexeme
1217                )
1218            })?;
1219
1220            return Ok(Expr::List(Arc::new(List {
1221                items,
1222                brackets: (lb_token, rb_token.clone()),
1223            })));
1224        }
1225
1226        let cspan = self.previous().span_to(self.peek().span());
1227        let labels = vec![
1228            LabeledSpan::at(self.peek().span(), "primary expected here"),
1229            // LabeledSpan::at(cspan, "consider checking your upstream code"),
1230        ];
1231        // todo improve this message
1232        let report = miette!(
1233            labels = labels,
1234            help = "a primary is made up of the following set:\n\
1235            [expression | ident | literal | list]",
1236            "expected primary, instead found {}\n",
1237            self.peek()
1238        )
1239        .with_source_code(self.named_source.clone());
1240        // mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
1241        Err(report)
1242    }
1243}
1244/// Helper methods for the `Parser2` struct.
1245impl Parser {
1246    /// Synchronizes the parser by advancing tokens until it reaches a likely
1247    /// starting point for a new statement or declaration.
1248    fn synchronize(&mut self) {
1249        self.advance();
1250
1251        while !self.is_at_end() {
1252            // this is "good enough" for now
1253            // sometimes it does not recover properly
1254            // more robust recovery would great
1255            // it is worth looking into...
1256            match self.peek().token_type {
1257                Procedure | Repeat | For | If | Return | Continue | Break | Import | Export => {
1258                    return
1259                }
1260                _ => (),
1261            }
1262
1263            self.advance();
1264        }
1265    }
1266
1267    /// Consumes the next token if it matches the expected `token_type`.
1268    ///
1269    /// If the next token matches the expected type, it is consumed and returned.
1270    /// Otherwise, it reports an error using the provided `report` function.
1271    ///
1272    /// # Arguments
1273    ///
1274    /// * `token_type` - The expected token type to consume.
1275    /// * `report` - A closure that generates an error report when the token does not match.
1276    ///
1277    /// # Returns
1278    ///
1279    /// * `Ok(&Token)` - The consumed token if it matches the expected type.
1280    /// * `Err(miette::Report)` - An error report if the token does not match.
1281    fn consume(
1282        &mut self,
1283        token_type: &TokenType,
1284        report: impl FnOnce(&Token) -> Report,
1285    ) -> miette::Result<&Token> {
1286        let next_token = self.peek().clone();
1287        if next_token.token_type() == token_type {
1288            self.advance();
1289            let token = self.previous();
1290            Ok(token)
1291        } else {
1292            Err(report(&next_token).with_source_code(self.named_source.clone()))
1293        }
1294    }
1295
1296    /// Consumes consecutive semicolon tokens (`SoftSemi`).
1297    ///
1298    /// This method advances the parser while the current token is a semicolon.
1299    /// It helps in ignoring redundant semicolons in the input.
1300    fn take_semis(&mut self) {
1301        while self.check(&SoftSemi) {
1302            self.advance();
1303        }
1304    }
1305
1306    /// Checks if the current token matches the given `typ` without consuming it.
1307    ///
1308    /// # Arguments
1309    ///
1310    /// * `typ` - The token type to check for.
1311    ///
1312    /// # Returns
1313    ///
1314    /// * `true` if the current token matches `typ`.
1315    /// * `false` otherwise.
1316    fn check(&self, typ: &TokenType) -> bool {
1317        if self.is_at_end() {
1318            return false;
1319        }
1320
1321        self.peek().token_type() == typ
1322    }
1323
1324    /// Confirms that the previous token matches the expected `typ`.
1325    ///
1326    /// # Arguments
1327    ///
1328    /// * `typ` - The expected token type of the previous token.
1329    ///
1330    /// # Returns
1331    ///
1332    /// * `Ok(())` if the previous token matches `typ`.
1333    /// * `Err(miette::Report)` if it does not match.
1334    ///
1335    /// # Errors
1336    ///
1337    /// Returns an error report indicating the mismatch between the expected and actual token types.
1338    fn confirm(&self, typ: &TokenType) -> miette::Result<()> {
1339        let previous = self.previous();
1340
1341        if &previous.token_type != typ {
1342            return Err(miette!(
1343                "Expected previous token to be {:?}, but found {:?}.",
1344                typ,
1345                previous.token_type
1346            ));
1347        }
1348
1349        Ok(())
1350    }
1351
1352    /// Attempts to match and consume the next token if it matches `token_type`.
1353    ///
1354    /// # Arguments
1355    ///
1356    /// * `token_type` - The token type to match and consume.
1357    ///
1358    /// # Returns
1359    ///
1360    /// * `true` if the token was matched and consumed.
1361    /// * `false` otherwise.
1362    fn match_token(&mut self, token_type: &TokenType) -> bool {
1363        if self.check(token_type) {
1364            self.advance();
1365            return true;
1366        }
1367        false
1368    }
1369
1370    /// Attempts to match and consume any one of the specified token types.
1371    ///
1372    /// # Arguments
1373    ///
1374    /// * `types` - A slice of token types to match and consume.
1375    ///
1376    /// # Returns
1377    ///
1378    /// * `true` if any of the token types were matched and consumed.
1379    /// * `false` otherwise.
1380    fn match_tokens(&mut self, types: &[TokenType]) -> bool {
1381        for ty in types {
1382            if self.match_token(ty) {
1383                return true;
1384            }
1385        }
1386        false
1387    }
1388
1389    /// Consumes the next token and returns it.
1390    ///
1391    /// Advances the parser's current position and returns the token that was just consumed.
1392    ///
1393    /// # Returns
1394    ///
1395    /// * `&Token` - The token that was consumed.
1396    fn advance(&mut self) -> &Token {
1397        if !self.is_at_end() {
1398            self.current += 1;
1399        }
1400
1401        self.previous()
1402    }
1403
1404    /// Returns the current token without consuming it.
1405    ///
1406    /// # Returns
1407    ///
1408    /// * `&Token` - The current token.
1409    ///
1410    /// # Panics
1411    ///
1412    /// Panics if there is no token to peek at (should not happen if `is_at_end` is correctly used).
1413    fn peek(&self) -> &Token {
1414        self.tokens
1415            .get(self.current)
1416            .expect("Internal error: attempted to peek token when there is no token to peek.")
1417    }
1418
1419    /// Returns the previously consumed token.
1420    ///
1421    /// # Returns
1422    ///
1423    /// * `&Token` - The previously consumed token.
1424    ///
1425    /// # Panics
1426    ///
1427    /// Panics if there is no previous token (i.e., if at the start of the token stream).
1428    fn previous(&self) -> &Token {
1429        if self.current == 0 {
1430            panic!("Internal error: there is no previous token.");
1431        }
1432
1433        self.tokens
1434            .get(self.current - 1)
1435            .expect("Internal error: failed to retrieve previous token.")
1436    }
1437
1438    /// Determines if the parser has reached the end of the token stream.
1439    ///
1440    /// # Returns
1441    ///
1442    /// * `true` if the current token is `Eof`.
1443    /// * `false` otherwise.
1444    fn is_at_end(&self) -> bool {
1445        self.peek().token_type == Eof
1446    }
1447}
1448
1449pub(super) mod warning {
1450    use crate::parser::Parser;
1451    use miette::Report;
1452
1453    impl Parser {
1454        pub(super) fn warning(&mut self, report: Report) {
1455            self._warnings
1456                .push(report.with_source_code(self.named_source.clone()))
1457        }
1458    }
1459}
1460
1461trait ExpectMiette<T> {
1462    fn miette_expect(self, report_handler: fn() -> Report) -> T;
1463}
1464
1465impl<T, E> ExpectMiette<T> for Result<T, E> {
1466    fn miette_expect(self, report_handler: fn() -> Report) -> T {
1467        match self {
1468            Ok(t) => t,
1469            Err(_) => {
1470                let _report = report_handler();
1471                panic!()
1472            }
1473        }
1474    }
1475}
1476
1477impl<T> ExpectMiette<T> for Option<T> {
1478    fn miette_expect(self, report_handler: fn() -> Report) -> T {
1479        match self {
1480            Some(t) => t,
1481            None => {
1482                let _report = report_handler();
1483                panic!()
1484            }
1485        }
1486    }
1487}