FEATURE: Add the %% modulo operator.

This commit is contained in:
Jeremy Wall 2019-02-18 21:09:42 -06:00
parent de97109681
commit c7a87894ba
5 changed files with 54 additions and 3 deletions

View File

@ -62,3 +62,13 @@ assert {
ok = (1 == 1) || (1 != 1) == true,
desc = "(1 == 1) && (1 != 1) == true",
};
assert {
ok = 4 %% 2 == 0,
desc = "4 %% 2 is 0",
};
assert {
ok = 4 %% 3 == 1,
desc = "4 %% 3 is 1",
};

View File

@ -392,6 +392,7 @@ pub enum BinaryExprType {
Sub,
Mul,
Div,
Mod,
// Boolean
AND,
OR,
@ -433,6 +434,7 @@ impl BinaryExprType {
// Product operators are next tightly bound
BinaryExprType::Mul => 4,
BinaryExprType::Div => 4,
BinaryExprType::Mod => 4,
// Boolean operators bind tighter than math
BinaryExprType::AND => 5,
BinaryExprType::OR => 5,

View File

@ -613,6 +613,33 @@ impl<'a> FileBuilder<'a> {
}
}
fn mod_vals(
&self,
lpos: &Position,
rpos: &Position,
left: Rc<Val>,
right: Rc<Val>,
) -> Result<Rc<Val>, Box<dyn Error>> {
match *left {
Val::Int(i) => {
eval_binary_expr!(&Val::Int(ii), rpos, right, Val::Int(i % ii), "Integer")
}
Val::Float(f) => {
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f % ff), "Float")
}
ref expr => {
return Err(Box::new(error::BuildError::new(
format!(
"{} does not support the 'modulus' operation",
expr.type_name()
),
error::ErrorType::Unsupported,
lpos.clone(),
)));
}
}
}
fn divide_vals(
&self,
lpos: &Position,
@ -964,6 +991,7 @@ impl<'a> FileBuilder<'a> {
&BinaryExprType::Sub => self.subtract_vals(&def.pos, def.right.pos(), left, right),
&BinaryExprType::Mul => self.multiply_vals(&def.pos, def.right.pos(), left, right),
&BinaryExprType::Div => self.divide_vals(&def.pos, def.right.pos(), left, right),
&BinaryExprType::Mod => self.mod_vals(&def.pos, def.right.pos(), left, right),
// Handle Comparison operators here
&BinaryExprType::Equal => self.do_deep_equal(def.right.pos(), left, right),
&BinaryExprType::GT => self.do_gt(&def.right.pos(), left, right),

View File

@ -59,7 +59,10 @@ make_fn!(
(Element::Op(BinaryExprType::Mul))),
do_each!(
_ => punct!("/"),
(Element::Op(BinaryExprType::Div)))
(Element::Op(BinaryExprType::Div))),
do_each!(
_ => punct!("%%"),
(Element::Op(BinaryExprType::Mod)))
)
);
@ -175,6 +178,9 @@ fn parse_product_operator(i: SliceIter<Element>) -> Result<SliceIter<Element>, B
&BinaryExprType::Div => {
return Result::Complete(i_.clone(), op.clone());
}
&BinaryExprType::Mod => {
return Result::Complete(i_.clone(), op.clone());
}
_other => {
// noop
}
@ -423,9 +429,9 @@ pub fn op_expression<'a>(i: SliceIter<'a, Token>) -> Result<SliceIter<Token>, Ex
);
Result::Fail(err)
}
Result::Abort(_e) => {
Result::Abort(e) => {
let err = Error::new(
"Abort while parsing operator expression",
format!("Abort while parsing operator expression\n{}", e),
Box::new(rest.clone()),
);
Result::Abort(err)

View File

@ -198,6 +198,10 @@ make_fn!(slashtok<OffsetStrIter, Token>,
do_text_token_tok!(TokenType::PUNCT, "/")
);
make_fn!(modulustok<OffsetStrIter, Token>,
do_text_token_tok!(TokenType::PUNCT, "%%")
);
make_fn!(pcttok<OffsetStrIter, Token>,
do_text_token_tok!(TokenType::PUNCT, "%")
);
@ -403,6 +407,7 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result<OffsetStrIter<'a>, Token> {
startok,
comment, // Note comment must come before slashtok
slashtok,
modulustok,
pcttok,
eqeqtok,
notequaltok,