roost-lang 2.0.4

Interpreter library for the roost language
Documentation
use std::{mem, result};

use crate::{
    error::{Error, Result, Span},
    lexer::Lexer,
    nodes::*,
    tokens::{Token, TokenKind},
};

macro_rules! syntax_err {
    ($self:ident, $($arg:tt)*) => {
        error!(SyntaxError, $self.curr_tok.span, $($arg)*)
    };
}

macro_rules! expect {
    ($self:ident, $kind:ident, $name:expr) => {
        if !of_kinds!($self, $kind) {
            $self.errors.push(error_val!(
                SyntaxError,
                $self.curr_tok.span,
                "Expected {}, found '{}'",
                $name,
                $self.curr_tok.value(),
            ));
        }
        $self.advance();
    };
}

macro_rules! expect_ident {
    ($self:ident) => {{
        if !of_kinds!($self, Identifier) {
            $self.errors.push(error_val!(
                SyntaxError,
                $self.curr_tok.span,
                "Expected identifier, found '{}'",
                $self.curr_tok.value(),
            ));
        }
        let ident = $self.curr_tok.value.take().unwrap_or_default();
        $self.advance();
        ident
    }};
}

macro_rules! expect_eol {
    ($self:ident) => {
        if of_kinds!($self, Semicolon) {
            $self.advance();
        } else if $self.prev_tok.kind != TokenKind::Eol {
            $self.errors.push(error_val!(
                SyntaxError,
                $self.curr_tok.span,
                "Expected ';' or line break, found '{}'",
                $self.curr_tok.value(),
            ));
        }
    };
}

macro_rules! of_kinds {
    ($self:ident, Eol, Semicolon) => {{
        of_kinds!(@skip $self);
        $self.prev_tok.kind == TokenKind::Eol
            || $self.curr_tok.kind == TokenKind::Semicolon
    }};
    ($self:ident, $kind:ident) => {{
        of_kinds!(@skip $self);
        $self.curr_tok.kind == TokenKind::$kind
    }};
    ($self:ident, $($kind:ident),+ $(,)?) => {{
        of_kinds!(@skip $self);
        [$(TokenKind::$kind, )*].contains(&$self.curr_tok.kind)
    }};
    (@skip $self:ident) => {
        while $self.curr_tok.kind == TokenKind::Eol {
            $self.advance();
        }
    };
}

macro_rules! simple_expr {
    ($name:ident -> $type:ident : $($tok:ident),+ => $next:ident $kind:tt) => {
        fn $name(&mut self, expects_stmt: bool) -> Result<$type> {
            let start = self.curr_tok.span.start;
            simple_expr!(@kind self, start, expects_stmt, $type, $($tok),+ | $next, $kind)
        }
    };
    (@kind $self:ident, $start:ident, $expects_stmt:ident, $type:ident, $($tok:ident),+ | $next:ident, *) => {{
        let base = $self.$next($expects_stmt)?;
        let mut following = vec![];
        while of_kinds!($self, $($tok),+) {
            following.push(simple_expr!(@inner $self, $next, $($tok),+));
        }
        done!($type, $start, $self; base, following)
    }};
    (@kind $self:ident, $start:ident, $expects_stmt:ident, $type:ident, $($tok:ident),+ | $next:ident, ?) => {{
        let left = $self.$next($expects_stmt)?;
        let right = if of_kinds!($self, $($tok),+) {
            Some(simple_expr!(@inner $self, $next, $($tok),+))
        } else {
            None
        };
        done!($type, $start, $self; left, right)
    }};
    (@inner $self:ident, $next:ident, $_:ident) => {{
        $self.advance();
        $self.$next(false)?
    }};
    (@inner $self:ident, $next:ident, $($_:ident),+) => {{
        let tok = $self.curr_tok.kind;
        $self.advance();
        (tok, $self.$next(false)?)
    }};
}

macro_rules! done {
    ($type:ident, $start:ident, $self:ident; $($tt:tt)*) => {
        Ok($type {
            span: Span::new($start, $self.prev_tok.span.end),
            $($tt)*
        })
    };
}

pub struct Parser<'i> {
    lexer: Lexer<'i>,
    prev_tok: Token,
    curr_tok: Token,
    errors: Vec<Error>,
}

impl<'i> Parser<'i> {
    pub fn new(lexer: Lexer<'i>) -> Self {
        Self {
            lexer,
            prev_tok: Token::dummy(),
            curr_tok: Token::dummy(),
            errors: vec![],
        }
    }

    pub fn parse(&mut self) -> result::Result<Program, Vec<Error>> {
        self.advance();
        let statements = match Self::program(self) {
            Ok(statements) => statements,
            Err(error) => {
                self.errors.push(error);
                return Err(mem::take(&mut self.errors));
            }
        };

        if !of_kinds!(self, Eof) {
            self.errors
                .push(error_val!(SyntaxError, self.curr_tok.span, "Expected EOF",));
        }
        if !self.errors.is_empty() {
            return Err(mem::take(&mut self.errors));
        }
        Ok(statements)
    }

    fn advance(&mut self) {
        mem::swap(&mut self.prev_tok, &mut self.curr_tok);
        self.curr_tok = match self.lexer.next_token() {
            Ok(token) => token,
            Err((error, token)) => {
                self.errors.push(error);
                token
            }
        };
    }

    // ---------------------------------------

    #[inline]
    fn program(&mut self) -> Result<Program> {
        self.statements()
    }

    fn statements(&mut self) -> Result<Statements> {
        let mut stmts = vec![];
        if !of_kinds!(self, RBrace, Eof) {
            stmts.push(self.statement()?);
            while of_kinds!(self, Eol, Semicolon) {
                if self.curr_tok.kind == TokenKind::Semicolon {
                    self.advance();
                }
                if of_kinds!(self, RBrace, Eof) {
                    break;
                }
                stmts.push(self.statement()?);
            }
        }

        Ok(stmts)
    }

    fn block(&mut self) -> Result<Block> {
        if of_kinds!(self, LBrace) {
            Ok(self.block_expr()?)
        } else {
            Ok(vec![self.statement()?])
        }
    }

    fn statement(&mut self) -> Result<Statement> {
        Ok(match self.curr_tok.kind {
            TokenKind::Var => Statement::Var(self.var_stmt()?),
            TokenKind::Fun => Statement::Function(self.function_decl()?),
            TokenKind::Class => Statement::Class(self.class_decl()?),
            TokenKind::Break => Statement::Break(self.break_stmt()?),
            TokenKind::Continue => Statement::Continue(self.continue_stmt()?),
            TokenKind::Return => Statement::Return(self.return_stmt()?),
            _ => Statement::Expr(self.expression(true)?),
        })
    }

    fn var_stmt(&mut self) -> Result<VarStmt> {
        let start = self.curr_tok.span.start;

        expect!(self, Var, "'var'");
        let ident = expect_ident!(self);

        let expr = if of_kinds!(self, Assign) {
            self.advance();
            Some(self.expression(false)?)
        } else {
            None
        };

        done!(VarStmt, start, self; ident, expr)
    }

    fn function_decl(&mut self) -> Result<FunctionDecl> {
        let start = self.curr_tok.span.start;

        expect!(self, Fun, "'fun'");
        let ident = expect_ident!(self);
        let args = self.params()?;
        let block = self.block()?;

        done!(FunctionDecl, start, self; ident, args, block)
    }

    fn class_decl(&mut self) -> Result<ClassDecl> {
        let start = self.curr_tok.span.start;

        expect!(self, Class, "'class'");
        let ident = expect_ident!(self);
        let block = self.member_block()?;

        done!(ClassDecl, start, self; ident, block)
    }

    fn break_stmt(&mut self) -> Result<BreakStmt> {
        let start = self.curr_tok.span.start;

        expect!(self, Break, "'break'");
        let expr = if !of_kinds!(self, Eof, Eol, RBrace) {
            Some(self.expression(false)?)
        } else {
            None
        };

        done!(BreakStmt, start, self; expr)
    }

    fn continue_stmt(&mut self) -> Result<ContinueStmt> {
        let start = self.curr_tok.span.start;

        expect!(self, Continue, "'continue'");

        done!(ContinueStmt, start, self;)
    }
    fn return_stmt(&mut self) -> Result<ReturnStmt> {
        let start = self.curr_tok.span.start;

        expect!(self, Return, "'return'");
        let expr = if !of_kinds!(self, Eof, Eol, RBrace) {
            Some(self.expression(false)?)
        } else {
            None
        };

        done!(ReturnStmt, start, self; expr)
    }

    fn member(&mut self) -> Result<Member> {
        let start = self.curr_tok.span.start;

        let is_static = of_kinds!(self, Static);
        if is_static {
            self.advance();
        }
        let kind = if of_kinds!(self, Var) {
            MemberKind::Attribute(self.var_stmt()?)
        } else {
            MemberKind::Method(self.function_decl()?)
        };

        done!(Member, start, self; is_static, kind)
    }

    fn member_block(&mut self) -> Result<MemberBlock> {
        let start = self.curr_tok.span.start;

        expect!(self, LBrace, "'{'");
        let mut members = vec![];
        while !of_kinds!(self, RBrace, Eof) {
            members.push(self.member()?);
            expect_eol!(self);
        }
        expect!(self, RBrace, "'}'");

        done!(MemberBlock, start, self; members)
    }

    #[inline]
    fn expression(&mut self, expects_stmt: bool) -> Result<Expression> {
        self.range_expr(expects_stmt)
    }

    fn range_expr(&mut self, expects_stmt: bool) -> Result<RangeExpr> {
        let start = self.curr_tok.span.start;

        if of_kinds!(self, Dots, DotsInclusive) {
            let tok = self.curr_tok.kind;
            self.advance();
            if of_kinds!(self, RParen, RBrack, RBrace, Comma, Eof)
                || of_kinds!(self, Eol, Semicolon)
            {
                if tok == TokenKind::DotsInclusive {
                    self.errors.push(error_val!(
                        SyntaxError,
                        self.curr_tok.span,
                        "Open ended range must be constructed with '..' not '..='",
                    ));
                }
                Ok(RangeExpr::Open)
            } else {
                let right = Box::new(self.or_expr(expects_stmt)?);
                Ok(RangeExpr::OpenStart(
                    tok,
                    right,
                    Span::new(start, self.prev_tok.span.end),
                ))
            }
        } else {
            let left = Box::new(self.or_expr(expects_stmt)?);
            if !of_kinds!(self, Dots, DotsInclusive) {
                Ok(RangeExpr::None(left))
            } else {
                let tok = self.curr_tok.kind;
                self.advance();
                if of_kinds!(self, RParen, RBrack, RBrace, Comma, Eof)
                    || of_kinds!(self, Eol, Semicolon)
                {
                    if tok == TokenKind::DotsInclusive {
                        self.errors.push(error_val!(
                            SyntaxError,
                            self.curr_tok.span,
                            "Open ended range must be constructed with '..' not '..='",
                        ));
                    }
                    Ok(RangeExpr::OpenEnd(
                        left,
                        Span::new(start, self.prev_tok.span.end),
                    ))
                } else {
                    let right = Box::new(self.or_expr(expects_stmt)?);
                    Ok(RangeExpr::Closed(
                        left,
                        tok,
                        right,
                        Span::new(start, self.prev_tok.span.end),
                    ))
                }
            }
        }
    }

    simple_expr!(or_expr -> OrExpr: Or => and_expr *);
    simple_expr!(and_expr -> AndExpr: And => bit_or_expr *);
    simple_expr!(bit_or_expr -> BitOrExpr: BitOr => bit_xor_expr *);
    simple_expr!(bit_xor_expr -> BitXorExpr: BitXor => bit_and_expr *);
    simple_expr!(bit_and_expr -> BitAndExpr: BitAnd => eq_expr *);
    simple_expr!(eq_expr -> EqExpr: Equal, NotEqual => rel_expr ?);
    simple_expr!(rel_expr -> RelExpr: LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual => shift_expr ?);
    simple_expr!(shift_expr -> ShiftExpr: ShiftLeft, ShiftRight => add_expr *);
    simple_expr!(add_expr -> AddExpr: Plus, Minus => mul_expr *);
    simple_expr!(mul_expr -> MulExpr: Star, Slash, Rem, Backslash => unary_expr *);

    fn unary_expr(&mut self, expects_stmt: bool) -> Result<UnaryExpr> {
        let start = self.curr_tok.span.start;

        if of_kinds!(self, Plus, Minus, Not) {
            let operator = self.curr_tok.kind;
            self.advance();
            let expr = Box::new(self.unary_expr(false)?);
            Ok(UnaryExpr::Unary {
                span: Span::new(start, self.prev_tok.span.end),
                operator,
                expr,
            })
        } else {
            Ok(UnaryExpr::Done(Box::new(self.exp_expr(expects_stmt)?)))
        }
    }

    fn exp_expr(&mut self, expects_stmt: bool) -> Result<ExpExpr> {
        let start = self.curr_tok.span.start;

        let base = self.assign_expr(expects_stmt)?;
        let exponent = if of_kinds!(self, Pow) {
            self.advance();
            Some(self.unary_expr(false)?)
        } else {
            None
        };

        done!(ExpExpr, start, self; base, exponent)
    }

    fn assign_expr(&mut self, expects_stmt: bool) -> Result<AssignExpr> {
        let start = self.curr_tok.span.start;

        let left = self.call_expr(expects_stmt)?;
        let right = if of_kinds!(
            self,
            Assign,
            StarAssign,
            SlashAssign,
            BackslashAssign,
            RemAssign,
            PlusAssign,
            MinusAssign,
            ShiftLeftAssign,
            ShiftRightAssign,
            BitAndAssign,
            BitXorAssign,
            BitOrAssign,
        ) {
            let tok = self.curr_tok.kind;
            self.advance();
            Some((tok, self.expression(false)?))
        } else {
            None
        };

        done!(AssignExpr, start, self; left, right)
    }

    fn call_expr(&mut self, expects_stmt: bool) -> Result<CallExpr> {
        let start = self.curr_tok.span.start;

        let base = self.member_expr(expects_stmt)?;
        let mut following = vec![];
        if of_kinds!(self, LParen) {
            following.push(CallPart::Args(self.args()?));
            while of_kinds!(self, LParen, Dot, LBrack) {
                following.push(self.call_part()?);
            }
        }

        done!(CallExpr, start, self; base, following)
    }

    fn member_expr(&mut self, expects_stmt: bool) -> Result<MemberExpr> {
        let start = self.curr_tok.span.start;

        let base = self.atom(expects_stmt)?;
        let mut following = vec![];
        while of_kinds!(self, Dot, LBrack) {
            following.push(self.member_part()?);
        }

        done!(MemberExpr, start, self; base, following)
    }

    fn atom(&mut self, expects_stmt: bool) -> Result<Atom> {
        let start = self.curr_tok.span.start;

        Ok(match self.curr_tok.kind {
            TokenKind::Number => {
                let num = self.curr_tok.take_value();
                self.advance();
                Atom::Number(match num.parse() {
                    Ok(num) => num,
                    Err(rust_decimal::Error::ErrorString(msg)) => {
                        error!(ValueError, (start, self.prev_tok.span.end), "{}", msg);
                    }
                    Err(rust_decimal::Error::ExceedsMaximumPossibleValue) => {
                        error!(
                            ValueError,
                            (start, self.prev_tok.span.end),
                            "Value too high"
                        );
                    }
                    Err(rust_decimal::Error::LessThanMinimumPossibleValue) => {
                        error!(ValueError, (start, self.prev_tok.span.end), "Value too low");
                    }
                    Err(rust_decimal::Error::ScaleExceedsMaximumPrecision(_)) => {
                        error!(
                            ValueError,
                            (start, self.prev_tok.span.end),
                            "Value too precise"
                        );
                    }
                    Err(_) => error!(
                        ValueError,
                        (start, self.prev_tok.span.end),
                        "Failed to parse number"
                    ),
                })
            }
            TokenKind::True => {
                self.advance();
                Atom::Bool(true)
            }
            TokenKind::False => {
                self.advance();
                Atom::Bool(false)
            }
            TokenKind::String => {
                let str = self.curr_tok.take_value();
                self.advance();
                Atom::String(str)
            }
            TokenKind::Null => {
                self.advance();
                Atom::Null
            }
            TokenKind::Identifier => {
                let name = self.curr_tok.take_value();
                self.advance();
                Atom::Identifier {
                    span: Span::new(start, self.prev_tok.span.end),
                    name,
                }
            }
            TokenKind::LParen => {
                self.advance();
                let expr = self.expression(false)?;
                expect!(self, RParen, "')'");
                Atom::Expr(expr)
            }
            TokenKind::LBrack => Atom::List(self.list_literal()?),
            TokenKind::If => Atom::IfExpr(self.if_expr()?),
            TokenKind::For => Atom::ForExpr(self.for_expr()?),
            TokenKind::While => Atom::WhileExpr(self.while_expr()?),
            TokenKind::Loop => Atom::LoopExpr(self.loop_expr()?),
            TokenKind::Fun => Atom::FunExpr(self.fun_expr()?),
            TokenKind::Class => Atom::ClassExpr(self.class_expr()?),
            TokenKind::Try => Atom::TryExpr(self.try_expr()?),
            TokenKind::LBrace => Atom::BlockExpr(self.block_expr()?),
            _ => syntax_err!(
                self,
                "Expected {}, found '{}'",
                if expects_stmt {
                    "statement"
                } else {
                    "expression"
                },
                self.curr_tok.value(),
            ),
        })
    }

    fn list_literal(&mut self) -> Result<ListLiteral> {
        expect!(self, LBrack, "'['");
        let mut exprs = vec![];
        if !of_kinds!(self, RBrack) {
            exprs.push(self.expression(false)?);
            while of_kinds!(self, Comma) {
                self.advance();
                if of_kinds!(self, RBrack) {
                    break;
                }
                exprs.push(self.expression(false)?);
            }
        }
        expect!(self, RBrack, "']'");

        Ok(exprs)
    }

    fn if_expr(&mut self) -> Result<IfExpr> {
        let start = self.curr_tok.span.start;

        expect!(self, If, "'if'");
        expect!(self, LParen, "'('");
        let cond = self.expression(false)?;
        expect!(self, RParen, "')'");
        let block = self.block()?;
        let else_block = if of_kinds!(self, Else) {
            self.advance();
            Some(self.block()?)
        } else {
            None
        };

        done!(IfExpr, start, self; cond, block, else_block)
    }

    fn for_expr(&mut self) -> Result<ForExpr> {
        let start = self.curr_tok.span.start;

        expect!(self, For, "'for'");
        expect!(self, LParen, "'('");
        let ident = expect_ident!(self);
        expect!(self, In, "'in'");
        let iter = self.expression(false)?;
        expect!(self, RParen, "')'");
        let block = self.block()?;

        done!(ForExpr, start, self; ident, iter, block)
    }

    fn while_expr(&mut self) -> Result<WhileExpr> {
        let start = self.curr_tok.span.start;

        expect!(self, While, "'while'");
        expect!(self, LParen, "'('");
        let cond = self.expression(false)?;
        expect!(self, RParen, "')'");
        let block = self.block()?;

        done!(WhileExpr, start, self; cond, block)
    }

    fn loop_expr(&mut self) -> Result<LoopExpr> {
        let start = self.curr_tok.span.start;

        expect!(self, Loop, "'loop'");
        let block = self.block()?;

        done!(LoopExpr, start, self; block)
    }

    fn fun_expr(&mut self) -> Result<FunExpr> {
        let start = self.curr_tok.span.start;

        expect!(self, Fun, "'fun'");
        let args = self.params()?;
        let block = self.block()?;

        done!(FunExpr, start, self; args, block)
    }

    fn class_expr(&mut self) -> Result<ClassExpr> {
        let start = self.curr_tok.span.start;

        expect!(self, Class, "'class'");
        let block = self.member_block()?;

        done!(ClassExpr, start, self; block)
    }

    fn try_expr(&mut self) -> Result<TryExpr> {
        let start = self.curr_tok.span.start;

        expect!(self, Try, "'try'");
        let try_block = self.block()?;
        expect!(self, Catch, "'catch'");
        expect!(self, LParen, "'('");
        let ident = expect_ident!(self);
        expect!(self, RParen, "')'");
        let catch_block = self.block()?;

        done!(TryExpr, start, self; try_block, ident, catch_block)
    }

    fn block_expr(&mut self) -> Result<BlockExpr> {
        expect!(self, LBrace, "'{'");
        let stmts = self.statements()?;
        expect!(self, RBrace, "'}'");

        Ok(stmts)
    }

    fn member_part(&mut self) -> Result<MemberPart> {
        Ok(match self.curr_tok.kind {
            TokenKind::Dot => {
                self.advance();
                MemberPart::Field(expect_ident!(self))
            }
            TokenKind::LBrack => {
                self.advance();
                let expr = self.expression(false)?;
                expect!(self, RBrack, "']'");
                MemberPart::Index(expr)
            }
            _ => error!(
                SyntaxError,
                self.curr_tok.span,
                "Expected '.' or '[', found '{}'",
                self.curr_tok.value(),
            ),
        })
    }

    fn call_part(&mut self) -> Result<CallPart> {
        Ok(if of_kinds!(self, LParen) {
            CallPart::Args(self.args()?)
        } else {
            CallPart::Member(self.member_part()?)
        })
    }

    fn args(&mut self) -> Result<Args> {
        let mut args = vec![];
        expect!(self, LParen, "'('");
        if !of_kinds!(self, RParen) {
            args.push(self.expression(false)?);
            while of_kinds!(self, Comma) {
                self.advance();
                if of_kinds!(self, RParen) {
                    break;
                }
                args.push(self.expression(false)?);
            }
        }
        expect!(self, RParen, "')'");
        Ok(args)
    }

    fn params(&mut self) -> Result<Params> {
        let mut args = vec![];
        expect!(self, LParen, "'('");
        if !of_kinds!(self, RParen) {
            args.push(expect_ident!(self));
            while of_kinds!(self, Comma) {
                self.advance();
                if of_kinds!(self, RParen) {
                    break;
                }
                args.push(expect_ident!(self));
            }
        }
        expect!(self, RParen, "')'");
        Ok(args)
    }
}