Compare commits
3 commits
8084e34cc0
...
9dd6bee0e3
| Author | SHA1 | Date | |
|---|---|---|---|
| 9dd6bee0e3 | |||
| 9b78cf2786 | |||
| 074c7a10e4 |
2 changed files with 39 additions and 11 deletions
16
src/dice.rs
16
src/dice.rs
|
|
@ -17,6 +17,7 @@ pub enum Expression {
|
||||||
Mul(ExpBox, ExpBox),
|
Mul(ExpBox, ExpBox),
|
||||||
Div(ExpBox, ExpBox),
|
Div(ExpBox, ExpBox),
|
||||||
IntDiv(ExpBox, ExpBox),
|
IntDiv(ExpBox, ExpBox),
|
||||||
|
Pow(ExpBox, ExpBox),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
|
@ -121,9 +122,6 @@ impl Expression {
|
||||||
// Exploding dice are early, they add rolls
|
// Exploding dice are early, they add rolls
|
||||||
if let Some(fragments) = x {
|
if let Some(fragments) = x {
|
||||||
write!(w, "x")?;
|
write!(w, "x")?;
|
||||||
if size < 2 {
|
|
||||||
bail!("Infinite explosion.")
|
|
||||||
}
|
|
||||||
let mut comparers = Vec::with_capacity(fragments.len());
|
let mut comparers = Vec::with_capacity(fragments.len());
|
||||||
for fragment in fragments {
|
for fragment in fragments {
|
||||||
comparers.push(fragment.comparer(rng, w)?);
|
comparers.push(fragment.comparer(rng, w)?);
|
||||||
|
|
@ -265,6 +263,12 @@ impl Expression {
|
||||||
let rhs = rhs_node.evaluate(rng, w, precedence)?;
|
let rhs = rhs_node.evaluate(rng, w, precedence)?;
|
||||||
lhs.div_euclid(rhs)
|
lhs.div_euclid(rhs)
|
||||||
}
|
}
|
||||||
|
Pow(lhs_node, rhs_node) => {
|
||||||
|
let lhs = lhs_node.evaluate(rng, w, precedence)?;
|
||||||
|
write!(w, " ^ ")?;
|
||||||
|
let rhs = rhs_node.evaluate(rng, w, precedence)?;
|
||||||
|
lhs.powf(rhs)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if needs_parens {
|
if needs_parens {
|
||||||
write!(w, ")")?;
|
write!(w, ")")?;
|
||||||
|
|
@ -294,7 +298,7 @@ impl Expression {
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
};
|
};
|
||||||
if count > 1_000_000 {
|
if count > DICE_POOL_LIMIT {
|
||||||
bail!("Too many dice.")
|
bail!("Too many dice.")
|
||||||
};
|
};
|
||||||
let size = size.avg()? as i64;
|
let size = size.avg()? as i64;
|
||||||
|
|
@ -326,6 +330,7 @@ impl Expression {
|
||||||
Expression::Mul(lhs, rhs) => lhs.avg()? * rhs.avg()?,
|
Expression::Mul(lhs, rhs) => lhs.avg()? * rhs.avg()?,
|
||||||
Expression::Div(lhs, rhs) => lhs.avg()? / rhs.avg()?,
|
Expression::Div(lhs, rhs) => lhs.avg()? / rhs.avg()?,
|
||||||
Expression::IntDiv(lhs, rhs) => lhs.avg()?.div_euclid(rhs.avg()?),
|
Expression::IntDiv(lhs, rhs) => lhs.avg()?.div_euclid(rhs.avg()?),
|
||||||
|
Expression::Pow(lhs, rhs) => lhs.avg()?.powf(rhs.avg()?),
|
||||||
};
|
};
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
@ -377,6 +382,7 @@ impl Expression {
|
||||||
match self {
|
match self {
|
||||||
Const(_) => 1,
|
Const(_) => 1,
|
||||||
Dice { .. } => 2,
|
Dice { .. } => 2,
|
||||||
|
Pow(_, _) => 4,
|
||||||
Neg(_) => 5,
|
Neg(_) => 5,
|
||||||
Mul(_, _) | Div(_, _) | IntDiv(_, _) => 7,
|
Mul(_, _) | Div(_, _) | IntDiv(_, _) => 7,
|
||||||
Add(_, _) | Sub(_, _) => 8,
|
Add(_, _) | Sub(_, _) => 8,
|
||||||
|
|
@ -480,7 +486,7 @@ impl<'a> WitnessSet for DiscordMdWitnessSet<'a> {
|
||||||
type Error = DiscordMdWitnessError;
|
type Error = DiscordMdWitnessError;
|
||||||
|
|
||||||
fn witness_roll(&mut self, dice: DiceRoll) -> Result<Self::Ok, Self::Error> {
|
fn witness_roll(&mut self, dice: DiceRoll) -> Result<Self::Ok, Self::Error> {
|
||||||
if self.parent.dice_written >= 100 {
|
if self.parent.dice_written >= 50 {
|
||||||
if !self.dice_elided {
|
if !self.dice_elided {
|
||||||
write!(self.parent.buffer, "…")?;
|
write!(self.parent.buffer, "…")?;
|
||||||
self.dice_elided = true;
|
self.dice_elided = true;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
use crate::dice::{CompareFragment, DiceFormula, Expression::{self, Const}};
|
use crate::dice::{
|
||||||
|
CompareFragment, DiceFormula,
|
||||||
|
Expression::{self, Const},
|
||||||
|
};
|
||||||
use Assoc::Left;
|
use Assoc::Left;
|
||||||
|
use nom::character::complete::digit0;
|
||||||
|
use nom::combinator::recognize;
|
||||||
use nom::{
|
use nom::{
|
||||||
Parser,
|
Parser,
|
||||||
branch::alt,
|
branch::alt,
|
||||||
|
|
@ -89,6 +94,7 @@ fn expr<'c, 'i>(
|
||||||
complete(unary_op(5, tag("-"))),
|
complete(unary_op(5, tag("-"))),
|
||||||
fail(),
|
fail(),
|
||||||
complete(alt((
|
complete(alt((
|
||||||
|
binary_op(4, Left, spaced_op("^")),
|
||||||
binary_op(7, Left, spaced_op("*")),
|
binary_op(7, Left, spaced_op("*")),
|
||||||
binary_op(7, Left, spaced_op("//")),
|
binary_op(7, Left, spaced_op("//")),
|
||||||
binary_op(7, Left, spaced_op("/")),
|
binary_op(7, Left, spaced_op("/")),
|
||||||
|
|
@ -101,6 +107,7 @@ fn expr<'c, 'i>(
|
||||||
|
|
||||||
Ok(match op {
|
Ok(match op {
|
||||||
Prefix("-", x) => Neg(Box::new(x)),
|
Prefix("-", x) => Neg(Box::new(x)),
|
||||||
|
Binary(lhs, "^", rhs) => Pow(Box::new(lhs), Box::new(rhs)),
|
||||||
Binary(lhs, "*", rhs) => Mul(Box::new(lhs), Box::new(rhs)),
|
Binary(lhs, "*", rhs) => Mul(Box::new(lhs), Box::new(rhs)),
|
||||||
Binary(lhs, "//", rhs) => IntDiv(Box::new(lhs), Box::new(rhs)),
|
Binary(lhs, "//", rhs) => IntDiv(Box::new(lhs), Box::new(rhs)),
|
||||||
Binary(lhs, "/", rhs) => Div(Box::new(lhs), Box::new(rhs)),
|
Binary(lhs, "/", rhs) => Div(Box::new(lhs), Box::new(rhs)),
|
||||||
|
|
@ -115,7 +122,10 @@ fn expr<'c, 'i>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn number(i: &str) -> IResult<&str, Expression> {
|
fn number(i: &str) -> IResult<&str, Expression> {
|
||||||
map_res(digit1(), |s: &str| s.parse::<f64>())
|
map_res(
|
||||||
|
alt((recognize((digit0, tag("."), digit1())), digit1())),
|
||||||
|
|s: &str| s.parse::<f64>(),
|
||||||
|
)
|
||||||
.map(Const)
|
.map(Const)
|
||||||
.parse_complete(i)
|
.parse_complete(i)
|
||||||
}
|
}
|
||||||
|
|
@ -154,6 +164,18 @@ mod test {
|
||||||
assert_matches!(expression, Expression::Dice { .. });
|
assert_matches!(expression, Expression::Dice { .. });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn parse_decimal() {
|
||||||
|
let expression = parse("2.5+2.5").unwrap();
|
||||||
|
assert_matches!(expression, Expression::Add { .. });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn parse_decimal2() {
|
||||||
|
let expression = parse(".4*.8").unwrap();
|
||||||
|
assert_matches!(expression, Expression::Mul { .. });
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn parse_bare_dice() {
|
pub fn parse_bare_dice() {
|
||||||
let expression = parse("d8").unwrap();
|
let expression = parse("d8").unwrap();
|
||||||
|
|
@ -162,7 +184,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn parse_math() {
|
pub fn parse_math() {
|
||||||
let expression = parse("8 * 2 + 2 * 5").unwrap();
|
let expression = parse("8 * 2 + 2 * 5 ^ 4").unwrap();
|
||||||
assert_matches!(expression, Expression::Add { .. });
|
assert_matches!(expression, Expression::Add { .. });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue