mod display;
mod impls;
mod traversal;
mod walk;
use std::{
borrow::Cow,
fmt::{self, Display, Formatter}
};
pub(crate) use walk::{Event, Node, Walk};
use crate::span::{SourceSpan, Spanned};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Function<'src>
{
pub parameters: Option<Vec<Parameter<'src>>>,
pub body: Expression<'src>,
pub span: SourceSpan
}
impl<'src> Function<'src>
{
pub fn accept<'a, V: ASTVisitor<'a, 'src>>(
&'a self,
visitor: &mut V
) -> Result<V::Output, V::Error>
{
visitor.enter_function(self)?;
let body = self.body.accept(visitor)?;
visitor.visit_function(self, body)
}
}
impl Display for Function<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Parameter<'src>
{
pub name: Cow<'src, str>,
pub span: SourceSpan
}
impl Display for Parameter<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Group<'src>
{
pub expression: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Group<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Constant
{
pub value: i32,
pub span: SourceSpan
}
impl Display for Constant
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Variable<'src>
{
pub name: Cow<'src, str>,
pub span: SourceSpan
}
impl Display for Variable<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Binding<'src>
{
pub name: Cow<'src, str>,
pub name_span: SourceSpan,
pub expression: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Binding<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Range<'src>
{
pub start: Box<Expression<'src>>,
pub end: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Range<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
pub enum Expression<'src>
{
Group(Group<'src>),
Constant(Constant),
Variable(Variable<'src>),
Binding(Binding<'src>),
Range(Range<'src>),
Dice(DiceExpression<'src>),
Arithmetic(ArithmeticExpression<'src>)
}
impl<'src> Expression<'src>
{
pub fn accept<'a, V: ASTVisitor<'a, 'src>>(
&'a self,
visitor: &mut V
) -> Result<V::Output, V::Error>
{
walk::fold(walk::Node::Expression(self), visitor)
}
}
impl Display for Expression<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct StandardDice<'src>
{
pub count: Box<Expression<'src>>,
pub faces: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for StandardDice<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CustomDice<'src>
{
pub count: Box<Expression<'src>>,
pub faces: Vec<i32>,
pub span: SourceSpan
}
impl Display for CustomDice<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DropLowest<'src>
{
pub dice: Box<DiceExpression<'src>>,
pub drop: Option<Box<Expression<'src>>>,
pub span: SourceSpan
}
impl Display for DropLowest<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DropHighest<'src>
{
pub dice: Box<DiceExpression<'src>>,
pub drop: Option<Box<Expression<'src>>>,
pub span: SourceSpan
}
impl Display for DropHighest<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
pub enum DiceExpression<'src>
{
Standard(StandardDice<'src>),
Custom(CustomDice<'src>),
DropLowest(DropLowest<'src>),
DropHighest(DropHighest<'src>)
}
impl<'src> DiceExpression<'src>
{
pub fn accept<'a, V: ASTVisitor<'a, 'src>>(
&'a self,
visitor: &mut V
) -> Result<V::Output, V::Error>
{
walk::fold(walk::Node::Dice(self), visitor)
}
}
impl Display for DiceExpression<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Add<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Add<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Sub<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Sub<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Mul<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Mul<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Div<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Div<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Mod<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Mod<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Exp<'src>
{
pub left: Box<Expression<'src>>,
pub right: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Exp<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Neg<'src>
{
pub operand: Box<Expression<'src>>,
pub span: SourceSpan
}
impl Display for Neg<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
#[cfg_attr(doc, aquamarine::aquamarine)]
pub trait ASTVisitor<'a, 'src: 'a>
{
type Output;
type Error;
fn enter_function(
&mut self,
_node: &'a Function<'src>
) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_group(&mut self, _node: &'a Group<'src>)
-> Result<(), Self::Error>
{
Ok(())
}
fn enter_constant(&mut self, _node: &'a Constant)
-> Result<(), Self::Error>
{
Ok(())
}
fn enter_variable(
&mut self,
_node: &'a Variable<'src>
) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_binding(
&mut self,
_node: &'a Binding<'src>
) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_range(&mut self, _node: &'a Range<'src>)
-> Result<(), Self::Error>
{
Ok(())
}
fn enter_standard_dice(
&mut self,
_node: &'a StandardDice<'src>
) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_custom_dice(
&mut self,
_node: &'a CustomDice<'src>
) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_drop_lowest(
&mut self,
_node: &'a DropLowest<'src>
) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_drop_highest(
&mut self,
_node: &'a DropHighest<'src>
) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_add(&mut self, _node: &'a Add<'src>) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_sub(&mut self, _node: &'a Sub<'src>) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_mul(&mut self, _node: &'a Mul<'src>) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_div(&mut self, _node: &'a Div<'src>) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_mod(&mut self, _node: &'a Mod<'src>) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_exp(&mut self, _node: &'a Exp<'src>) -> Result<(), Self::Error>
{
Ok(())
}
fn enter_neg(&mut self, _node: &'a Neg<'src>) -> Result<(), Self::Error>
{
Ok(())
}
fn visit_function(
&mut self,
node: &'a Function<'src>,
body: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_group(
&mut self,
node: &'a Group<'src>,
expression: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_constant(
&mut self,
node: &'a Constant
) -> Result<Self::Output, Self::Error>;
fn visit_variable(
&mut self,
node: &'a Variable<'src>
) -> Result<Self::Output, Self::Error>;
fn visit_binding(
&mut self,
node: &'a Binding<'src>,
expression: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_range(
&mut self,
node: &'a Range<'src>,
start: Self::Output,
end: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_standard_dice(
&mut self,
node: &'a StandardDice<'src>,
count: Self::Output,
faces: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_custom_dice(
&mut self,
node: &'a CustomDice<'src>,
count: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_drop_lowest(
&mut self,
node: &'a DropLowest<'src>,
dice: Self::Output,
drop: Option<Self::Output>
) -> Result<Self::Output, Self::Error>;
fn visit_drop_highest(
&mut self,
node: &'a DropHighest<'src>,
dice: Self::Output,
drop: Option<Self::Output>
) -> Result<Self::Output, Self::Error>;
fn visit_add(
&mut self,
node: &'a Add<'src>,
left: Self::Output,
right: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_sub(
&mut self,
node: &'a Sub<'src>,
left: Self::Output,
right: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_mul(
&mut self,
node: &'a Mul<'src>,
left: Self::Output,
right: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_div(
&mut self,
node: &'a Div<'src>,
left: Self::Output,
right: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_mod(
&mut self,
node: &'a Mod<'src>,
left: Self::Output,
right: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_exp(
&mut self,
node: &'a Exp<'src>,
left: Self::Output,
right: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_neg(
&mut self,
node: &'a Neg<'src>,
operand: Self::Output
) -> Result<Self::Output, Self::Error>;
fn visit_expression(
&mut self,
_node: &'a Expression<'src>,
output: Self::Output
) -> Result<Self::Output, Self::Error>
{
Ok(output)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
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<'a, V: ASTVisitor<'a, 'src>>(
&'a self,
visitor: &mut V
) -> Result<V::Output, V::Error>
{
walk::fold(walk::Node::Arithmetic(self), visitor)
}
}
impl Display for ArithmeticExpression<'_>
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
display::render(self, f)
}
}
impl Spanned for Function<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Function {
parameters: self
.parameters
.as_ref()
.map(|ps| ps.iter().map(Spanned::untethered).collect()),
body: self.body.untethered(),
span: SourceSpan::default()
}
}
}
impl Spanned for Parameter<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Parameter {
name: self.name.clone(),
span: SourceSpan::default()
}
}
}
impl Spanned for Group<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Group {
expression: Box::new(self.expression.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Constant
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Constant {
value: self.value,
span: SourceSpan::default()
}
}
}
impl Spanned for Variable<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Variable {
name: self.name.clone(),
span: SourceSpan::default()
}
}
}
impl Spanned for Binding<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Binding {
name: self.name.clone(),
name_span: SourceSpan::default(),
expression: Box::new(self.expression.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Range<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Range {
start: Box::new(self.start.untethered()),
end: Box::new(self.end.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Expression<'_>
{
fn span(&self) -> SourceSpan
{
match self
{
Expression::Group(g) => g.span(),
Expression::Constant(c) => c.span(),
Expression::Variable(v) => v.span(),
Expression::Binding(b) => b.span(),
Expression::Range(r) => r.span(),
Expression::Dice(d) => d.span(),
Expression::Arithmetic(a) => a.span()
}
}
fn untethered(&self) -> Self { impls::untether(self) }
}
impl Spanned for StandardDice<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
StandardDice {
count: Box::new(self.count.untethered()),
faces: Box::new(self.faces.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for CustomDice<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
CustomDice {
count: Box::new(self.count.untethered()),
faces: self.faces.clone(),
span: SourceSpan::default()
}
}
}
impl Spanned for DropLowest<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
DropLowest {
dice: Box::new(self.dice.untethered()),
drop: self.drop.as_ref().map(|d| Box::new(d.untethered())),
span: SourceSpan::default()
}
}
}
impl Spanned for DropHighest<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
DropHighest {
dice: Box::new(self.dice.untethered()),
drop: self.drop.as_ref().map(|d| Box::new(d.untethered())),
span: SourceSpan::default()
}
}
}
impl Spanned for DiceExpression<'_>
{
fn span(&self) -> SourceSpan
{
match self
{
DiceExpression::Standard(d) => d.span(),
DiceExpression::Custom(d) => d.span(),
DiceExpression::DropLowest(d) => d.span(),
DiceExpression::DropHighest(d) => d.span()
}
}
fn untethered(&self) -> Self { impls::untether_dice(self) }
}
impl Spanned for Add<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Add {
left: Box::new(self.left.untethered()),
right: Box::new(self.right.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Sub<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Sub {
left: Box::new(self.left.untethered()),
right: Box::new(self.right.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Mul<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Mul {
left: Box::new(self.left.untethered()),
right: Box::new(self.right.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Div<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Div {
left: Box::new(self.left.untethered()),
right: Box::new(self.right.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Mod<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Mod {
left: Box::new(self.left.untethered()),
right: Box::new(self.right.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Exp<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Exp {
left: Box::new(self.left.untethered()),
right: Box::new(self.right.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for Neg<'_>
{
fn span(&self) -> SourceSpan { self.span }
fn untethered(&self) -> Self
{
Neg {
operand: Box::new(self.operand.untethered()),
span: SourceSpan::default()
}
}
}
impl Spanned for ArithmeticExpression<'_>
{
fn span(&self) -> SourceSpan
{
match self
{
ArithmeticExpression::Add(a) => a.span(),
ArithmeticExpression::Sub(s) => s.span(),
ArithmeticExpression::Mul(m) => m.span(),
ArithmeticExpression::Div(d) => d.span(),
ArithmeticExpression::Mod(m) => m.span(),
ArithmeticExpression::Exp(e) => e.span(),
ArithmeticExpression::Neg(n) => n.span()
}
}
fn untethered(&self) -> Self
{
match self
{
ArithmeticExpression::Add(a) =>
{
ArithmeticExpression::Add(a.untethered())
},
ArithmeticExpression::Sub(s) =>
{
ArithmeticExpression::Sub(s.untethered())
},
ArithmeticExpression::Mul(m) =>
{
ArithmeticExpression::Mul(m.untethered())
},
ArithmeticExpression::Div(d) =>
{
ArithmeticExpression::Div(d.untethered())
},
ArithmeticExpression::Mod(m) =>
{
ArithmeticExpression::Mod(m.untethered())
},
ArithmeticExpression::Exp(e) =>
{
ArithmeticExpression::Exp(e.untethered())
},
ArithmeticExpression::Neg(n) =>
{
ArithmeticExpression::Neg(n.untethered())
},
}
}
}