Add more operators (#401)

This commit is contained in:
viandox 2022-02-15 10:12:35 +01:00 committed by GitHub
parent bce4ade6da
commit 3fc24a9c72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 19 additions and 1 deletions

View file

@ -17,6 +17,8 @@ pub enum BinOp {
#[strum(serialize = "!=")] NotEquals, #[strum(serialize = "!=")] NotEquals,
#[strum(serialize = "&&")] And, #[strum(serialize = "&&")] And,
#[strum(serialize = "||")] Or, #[strum(serialize = "||")] Or,
#[strum(serialize = ">=") ] GE,
#[strum(serialize = "<=") ] LE,
#[strum(serialize = ">") ] GT, #[strum(serialize = ">") ] GT,
#[strum(serialize = "<") ] LT, #[strum(serialize = "<") ] LT,
#[strum(serialize = "?:")] Elvis, #[strum(serialize = "?:")] Elvis,
@ -27,6 +29,8 @@ pub enum BinOp {
pub enum UnaryOp { pub enum UnaryOp {
#[strum(serialize = "!")] #[strum(serialize = "!")]
Not, Not,
#[strum(serialize = "-")]
Negative,
} }
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]

View file

@ -190,6 +190,8 @@ impl SimplExpr {
BinOp::Mod => DynVal::from(a.as_f64()? % b.as_f64()?), BinOp::Mod => DynVal::from(a.as_f64()? % b.as_f64()?),
BinOp::GT => DynVal::from(a.as_f64()? > b.as_f64()?), BinOp::GT => DynVal::from(a.as_f64()? > b.as_f64()?),
BinOp::LT => DynVal::from(a.as_f64()? < b.as_f64()?), BinOp::LT => DynVal::from(a.as_f64()? < b.as_f64()?),
BinOp::GE => DynVal::from(a.as_f64()? >= b.as_f64()?),
BinOp::LE => DynVal::from(a.as_f64()? <= b.as_f64()?),
#[allow(clippy::useless_conversion)] #[allow(clippy::useless_conversion)]
BinOp::Elvis => DynVal::from(if a.0.is_empty() { b } else { a }), BinOp::Elvis => DynVal::from(if a.0.is_empty() { b } else { a }),
BinOp::RegexMatch => { BinOp::RegexMatch => {
@ -203,6 +205,7 @@ impl SimplExpr {
let a = a.eval(values)?; let a = a.eval(values)?;
Ok(match op { Ok(match op {
UnaryOp::Not => DynVal::from(!a.as_bool()?).at(*span), UnaryOp::Not => DynVal::from(!a.as_bool()?).at(*span),
UnaryOp::Negative => DynVal::from(-a.as_f64()?).at(*span),
}) })
} }
SimplExpr::IfElse(_, cond, yes, no) => { SimplExpr::IfElse(_, cond, yes, no) => {

View file

@ -23,12 +23,15 @@ pub enum Token {
NotEquals, NotEquals,
And, And,
Or, Or,
GE,
LE,
GT, GT,
LT, LT,
Elvis, Elvis,
RegexMatch, RegexMatch,
Not, Not,
Negative,
Comma, Comma,
Question, Question,
@ -80,12 +83,15 @@ regex_rules! {
escape(r"!=") => |_| Token::NotEquals, escape(r"!=") => |_| Token::NotEquals,
escape(r"&&") => |_| Token::And, escape(r"&&") => |_| Token::And,
escape(r"||") => |_| Token::Or, escape(r"||") => |_| Token::Or,
escape(r">=") => |_| Token::GE,
escape(r"<=") => |_| Token::LE,
escape(r">") => |_| Token::GT, escape(r">") => |_| Token::GT,
escape(r"<") => |_| Token::LT, escape(r"<") => |_| Token::LT,
escape(r"?:") => |_| Token::Elvis, escape(r"?:") => |_| Token::Elvis,
escape(r"=~") => |_| Token::RegexMatch, escape(r"=~") => |_| Token::RegexMatch,
escape(r"!" ) => |_| Token::Not, escape(r"!" ) => |_| Token::Not,
escape(r"-" ) => |_| Token::Negative,
escape(r",") => |_| Token::Comma, escape(r",") => |_| Token::Comma,
escape(r"?") => |_| Token::Question, escape(r"?") => |_| Token::Question,

View file

@ -20,6 +20,8 @@ extern {
"!=" => Token::NotEquals, "!=" => Token::NotEquals,
"&&" => Token::And, "&&" => Token::And,
"||" => Token::Or, "||" => Token::Or,
">=" => Token::GE,
"<=" => Token::LE,
">" => Token::GT, ">" => Token::GT,
"<" => Token::LT, "<" => Token::LT,
"?:" => Token::Elvis, "?:" => Token::Elvis,
@ -81,6 +83,7 @@ pub Expr: SimplExpr = {
#[precedence(level="2")] #[assoc(side="right")] #[precedence(level="2")] #[assoc(side="right")]
<l:@L> "!" <e:Expr> <r:@R> => UnaryOp(Span(l, r, fid), Not, b(e)), <l:@L> "!" <e:Expr> <r:@R> => UnaryOp(Span(l, r, fid), Not, b(e)),
<l:@L> "-" <e:Expr> <r:@R> => UnaryOp(Span(l, r, fid), Negative, b(e)),
#[precedence(level="3")] #[assoc(side="left")] #[precedence(level="3")] #[assoc(side="left")]
<l:@L> <le:Expr> "*" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Times, b(re)), <l:@L> <le:Expr> "*" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Times, b(re)),
@ -94,6 +97,8 @@ pub Expr: SimplExpr = {
#[precedence(level="5")] #[assoc(side="left")] #[precedence(level="5")] #[assoc(side="left")]
<l:@L> <le:Expr> "==" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Equals, b(re)), <l:@L> <le:Expr> "==" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), Equals, b(re)),
<l:@L> <le:Expr> "!=" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), NotEquals, b(re)), <l:@L> <le:Expr> "!=" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), NotEquals, b(re)),
<l:@L> <le:Expr> ">=" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), GE, b(re)),
<l:@L> <le:Expr> "<=" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), LE, b(re)),
<l:@L> <le:Expr> ">" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), GT, b(re)), <l:@L> <le:Expr> ">" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), GT, b(re)),
<l:@L> <le:Expr> "<" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), LT, b(re)), <l:@L> <le:Expr> "<" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), LT, b(re)),
<l:@L> <le:Expr> "=~" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), RegexMatch, b(re)), <l:@L> <le:Expr> "=~" <re:Expr> <r:@R> => BinOp(Span(l, r, fid), b(le), RegexMatch, b(re)),

View file

@ -21,7 +21,7 @@ as well as within strings, inside string-interpolation blocks (`"foo ${ ... } ba
Supported currently are the following features: Supported currently are the following features:
- simple mathematical operations (`+`, `-`, `*`, `/`, `%`) - simple mathematical operations (`+`, `-`, `*`, `/`, `%`)
- comparisons (`==`, `!=`, `>`, `<`) - comparisons (`==`, `!=`, `>`, `<`, `<=`, `>=`)
- boolean operations (`||`, `&&`, `!`) - boolean operations (`||`, `&&`, `!`)
- elvis operator (`?:`) - elvis operator (`?:`)
- if the left side is `""`, then returns the right side, otherwise evaluates to the left side. - if the left side is `""`, then returns the right side, otherwise evaluates to the left side.