use std::fmt::{self, Display, Formatter};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Function<'src>
{
pub parameters: Option<Vec<&'src str>>,
pub body: Expression<'src>
}
impl Display for Function<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
if let Some(ref parameters) = self.parameters
{
for (i, param) in parameters.iter().enumerate()
{
if i > 0
{
write!(f, ", ")?;
}
write!(f, "{}", param)?;
}
write!(f, ": ")?;
}
write!(f, "{}", self.body)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Group<'src>
{
pub expression: Box<Expression<'src>>
}
impl Display for Group<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "({})", self.expression)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Constant(pub i32);
impl Display for Constant
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{}", self.0)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Variable<'src>(pub &'src str);
impl Display for Variable<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{{{}}}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Range<'src>
{
pub start: Box<Expression<'src>>,
pub end: Box<Expression<'src>>
}
impl Display for Range<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "[{}:{}]", self.start, self.end)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expression<'src>
{
Group(Group<'src>),
Constant(Constant),
Variable(Variable<'src>),
Range(Range<'src>),
Dice(DiceExpression<'src>),
Arithmetic(ArithmeticExpression<'src>)
}
impl<'src> Expression<'src>
{
pub fn accept<V: ASTVisitor<'src>>(
&'src self,
visitor: &mut V
) -> Result<V::Output, V::Error>
{
match self
{
Expression::Group(g) => visitor.visit_group(g),
Expression::Constant(c) => visitor.visit_constant(c),
Expression::Variable(v) => visitor.visit_variable(v),
Expression::Range(r) => visitor.visit_range(r),
Expression::Dice(d) => d.accept(visitor),
Expression::Arithmetic(a) => a.accept(visitor)
}
}
}
impl Display for Expression<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
match self
{
Expression::Group(group) => write!(f, "{}", group),
Expression::Constant(constant) => write!(f, "{}", constant),
Expression::Variable(variable) => write!(f, "{}", variable),
Expression::Range(range) => write!(f, "{}", range),
Expression::Dice(dice) => write!(f, "{}", dice),
Expression::Arithmetic(arithmetic) => write!(f, "{}", arithmetic)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StandardDice<'src>
{
pub count: Box<Expression<'src>>,
pub faces: Box<Expression<'src>>
}
impl Display for StandardDice<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{}D{}", self.count, self.faces)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CustomDice<'src>
{
pub count: Box<Expression<'src>>,
pub faces: Vec<i32>
}
impl Display for CustomDice<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{}D[", self.count)?;
for (i, face) in self.faces.iter().enumerate()
{
if i > 0
{
write!(f, ", ")?;
}
write!(f, "{}", face)?;
}
write!(f, "]")
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DropLowest<'src>
{
pub dice: Box<DiceExpression<'src>>,
pub drop: Option<Box<Expression<'src>>>
}
impl Display for DropLowest<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{} drop lowest", self.dice)?;
if let Some(ref drop) = self.drop
{
write!(f, " {}", drop)?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DropHighest<'src>
{
pub dice: Box<DiceExpression<'src>>,
pub drop: Option<Box<Expression<'src>>>
}
impl Display for DropHighest<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{} drop highest", self.dice)?;
if let Some(ref drop) = self.drop
{
write!(f, " {}", drop)?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DiceExpression<'src>
{
Standard(StandardDice<'src>),
Custom(CustomDice<'src>),
DropLowest(DropLowest<'src>),
DropHighest(DropHighest<'src>)
}
impl<'src> DiceExpression<'src>
{
pub fn accept<V: ASTVisitor<'src>>(
&'src self,
visitor: &mut V
) -> Result<V::Output, V::Error>
{
match self
{
DiceExpression::Standard(d) => visitor.visit_standard_dice(d),
DiceExpression::Custom(d) => visitor.visit_custom_dice(d),
DiceExpression::DropLowest(d) => visitor.visit_drop_lowest(d),
DiceExpression::DropHighest(d) => visitor.visit_drop_highest(d)
}
}
}
impl Display for DiceExpression<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
match self
{
DiceExpression::Standard(dice) => write!(f, "{}", dice),
DiceExpression::Custom(dice) => write!(f, "{}", dice),
DiceExpression::DropLowest(drop) => write!(f, "{}", drop),
DiceExpression::DropHighest(drop) => write!(f, "{}", drop)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Add<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>
}
impl Display for Add<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{} + {}", self.left, self.right)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Sub<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>
}
impl Display for Sub<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{} - {}", self.left, self.right)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Mul<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>
}
impl Display for Mul<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{} * {}", self.left, self.right)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Div<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>
}
impl Display for Div<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{} / {}", self.left, self.right)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Mod<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>
}
impl Display for Mod<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{} % {}", self.left, self.right)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Exp<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>
}
impl Display for Exp<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{} ^ {}", self.left, self.right)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Neg<'src>
{
pub operand: Box<Expression<'src>>
}
impl Display for Neg<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "-{}", self.operand)
}
}
pub trait ASTVisitor<'src>
{
type Output;
type Error;
fn visit_function(
&mut self,
node: &'src Function<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_group(
&mut self,
node: &'src Group<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_constant(
&mut self,
node: &Constant
) -> Result<Self::Output, Self::Error>;
fn visit_variable(
&mut self,
node: &'src Variable<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_range(
&mut self,
node: &'src Range<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_standard_dice(
&mut self,
node: &'src StandardDice<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_custom_dice(
&mut self,
node: &'src CustomDice<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_drop_lowest(
&mut self,
node: &'src DropLowest<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_drop_highest(
&mut self,
node: &'src DropHighest<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_add(
&mut self,
node: &'src Add<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_sub(
&mut self,
node: &'src Sub<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_mul(
&mut self,
node: &'src Mul<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_div(
&mut self,
node: &'src Div<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_mod(
&mut self,
node: &'src Mod<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_exp(
&mut self,
node: &'src Exp<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_neg(
&mut self,
node: &'src Neg<'src>
) -> Result<Self::Output, Self::Error>;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ArithmeticExpression<'src>
{
Add(Add<'src>),
Sub(Sub<'src>),
Mul(Mul<'src>),
Div(Div<'src>),
Mod(Mod<'src>),
Exp(Exp<'src>),
Neg(Neg<'src>)
}
impl<'src> ArithmeticExpression<'src>
{
pub fn accept<V: ASTVisitor<'src>>(
&'src self,
visitor: &mut V
) -> Result<V::Output, V::Error>
{
match self
{
ArithmeticExpression::Add(a) => visitor.visit_add(a),
ArithmeticExpression::Sub(s) => visitor.visit_sub(s),
ArithmeticExpression::Mul(m) => visitor.visit_mul(m),
ArithmeticExpression::Div(d) => visitor.visit_div(d),
ArithmeticExpression::Mod(m) => visitor.visit_mod(m),
ArithmeticExpression::Exp(e) => visitor.visit_exp(e),
ArithmeticExpression::Neg(n) => visitor.visit_neg(n)
}
}
}
impl Display for ArithmeticExpression<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
match self
{
ArithmeticExpression::Add(add) => write!(f, "{}", add),
ArithmeticExpression::Sub(sub) => write!(f, "{}", sub),
ArithmeticExpression::Mul(mul) => write!(f, "{}", mul),
ArithmeticExpression::Div(div) => write!(f, "{}", div),
ArithmeticExpression::Mod(r#mod) => write!(f, "{}", r#mod),
ArithmeticExpression::Exp(exp) => write!(f, "{}", exp),
ArithmeticExpression::Neg(neg) => write!(f, "{}", neg)
}
}
}