rascal_parser 0.1.2

Rascal programming language parser.
Documentation
/// These binding power functions return the "binding power", or precedence, of an operation. This
/// allows the parser to decide which grouping of operators-to-operands should be chosen. This is
/// equivalent to the PEMDAS rules for algebra.
///
/// For this given statement:
///
/// `a + b * c`
///
/// The multiplication operator should take precedence over the addition operator, so it has a
/// higher binding power. For cases in which there are a chain of operators with the same
/// precedence, we bias the precedence to the left to ensure that in these ambiguous cases, the
/// expression is evaluated left to right.
pub mod binding_power {

    use crate::{parser::ParserError, scanner::token::Token};

    /// The binding power of the operator, on the left hand side operand.
    pub struct Lhs(u8);
    impl From<u8> for Lhs {
        fn from(num: u8) -> Self {
            Lhs(num)
        }
    }
    impl From<Lhs> for u8 {
        fn from(lhs: Lhs) -> Self {
            lhs.0
        }
    }

    /// The binding power of the operator, on the right hand side operand.
    pub struct Rhs(u8);
    impl From<u8> for Rhs {
        fn from(num: u8) -> Self {
            Rhs(num)
        }
    }
    impl From<Rhs> for u8 {
        fn from(rhs: Rhs) -> Self {
            rhs.0
        }
    }

    /// Given a token used as a prefix operator, returns the right hand side binding power.
    pub fn prefix(token: &Token) -> Result<Rhs, ParserError> {
        let res = match token {
            Token::Plus | Token::Minus => ((), 9),
            t => return Err(ParserError::UnexpectedToken(t.clone())),
        };
        Ok(res.1.into())
    }

    /// Given a token used as a postfix operator, returns the left hand side binding power.
    pub fn postfix(token: Token) -> Option<Lhs> {
        let res = match token {
            Token::Bang => (11, ()),
            //'[' => (11, ()),
            _ => return None,
        };
        Some(res.0.into())
    }

    /// Given a token used as a infix operator, returns the binding power of both sides.
    pub fn infix(token: Token) -> Option<(Lhs, Rhs)> {
        let res = match token {
            Token::Equal => (2, 1),
            //'?' => (4, 3),
            Token::Plus | Token::Minus => (5, 6),
            Token::Star | Token::Slash => (7, 8),
            Token::Dot => (14, 13),
            _ => return None,
        };
        Some((res.0.into(), res.1.into()))
    }
}