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))); 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] #[test]
fn test_type_errors() { fn test_type_errors() {
assert_eq!( assert_eq!(

View File

@ -21,12 +21,14 @@ pub trait Operator {
} }
pub struct RootNode; pub struct RootNode;
pub struct Braced;
pub struct Add; pub struct Add;
pub struct Sub; pub struct Sub;
pub struct Neg; pub struct Neg;
pub struct Mul; pub struct Mul;
pub struct Div; pub struct Div;
pub struct Braced; pub struct Mod;
pub struct Const { pub struct Const {
value: Value, value: Value,
@ -50,15 +52,16 @@ impl Identifier {
impl Operator for RootNode { impl Operator for RootNode {
fn precedence(&self) -> i32 { fn precedence(&self) -> i32 {
i32::min_value() 200
} }
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
1 1
} }
fn eval(&self, _arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
Err(Error::EvaluatedRootNode) 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 { impl Operator for Const {
fn precedence(&self) -> i32 { fn precedence(&self) -> i32 {
200 200
@ -218,18 +247,3 @@ impl Operator for Identifier {
configuration.get_value(&self.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, Minus,
Star, Star,
Slash, Slash,
Percent,
LBrace, LBrace,
RBrace, RBrace,
Whitespace, Whitespace,
@ -30,6 +31,7 @@ fn char_to_token(c: char) -> PartialToken {
'-' => PartialToken::Token(Token::Minus), '-' => PartialToken::Token(Token::Minus),
'*' => PartialToken::Token(Token::Star), '*' => PartialToken::Token(Token::Star),
'/' => PartialToken::Token(Token::Slash), '/' => PartialToken::Token(Token::Slash),
'%' => PartialToken::Token(Token::Percent),
'(' => PartialToken::Token(Token::LBrace), '(' => PartialToken::Token(Token::LBrace),
')' => PartialToken::Token(Token::RBrace), ')' => PartialToken::Token(Token::RBrace),
c => { c => {
@ -50,6 +52,7 @@ impl Token {
Token::Minus => false, Token::Minus => false,
Token::Star => false, Token::Star => false,
Token::Slash => false, Token::Slash => false,
Token::Percent => false,
Token::LBrace => false, Token::LBrace => false,
Token::RBrace => true, Token::RBrace => true,
Token::Whitespace => false, Token::Whitespace => false,

View File

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