command = "${" component "}" cmdarg = "$" ~r"\d+\*?" parenthised = ("(" component ")") / ("{" component "}") true = "True" / "true" false = "False" / "false" bool = true / false basicterm = bool / numeric / parenthised / quoted / cmdarg / var term = ws* (function / basicterm) ws* var = (parenthised / keyword) ("." keyword)* function = var (ws+ basicterm)+ type = keyword typecast = basicterm "::" type test_eq = term "==" term test_neq = term "!=" term test_gt = term ">" term test_geq = term ">=" term test_lt = term "<" term test_leq = term "<=" term test = (test_eq/test_neq/test_gt/test_geq/test_lt/test_leq) op_or = term ("||" term)+ op_and = term ("&&" term)+ op_add = term ("+" term)+ op_minus = term ("-" term)+ op_times = term ("*" term)+ op_exp = term ("**" term)+ op_divide = term ("/" term)+ op_div = term ("//" term)+ op_mod = term ("%" term)+ binop = (op_or/op_and/op_add/op_minus/op_times/op_exp/op_divide/op_div/op_mod) cascade = term ("|" term)+ ternary = term "?" term ":" term ifthenelse = "if" ws term ws "then" ws term (ws "elif" ws term ws "then" ws term)* (ws "else" ws term)? "fi" equals = keyword ws* '=' ws* term defines = keyword ws* ":=" ws* term definesterm = keyword ws* "::=" ws* term component = ws* (cascade / ternary / equals / defines / definesterm / binop / test / term) ws* word = ~r"[_\w]+" keyword = word quoted = ~'"[^\"]*"' numeric = ~r"[\d]+" ws = ~r"\s+"