forked from projectmoon/tenebrous-dicebot
116 lines
3.4 KiB
Rust
116 lines
3.4 KiB
Rust
|
use nom::{
|
||
|
alt,
|
||
|
bytes::complete::{tag, take_while},
|
||
|
character::complete::digit1,
|
||
|
complete, many0, named,
|
||
|
sequence::tuple,
|
||
|
tag, IResult,
|
||
|
};
|
||
|
|
||
|
use crate::parser::eat_whitespace;
|
||
|
use crate::commands::{Command, RollCommand};
|
||
|
use crate::dice::parser::parse_element_expression;
|
||
|
|
||
|
// Parse a roll expression.
|
||
|
fn parse_roll(input: &str) -> IResult<&str, Command> {
|
||
|
named!(invocation(&str) -> &str, alt!(complete!(tag!("!r")) | complete!(tag!("!roll"))));
|
||
|
let (input, _) = eat_whitespace(input)?;
|
||
|
let (input, _) = invocation(input)?;
|
||
|
let (input, _) = eat_whitespace(input)?;
|
||
|
let (input, expression) = parse_element_expression(input)?;
|
||
|
Ok((input, Command::Roll(RollCommand(expression))))
|
||
|
}
|
||
|
|
||
|
// Parse a command expression.
|
||
|
pub fn parse_command(input: &str) -> IResult<&str, Command> {
|
||
|
// Add new commands to alt!
|
||
|
named!(command(&str) -> Command, alt!(parse_roll));
|
||
|
command(input)
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::*;
|
||
|
#[test]
|
||
|
fn dice_test() {
|
||
|
assert_eq!(parse_dice("2d4"), Ok(("", Dice::new(2, 4))));
|
||
|
assert_eq!(parse_dice("20d40"), Ok(("", Dice::new(20, 40))));
|
||
|
assert_eq!(parse_dice("8d7"), Ok(("", Dice::new(8, 7))));
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn element_test() {
|
||
|
assert_eq!(
|
||
|
parse_element(" \t\n\r\n 8d7 \n"),
|
||
|
Ok((" \n", Element::Dice(Dice::new(8, 7))))
|
||
|
);
|
||
|
assert_eq!(
|
||
|
parse_element(" \t\n\r\n 8 \n"),
|
||
|
Ok((" \n", Element::Bonus(8)))
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn signed_element_test() {
|
||
|
assert_eq!(
|
||
|
parse_signed_element("+ 7"),
|
||
|
Ok(("", SignedElement::Positive(Element::Bonus(7))))
|
||
|
);
|
||
|
assert_eq!(
|
||
|
parse_signed_element(" \t\n\r\n- 8 \n"),
|
||
|
Ok((" \n", SignedElement::Negative(Element::Bonus(8))))
|
||
|
);
|
||
|
assert_eq!(
|
||
|
parse_signed_element(" \t\n\r\n- 8d4 \n"),
|
||
|
Ok((
|
||
|
" \n",
|
||
|
SignedElement::Negative(Element::Dice(Dice::new(8, 4)))
|
||
|
))
|
||
|
);
|
||
|
assert_eq!(
|
||
|
parse_signed_element(" \t\n\r\n+ 8d4 \n"),
|
||
|
Ok((
|
||
|
" \n",
|
||
|
SignedElement::Positive(Element::Dice(Dice::new(8, 4)))
|
||
|
))
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn element_expression_test() {
|
||
|
assert_eq!(
|
||
|
parse_element_expression("8d4"),
|
||
|
Ok((
|
||
|
"",
|
||
|
ElementExpression(vec![SignedElement::Positive(Element::Dice(Dice::new(
|
||
|
8, 4
|
||
|
)))])
|
||
|
))
|
||
|
);
|
||
|
assert_eq!(
|
||
|
parse_element_expression(" - 8d4 \n "),
|
||
|
Ok((
|
||
|
" \n ",
|
||
|
ElementExpression(vec![SignedElement::Negative(Element::Dice(Dice::new(
|
||
|
8, 4
|
||
|
)))])
|
||
|
))
|
||
|
);
|
||
|
assert_eq!(
|
||
|
parse_element_expression("\t3d4 + 7 - 5 - 6d12 + 1d1 + 53 1d5 "),
|
||
|
Ok((
|
||
|
" 1d5 ",
|
||
|
ElementExpression(vec![
|
||
|
SignedElement::Positive(Element::Dice(Dice::new(3, 4))),
|
||
|
SignedElement::Positive(Element::Bonus(7)),
|
||
|
SignedElement::Negative(Element::Bonus(5)),
|
||
|
SignedElement::Negative(Element::Dice(Dice::new(6, 12))),
|
||
|
SignedElement::Positive(Element::Dice(Dice::new(1, 1))),
|
||
|
SignedElement::Positive(Element::Bonus(53)),
|
||
|
])
|
||
|
))
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|