use crate::scanner::token::Token;
use core::fmt;
#[derive(Debug, Clone)]
pub enum Expression {
LiteralStr(Literal<String>), 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)
}
}