rascal_parser 0.1.2

Rascal programming language parser.
Documentation
use crate::scanner::token::Token;
use core::fmt;

#[derive(Debug, Clone)]
pub enum Expression {
    LiteralStr(Literal<String>), // TODO: when adding types, condense these into a single `Literal(type, value)`.
    // Can then use this to type check expressions, that the
    // literals' type matches the variables' types.
    LiteralNum(Literal<f64>),
    LiteralBool(Literal<bool>),
    Unary(Unary),
    Binary(Binary),
    Grouping(Grouping),
}
impl Expression {
    pub fn literal_str(value: String) -> Expression {
        Expression::LiteralStr(Literal { value })
    }
    pub fn literal_num(value: f64) -> Expression {
        Expression::LiteralNum(Literal { value })
    }
    pub fn literal_bool(value: bool) -> Expression {
        Expression::LiteralBool(Literal { value })
    }
    pub fn unary(operator: Token, right: Expression) -> Expression {
        Expression::Unary(Unary {
            operator,
            right: Box::new(right),
        })
    }
    pub fn binary(left: Expression, operator: Token, right: Expression) -> Expression {
        Expression::Binary(Binary {
            left: Box::new(left),
            operator,
            right: Box::new(right),
        })
    }
    pub fn grouping(expression: Expression) -> Expression {
        Expression::Grouping(Grouping {
            expression: Box::new(expression),
        })
    }
}
impl fmt::Display for Expression {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self {
            &Self::LiteralStr(s) => fmt::Display::fmt(&s, f),
            &Self::LiteralNum(s) => fmt::Display::fmt(&s, f),
            &Self::LiteralBool(s) => fmt::Display::fmt(&s, f),
            &Self::Unary(s) => fmt::Display::fmt(&s, f),
            &Self::Binary(s) => fmt::Display::fmt(&s, f),
            &Self::Grouping(s) => fmt::Display::fmt(&s, f),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Binary {
    pub left: Box<Expression>,
    pub operator: Token,
    pub right: Box<Expression>,
}
impl fmt::Display for Binary {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({} {} {})", self.operator, self.left, self.right)
    }
}

#[derive(Debug, Clone)]
pub struct Grouping {
    pub expression: Box<Expression>,
}
impl fmt::Display for Grouping {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({})", self.expression)
    }
}

#[derive(Debug, Clone)]
pub struct Literal<T: fmt::Display + core::fmt::Debug> {
    pub value: T,
}
impl<T: fmt::Display + core::fmt::Debug> fmt::Display for Literal<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.value)
    }
}
impl From<f64> for Literal<f64> {
    fn from(value: f64) -> Self {
        Literal { value }
    }
}
impl From<String> for Literal<String> {
    fn from(value: String) -> Self {
        Literal { value }
    }
}
impl From<bool> for Literal<bool> {
    fn from(value: bool) -> Self {
        Literal { value }
    }
}

#[derive(Debug, Clone)]
pub struct Unary {
    pub operator: Token,
    pub right: Box<Expression>,
}
impl fmt::Display for Unary {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}{})", self.operator, self.right)
    }
}