Implemented mod and replaced Braced with RootNode

This commit is contained in:
Sebastian Schmidt 2019-03-15 18:34:40 +02:00
parent 1bc2909c1b
commit a1ba054609
4 changed files with 45 additions and 24 deletions

View File

@ -82,6 +82,13 @@ mod test {
assert_eq!(eval("7/(7/(7/(7/(7/(7)))))"), Ok(Value::Int(1)));
}
#[test]
fn test_mod_examples() {
assert_eq!(eval("1 % 4"), Ok(Value::Int(1)));
assert_eq!(eval("6 % 4"), Ok(Value::Int(2)));
assert_eq!(eval("1 % 4 + 2"), Ok(Value::Int(3)));
}
#[test]
fn test_type_errors() {
assert_eq!(

View File

@ -21,12 +21,14 @@ pub trait Operator {
}
pub struct RootNode;
pub struct Braced;
pub struct Add;
pub struct Sub;
pub struct Neg;
pub struct Mul;
pub struct Div;
pub struct Braced;
pub struct Mod;
pub struct Const {
value: Value,
@ -50,15 +52,16 @@ impl Identifier {
impl Operator for RootNode {
fn precedence(&self) -> i32 {
i32::min_value()
200
}
fn argument_amount(&self) -> usize {
1
}
fn eval(&self, _arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
Err(Error::EvaluatedRootNode)
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 1)?;
Ok(arguments[0].clone())
}
}
@ -187,6 +190,32 @@ impl Operator for Div {
}
}
impl Operator for Mod {
fn precedence(&self) -> i32 {
100
}
fn argument_amount(&self) -> usize {
2
}
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?;
expect_number(&arguments[1])?;
if arguments[0].is_int() && arguments[1].is_int() {
Ok(Value::Int(
arguments[0].as_int().unwrap() % arguments[1].as_int().unwrap(),
))
} else {
Ok(Value::Float(
arguments[0].as_float().unwrap() % arguments[1].as_float().unwrap(),
))
}
}
}
impl Operator for Const {
fn precedence(&self) -> i32 {
200
@ -218,18 +247,3 @@ impl Operator for Identifier {
configuration.get_value(&self.identifier)
}
}
impl Operator for Braced {
fn precedence(&self) -> i32 {
200
}
fn argument_amount(&self) -> usize {
1
}
fn eval(&self, arguments: &[Value], configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 1)?;
Ok(arguments[0].clone())
}
}

View File

@ -7,6 +7,7 @@ pub enum Token {
Minus,
Star,
Slash,
Percent,
LBrace,
RBrace,
Whitespace,
@ -30,6 +31,7 @@ fn char_to_token(c: char) -> PartialToken {
'-' => PartialToken::Token(Token::Minus),
'*' => PartialToken::Token(Token::Star),
'/' => PartialToken::Token(Token::Slash),
'%' => PartialToken::Token(Token::Percent),
'(' => PartialToken::Token(Token::LBrace),
')' => PartialToken::Token(Token::RBrace),
c => {
@ -50,6 +52,7 @@ impl Token {
Token::Minus => false,
Token::Star => false,
Token::Slash => false,
Token::Percent => false,
Token::LBrace => false,
Token::RBrace => true,
Token::Whitespace => false,

View File

@ -18,10 +18,6 @@ impl Node {
Self::new(RootNode)
}
fn braced_node() -> Self {
Self::new(Braced)
}
pub fn eval(&self, configuration: &Configuration) -> Result<Value, Error> {
let mut arguments = Vec::new();
for child in self.children() {
@ -91,8 +87,9 @@ pub fn tokens_to_operator_tree(tokens: Vec<Token>) -> Result<Node, Error> {
}
Token::Star => Some(Node::new(Mul)),
Token::Slash => Some(Node::new(Div)),
Token::Percent => Some(Node::new(Mod)),
Token::LBrace => {
root.push(Node::braced_node());
root.push(Node::root_node());
None
},
Token::RBrace => {