bomlamaal 0.1.0

Bømlamål as a programming language.
use super::ast::Node;
use super::lexer::Lexer;
use super::token::Token;
use super::types::Type;

pub struct Parser {
    current_token: Token,
    lexer: Box<Lexer>,
}

impl Parser {
    pub fn new(mut lexer: Box<Lexer>) -> Self {
        Self {
            current_token: lexer.get_next_token(),
            lexer: lexer,
        }
    }

    fn program(&mut self) -> Box<Node> {
        let node = self.compound_statement();
        self.eat(Type::DOT);
        return node;
    }

    fn compound_statement(&mut self) -> Box<Node> {
        self.eat(Type::BEGIN);
        let nodes = self.statement_list();
        self.eat(Type::END);

        return Node::compound_op(self.current_token.clone(), nodes);
    }

    fn statement_list(&mut self) -> Vec<Box<Node>> {
        let node = self.statement();

        let mut v = Vec::new();

        v.push(node);

        while *self.current_token.get_type() == Type::SEMI {
            self.eat(Type::SEMI);
            v.push(self.statement());
        }

        return v;
    }

    fn statement(&mut self) -> Box<Node> {
        match *self.current_token.get_type() {
            Type::BEGIN => {
                return self.compound_statement();
            }
            Type::VARIABLE => {
                return self.assignment_statement();
            }
            _ => return self.empty(),
        }
    }

    fn assignment_statement(&mut self) -> Box<Node> {
        let left = self.variable();
        let token = self.current_token.clone();
        self.eat(Type::ASSIGN);
        let right = self.expr();
        return Node::assign(token, left, right);
    }

    fn variable(&mut self) -> Box<Node> {
        let node = Node::var(self.current_token.clone());
        self.eat(Type::VARIABLE);
        return node;
    }

    fn factor(&mut self) -> Box<Node> {
        let token = self.current_token.clone();

        match *token.get_type() {
            Type::MINUS => {
                self.eat(Type::MINUS);
                let node = Node::unary_op(token, self.expr());
                return node;
            }
            Type::PLUS => {
                self.eat(Type::PLUS);
                let node = Node::unary_op(token, self.expr());
                return node;
            }
            Type::LPAREN => {
                self.eat(Type::LPAREN);
                let node = self.expr();
                self.eat(Type::RPAREN);
                return node;
            }
            Type::INTEGER => {
                self.eat(Type::INTEGER);
                let node = Node::num(token);
                return node;
            }
            _ => {
                return self.variable();
            }
        }
    }

    fn term(&mut self) -> Box<Node> {
        let mut node = self.factor();

        while vec![Type::MULTIPLY, Type::DIVIDE].contains(&self.current_token.get_type()) {
            let token = self.current_token.clone();

            if *token.get_type() == Type::MULTIPLY {
                self.eat(Type::MULTIPLY);
            }

            if *token.get_type() == Type::DIVIDE {
                self.eat(Type::DIVIDE);
            }

            node = Node::bin_op(token, node, self.factor());
        }

        return node;
    }

    pub fn expr(&mut self) -> Box<Node> {
        let mut node = self.term();

        while vec![Type::PLUS, Type::MINUS].contains(&self.current_token.get_type()) {
            let token = self.current_token.clone();

            if *token.get_type() == Type::PLUS {
                self.eat(Type::PLUS);
            }

            if *token.get_type() == Type::MINUS {
                self.eat(Type::MINUS);
            }

            node = Node::bin_op(token, node, self.term());
        }

        return node;
    }

    fn empty(&self) -> Box<Node> {
        return Node::no_op();
    }

    fn eat(&mut self, _type: Type) {
        if *self.current_token.get_type() == _type {
            self.current_token = self.lexer.get_next_token()
        } else {
            self.error();
        }
    }

    pub fn parse(&mut self) -> Box<Node> {
        return self.program();
    }

    fn error(&self) {
        panic!("Syntax error");
    }
}