mathic 0.2.0

A compiler with builtin support of symbolic operations, built with LLVM/MLIR
use crate::parser::{
    MathicParser, ParserResult, Span,
    ast::{
        declaration::DeclStmt,
        expression::ExprStmt,
        statement::{BlockStmt, Stmt, StmtKind},
    },
    token::Token,
};

impl<'a> MathicParser<'a> {
    pub fn parse_stmt(&self) -> ParserResult<Stmt> {
        let lookahead = self.peek_not_none()?;

        let start_span = lookahead.span;

        let (kind, span) = match lookahead.token {
            Token::Df => {
                let func = self.parse_func()?;

                let span = Span::from_merged_spans(start_span, self.current_span());
                (StmtKind::Decl(DeclStmt::Func(func)), span)
            }
            Token::If => {
                let if_stmt = self.parse_if_stmt()?;
                let span = Span::from_merged_spans(start_span, self.current_span());
                (StmtKind::If(if_stmt), span)
            }
            Token::While => {
                let while_stmt = self.parse_while_stmt()?;
                let span = Span::from_merged_spans(start_span, self.current_span());
                (StmtKind::While(while_stmt), span)
            }
            Token::For => {
                let for_stmt = self.parse_for_stmt()?;
                let span = Span::from_merged_spans(start_span, self.current_span());
                (StmtKind::For(for_stmt), span)
            }
            Token::Let => {
                let var = self.parse_var_decl()?;
                let span = Span::from_merged_spans(start_span, var.expr.span);
                (StmtKind::Decl(DeclStmt::Var(var)), span)
            }
            Token::Struct => {
                let struct_decl = self.parse_struct()?;
                let span = Span::from_merged_spans(start_span, self.current_span());
                (StmtKind::Decl(DeclStmt::Struct(struct_decl)), span)
            }
            Token::Sym => {
                let sym = self.parse_sym_decl()?;
                let span = Span::from_merged_spans(start_span, self.current_span());
                (StmtKind::Decl(DeclStmt::Sym(sym)), span)
            }
            Token::Return => {
                let expr = self.parse_return()?;
                let span = Span::from_merged_spans(start_span, expr.span);
                (StmtKind::Return(expr), span)
            }
            Token::LBrace => {
                let block = self.parse_block()?;
                let span = if let Some(last) = block.stmts.last() {
                    Span::from_merged_spans(start_span, last.span)
                } else {
                    start_span
                };
                (StmtKind::Block(block), span)
            }
            _ => {
                let expr_stmt = self.parse_expr_stmt()?;
                (expr_stmt.kind, expr_stmt.span)
            }
        };

        Ok(Stmt { kind, span })
    }

    pub fn parse_block(&self) -> ParserResult<BlockStmt> {
        let start_span = self.consume_token(Token::LBrace)?;

        let mut stmts = Vec::new();

        while !self.check_next(Token::RBrace)? {
            stmts.push(self.parse_stmt()?);
        }

        let end_span = self.consume_token(Token::RBrace)?;

        Ok(BlockStmt {
            stmts,
            span: Span::from_merged_spans(start_span.span, end_span.span),
        })
    }

    pub fn parse_return(&self) -> ParserResult<ExprStmt> {
        let return_token = self.next()?;

        let value = self.parse_expr()?;

        self.consume_token(Token::Semicolon)?;

        let span = Span::from_merged_spans(return_token.span, self.current_span());

        Ok(ExprStmt {
            kind: value.kind,
            span,
        })
    }

    fn parse_expr_stmt(&self) -> ParserResult<Stmt> {
        let expr = self.parse_expr()?;

        self.consume_token(Token::Semicolon)?;

        let span = Span::from_merged_spans(expr.span, self.current_span());

        Ok(Stmt {
            kind: StmtKind::Expr(expr),
            span,
        })
    }
}