gears 0.1.7

Gears core implementation
Documentation
use structure::xflow::XFlowValue;
use runtime::xfstate::XFState;

#![arguments(context: &XFState)]

pub expression -> XFlowValue
  = boolean_expression
  / arithmetic_expression
  / variable
  / atom
  / parenthesized<expression>

// Arithmetic

pub arithmetic_expression -> XFlowValue
  = e:arithmetic_test { XFlowValue::Integer(e) }

arithmetic_test -> i64
  = #infix<integer> {
      #L x plus y { x + y }
         x minus y { x - y }
      #L x times y { x * y }
         x division y { x / y }
      #R x power y { x.pow(y as u32) }
  }
  / integer

// Boolean

pub boolean_expression -> XFlowValue
  = e:boolean_test { XFlowValue::Boolean(e) }

boolean_test -> bool
  = l:integer eq r:integer { l == r }
  / l:integer ne r:integer { l != r }
  / l:integer gt r:integer { l > r }
  / l:integer lt r:integer { l < r }
  / l:integer gte r:integer { l >= r }
  / l:integer lte r:integer { l <= r }
  / boolean_infix

boolean_infix -> bool
  = #infix<boolean> {
      #L l eq r { l == r }
         l ne r { l != r }
      #R l and r { l && r }
         l or r { l || r }
  }
  / not
  / parenthesized<boolean_test>
  / boolean

parenthesized<foo>
  = "(" s:foo ")" { s }

// Operators

plus -> ()
 = _ "+" _

minus -> ()
 = _ "-" _

times -> ()
 = _ "*" _

division -> ()
 = _ "/" _

power -> ()
 = _ "^" _

eq -> ()
 = _ "==" _

ne -> ()
 = _ "!=" _

gt -> ()
 = _ ">" _

lt -> ()
 = _ "<" _

gte -> ()
 = _ ">=" _

lte -> ()
 = _ "<=" _

and -> ()
 = _ "&&" _

or -> ()
 = _ "||" _

not -> bool
  = "!" l:boolean { !l }
  / "!" l:parenthesized<boolean> { !l }

// Primitives

boolean -> bool
  = "true" { true }
  / "false" { false }
  / boolean_variable
  / parenthesized<boolean_test>
  / parenthesized<boolean>

integer -> i64
  = n:$([0-9]+) { n.parse().unwrap() }
  / integer_variable
  / parenthesized<integer>
  / parenthesized<arithmetic_test>

variable -> XFlowValue
  = i:integer_variable { XFlowValue::Integer(i) }
  / b:boolean_variable { XFlowValue::Boolean(b) }

boolean_variable -> bool
  = "$" s:$([A-Za-z]+) {?
    match context.get(s) {
        Some(val) => {
            match val.value {
                XFlowValue::Boolean(b) => Ok(b),
                _ => Err("Incorrect Value Found (Boolean)")
            }
        }
        None => Err("Value not found in local state (Boolean)")
    }
}

integer_variable -> i64
 = "$" s:$([A-Za-z]+) {?
    match context.get(s) {
        Some(val) => {
            match val.value {
                XFlowValue::Integer(i) => Ok(i),
                _ => Err("Incorrect Value Found")
            }
        }
        None => Err("Value not found in local state")
    }
}

space -> ()
  = " "
  / newline

newline -> ()
  = "\n"
  / "\r"
  / "\r\n"

_ -> ()
  = space*

atom -> XFlowValue
  = i:integer { XFlowValue::Integer(i) }
  / b:boolean { XFlowValue::Boolean(b) }

//
// Supporting utilities
//

pub variable_names -> Vec<&'input str>
  = var_name*
  / !var_name { Vec::<&'input str>::new() }

var_name -> &'input str
 = non_var_start* "$" s:$([A-Za-z]+) non_var_start* { s }

non_var_start -> ()
 = $([^$]) {}