@halleyassist/rule-parser 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1920,9 +1920,9 @@ exports.Grammars = require("./Grammars");
1920
1920
  module.exports = require('./RuleParser.production')
1921
1921
 
1922
1922
  },{"./RuleParser.production":12}],11:[function(require,module,exports){
1923
- module.exports=[{"name":"statement_main","bnf":[["statement","EOF"]]},{"name":"logical_operator","bnf":[["AND"],["OR"]]},{"name":"%statement[2]","bnf":[["logical_operator","expression"]],"fragment":true},{"name":"statement","bnf":[["expression","%statement[2]*"]]},{"name":"expression","bnf":[["not_expression"],["standard_expression"],["parenthesis_expression"]]},{"name":"parenthesis_expression","bnf":[["BEGIN_PARENTHESIS","WS*","statement","WS*","END_PARENTHESIS"]]},{"name":"%not_expression[2]","bnf":[["result"],["parenthesis_expression"]],"fragment":true},{"name":"not_expression","bnf":[["NOT","%not_expression[2]"]]},{"name":"%standard_expression[2][1]","bnf":[["WS*","eq_approx"]],"fragment":true},{"name":"%standard_expression[2][2]","bnf":[["WS*","basic_rhs"]],"fragment":true},{"name":"%standard_expression[2][3][1]","bnf":[["WS+","IS"]],"fragment":true},{"name":"%standard_expression[2][3]","bnf":[["%standard_expression[2][3][1]?","WS+","between"]],"fragment":true},{"name":"%standard_expression[2][4]","bnf":[["WS+","in_expr"]],"fragment":true},{"name":"%standard_expression[2]","bnf":[["%standard_expression[2][1]"],["%standard_expression[2][2]"],["%standard_expression[2][3]"],["%standard_expression[2][4]"]],"fragment":true},{"name":"standard_expression","bnf":[["result","%standard_expression[2]?"]]},{"name":"basic_rhs","bnf":[["operator","WS*","result"]]},{"name":"eq_approx","bnf":[["eq_operator","WS*","\"~\"","WS*","result"]]},{"name":"PLUS","bnf":[["\"+\""]]},{"name":"MINUS","bnf":[["\"-\""]]},{"name":"MULTIPLY","bnf":[["\"*\""]]},{"name":"DIVIDE","bnf":[["\"/\""]]},{"name":"MODULUS","bnf":[["\"%\""]]},{"name":"DEFAULT_VAL","bnf":[["\"??\""]]},{"name":"arithmetic_operator","bnf":[["PLUS"],["MINUS"],["MULTIPLY"],["DIVIDE"],["MODULUS"],["DEFAULT_VAL"]]},{"name":"arithmetic_operand","bnf":[["fcall"],["number_time"],["number"]]},{"name":"%arithmetic_result[5]","bnf":[["arithmetic_result"],["arithmetic_operand"]],"fragment":true},{"name":"arithmetic_result","bnf":[["arithmetic_operand","WS*","arithmetic_operator","WS*","%arithmetic_result[5]"]]},{"name":"simple_result","bnf":[["fcall"],["value"]]},{"name":"result","bnf":[["arithmetic_result"],["simple_result"]]},{"name":"value","bnf":[["false"],["true"],["array"],["time_period"],["number_time"],["number"],["number_tod"],["string"]]},{"name":"BEGIN_ARRAY","bnf":[["WS*",/\x5B/,"WS*"]]},{"name":"BEGIN_OBJECT","bnf":[["WS*",/\x7B/,"WS*"]]},{"name":"END_ARRAY","bnf":[["WS*",/\x5D/,"WS*"]]},{"name":"END_OBJECT","bnf":[["WS*",/\x7D/,"WS*"]]},{"name":"NAME_SEPARATOR","bnf":[["WS*",/\x3A/,"WS*"]]},{"name":"VALUE_SEPARATOR","bnf":[["WS*",/\x2C/,"WS*"]]},{"name":"WS","bnf":[[/[\x20\x09\x0A\x0D]/]]},{"name":"operator","bnf":[["GTE"],["LTE"],["GT"],["LT"],["EQ"],["NEQ"]]},{"name":"eq_operator","bnf":[["EQ"],["NEQ"]]},{"name":"BEGIN_ARGUMENT","bnf":[["\"(\""]]},{"name":"END_ARGUMENT","bnf":[["\")\""]]},{"name":"BEGIN_PARENTHESIS","bnf":[["\"(\""]]},{"name":"END_PARENTHESIS","bnf":[["\")\""]]},{"name":"BEGIN_IN","bnf":[[/[Ii]/,/[Nn]/]]},{"name":"in_expr","bnf":[["BEGIN_IN","WS*","BEGIN_PARENTHESIS","WS*","arguments","END_PARENTHESIS"]]},{"name":"argument","bnf":[["statement","WS*"]]},{"name":"%arguments[2]","bnf":[["WS*","\",\"","WS*","argument"]],"fragment":true},{"name":"arguments","bnf":[["argument","%arguments[2]*"]]},{"name":"%fname[1]","bnf":[[/[a-zA-z0-9]/]]},{"name":"fname","bnf":[["%fname[1]+"]]},{"name":"fcall","bnf":[["fname","WS*","BEGIN_ARGUMENT","WS*","arguments?","END_ARGUMENT"]]},{"name":"%between_number[1]","bnf":[["number_time"],["number"]],"fragment":true},{"name":"%between_number[2][1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_number[2][2]","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"%between_number[2]","bnf":[["%between_number[2][1]"],["%between_number[2][2]"]],"fragment":true},{"name":"%between_number[3]","bnf":[["number_time"],["number"]],"fragment":true},{"name":"between_number","bnf":[["%between_number[1]","%between_number[2]","%between_number[3]"]]},{"name":"%between_number_time[2][1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_number_time[2][2]","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"%between_number_time[2]","bnf":[["%between_number_time[2][1]"],["%between_number_time[2][2]"]],"fragment":true},{"name":"%between_number_time[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_number_time","bnf":[["number_time","%between_number_time[2]","number_time","%between_number_time[4]?"]]},{"name":"%between_tod[2][1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_tod[2]","bnf":[["%between_tod[2][1]"]],"fragment":true},{"name":"%between_tod[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_tod","bnf":[["number_tod","%between_tod[2]","number_tod","%between_tod[4]?"]]},{"name":"%between[3]","bnf":[["between_number"],["between_tod"]],"fragment":true},{"name":"between","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","%between[3]"]]},{"name":"dow","bnf":[[/[Mm]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Oo]/,/[Nn]/],[/[Tt]/,/[Uu]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Uu]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Dd]/,/[Nn]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ww]/,/[Ee]/,/[Dd]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Hh]/,/[Uu]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/],[/[Ff]/,/[Rr]/,/[Ii]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ff]/,/[Rr]/,/[Ii]/],[/[Ss]/,/[Aa]/,/[Tt]/,/[Uu]/,/[Rr]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Aa]/,/[Tt]/],[/[Ss]/,/[Uu]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Uu]/,/[Nn]/]]},{"name":"%dow_range[4]","bnf":[["WS+",/[Tt]/,/[Oo]/,"WS+","dow"]],"fragment":true},{"name":"dow_range","bnf":[[/[Oo]/,/[Nn]/,"WS+","dow","%dow_range[4]?"]]},{"name":"between_time_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_number_time"]]},{"name":"between_tod_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_tod"]]},{"name":"%AND[1]","bnf":[["WS*",/&/,/&/,"WS*"]],"fragment":true},{"name":"%AND[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"AND","bnf":[["%AND[1]"],["%AND[2]"]]},{"name":"%OR[1]","bnf":[["WS*",/\|/,/\|/,"WS*"]],"fragment":true},{"name":"%OR[2]","bnf":[["WS+",/[Oo]/,/[Rr]/,"WS+"]],"fragment":true},{"name":"OR","bnf":[["%OR[1]"],["%OR[2]"]]},{"name":"AGO","bnf":[[/[Aa]/,/[Gg]/,/[Oo]/]]},{"name":"GT","bnf":[["\">\""]]},{"name":"LT","bnf":[["\"<\""]]},{"name":"GTE","bnf":[["\">=\""]]},{"name":"LTE","bnf":[["\"<=\""]]},{"name":"IS","bnf":[[/[Ii]/,/[Ss]/]]},{"name":"EQ","bnf":[["\"==\""],["\"=\""]]},{"name":"NEQ","bnf":[["\"!=\""]]},{"name":"%NOT[1]","bnf":[[/!/,"WS*"]],"fragment":true},{"name":"%NOT[2]","bnf":[[/[Nn]/,/[Oo]/,/[Tt]/,"WS+"]],"fragment":true},{"name":"NOT","bnf":[["%NOT[1]"],["%NOT[2]"]]},{"name":"false","bnf":[[/[Ff]/,/[Aa]/,/[Ll]/,/[Ss]/,/[Ee]/]]},{"name":"null","bnf":[[/[Nn]/,/[Uu]/,/[Ll]/,/[Ll]/]]},{"name":"true","bnf":[[/[Tt]/,/[Rr]/,/[Uu]/,/[Ee]/]]},{"name":"%array[2][2]","bnf":[["VALUE_SEPARATOR","value"]],"fragment":true},{"name":"%array[2]","bnf":[["value","%array[2][2]*"]],"fragment":true},{"name":"array","bnf":[["BEGIN_ARRAY","%array[2]?","END_ARRAY"]]},{"name":"unit","bnf":[[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/,/[Ss]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/,/[Ss]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/,/[Ss]/],[/[Dd]/,/[Aa]/,/[Yy]/,/[Ss]/],[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/],[/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/]]},{"name":"%number[2][1]","bnf":[[/[0-9]/]]},{"name":"%number[2]","bnf":[["%number[2][1]+"]],"fragment":true},{"name":"%number[3][2]","bnf":[[/[0-9]/]]},{"name":"%number[3]","bnf":[["\".\"","%number[3][2]+"]],"fragment":true},{"name":"%number[4][2]","bnf":[["\"-\""],["\"+\""]],"fragment":true},{"name":"%number[4][3][2]","bnf":[[/[0-9]/]]},{"name":"%number[4][3]","bnf":[["\"0\""],[/[1-9]/,"%number[4][3][2]*"]],"fragment":true},{"name":"%number[4]","bnf":[["\"e\"","%number[4][2]?","%number[4][3]"]],"fragment":true},{"name":"number","bnf":[["\"-\"?","%number[2]","%number[3]?","%number[4]?"]]},{"name":"number_time","bnf":[["number","WS+","unit"]]},{"name":"%number_tod[1][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[1]","bnf":[["%number_tod[1][1]+"]],"fragment":true},{"name":"%number_tod[3][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[3]","bnf":[["%number_tod[3][1]+"]],"fragment":true},{"name":"number_tod","bnf":[["%number_tod[1]","\":\"","%number_tod[3]"]]},{"name":"%time_period_ago[2]","bnf":[["WS+","number_time"]],"fragment":true},{"name":"time_period_ago","bnf":[["number_time","%time_period_ago[2]*","WS+","AGO"]]},{"name":"%time_period_ago_between[2]","bnf":[["WS+","number_time"]],"fragment":true},{"name":"time_period_ago_between","bnf":[["number_time","%time_period_ago_between[2]*","WS+","AGO","WS+","between_tod_only"]]},{"name":"time_period_const","bnf":[[/[Tt]/,/[Oo]/,/[Dd]/,/[Aa]/,/[Yy]/],["time_period_ago"]]},{"name":"time_period","bnf":[["time_period_ago_between"],["time_period_const"],["between_tod_only"],["between_time_only"]]},{"name":"%string[2][1]","bnf":[[/[\x20-\x21]/],[/[\x23-\x5B]/],[/[\x5D-\uFFFF]/]],"fragment":true},{"name":"%string[2][2]","bnf":[[/\x22/],[/\x5C/],[/\x2F/],[/\x62/],[/\x66/],[/\x6E/],[/\x72/],[/\x74/],[/\x75/,"HEXDIG","HEXDIG","HEXDIG","HEXDIG"]],"fragment":true},{"name":"%string[2]","bnf":[["%string[2][1]"],[/\x5C/,"%string[2][2]"]],"fragment":true},{"name":"string","bnf":[["'\"'","%string[2]*","'\"'"]]},{"name":"HEXDIG","bnf":[[/[a-fA-F0-9]/]]}]
1923
+ module.exports=[{"name":"statement_main","bnf":[["statement","EOF"]]},{"name":"logical_operator","bnf":[["AND"],["OR"]]},{"name":"%statement[2]","bnf":[["logical_operator","expression"]],"fragment":true},{"name":"statement","bnf":[["expression","%statement[2]*"]]},{"name":"expression","bnf":[["not_expression"],["standard_expression"],["parenthesis_expression"]]},{"name":"parenthesis_expression","bnf":[["BEGIN_PARENTHESIS","WS*","statement","WS*","END_PARENTHESIS"]]},{"name":"%not_expression[2]","bnf":[["result"],["parenthesis_expression"]],"fragment":true},{"name":"not_expression","bnf":[["NOT","%not_expression[2]"]]},{"name":"%standard_expression[2][1]","bnf":[["WS*","eq_approx"]],"fragment":true},{"name":"%standard_expression[2][2]","bnf":[["WS*","basic_rhs"]],"fragment":true},{"name":"%standard_expression[2][3][1]","bnf":[["WS+","IS"]],"fragment":true},{"name":"%standard_expression[2][3]","bnf":[["%standard_expression[2][3][1]?","WS+","between"]],"fragment":true},{"name":"%standard_expression[2][4]","bnf":[["WS+","in_expr"]],"fragment":true},{"name":"%standard_expression[2]","bnf":[["%standard_expression[2][1]"],["%standard_expression[2][2]"],["%standard_expression[2][3]"],["%standard_expression[2][4]"]],"fragment":true},{"name":"standard_expression","bnf":[["result","%standard_expression[2]?"]]},{"name":"basic_rhs","bnf":[["operator","WS*","result"]]},{"name":"eq_approx","bnf":[["eq_operator","WS*","\"~\"","WS*","result"]]},{"name":"PLUS","bnf":[["\"+\""]]},{"name":"MINUS","bnf":[["\"-\""]]},{"name":"MULTIPLY","bnf":[["\"*\""]]},{"name":"DIVIDE","bnf":[["\"/\""]]},{"name":"MODULUS","bnf":[["\"%\""]]},{"name":"DEFAULT_VAL","bnf":[["\"??\""]]},{"name":"arithmetic_operator","bnf":[["PLUS"],["MINUS"],["MULTIPLY"],["DIVIDE"],["MODULUS"],["DEFAULT_VAL"]]},{"name":"number_atom","bnf":[["number"]]},{"name":"number_time_atom","bnf":[["number_time"]]},{"name":"tod_atom","bnf":[["number_tod"]]},{"name":"dow_atom","bnf":[["dow"]]},{"name":"arithmetic_operand","bnf":[["fcall"],["number_time_atom"],["number_atom"]]},{"name":"%arithmetic_result[5]","bnf":[["arithmetic_result"],["arithmetic_operand"]],"fragment":true},{"name":"arithmetic_result","bnf":[["arithmetic_operand","WS*","arithmetic_operator","WS*","%arithmetic_result[5]"]]},{"name":"simple_result","bnf":[["fcall"],["value"]]},{"name":"result","bnf":[["arithmetic_result"],["simple_result"]]},{"name":"value_atom","bnf":[["false"],["true"],["array"],["time_period"],["number_time_atom"],["number_atom"],["tod_atom"],["string"]]},{"name":"value","bnf":[["value_atom"]]},{"name":"BEGIN_ARRAY","bnf":[["WS*",/\x5B/,"WS*"]]},{"name":"BEGIN_OBJECT","bnf":[["WS*",/\x7B/,"WS*"]]},{"name":"END_ARRAY","bnf":[["WS*",/\x5D/,"WS*"]]},{"name":"END_OBJECT","bnf":[["WS*",/\x7D/,"WS*"]]},{"name":"NAME_SEPARATOR","bnf":[["WS*",/\x3A/,"WS*"]]},{"name":"VALUE_SEPARATOR","bnf":[["WS*",/\x2C/,"WS*"]]},{"name":"WS","bnf":[[/[\x20\x09\x0A\x0D]/]]},{"name":"operator","bnf":[["GTE"],["LTE"],["GT"],["LT"],["EQ"],["NEQ"]]},{"name":"eq_operator","bnf":[["EQ"],["NEQ"]]},{"name":"BEGIN_ARGUMENT","bnf":[["\"(\""]]},{"name":"END_ARGUMENT","bnf":[["\")\""]]},{"name":"BEGIN_PARENTHESIS","bnf":[["\"(\""]]},{"name":"END_PARENTHESIS","bnf":[["\")\""]]},{"name":"BEGIN_IN","bnf":[[/[Ii]/,/[Nn]/]]},{"name":"in_expr","bnf":[["BEGIN_IN","WS*","BEGIN_PARENTHESIS","WS*","arguments","END_PARENTHESIS"]]},{"name":"argument","bnf":[["statement","WS*"]]},{"name":"%arguments[2]","bnf":[["WS*","\",\"","WS*","argument"]],"fragment":true},{"name":"arguments","bnf":[["argument","%arguments[2]*"]]},{"name":"%fname[1]","bnf":[[/[A-Za-z0-9]/]]},{"name":"fname","bnf":[["%fname[1]+"]]},{"name":"fcall","bnf":[["fname","WS*","BEGIN_ARGUMENT","WS*","arguments?","END_ARGUMENT"]]},{"name":"%between_dash_or_and[1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_dash_or_and[2]","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"between_dash_or_and","bnf":[["%between_dash_or_and[1]"],["%between_dash_or_and[2]"]]},{"name":"between_number_inner","bnf":[["number_atom"],["number_time_atom"]]},{"name":"between_number","bnf":[["between_number_inner","between_dash_or_and","between_number_inner"]]},{"name":"between_number_time_inner","bnf":[["number_time_atom"]]},{"name":"%between_number_time[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_number_time","bnf":[["between_number_time_inner","between_dash_or_and","between_number_time_inner","%between_number_time[4]?"]]},{"name":"between_tod_inner","bnf":[["tod_atom"]]},{"name":"%between_tod[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_tod[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_tod","bnf":[["between_tod_inner","%between_tod[2]","between_tod_inner","%between_tod[4]?"]]},{"name":"%between[3]","bnf":[["between_number"],["between_tod"]],"fragment":true},{"name":"between","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","%between[3]"]]},{"name":"dow","bnf":[[/[Mm]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Oo]/,/[Nn]/],[/[Tt]/,/[Uu]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Uu]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Dd]/,/[Nn]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ww]/,/[Ee]/,/[Dd]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Hh]/,/[Uu]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/],[/[Ff]/,/[Rr]/,/[Ii]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ff]/,/[Rr]/,/[Ii]/],[/[Ss]/,/[Aa]/,/[Tt]/,/[Uu]/,/[Rr]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Aa]/,/[Tt]/],[/[Ss]/,/[Uu]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Uu]/,/[Nn]/]]},{"name":"dow_range_inner","bnf":[["dow_atom"]]},{"name":"%dow_range[4]","bnf":[["WS+",/[Tt]/,/[Oo]/,"WS+","dow_range_inner"]],"fragment":true},{"name":"dow_range","bnf":[[/[Oo]/,/[Nn]/,"WS+","dow_range_inner","%dow_range[4]?"]]},{"name":"between_time_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_number_time"]]},{"name":"between_tod_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_tod"]]},{"name":"between_time_only_atom","bnf":[["between_time_only"]]},{"name":"between_tod_only_atom","bnf":[["between_tod_only"]]},{"name":"%AND[1]","bnf":[["WS*",/&/,/&/,"WS*"]],"fragment":true},{"name":"%AND[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"AND","bnf":[["%AND[1]"],["%AND[2]"]]},{"name":"%OR[1]","bnf":[["WS*",/\|/,/\|/,"WS*"]],"fragment":true},{"name":"%OR[2]","bnf":[["WS+",/[Oo]/,/[Rr]/,"WS+"]],"fragment":true},{"name":"OR","bnf":[["%OR[1]"],["%OR[2]"]]},{"name":"AGO","bnf":[[/[Aa]/,/[Gg]/,/[Oo]/]]},{"name":"GT","bnf":[["\">\""]]},{"name":"LT","bnf":[["\"<\""]]},{"name":"GTE","bnf":[["\">=\""]]},{"name":"LTE","bnf":[["\"<=\""]]},{"name":"IS","bnf":[[/[Ii]/,/[Ss]/]]},{"name":"EQ","bnf":[["\"==\""],["\"=\""]]},{"name":"NEQ","bnf":[["\"!=\""]]},{"name":"%NOT[1]","bnf":[[/!/,"WS*"]],"fragment":true},{"name":"%NOT[2]","bnf":[[/[Nn]/,/[Oo]/,/[Tt]/,"WS+"]],"fragment":true},{"name":"NOT","bnf":[["%NOT[1]"],["%NOT[2]"]]},{"name":"false","bnf":[[/[Ff]/,/[Aa]/,/[Ll]/,/[Ss]/,/[Ee]/]]},{"name":"null","bnf":[[/[Nn]/,/[Uu]/,/[Ll]/,/[Ll]/]]},{"name":"true","bnf":[[/[Tt]/,/[Rr]/,/[Uu]/,/[Ee]/]]},{"name":"%array[2][2]","bnf":[["VALUE_SEPARATOR","value"]],"fragment":true},{"name":"%array[2]","bnf":[["value","%array[2][2]*"]],"fragment":true},{"name":"array","bnf":[["BEGIN_ARRAY","%array[2]?","END_ARRAY"]]},{"name":"unit","bnf":[[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/,/[Ss]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/,/[Ss]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/,/[Ss]/],[/[Dd]/,/[Aa]/,/[Yy]/,/[Ss]/],[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/],[/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/]]},{"name":"%number[2][1]","bnf":[[/[0-9]/]]},{"name":"%number[2]","bnf":[["%number[2][1]+"]],"fragment":true},{"name":"%number[3][2]","bnf":[[/[0-9]/]]},{"name":"%number[3]","bnf":[["\".\"","%number[3][2]+"]],"fragment":true},{"name":"%number[4][2]","bnf":[["\"-\""],["\"+\""]],"fragment":true},{"name":"%number[4][3][2]","bnf":[[/[0-9]/]]},{"name":"%number[4][3]","bnf":[["\"0\""],[/[1-9]/,"%number[4][3][2]*"]],"fragment":true},{"name":"%number[4]","bnf":[["\"e\"","%number[4][2]?","%number[4][3]"]],"fragment":true},{"name":"number","bnf":[["\"-\"?","%number[2]","%number[3]?","%number[4]?"]]},{"name":"number_time","bnf":[["number","WS+","unit"]]},{"name":"%number_tod[1][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[1]","bnf":[["%number_tod[1][1]+"]],"fragment":true},{"name":"%number_tod[3][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[3]","bnf":[["%number_tod[3][1]+"]],"fragment":true},{"name":"number_tod","bnf":[["%number_tod[1]","\":\"","%number_tod[3]"]]},{"name":"%time_period_ago[2]","bnf":[["WS+","number_time_atom"]],"fragment":true},{"name":"time_period_ago","bnf":[["number_time_atom","%time_period_ago[2]*","WS+","AGO"]]},{"name":"%time_period_ago_between[2]","bnf":[["WS+","number_time_atom"]],"fragment":true},{"name":"%time_period_ago_between[6]","bnf":[["between_time_only_atom"],["between_tod_only_atom"]],"fragment":true},{"name":"time_period_ago_between","bnf":[["number_time_atom","%time_period_ago_between[2]*","WS+","AGO","WS+","%time_period_ago_between[6]"]]},{"name":"time_period_const","bnf":[[/[Tt]/,/[Oo]/,/[Dd]/,/[Aa]/,/[Yy]/],["time_period_ago"]]},{"name":"time_period","bnf":[["time_period_ago_between"],["time_period_const"],["between_tod_only"],["between_time_only"]]},{"name":"%string[2][1]","bnf":[[/[\x20-\x21]/],[/[\x23-\x5B]/],[/[\x5D-\uFFFF]/]],"fragment":true},{"name":"%string[2][2]","bnf":[[/\x22/],[/\x5C/],[/\x2F/],[/\x62/],[/\x66/],[/\x6E/],[/\x72/],[/\x74/],[/\x75/,"HEXDIG","HEXDIG","HEXDIG","HEXDIG"]],"fragment":true},{"name":"%string[2]","bnf":[["%string[2][1]"],[/\x5C/,"%string[2][2]"]],"fragment":true},{"name":"string","bnf":[["'\"'","%string[2]*","'\"'"]]},{"name":"HEXDIG","bnf":[[/[a-fA-F0-9]/]]}]
1924
1924
  },{}],12:[function(require,module,exports){
1925
- const {Parser} = require('ebnf/dist/Parser.js'), {ParsingError} = require('ebnf');
1925
+ const {Parser} = require('ebnf/dist/Parser.js'), {ParsingError} = require('ebnf'), RuleParseError = require('./errors/RuleParseError');
1926
1926
  let ParserRules = require('./RuleParser.production.ebnf.js');
1927
1927
  let ParserCache;
1928
1928
  const {ErrorAnalyzer} = require('./errors/ErrorAnalyzer');
@@ -2015,14 +2015,17 @@ class RuleParser {
2015
2015
  }
2016
2016
  static _parseDowRange(dowRange) {
2017
2017
  if (dowRange.children.length === 1) {
2018
+ const dayText = RuleParser.__parseValue(dowRange.children[0]);
2018
2019
  return {
2019
- start: normalizeDow(dowRange.children[0].text),
2020
- end: normalizeDow(dowRange.children[0].text)
2020
+ start: dayText,
2021
+ end: dayText
2021
2022
  };
2022
2023
  } else if (dowRange.children.length === 2) {
2024
+ const startDay = RuleParser.__parseValue(dowRange.children[0]);
2025
+ const endDay = RuleParser.__parseValue(dowRange.children[1]);
2023
2026
  return {
2024
- start: normalizeDow(dowRange.children[0].text),
2025
- end: normalizeDow(dowRange.children[1].text)
2027
+ start: startDay,
2028
+ end: endDay
2026
2029
  };
2027
2030
  } else {
2028
2031
  throw new Error(`Invalid dow_range with ${ dowRange.children.length } children`);
@@ -2043,14 +2046,15 @@ class RuleParser {
2043
2046
  let totalSeconds = 0;
2044
2047
  const components = [];
2045
2048
  for (const child of timePeriodAgo.children) {
2046
- if (child.type === 'number_time') {
2047
- const number = parseFloat(child.children[0].text);
2048
- const unit = child.children[1].text.toUpperCase();
2049
+ if (child.type === 'number_time_atom') {
2050
+ const numberTime = child.children[0];
2051
+ const number = parseFloat(numberTime.children[0].text);
2052
+ const unit = numberTime.children[1].text.toUpperCase();
2049
2053
  components.push([
2050
2054
  number,
2051
2055
  unit
2052
2056
  ]);
2053
- totalSeconds += RuleParser.__parseValue(child);
2057
+ totalSeconds += RuleParser.__parseValue(numberTime);
2054
2058
  }
2055
2059
  }
2056
2060
  if (components.length === 1) {
@@ -2073,29 +2077,67 @@ class RuleParser {
2073
2077
  ];
2074
2078
  case 'time_period_ago_between': {
2075
2079
  let totalSeconds = 0;
2076
- let betweenTodOnly = null;
2080
+ let betweenNode = null;
2081
+ let isBetweenTod = false;
2077
2082
  for (let i = 0; i < tp.children.length; i++) {
2078
- if (tp.children[i].type === 'number_time') {
2079
- totalSeconds += RuleParser.__parseValue(tp.children[i]);
2080
- } else if (tp.children[i].type === 'between_tod_only') {
2081
- betweenTodOnly = tp.children[i];
2083
+ if (tp.children[i].type === 'number_time_atom') {
2084
+ totalSeconds += RuleParser.__parseValue(tp.children[i].children[0]);
2085
+ } else if (tp.children[i].type === 'between_time_only' || tp.children[i].type === 'between_time_only_atom') {
2086
+ betweenNode = tp.children[i].type === 'between_time_only_atom' ? tp.children[i].children[0] : tp.children[i];
2087
+ isBetweenTod = false;
2088
+ } else if (tp.children[i].type === 'between_tod_only' || tp.children[i].type === 'between_tod_only_atom') {
2089
+ betweenNode = tp.children[i].type === 'between_tod_only_atom' ? tp.children[i].children[0] : tp.children[i];
2090
+ isBetweenTod = true;
2082
2091
  }
2083
2092
  }
2084
- if (!betweenTodOnly) {
2085
- throw new Error('time_period_ago_between requires between_tod_only child');
2093
+ if (!betweenNode) {
2094
+ throw new Error('time_period_ago_between requires between_time_only or between_tod_only child');
2086
2095
  }
2087
- const betweenTod = betweenTodOnly.children[0];
2088
- let startTod = RuleParser.__parseValue(betweenTod.children[0]);
2089
- let endTod = RuleParser.__parseValue(betweenTod.children[1]);
2090
- if (betweenTod.children.length > 2) {
2091
- RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2]);
2096
+ if (isBetweenTod) {
2097
+ const betweenTod = betweenNode.children[0];
2098
+ let startTod = RuleParser.__parseValue(betweenTod.children[0]);
2099
+ let endTod = RuleParser.__parseValue(betweenTod.children[1]);
2100
+ if (betweenTod.children.length > 2) {
2101
+ RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2]);
2102
+ }
2103
+ return [
2104
+ 'TimePeriodBetweenAgo',
2105
+ totalSeconds,
2106
+ startTod,
2107
+ endTod
2108
+ ];
2109
+ } else {
2110
+ const betweenNumberTime = betweenNode.children[0];
2111
+ const startValue = RuleParser.__parseValue(betweenNumberTime.children[0]);
2112
+ const endValue = RuleParser.__parseValue(betweenNumberTime.children[2]);
2113
+ if (betweenNumberTime.children.length > 3 && betweenNumberTime.children[3].type === 'dow_range') {
2114
+ const dow = RuleParser._parseDowRange(betweenNumberTime.children[3]);
2115
+ if (dow.start === dow.end) {
2116
+ return [
2117
+ 'TimePeriodBetweenAgo',
2118
+ totalSeconds,
2119
+ startValue,
2120
+ endValue,
2121
+ dow.start
2122
+ ];
2123
+ } else {
2124
+ return [
2125
+ 'TimePeriodBetweenAgo',
2126
+ totalSeconds,
2127
+ startValue,
2128
+ endValue,
2129
+ dow.start,
2130
+ dow.end
2131
+ ];
2132
+ }
2133
+ }
2134
+ return [
2135
+ 'TimePeriodBetweenAgo',
2136
+ totalSeconds,
2137
+ startValue,
2138
+ endValue
2139
+ ];
2092
2140
  }
2093
- return [
2094
- 'TimePeriodBetweenAgo',
2095
- totalSeconds,
2096
- startTod,
2097
- endTod
2098
- ];
2099
2141
  }
2100
2142
  case 'between_tod_only': {
2101
2143
  const betweenTod = tp.children[0];
@@ -2123,9 +2165,9 @@ class RuleParser {
2123
2165
  case 'between_time_only': {
2124
2166
  const betweenNumberTime = tp.children[0];
2125
2167
  const startValue = RuleParser.__parseValue(betweenNumberTime.children[0]);
2126
- const endValue = RuleParser.__parseValue(betweenNumberTime.children[1]);
2127
- if (betweenNumberTime.children.length > 2 && betweenNumberTime.children[2].type === 'dow_range') {
2128
- const dow = RuleParser._parseDowRange(betweenNumberTime.children[2]);
2168
+ const endValue = RuleParser.__parseValue(betweenNumberTime.children[2]);
2169
+ if (betweenNumberTime.children.length > 3 && betweenNumberTime.children[3].type === 'dow_range') {
2170
+ const dow = RuleParser._parseDowRange(betweenNumberTime.children[3]);
2129
2171
  if (dow.start === dow.end) {
2130
2172
  return [
2131
2173
  'TimePeriodBetween',
@@ -2154,6 +2196,22 @@ class RuleParser {
2154
2196
  static __parseValue(child) {
2155
2197
  const type = child.type;
2156
2198
  switch (type) {
2199
+ case 'value': {
2200
+ return RuleParser.__parseValue(child.children[0]);
2201
+ }
2202
+ case 'value_atom': {
2203
+ return RuleParser.__parseValue(child.children[0]);
2204
+ }
2205
+ case 'number_atom':
2206
+ case 'number_time_atom':
2207
+ case 'tod_atom':
2208
+ case 'dow_atom':
2209
+ case 'between_tod_inner':
2210
+ case 'between_number_inner':
2211
+ case 'between_number_time_inner':
2212
+ case 'dow_range_inner': {
2213
+ return RuleParser.__parseValue(child.children[0]);
2214
+ }
2157
2215
  case 'string': {
2158
2216
  const str = child.text;
2159
2217
  return str.slice(1, -1);
@@ -2209,10 +2267,13 @@ class RuleParser {
2209
2267
  case 'array': {
2210
2268
  const ret = [];
2211
2269
  for (const c of child.children) {
2212
- ret.push(RuleParser.__parseValue(c.children[0]));
2270
+ ret.push(RuleParser.__parseValue(c));
2213
2271
  }
2214
2272
  return ret;
2215
2273
  }
2274
+ case 'dow': {
2275
+ return normalizeDow(child.text);
2276
+ }
2216
2277
  default:
2217
2278
  throw new Error(`Unknown value type ${ type }`);
2218
2279
  }
@@ -2221,6 +2282,17 @@ class RuleParser {
2221
2282
  const child = value.children[0];
2222
2283
  const type = child.type;
2223
2284
  switch (type) {
2285
+ case 'value_atom': {
2286
+ const atomChild = child.children[0];
2287
+ if (atomChild.type === 'time_period') {
2288
+ const tp = atomChild.children[0];
2289
+ return RuleParser._parseTimePeriod(tp);
2290
+ }
2291
+ return [
2292
+ 'Value',
2293
+ RuleParser.__parseValue(atomChild)
2294
+ ];
2295
+ }
2224
2296
  case 'time_period': {
2225
2297
  const tp = child.children[0];
2226
2298
  return RuleParser._parseTimePeriod(tp);
@@ -2249,6 +2321,13 @@ class RuleParser {
2249
2321
  switch (type) {
2250
2322
  case 'fcall':
2251
2323
  return RuleParser._parseFcall(child);
2324
+ case 'number_atom':
2325
+ case 'number_time_atom': {
2326
+ return [
2327
+ 'Value',
2328
+ RuleParser.__parseValue(child.children[0])
2329
+ ];
2330
+ }
2252
2331
  case 'number':
2253
2332
  return [
2254
2333
  'Value',
@@ -2384,7 +2463,7 @@ class RuleParser {
2384
2463
  ],
2385
2464
  [
2386
2465
  'Value',
2387
- RuleParser.__parseValue(betweenChild.children[1])
2466
+ RuleParser.__parseValue(betweenChild.children[2])
2388
2467
  ]
2389
2468
  ];
2390
2469
  }
@@ -2399,7 +2478,7 @@ class RuleParser {
2399
2478
  ],
2400
2479
  [
2401
2480
  'Value',
2402
- RuleParser.__parseValue(rhs.children[0].children[1])
2481
+ RuleParser.__parseValue(rhs.children[0].children[2])
2403
2482
  ]
2404
2483
  ];
2405
2484
  case 'basic_rhs':
@@ -2538,8 +2617,6 @@ class RuleParser {
2538
2617
  if (e.message && e.message.includes('Invalid time of day')) {
2539
2618
  const match = e.message.match(/Invalid time of day[,:]?\s*([0-9:]+)/);
2540
2619
  const badTod = match ? match[1] : 'invalid';
2541
- const {ParsingError} = require('ebnf');
2542
- const {RuleParseError} = require('./errors/RuleParseError');
2543
2620
  const lines = txt.trim().split('\n');
2544
2621
  const position = {
2545
2622
  line: lines.length,
@@ -2551,7 +2628,6 @@ class RuleParser {
2551
2628
  if (e.message && e.message.includes('Invalid day of week')) {
2552
2629
  const match = e.message.match(/Invalid day of week[,:]?\s*(\w+)/);
2553
2630
  const badDow = match ? match[1] : 'invalid';
2554
- const {RuleParseError} = require('./errors/RuleParseError');
2555
2631
  const lines = txt.trim().split('\n');
2556
2632
  const position = {
2557
2633
  line: lines.length,
@@ -2573,11 +2649,12 @@ class RuleParser {
2573
2649
  }
2574
2650
  }
2575
2651
  module.exports = RuleParser;
2576
- module.exports.ParsingError = require('ebnf').ParsingError;
2577
- module.exports.RuleParseError = require('./errors/RuleParseError').RuleParseError;
2652
+ module.exports.ParserRules = ParserRules;
2653
+ module.exports.ParsingError = ParsingError;
2654
+ module.exports.RuleParseError = RuleParseError;
2578
2655
  },{"./RuleParser.production.ebnf.js":11,"./errors/ErrorAnalyzer":13,"./errors/RuleParseError":14,"ebnf":9,"ebnf/dist/Parser.js":5}],13:[function(require,module,exports){
2579
2656
  const { ParsingError } = require('ebnf');
2580
- const { RuleParseError } = require('./RuleParseError');
2657
+ const RuleParseError = require('./RuleParseError');
2581
2658
 
2582
2659
  /**
2583
2660
  * Analyzes parsing errors and maps them to user-friendly error codes
@@ -3565,7 +3642,7 @@ class RuleParseError extends Error {
3565
3642
  }
3566
3643
  }
3567
3644
 
3568
- module.exports = { RuleParseError };
3645
+ module.exports = RuleParseError;
3569
3646
 
3570
3647
  },{}]},{},[10])(10)
3571
3648
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@halleyassist/rule-parser",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "The grammar for HalleyAssist rules",
5
5
  "main": "src/RuleParser.production.js",
6
6
  "browser": "./dist/rule-parser.browser.js",
@@ -5,10 +5,10 @@ statement_main ::= statement EOF
5
5
  logical_operator ||= AND | OR
6
6
  statement ::= expression (logical_operator expression)*
7
7
  expression ::= not_expression | standard_expression | parenthesis_expression
8
- parenthesis_expression::= BEGIN_PARENTHESIS WS* statement WS* END_PARENTHESIS
8
+ parenthesis_expression ::= BEGIN_PARENTHESIS WS* statement WS* END_PARENTHESIS
9
9
  not_expression ||= NOT (result | parenthesis_expression)
10
10
  standard_expression ||= result ((WS* eq_approx) | (WS* basic_rhs) | ((WS+ IS)? WS+ between) | (WS+ in_expr))?
11
- basic_rhs ::= operator WS* result
11
+ basic_rhs ::= operator WS* result
12
12
  eq_approx ::= eq_operator WS* "~" WS* result
13
13
 
14
14
  PLUS ::= "+"
@@ -18,46 +18,67 @@ DIVIDE ::= "/"
18
18
  MODULUS ::= "%"
19
19
  DEFAULT_VAL ::= "??"
20
20
  arithmetic_operator ::= PLUS | MINUS | MULTIPLY | DIVIDE | MODULUS | DEFAULT_VAL
21
- arithmetic_operand ::= fcall | number_time | number
22
- arithmetic_result ::= arithmetic_operand WS* arithmetic_operator WS* ( arithmetic_result | arithmetic_operand )
21
+
22
+ number_atom ::= number
23
+ number_time_atom ::= number_time
24
+ tod_atom ::= number_tod
25
+ dow_atom ::= dow
26
+
27
+ arithmetic_operand ::= fcall | number_time_atom | number_atom
28
+ arithmetic_result ::= arithmetic_operand WS* arithmetic_operator WS* (arithmetic_result | arithmetic_operand)
23
29
 
24
30
  simple_result ::= fcall | value
25
31
  result ::= arithmetic_result | simple_result
26
- value ::= false | true | array | time_period | number_time | number | number_tod | string
27
- BEGIN_ARRAY ::= WS* #x5B WS* /* [ left square bracket */
28
- BEGIN_OBJECT ::= WS* #x7B WS* /* { left curly bracket */
29
- END_ARRAY ::= WS* #x5D WS* /* ] right square bracket */
30
- END_OBJECT ::= WS* #x7D WS* /* } right curly bracket */
31
- NAME_SEPARATOR ::= WS* #x3A WS* /* : colon */
32
- VALUE_SEPARATOR ::= WS* #x2C WS* /* , comma */
33
- WS ::= [#x20#x09#x0A#x0D] /* Space | Tab | \n | \r */
32
+
33
+ value_atom ::= false | true | array | time_period | number_time_atom | number_atom | tod_atom | string
34
+ value ::= value_atom
35
+
36
+ BEGIN_ARRAY ::= WS* #x5B WS* /* [ */
37
+ BEGIN_OBJECT ::= WS* #x7B WS* /* { */
38
+ END_ARRAY ::= WS* #x5D WS* /* ] */
39
+ END_OBJECT ::= WS* #x7D WS* /* } */
40
+ NAME_SEPARATOR ::= WS* #x3A WS* /* : */
41
+ VALUE_SEPARATOR ::= WS* #x2C WS* /* , */
42
+ WS ::= [#x20#x09#x0A#x0D]
34
43
 
35
44
  operator ::= GTE | LTE | GT | LT | EQ | NEQ
36
45
  eq_operator ::= EQ | NEQ
37
46
 
38
47
  BEGIN_ARGUMENT ::= "("
39
48
  END_ARGUMENT ::= ")"
40
-
41
49
  BEGIN_PARENTHESIS ::= "("
42
50
  END_PARENTHESIS ::= ")"
43
51
 
44
52
  BEGIN_IN ||= "IN"
45
-
46
53
  in_expr ::= BEGIN_IN WS* BEGIN_PARENTHESIS WS* arguments END_PARENTHESIS
47
54
 
48
55
  argument ::= statement WS*
49
56
  arguments ::= argument (WS* "," WS* argument)*
50
- fname ::= [a-zA-z0-9]+
57
+ fname ::= [A-Za-z0-9]+
51
58
  fcall ::= fname WS* BEGIN_ARGUMENT WS* arguments? END_ARGUMENT
52
59
 
53
- between_number ||= (number_time | number) ((WS+ "AND" WS+) | (WS* "-" WS*)) (number_time | number)
54
- between_number_time ||= number_time ((WS+ "AND" WS+) | (WS* "-" WS*)) number_time (WS+ dow_range)?
55
- between_tod ||= number_tod ((WS+ "AND" WS+)) number_tod (WS+ dow_range)?
60
+ between_dash_or_and ||= (WS+ "AND" WS+) | (WS* "-" WS*)
61
+
62
+ between_number_inner ::= number_atom | number_time_atom
63
+ between_number ||= between_number_inner between_dash_or_and between_number_inner
64
+
65
+ between_number_time_inner ::= number_time_atom
66
+ between_number_time ||= between_number_time_inner between_dash_or_and between_number_time_inner (WS+ dow_range)?
67
+
68
+ between_tod_inner ::= tod_atom
69
+ between_tod ||= between_tod_inner (WS+ "AND" WS+) between_tod_inner (WS+ dow_range)?
70
+
56
71
  between ||= "BETWEEN" WS+ (between_number | between_tod)
72
+
57
73
  dow ||= "MONDAY" | "MON" | "TUESDAY" | "TUE" | "WEDNESDAY" | "WED" | "THURSDAY" | "THU" | "THUR" | "FRIDAY" | "FRI" | "SATURDAY" | "SAT" | "SUNDAY" | "SUN"
58
- dow_range ||= "ON" WS+ dow (WS+ "TO" WS+ dow)?
74
+
75
+ dow_range_inner ::= dow_atom
76
+ dow_range ||= "ON" WS+ dow_range_inner (WS+ "TO" WS+ dow_range_inner)?
77
+
59
78
  between_time_only ||= "BETWEEN" WS+ between_number_time
60
79
  between_tod_only ||= "BETWEEN" WS+ between_tod
80
+ between_time_only_atom ::= between_time_only
81
+ between_tod_only_atom ::= between_tod_only
61
82
 
62
83
  AND ||= (WS* "&&" WS*) | (WS+ "AND" WS+)
63
84
  OR ||= (WS* "||" WS*) | (WS+ "OR" WS+)
@@ -70,18 +91,21 @@ IS ||= "is"
70
91
  EQ ::= "==" | "="
71
92
  NEQ ::= "!="
72
93
  NOT ||= ("!" WS*) | ("not" WS+)
94
+
73
95
  false ||= "FALSE"
74
96
  null ||= "null"
75
97
  true ||= "TRUE"
98
+
76
99
  array ::= BEGIN_ARRAY (value (VALUE_SEPARATOR value)*)? END_ARRAY
77
100
 
78
101
  unit ||= "seconds" | "minutes" | "hours" | "weeks" | "days" | "second" | "minute" | "week" | "hour" | "day" | "mins" | "min"
79
- number ::= "-"? ([0-9]+) ("." [0-9]+)? ("e" ( "-" | "+" )? ("0" | [1-9] [0-9]*))?
102
+
103
+ number ::= "-"? ([0-9]+) ("." [0-9]+)? ("e" ("-" | "+")? ("0" | [1-9] [0-9]*))?
80
104
  number_time ::= number WS+ unit
81
105
  number_tod ::= ([0-9]+) ":" ([0-9]+)
82
106
 
83
- time_period_ago ||= number_time (WS+ number_time)* WS+ AGO
84
- time_period_ago_between ||= number_time (WS+ number_time)* WS+ AGO WS+ between_tod_only
107
+ time_period_ago ||= number_time_atom (WS+ number_time_atom)* WS+ AGO
108
+ time_period_ago_between ||= number_time_atom (WS+ number_time_atom)* WS+ AGO WS+ (between_time_only_atom | between_tod_only_atom)
85
109
  time_period_const ||= "today" | time_period_ago
86
110
  time_period ::= time_period_ago_between | time_period_const | between_tod_only | between_time_only
87
111
 
package/src/RuleParser.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const {Parser} = require('ebnf/dist/Parser.js'),
2
2
  {ParsingError} = require('ebnf'),
3
- assert = require('assert')
3
+ assert = require('assert'),
4
+ RuleParseError = require('./errors/RuleParseError')
4
5
 
5
6
  let ParserRules = require('./RuleParser.ebnf.js')
6
7
  let ParserCache;
@@ -108,10 +109,14 @@ class RuleParser {
108
109
  // dow_range can have 1 or 2 children (single day or range)
109
110
  if (dowRange.children.length === 1) {
110
111
  // Single day: ON MONDAY - return just the day string
111
- return { start: normalizeDow(dowRange.children[0].text), end: normalizeDow(dowRange.children[0].text) };
112
+ // New structure: dow_range -> dow_range_inner -> dow_atom -> dow
113
+ const dayText = RuleParser.__parseValue(dowRange.children[0])
114
+ return { start: dayText, end: dayText };
112
115
  } else if (dowRange.children.length === 2) {
113
116
  // Range: ON MONDAY TO FRIDAY - return both start and end days
114
- return { start: normalizeDow(dowRange.children[0].text), end: normalizeDow(dowRange.children[1].text) };
117
+ const startDay = RuleParser.__parseValue(dowRange.children[0])
118
+ const endDay = RuleParser.__parseValue(dowRange.children[1])
119
+ return { start: startDay, end: endDay };
115
120
  } else {
116
121
  throw new Error(`Invalid dow_range with ${dowRange.children.length} children`);
117
122
  }
@@ -133,12 +138,14 @@ class RuleParser {
133
138
  let totalSeconds = 0
134
139
  const components = []
135
140
  for (const child of timePeriodAgo.children) {
136
- if (child.type === 'number_time') {
137
- const number = parseFloat(child.children[0].text)
138
- const unit = child.children[1].text.toUpperCase()
141
+ if (child.type === 'number_time_atom') {
142
+ // New structure: number_time_atom -> number_time -> number, unit
143
+ const numberTime = child.children[0]
144
+ const number = parseFloat(numberTime.children[0].text)
145
+ const unit = numberTime.children[1].text.toUpperCase()
139
146
  components.push([number, unit])
140
147
  // Parse the value to get seconds
141
- totalSeconds += RuleParser.__parseValue(child)
148
+ totalSeconds += RuleParser.__parseValue(numberTime)
142
149
  }
143
150
  }
144
151
  // If there's only one component, use its number and unit
@@ -151,40 +158,69 @@ class RuleParser {
151
158
  }
152
159
  return ["TimePeriodConst", tp.text]
153
160
  case 'time_period_ago_between': {
154
- // time_period_ago_between has: number_time (WS+ number_time)* WS+ AGO WS+ between_tod_only
161
+ // time_period_ago_between has: number_time_atom (WS+ number_time_atom)* WS+ AGO WS+ (between_time_only | between_tod_only)
155
162
  // We need to extract all number_time children and sum them up, then return TimePeriodBetweenAgo
156
163
  let totalSeconds = 0
157
- let betweenTodOnly = null
164
+ let betweenNode = null
165
+ let isBetweenTod = false
158
166
 
159
- // Find all number_time children and the between_tod_only child
167
+ // Find all number_time_atom children and the between node (either between_time_only or between_tod_only)
160
168
  for (let i = 0; i < tp.children.length; i++) {
161
- if (tp.children[i].type === 'number_time') {
162
- totalSeconds += RuleParser.__parseValue(tp.children[i])
163
- } else if (tp.children[i].type === 'between_tod_only') {
164
- betweenTodOnly = tp.children[i]
169
+ if (tp.children[i].type === 'number_time_atom') {
170
+ // New structure: number_time_atom -> number_time
171
+ totalSeconds += RuleParser.__parseValue(tp.children[i].children[0])
172
+ } else if (tp.children[i].type === 'between_time_only' || tp.children[i].type === 'between_time_only_atom') {
173
+ betweenNode = tp.children[i].type === 'between_time_only_atom' ? tp.children[i].children[0] : tp.children[i]
174
+ isBetweenTod = false
175
+ } else if (tp.children[i].type === 'between_tod_only' || tp.children[i].type === 'between_tod_only_atom') {
176
+ betweenNode = tp.children[i].type === 'between_tod_only_atom' ? tp.children[i].children[0] : tp.children[i]
177
+ isBetweenTod = true
165
178
  }
166
179
  }
167
180
 
168
181
  // This should always be present based on the grammar, but check defensively
169
- if (!betweenTodOnly) {
170
- throw new Error('time_period_ago_between requires between_tod_only child')
182
+ if (!betweenNode) {
183
+ throw new Error('time_period_ago_between requires between_time_only or between_tod_only child')
171
184
  }
172
185
 
173
- const betweenTod = betweenTodOnly.children[0]
174
- let startTod = RuleParser.__parseValue(betweenTod.children[0])
175
- let endTod = RuleParser.__parseValue(betweenTod.children[1])
176
-
177
- // Check if there's a dow_range at betweenTod.children[2]
178
- // Note: startTod and endTod should always be objects from number_tod parsing
179
- if (betweenTod.children.length > 2) {
180
- RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2])
186
+ if (isBetweenTod) {
187
+ const betweenTod = betweenNode.children[0]
188
+ // between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
189
+ let startTod = RuleParser.__parseValue(betweenTod.children[0])
190
+ let endTod = RuleParser.__parseValue(betweenTod.children[1])
191
+
192
+ // Check if there's a dow_range at betweenTod.children[2]
193
+ // Note: startTod and endTod should always be objects from number_tod parsing
194
+ if (betweenTod.children.length > 2) {
195
+ RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2])
196
+ }
197
+
198
+ return ["TimePeriodBetweenAgo", totalSeconds, startTod, endTod]
199
+ } else {
200
+ const betweenNumberTime = betweenNode.children[0]
201
+ // between_number_time has: children[0] = first time_inner, children[1] = separator, children[2] = second time_inner, children[3] = optional dow_range
202
+ const startValue = RuleParser.__parseValue(betweenNumberTime.children[0])
203
+ const endValue = RuleParser.__parseValue(betweenNumberTime.children[2])
204
+
205
+ // Check if there's a dow_range at betweenNumberTime.children[3]
206
+ if (betweenNumberTime.children.length > 3 && betweenNumberTime.children[3].type === 'dow_range') {
207
+ const dow = RuleParser._parseDowRange(betweenNumberTime.children[3])
208
+ if (dow.start === dow.end) {
209
+ // Single day: ["TimePeriodBetweenAgo", totalSeconds, start, end, "MONDAY"]
210
+ return ["TimePeriodBetweenAgo", totalSeconds, startValue, endValue, dow.start]
211
+ } else {
212
+ // Range: ["TimePeriodBetweenAgo", totalSeconds, start, end, "MONDAY", "FRIDAY"]
213
+ return ["TimePeriodBetweenAgo", totalSeconds, startValue, endValue, dow.start, dow.end]
214
+ }
215
+ }
216
+
217
+ return ["TimePeriodBetweenAgo", totalSeconds, startValue, endValue]
181
218
  }
182
-
183
- return ["TimePeriodBetweenAgo", totalSeconds, startTod, endTod]
184
219
  }
185
220
  case 'between_tod_only': {
186
221
  // between_tod_only has children[0] = between_tod node
187
222
  const betweenTod = tp.children[0]
223
+ // between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
188
224
  let startTod = RuleParser.__parseValue(betweenTod.children[0])
189
225
  let endTod = RuleParser.__parseValue(betweenTod.children[1])
190
226
 
@@ -200,13 +236,14 @@ class RuleParser {
200
236
  case 'between_time_only': {
201
237
  // between_time_only has children[0] = between_number_time node
202
238
  const betweenNumberTime = tp.children[0]
239
+ // between_number_time has: children[0] = first time_inner, children[1] = separator, children[2] = second time_inner, children[3] = optional dow_range
203
240
  const startValue = RuleParser.__parseValue(betweenNumberTime.children[0])
204
- const endValue = RuleParser.__parseValue(betweenNumberTime.children[1])
241
+ const endValue = RuleParser.__parseValue(betweenNumberTime.children[2])
205
242
 
206
- // Check if there's a dow_range at betweenNumberTime.children[2]
243
+ // Check if there's a dow_range at betweenNumberTime.children[3]
207
244
  // If DOW filters are provided, append them as additional parameters
208
- if (betweenNumberTime.children.length > 2 && betweenNumberTime.children[2].type === 'dow_range') {
209
- const dow = RuleParser._parseDowRange(betweenNumberTime.children[2])
245
+ if (betweenNumberTime.children.length > 3 && betweenNumberTime.children[3].type === 'dow_range') {
246
+ const dow = RuleParser._parseDowRange(betweenNumberTime.children[3])
210
247
  if (dow.start === dow.end) {
211
248
  // Single day: ["TimePeriodBetween", start, end, "MONDAY"]
212
249
  return ["TimePeriodBetween", startValue, endValue, dow.start]
@@ -223,6 +260,25 @@ class RuleParser {
223
260
  static __parseValue(child){
224
261
  const type = child.type
225
262
  switch(type){
263
+ case 'value': {
264
+ // Arrays have value nodes as children - unwrap to get value_atom
265
+ return RuleParser.__parseValue(child.children[0])
266
+ }
267
+ case 'value_atom': {
268
+ // New layer: unwrap value_atom to get the actual atomic type
269
+ return RuleParser.__parseValue(child.children[0])
270
+ }
271
+ case 'number_atom':
272
+ case 'number_time_atom':
273
+ case 'tod_atom':
274
+ case 'dow_atom':
275
+ case 'between_tod_inner':
276
+ case 'between_number_inner':
277
+ case 'between_number_time_inner':
278
+ case 'dow_range_inner': {
279
+ // New layer: unwrap atom wrappers to get the actual leaf nodes
280
+ return RuleParser.__parseValue(child.children[0])
281
+ }
226
282
  case 'string': {
227
283
  const str = child.text
228
284
  return str.slice(1, -1)
@@ -274,10 +330,13 @@ class RuleParser {
274
330
  case 'array': {
275
331
  const ret = []
276
332
  for(const c of child.children){
277
- ret.push(RuleParser.__parseValue(c.children[0]))
333
+ ret.push(RuleParser.__parseValue(c))
278
334
  }
279
335
  return ret;
280
336
  }
337
+ case 'dow': {
338
+ return normalizeDow(child.text)
339
+ }
281
340
  default:
282
341
  throw new Error(`Unknown value type ${type}`)
283
342
  }
@@ -287,7 +346,17 @@ class RuleParser {
287
346
 
288
347
  const type = child.type
289
348
  switch(type){
349
+ case 'value_atom': {
350
+ // New layer: unwrap value_atom to get the actual atomic type
351
+ const atomChild = child.children[0]
352
+ if (atomChild.type === 'time_period') {
353
+ const tp = atomChild.children[0]
354
+ return RuleParser._parseTimePeriod(tp)
355
+ }
356
+ return ['Value', RuleParser.__parseValue(atomChild)]
357
+ }
290
358
  case 'time_period': {
359
+ // Old structure (shouldn't happen with new EBNF)
291
360
  const tp = child.children[0]
292
361
  return RuleParser._parseTimePeriod(tp)
293
362
  }
@@ -314,6 +383,11 @@ class RuleParser {
314
383
  switch(type){
315
384
  case 'fcall':
316
385
  return RuleParser._parseFcall(child)
386
+ case 'number_atom':
387
+ case 'number_time_atom': {
388
+ // New layer: unwrap atom wrappers to get the actual leaf nodes
389
+ return ['Value', RuleParser.__parseValue(child.children[0])]
390
+ }
317
391
  case 'number':
318
392
  return ['Value', parseFloat(child.text)]
319
393
  case 'number_time':
@@ -406,7 +480,7 @@ class RuleParser {
406
480
  switch(rhs.type){
407
481
  case 'between_tod': {
408
482
  // Direct between_tod (without wrapping between node)
409
- // between_tod has: children[0] = first tod, children[1] = second tod, children[2] = optional dow_range
483
+ // between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
410
484
  const startTod = RuleParser.__parseValue(rhs.children[0])
411
485
  const endTod = RuleParser.__parseValue(rhs.children[1])
412
486
 
@@ -421,7 +495,7 @@ class RuleParser {
421
495
  // between wraps either between_number or between_tod
422
496
  const betweenChild = rhs.children[0]
423
497
  if (betweenChild.type === 'between_tod') {
424
- // between_tod has: children[0] = first tod, children[1] = second tod, children[2] = optional dow_range
498
+ // between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
425
499
  const startTod = RuleParser.__parseValue(betweenChild.children[0])
426
500
  const endTod = RuleParser.__parseValue(betweenChild.children[1])
427
501
 
@@ -432,12 +506,13 @@ class RuleParser {
432
506
 
433
507
  return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', startTod], ['Value', endTod]]
434
508
  } else {
435
- // between_number - no dow support
436
- return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', RuleParser.__parseValue(betweenChild.children[0])], ['Value', RuleParser.__parseValue(betweenChild.children[1])]]
509
+ // between_number has: children[0] = first number_inner, children[1] = separator, children[2] = second number_inner
510
+ return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', RuleParser.__parseValue(betweenChild.children[0])], ['Value', RuleParser.__parseValue(betweenChild.children[2])]]
437
511
  }
438
512
  }
439
513
  case 'between_number':
440
- return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', RuleParser.__parseValue(rhs.children[0].children[0])], ['Value', RuleParser.__parseValue(rhs.children[0].children[1])]]
514
+ // between_number has: children[0] = first number_inner, children[1] = separator, children[2] = second number_inner
515
+ return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', RuleParser.__parseValue(rhs.children[0].children[0])], ['Value', RuleParser.__parseValue(rhs.children[0].children[2])]]
441
516
  case 'basic_rhs':
442
517
  return [OperatorFn[rhs.children[0].text], RuleParser._parseResult(expr.children[0]), RuleParser._parseResult(rhs.children[1])]
443
518
  case 'eq_approx': {
@@ -559,8 +634,6 @@ class RuleParser {
559
634
  // Extract the invalid time from the error message
560
635
  const match = e.message.match(/Invalid time of day[,:]?\s*([0-9:]+)/);
561
636
  const badTod = match ? match[1] : 'invalid';
562
- const { ParsingError } = require('ebnf');
563
- const { RuleParseError } = require('./errors/RuleParseError');
564
637
 
565
638
  // Calculate position (simplified - at end of input)
566
639
  const lines = txt.trim().split('\n');
@@ -585,7 +658,6 @@ class RuleParser {
585
658
  if (e.message && e.message.includes('Invalid day of week')) {
586
659
  const match = e.message.match(/Invalid day of week[,:]?\s*(\w+)/);
587
660
  const badDow = match ? match[1] : 'invalid';
588
- const { RuleParseError } = require('./errors/RuleParseError');
589
661
 
590
662
  const lines = txt.trim().split('\n');
591
663
  const position = {
@@ -611,5 +683,6 @@ class RuleParser {
611
683
  }
612
684
  }
613
685
  module.exports = RuleParser
614
- module.exports.ParsingError = require('ebnf').ParsingError
615
- module.exports.RuleParseError = require('./errors/RuleParseError').RuleParseError
686
+ module.exports.ParserRules = ParserRules
687
+ module.exports.ParsingError = ParsingError
688
+ module.exports.RuleParseError = RuleParseError
@@ -1 +1 @@
1
- module.exports=[{"name":"statement_main","bnf":[["statement","EOF"]]},{"name":"logical_operator","bnf":[["AND"],["OR"]]},{"name":"%statement[2]","bnf":[["logical_operator","expression"]],"fragment":true},{"name":"statement","bnf":[["expression","%statement[2]*"]]},{"name":"expression","bnf":[["not_expression"],["standard_expression"],["parenthesis_expression"]]},{"name":"parenthesis_expression","bnf":[["BEGIN_PARENTHESIS","WS*","statement","WS*","END_PARENTHESIS"]]},{"name":"%not_expression[2]","bnf":[["result"],["parenthesis_expression"]],"fragment":true},{"name":"not_expression","bnf":[["NOT","%not_expression[2]"]]},{"name":"%standard_expression[2][1]","bnf":[["WS*","eq_approx"]],"fragment":true},{"name":"%standard_expression[2][2]","bnf":[["WS*","basic_rhs"]],"fragment":true},{"name":"%standard_expression[2][3][1]","bnf":[["WS+","IS"]],"fragment":true},{"name":"%standard_expression[2][3]","bnf":[["%standard_expression[2][3][1]?","WS+","between"]],"fragment":true},{"name":"%standard_expression[2][4]","bnf":[["WS+","in_expr"]],"fragment":true},{"name":"%standard_expression[2]","bnf":[["%standard_expression[2][1]"],["%standard_expression[2][2]"],["%standard_expression[2][3]"],["%standard_expression[2][4]"]],"fragment":true},{"name":"standard_expression","bnf":[["result","%standard_expression[2]?"]]},{"name":"basic_rhs","bnf":[["operator","WS*","result"]]},{"name":"eq_approx","bnf":[["eq_operator","WS*","\"~\"","WS*","result"]]},{"name":"PLUS","bnf":[["\"+\""]]},{"name":"MINUS","bnf":[["\"-\""]]},{"name":"MULTIPLY","bnf":[["\"*\""]]},{"name":"DIVIDE","bnf":[["\"/\""]]},{"name":"MODULUS","bnf":[["\"%\""]]},{"name":"DEFAULT_VAL","bnf":[["\"??\""]]},{"name":"arithmetic_operator","bnf":[["PLUS"],["MINUS"],["MULTIPLY"],["DIVIDE"],["MODULUS"],["DEFAULT_VAL"]]},{"name":"arithmetic_operand","bnf":[["fcall"],["number_time"],["number"]]},{"name":"%arithmetic_result[5]","bnf":[["arithmetic_result"],["arithmetic_operand"]],"fragment":true},{"name":"arithmetic_result","bnf":[["arithmetic_operand","WS*","arithmetic_operator","WS*","%arithmetic_result[5]"]]},{"name":"simple_result","bnf":[["fcall"],["value"]]},{"name":"result","bnf":[["arithmetic_result"],["simple_result"]]},{"name":"value","bnf":[["false"],["true"],["array"],["time_period"],["number_time"],["number"],["number_tod"],["string"]]},{"name":"BEGIN_ARRAY","bnf":[["WS*",/\x5B/,"WS*"]]},{"name":"BEGIN_OBJECT","bnf":[["WS*",/\x7B/,"WS*"]]},{"name":"END_ARRAY","bnf":[["WS*",/\x5D/,"WS*"]]},{"name":"END_OBJECT","bnf":[["WS*",/\x7D/,"WS*"]]},{"name":"NAME_SEPARATOR","bnf":[["WS*",/\x3A/,"WS*"]]},{"name":"VALUE_SEPARATOR","bnf":[["WS*",/\x2C/,"WS*"]]},{"name":"WS","bnf":[[/[\x20\x09\x0A\x0D]/]]},{"name":"operator","bnf":[["GTE"],["LTE"],["GT"],["LT"],["EQ"],["NEQ"]]},{"name":"eq_operator","bnf":[["EQ"],["NEQ"]]},{"name":"BEGIN_ARGUMENT","bnf":[["\"(\""]]},{"name":"END_ARGUMENT","bnf":[["\")\""]]},{"name":"BEGIN_PARENTHESIS","bnf":[["\"(\""]]},{"name":"END_PARENTHESIS","bnf":[["\")\""]]},{"name":"BEGIN_IN","bnf":[[/[Ii]/,/[Nn]/]]},{"name":"in_expr","bnf":[["BEGIN_IN","WS*","BEGIN_PARENTHESIS","WS*","arguments","END_PARENTHESIS"]]},{"name":"argument","bnf":[["statement","WS*"]]},{"name":"%arguments[2]","bnf":[["WS*","\",\"","WS*","argument"]],"fragment":true},{"name":"arguments","bnf":[["argument","%arguments[2]*"]]},{"name":"%fname[1]","bnf":[[/[a-zA-z0-9]/]]},{"name":"fname","bnf":[["%fname[1]+"]]},{"name":"fcall","bnf":[["fname","WS*","BEGIN_ARGUMENT","WS*","arguments?","END_ARGUMENT"]]},{"name":"%between_number[1]","bnf":[["number_time"],["number"]],"fragment":true},{"name":"%between_number[2][1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_number[2][2]","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"%between_number[2]","bnf":[["%between_number[2][1]"],["%between_number[2][2]"]],"fragment":true},{"name":"%between_number[3]","bnf":[["number_time"],["number"]],"fragment":true},{"name":"between_number","bnf":[["%between_number[1]","%between_number[2]","%between_number[3]"]]},{"name":"%between_number_time[2][1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_number_time[2][2]","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"%between_number_time[2]","bnf":[["%between_number_time[2][1]"],["%between_number_time[2][2]"]],"fragment":true},{"name":"%between_number_time[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_number_time","bnf":[["number_time","%between_number_time[2]","number_time","%between_number_time[4]?"]]},{"name":"%between_tod[2][1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_tod[2]","bnf":[["%between_tod[2][1]"]],"fragment":true},{"name":"%between_tod[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_tod","bnf":[["number_tod","%between_tod[2]","number_tod","%between_tod[4]?"]]},{"name":"%between[3]","bnf":[["between_number"],["between_tod"]],"fragment":true},{"name":"between","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","%between[3]"]]},{"name":"dow","bnf":[[/[Mm]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Oo]/,/[Nn]/],[/[Tt]/,/[Uu]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Uu]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Dd]/,/[Nn]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ww]/,/[Ee]/,/[Dd]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Hh]/,/[Uu]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/],[/[Ff]/,/[Rr]/,/[Ii]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ff]/,/[Rr]/,/[Ii]/],[/[Ss]/,/[Aa]/,/[Tt]/,/[Uu]/,/[Rr]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Aa]/,/[Tt]/],[/[Ss]/,/[Uu]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Uu]/,/[Nn]/]]},{"name":"%dow_range[4]","bnf":[["WS+",/[Tt]/,/[Oo]/,"WS+","dow"]],"fragment":true},{"name":"dow_range","bnf":[[/[Oo]/,/[Nn]/,"WS+","dow","%dow_range[4]?"]]},{"name":"between_time_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_number_time"]]},{"name":"between_tod_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_tod"]]},{"name":"%AND[1]","bnf":[["WS*",/&/,/&/,"WS*"]],"fragment":true},{"name":"%AND[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"AND","bnf":[["%AND[1]"],["%AND[2]"]]},{"name":"%OR[1]","bnf":[["WS*",/\|/,/\|/,"WS*"]],"fragment":true},{"name":"%OR[2]","bnf":[["WS+",/[Oo]/,/[Rr]/,"WS+"]],"fragment":true},{"name":"OR","bnf":[["%OR[1]"],["%OR[2]"]]},{"name":"AGO","bnf":[[/[Aa]/,/[Gg]/,/[Oo]/]]},{"name":"GT","bnf":[["\">\""]]},{"name":"LT","bnf":[["\"<\""]]},{"name":"GTE","bnf":[["\">=\""]]},{"name":"LTE","bnf":[["\"<=\""]]},{"name":"IS","bnf":[[/[Ii]/,/[Ss]/]]},{"name":"EQ","bnf":[["\"==\""],["\"=\""]]},{"name":"NEQ","bnf":[["\"!=\""]]},{"name":"%NOT[1]","bnf":[[/!/,"WS*"]],"fragment":true},{"name":"%NOT[2]","bnf":[[/[Nn]/,/[Oo]/,/[Tt]/,"WS+"]],"fragment":true},{"name":"NOT","bnf":[["%NOT[1]"],["%NOT[2]"]]},{"name":"false","bnf":[[/[Ff]/,/[Aa]/,/[Ll]/,/[Ss]/,/[Ee]/]]},{"name":"null","bnf":[[/[Nn]/,/[Uu]/,/[Ll]/,/[Ll]/]]},{"name":"true","bnf":[[/[Tt]/,/[Rr]/,/[Uu]/,/[Ee]/]]},{"name":"%array[2][2]","bnf":[["VALUE_SEPARATOR","value"]],"fragment":true},{"name":"%array[2]","bnf":[["value","%array[2][2]*"]],"fragment":true},{"name":"array","bnf":[["BEGIN_ARRAY","%array[2]?","END_ARRAY"]]},{"name":"unit","bnf":[[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/,/[Ss]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/,/[Ss]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/,/[Ss]/],[/[Dd]/,/[Aa]/,/[Yy]/,/[Ss]/],[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/],[/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/]]},{"name":"%number[2][1]","bnf":[[/[0-9]/]]},{"name":"%number[2]","bnf":[["%number[2][1]+"]],"fragment":true},{"name":"%number[3][2]","bnf":[[/[0-9]/]]},{"name":"%number[3]","bnf":[["\".\"","%number[3][2]+"]],"fragment":true},{"name":"%number[4][2]","bnf":[["\"-\""],["\"+\""]],"fragment":true},{"name":"%number[4][3][2]","bnf":[[/[0-9]/]]},{"name":"%number[4][3]","bnf":[["\"0\""],[/[1-9]/,"%number[4][3][2]*"]],"fragment":true},{"name":"%number[4]","bnf":[["\"e\"","%number[4][2]?","%number[4][3]"]],"fragment":true},{"name":"number","bnf":[["\"-\"?","%number[2]","%number[3]?","%number[4]?"]]},{"name":"number_time","bnf":[["number","WS+","unit"]]},{"name":"%number_tod[1][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[1]","bnf":[["%number_tod[1][1]+"]],"fragment":true},{"name":"%number_tod[3][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[3]","bnf":[["%number_tod[3][1]+"]],"fragment":true},{"name":"number_tod","bnf":[["%number_tod[1]","\":\"","%number_tod[3]"]]},{"name":"%time_period_ago[2]","bnf":[["WS+","number_time"]],"fragment":true},{"name":"time_period_ago","bnf":[["number_time","%time_period_ago[2]*","WS+","AGO"]]},{"name":"%time_period_ago_between[2]","bnf":[["WS+","number_time"]],"fragment":true},{"name":"time_period_ago_between","bnf":[["number_time","%time_period_ago_between[2]*","WS+","AGO","WS+","between_tod_only"]]},{"name":"time_period_const","bnf":[[/[Tt]/,/[Oo]/,/[Dd]/,/[Aa]/,/[Yy]/],["time_period_ago"]]},{"name":"time_period","bnf":[["time_period_ago_between"],["time_period_const"],["between_tod_only"],["between_time_only"]]},{"name":"%string[2][1]","bnf":[[/[\x20-\x21]/],[/[\x23-\x5B]/],[/[\x5D-\uFFFF]/]],"fragment":true},{"name":"%string[2][2]","bnf":[[/\x22/],[/\x5C/],[/\x2F/],[/\x62/],[/\x66/],[/\x6E/],[/\x72/],[/\x74/],[/\x75/,"HEXDIG","HEXDIG","HEXDIG","HEXDIG"]],"fragment":true},{"name":"%string[2]","bnf":[["%string[2][1]"],[/\x5C/,"%string[2][2]"]],"fragment":true},{"name":"string","bnf":[["'\"'","%string[2]*","'\"'"]]},{"name":"HEXDIG","bnf":[[/[a-fA-F0-9]/]]}]
1
+ module.exports=[{"name":"statement_main","bnf":[["statement","EOF"]]},{"name":"logical_operator","bnf":[["AND"],["OR"]]},{"name":"%statement[2]","bnf":[["logical_operator","expression"]],"fragment":true},{"name":"statement","bnf":[["expression","%statement[2]*"]]},{"name":"expression","bnf":[["not_expression"],["standard_expression"],["parenthesis_expression"]]},{"name":"parenthesis_expression","bnf":[["BEGIN_PARENTHESIS","WS*","statement","WS*","END_PARENTHESIS"]]},{"name":"%not_expression[2]","bnf":[["result"],["parenthesis_expression"]],"fragment":true},{"name":"not_expression","bnf":[["NOT","%not_expression[2]"]]},{"name":"%standard_expression[2][1]","bnf":[["WS*","eq_approx"]],"fragment":true},{"name":"%standard_expression[2][2]","bnf":[["WS*","basic_rhs"]],"fragment":true},{"name":"%standard_expression[2][3][1]","bnf":[["WS+","IS"]],"fragment":true},{"name":"%standard_expression[2][3]","bnf":[["%standard_expression[2][3][1]?","WS+","between"]],"fragment":true},{"name":"%standard_expression[2][4]","bnf":[["WS+","in_expr"]],"fragment":true},{"name":"%standard_expression[2]","bnf":[["%standard_expression[2][1]"],["%standard_expression[2][2]"],["%standard_expression[2][3]"],["%standard_expression[2][4]"]],"fragment":true},{"name":"standard_expression","bnf":[["result","%standard_expression[2]?"]]},{"name":"basic_rhs","bnf":[["operator","WS*","result"]]},{"name":"eq_approx","bnf":[["eq_operator","WS*","\"~\"","WS*","result"]]},{"name":"PLUS","bnf":[["\"+\""]]},{"name":"MINUS","bnf":[["\"-\""]]},{"name":"MULTIPLY","bnf":[["\"*\""]]},{"name":"DIVIDE","bnf":[["\"/\""]]},{"name":"MODULUS","bnf":[["\"%\""]]},{"name":"DEFAULT_VAL","bnf":[["\"??\""]]},{"name":"arithmetic_operator","bnf":[["PLUS"],["MINUS"],["MULTIPLY"],["DIVIDE"],["MODULUS"],["DEFAULT_VAL"]]},{"name":"number_atom","bnf":[["number"]]},{"name":"number_time_atom","bnf":[["number_time"]]},{"name":"tod_atom","bnf":[["number_tod"]]},{"name":"dow_atom","bnf":[["dow"]]},{"name":"arithmetic_operand","bnf":[["fcall"],["number_time_atom"],["number_atom"]]},{"name":"%arithmetic_result[5]","bnf":[["arithmetic_result"],["arithmetic_operand"]],"fragment":true},{"name":"arithmetic_result","bnf":[["arithmetic_operand","WS*","arithmetic_operator","WS*","%arithmetic_result[5]"]]},{"name":"simple_result","bnf":[["fcall"],["value"]]},{"name":"result","bnf":[["arithmetic_result"],["simple_result"]]},{"name":"value_atom","bnf":[["false"],["true"],["array"],["time_period"],["number_time_atom"],["number_atom"],["tod_atom"],["string"]]},{"name":"value","bnf":[["value_atom"]]},{"name":"BEGIN_ARRAY","bnf":[["WS*",/\x5B/,"WS*"]]},{"name":"BEGIN_OBJECT","bnf":[["WS*",/\x7B/,"WS*"]]},{"name":"END_ARRAY","bnf":[["WS*",/\x5D/,"WS*"]]},{"name":"END_OBJECT","bnf":[["WS*",/\x7D/,"WS*"]]},{"name":"NAME_SEPARATOR","bnf":[["WS*",/\x3A/,"WS*"]]},{"name":"VALUE_SEPARATOR","bnf":[["WS*",/\x2C/,"WS*"]]},{"name":"WS","bnf":[[/[\x20\x09\x0A\x0D]/]]},{"name":"operator","bnf":[["GTE"],["LTE"],["GT"],["LT"],["EQ"],["NEQ"]]},{"name":"eq_operator","bnf":[["EQ"],["NEQ"]]},{"name":"BEGIN_ARGUMENT","bnf":[["\"(\""]]},{"name":"END_ARGUMENT","bnf":[["\")\""]]},{"name":"BEGIN_PARENTHESIS","bnf":[["\"(\""]]},{"name":"END_PARENTHESIS","bnf":[["\")\""]]},{"name":"BEGIN_IN","bnf":[[/[Ii]/,/[Nn]/]]},{"name":"in_expr","bnf":[["BEGIN_IN","WS*","BEGIN_PARENTHESIS","WS*","arguments","END_PARENTHESIS"]]},{"name":"argument","bnf":[["statement","WS*"]]},{"name":"%arguments[2]","bnf":[["WS*","\",\"","WS*","argument"]],"fragment":true},{"name":"arguments","bnf":[["argument","%arguments[2]*"]]},{"name":"%fname[1]","bnf":[[/[A-Za-z0-9]/]]},{"name":"fname","bnf":[["%fname[1]+"]]},{"name":"fcall","bnf":[["fname","WS*","BEGIN_ARGUMENT","WS*","arguments?","END_ARGUMENT"]]},{"name":"%between_dash_or_and[1]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_dash_or_and[2]","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"between_dash_or_and","bnf":[["%between_dash_or_and[1]"],["%between_dash_or_and[2]"]]},{"name":"between_number_inner","bnf":[["number_atom"],["number_time_atom"]]},{"name":"between_number","bnf":[["between_number_inner","between_dash_or_and","between_number_inner"]]},{"name":"between_number_time_inner","bnf":[["number_time_atom"]]},{"name":"%between_number_time[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_number_time","bnf":[["between_number_time_inner","between_dash_or_and","between_number_time_inner","%between_number_time[4]?"]]},{"name":"between_tod_inner","bnf":[["tod_atom"]]},{"name":"%between_tod[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_tod[4]","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_tod","bnf":[["between_tod_inner","%between_tod[2]","between_tod_inner","%between_tod[4]?"]]},{"name":"%between[3]","bnf":[["between_number"],["between_tod"]],"fragment":true},{"name":"between","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","%between[3]"]]},{"name":"dow","bnf":[[/[Mm]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Oo]/,/[Nn]/],[/[Tt]/,/[Uu]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Uu]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Dd]/,/[Nn]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ww]/,/[Ee]/,/[Dd]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Hh]/,/[Uu]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/],[/[Ff]/,/[Rr]/,/[Ii]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ff]/,/[Rr]/,/[Ii]/],[/[Ss]/,/[Aa]/,/[Tt]/,/[Uu]/,/[Rr]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Aa]/,/[Tt]/],[/[Ss]/,/[Uu]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Uu]/,/[Nn]/]]},{"name":"dow_range_inner","bnf":[["dow_atom"]]},{"name":"%dow_range[4]","bnf":[["WS+",/[Tt]/,/[Oo]/,"WS+","dow_range_inner"]],"fragment":true},{"name":"dow_range","bnf":[[/[Oo]/,/[Nn]/,"WS+","dow_range_inner","%dow_range[4]?"]]},{"name":"between_time_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_number_time"]]},{"name":"between_tod_only","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","between_tod"]]},{"name":"between_time_only_atom","bnf":[["between_time_only"]]},{"name":"between_tod_only_atom","bnf":[["between_tod_only"]]},{"name":"%AND[1]","bnf":[["WS*",/&/,/&/,"WS*"]],"fragment":true},{"name":"%AND[2]","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"AND","bnf":[["%AND[1]"],["%AND[2]"]]},{"name":"%OR[1]","bnf":[["WS*",/\|/,/\|/,"WS*"]],"fragment":true},{"name":"%OR[2]","bnf":[["WS+",/[Oo]/,/[Rr]/,"WS+"]],"fragment":true},{"name":"OR","bnf":[["%OR[1]"],["%OR[2]"]]},{"name":"AGO","bnf":[[/[Aa]/,/[Gg]/,/[Oo]/]]},{"name":"GT","bnf":[["\">\""]]},{"name":"LT","bnf":[["\"<\""]]},{"name":"GTE","bnf":[["\">=\""]]},{"name":"LTE","bnf":[["\"<=\""]]},{"name":"IS","bnf":[[/[Ii]/,/[Ss]/]]},{"name":"EQ","bnf":[["\"==\""],["\"=\""]]},{"name":"NEQ","bnf":[["\"!=\""]]},{"name":"%NOT[1]","bnf":[[/!/,"WS*"]],"fragment":true},{"name":"%NOT[2]","bnf":[[/[Nn]/,/[Oo]/,/[Tt]/,"WS+"]],"fragment":true},{"name":"NOT","bnf":[["%NOT[1]"],["%NOT[2]"]]},{"name":"false","bnf":[[/[Ff]/,/[Aa]/,/[Ll]/,/[Ss]/,/[Ee]/]]},{"name":"null","bnf":[[/[Nn]/,/[Uu]/,/[Ll]/,/[Ll]/]]},{"name":"true","bnf":[[/[Tt]/,/[Rr]/,/[Uu]/,/[Ee]/]]},{"name":"%array[2][2]","bnf":[["VALUE_SEPARATOR","value"]],"fragment":true},{"name":"%array[2]","bnf":[["value","%array[2][2]*"]],"fragment":true},{"name":"array","bnf":[["BEGIN_ARRAY","%array[2]?","END_ARRAY"]]},{"name":"unit","bnf":[[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/,/[Ss]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/,/[Ss]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/,/[Ss]/],[/[Dd]/,/[Aa]/,/[Yy]/,/[Ss]/],[/[Ss]/,/[Ee]/,/[Cc]/,/[Oo]/,/[Nn]/,/[Dd]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Uu]/,/[Tt]/,/[Ee]/],[/[Ww]/,/[Ee]/,/[Ee]/,/[Kk]/],[/[Hh]/,/[Oo]/,/[Uu]/,/[Rr]/],[/[Dd]/,/[Aa]/,/[Yy]/],[/[Mm]/,/[Ii]/,/[Nn]/,/[Ss]/],[/[Mm]/,/[Ii]/,/[Nn]/]]},{"name":"%number[2][1]","bnf":[[/[0-9]/]]},{"name":"%number[2]","bnf":[["%number[2][1]+"]],"fragment":true},{"name":"%number[3][2]","bnf":[[/[0-9]/]]},{"name":"%number[3]","bnf":[["\".\"","%number[3][2]+"]],"fragment":true},{"name":"%number[4][2]","bnf":[["\"-\""],["\"+\""]],"fragment":true},{"name":"%number[4][3][2]","bnf":[[/[0-9]/]]},{"name":"%number[4][3]","bnf":[["\"0\""],[/[1-9]/,"%number[4][3][2]*"]],"fragment":true},{"name":"%number[4]","bnf":[["\"e\"","%number[4][2]?","%number[4][3]"]],"fragment":true},{"name":"number","bnf":[["\"-\"?","%number[2]","%number[3]?","%number[4]?"]]},{"name":"number_time","bnf":[["number","WS+","unit"]]},{"name":"%number_tod[1][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[1]","bnf":[["%number_tod[1][1]+"]],"fragment":true},{"name":"%number_tod[3][1]","bnf":[[/[0-9]/]]},{"name":"%number_tod[3]","bnf":[["%number_tod[3][1]+"]],"fragment":true},{"name":"number_tod","bnf":[["%number_tod[1]","\":\"","%number_tod[3]"]]},{"name":"%time_period_ago[2]","bnf":[["WS+","number_time_atom"]],"fragment":true},{"name":"time_period_ago","bnf":[["number_time_atom","%time_period_ago[2]*","WS+","AGO"]]},{"name":"%time_period_ago_between[2]","bnf":[["WS+","number_time_atom"]],"fragment":true},{"name":"%time_period_ago_between[6]","bnf":[["between_time_only_atom"],["between_tod_only_atom"]],"fragment":true},{"name":"time_period_ago_between","bnf":[["number_time_atom","%time_period_ago_between[2]*","WS+","AGO","WS+","%time_period_ago_between[6]"]]},{"name":"time_period_const","bnf":[[/[Tt]/,/[Oo]/,/[Dd]/,/[Aa]/,/[Yy]/],["time_period_ago"]]},{"name":"time_period","bnf":[["time_period_ago_between"],["time_period_const"],["between_tod_only"],["between_time_only"]]},{"name":"%string[2][1]","bnf":[[/[\x20-\x21]/],[/[\x23-\x5B]/],[/[\x5D-\uFFFF]/]],"fragment":true},{"name":"%string[2][2]","bnf":[[/\x22/],[/\x5C/],[/\x2F/],[/\x62/],[/\x66/],[/\x6E/],[/\x72/],[/\x74/],[/\x75/,"HEXDIG","HEXDIG","HEXDIG","HEXDIG"]],"fragment":true},{"name":"%string[2]","bnf":[["%string[2][1]"],[/\x5C/,"%string[2][2]"]],"fragment":true},{"name":"string","bnf":[["'\"'","%string[2]*","'\"'"]]},{"name":"HEXDIG","bnf":[[/[a-fA-F0-9]/]]}]
@@ -1,6 +1,7 @@
1
1
  const {Parser} = require('ebnf/dist/Parser.js'),
2
2
  {ParsingError} = require('ebnf'),
3
- assert = require('assert')
3
+ assert = require('assert'),
4
+ RuleParseError = require('./errors/RuleParseError')
4
5
 
5
6
  let ParserRules = require('./RuleParser.production.ebnf.js')
6
7
  let ParserCache;
@@ -108,10 +109,14 @@ class RuleParser {
108
109
  // dow_range can have 1 or 2 children (single day or range)
109
110
  if (dowRange.children.length === 1) {
110
111
  // Single day: ON MONDAY - return just the day string
111
- return { start: normalizeDow(dowRange.children[0].text), end: normalizeDow(dowRange.children[0].text) };
112
+ // New structure: dow_range -> dow_range_inner -> dow_atom -> dow
113
+ const dayText = RuleParser.__parseValue(dowRange.children[0])
114
+ return { start: dayText, end: dayText };
112
115
  } else if (dowRange.children.length === 2) {
113
116
  // Range: ON MONDAY TO FRIDAY - return both start and end days
114
- return { start: normalizeDow(dowRange.children[0].text), end: normalizeDow(dowRange.children[1].text) };
117
+ const startDay = RuleParser.__parseValue(dowRange.children[0])
118
+ const endDay = RuleParser.__parseValue(dowRange.children[1])
119
+ return { start: startDay, end: endDay };
115
120
  } else {
116
121
  throw new Error(`Invalid dow_range with ${dowRange.children.length} children`);
117
122
  }
@@ -133,12 +138,14 @@ class RuleParser {
133
138
  let totalSeconds = 0
134
139
  const components = []
135
140
  for (const child of timePeriodAgo.children) {
136
- if (child.type === 'number_time') {
137
- const number = parseFloat(child.children[0].text)
138
- const unit = child.children[1].text.toUpperCase()
141
+ if (child.type === 'number_time_atom') {
142
+ // New structure: number_time_atom -> number_time -> number, unit
143
+ const numberTime = child.children[0]
144
+ const number = parseFloat(numberTime.children[0].text)
145
+ const unit = numberTime.children[1].text.toUpperCase()
139
146
  components.push([number, unit])
140
147
  // Parse the value to get seconds
141
- totalSeconds += RuleParser.__parseValue(child)
148
+ totalSeconds += RuleParser.__parseValue(numberTime)
142
149
  }
143
150
  }
144
151
  // If there's only one component, use its number and unit
@@ -151,40 +158,69 @@ class RuleParser {
151
158
  }
152
159
  return ["TimePeriodConst", tp.text]
153
160
  case 'time_period_ago_between': {
154
- // time_period_ago_between has: number_time (WS+ number_time)* WS+ AGO WS+ between_tod_only
161
+ // time_period_ago_between has: number_time_atom (WS+ number_time_atom)* WS+ AGO WS+ (between_time_only | between_tod_only)
155
162
  // We need to extract all number_time children and sum them up, then return TimePeriodBetweenAgo
156
163
  let totalSeconds = 0
157
- let betweenTodOnly = null
164
+ let betweenNode = null
165
+ let isBetweenTod = false
158
166
 
159
- // Find all number_time children and the between_tod_only child
167
+ // Find all number_time_atom children and the between node (either between_time_only or between_tod_only)
160
168
  for (let i = 0; i < tp.children.length; i++) {
161
- if (tp.children[i].type === 'number_time') {
162
- totalSeconds += RuleParser.__parseValue(tp.children[i])
163
- } else if (tp.children[i].type === 'between_tod_only') {
164
- betweenTodOnly = tp.children[i]
169
+ if (tp.children[i].type === 'number_time_atom') {
170
+ // New structure: number_time_atom -> number_time
171
+ totalSeconds += RuleParser.__parseValue(tp.children[i].children[0])
172
+ } else if (tp.children[i].type === 'between_time_only' || tp.children[i].type === 'between_time_only_atom') {
173
+ betweenNode = tp.children[i].type === 'between_time_only_atom' ? tp.children[i].children[0] : tp.children[i]
174
+ isBetweenTod = false
175
+ } else if (tp.children[i].type === 'between_tod_only' || tp.children[i].type === 'between_tod_only_atom') {
176
+ betweenNode = tp.children[i].type === 'between_tod_only_atom' ? tp.children[i].children[0] : tp.children[i]
177
+ isBetweenTod = true
165
178
  }
166
179
  }
167
180
 
168
181
  // This should always be present based on the grammar, but check defensively
169
- if (!betweenTodOnly) {
170
- throw new Error('time_period_ago_between requires between_tod_only child')
182
+ if (!betweenNode) {
183
+ throw new Error('time_period_ago_between requires between_time_only or between_tod_only child')
171
184
  }
172
185
 
173
- const betweenTod = betweenTodOnly.children[0]
174
- let startTod = RuleParser.__parseValue(betweenTod.children[0])
175
- let endTod = RuleParser.__parseValue(betweenTod.children[1])
176
-
177
- // Check if there's a dow_range at betweenTod.children[2]
178
- // Note: startTod and endTod should always be objects from number_tod parsing
179
- if (betweenTod.children.length > 2) {
180
- RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2])
186
+ if (isBetweenTod) {
187
+ const betweenTod = betweenNode.children[0]
188
+ // between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
189
+ let startTod = RuleParser.__parseValue(betweenTod.children[0])
190
+ let endTod = RuleParser.__parseValue(betweenTod.children[1])
191
+
192
+ // Check if there's a dow_range at betweenTod.children[2]
193
+ // Note: startTod and endTod should always be objects from number_tod parsing
194
+ if (betweenTod.children.length > 2) {
195
+ RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2])
196
+ }
197
+
198
+ return ["TimePeriodBetweenAgo", totalSeconds, startTod, endTod]
199
+ } else {
200
+ const betweenNumberTime = betweenNode.children[0]
201
+ // between_number_time has: children[0] = first time_inner, children[1] = separator, children[2] = second time_inner, children[3] = optional dow_range
202
+ const startValue = RuleParser.__parseValue(betweenNumberTime.children[0])
203
+ const endValue = RuleParser.__parseValue(betweenNumberTime.children[2])
204
+
205
+ // Check if there's a dow_range at betweenNumberTime.children[3]
206
+ if (betweenNumberTime.children.length > 3 && betweenNumberTime.children[3].type === 'dow_range') {
207
+ const dow = RuleParser._parseDowRange(betweenNumberTime.children[3])
208
+ if (dow.start === dow.end) {
209
+ // Single day: ["TimePeriodBetweenAgo", totalSeconds, start, end, "MONDAY"]
210
+ return ["TimePeriodBetweenAgo", totalSeconds, startValue, endValue, dow.start]
211
+ } else {
212
+ // Range: ["TimePeriodBetweenAgo", totalSeconds, start, end, "MONDAY", "FRIDAY"]
213
+ return ["TimePeriodBetweenAgo", totalSeconds, startValue, endValue, dow.start, dow.end]
214
+ }
215
+ }
216
+
217
+ return ["TimePeriodBetweenAgo", totalSeconds, startValue, endValue]
181
218
  }
182
-
183
- return ["TimePeriodBetweenAgo", totalSeconds, startTod, endTod]
184
219
  }
185
220
  case 'between_tod_only': {
186
221
  // between_tod_only has children[0] = between_tod node
187
222
  const betweenTod = tp.children[0]
223
+ // between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
188
224
  let startTod = RuleParser.__parseValue(betweenTod.children[0])
189
225
  let endTod = RuleParser.__parseValue(betweenTod.children[1])
190
226
 
@@ -200,13 +236,14 @@ class RuleParser {
200
236
  case 'between_time_only': {
201
237
  // between_time_only has children[0] = between_number_time node
202
238
  const betweenNumberTime = tp.children[0]
239
+ // between_number_time has: children[0] = first time_inner, children[1] = separator, children[2] = second time_inner, children[3] = optional dow_range
203
240
  const startValue = RuleParser.__parseValue(betweenNumberTime.children[0])
204
- const endValue = RuleParser.__parseValue(betweenNumberTime.children[1])
241
+ const endValue = RuleParser.__parseValue(betweenNumberTime.children[2])
205
242
 
206
- // Check if there's a dow_range at betweenNumberTime.children[2]
243
+ // Check if there's a dow_range at betweenNumberTime.children[3]
207
244
  // If DOW filters are provided, append them as additional parameters
208
- if (betweenNumberTime.children.length > 2 && betweenNumberTime.children[2].type === 'dow_range') {
209
- const dow = RuleParser._parseDowRange(betweenNumberTime.children[2])
245
+ if (betweenNumberTime.children.length > 3 && betweenNumberTime.children[3].type === 'dow_range') {
246
+ const dow = RuleParser._parseDowRange(betweenNumberTime.children[3])
210
247
  if (dow.start === dow.end) {
211
248
  // Single day: ["TimePeriodBetween", start, end, "MONDAY"]
212
249
  return ["TimePeriodBetween", startValue, endValue, dow.start]
@@ -223,6 +260,25 @@ class RuleParser {
223
260
  static __parseValue(child){
224
261
  const type = child.type
225
262
  switch(type){
263
+ case 'value': {
264
+ // Arrays have value nodes as children - unwrap to get value_atom
265
+ return RuleParser.__parseValue(child.children[0])
266
+ }
267
+ case 'value_atom': {
268
+ // New layer: unwrap value_atom to get the actual atomic type
269
+ return RuleParser.__parseValue(child.children[0])
270
+ }
271
+ case 'number_atom':
272
+ case 'number_time_atom':
273
+ case 'tod_atom':
274
+ case 'dow_atom':
275
+ case 'between_tod_inner':
276
+ case 'between_number_inner':
277
+ case 'between_number_time_inner':
278
+ case 'dow_range_inner': {
279
+ // New layer: unwrap atom wrappers to get the actual leaf nodes
280
+ return RuleParser.__parseValue(child.children[0])
281
+ }
226
282
  case 'string': {
227
283
  const str = child.text
228
284
  return str.slice(1, -1)
@@ -274,10 +330,13 @@ class RuleParser {
274
330
  case 'array': {
275
331
  const ret = []
276
332
  for(const c of child.children){
277
- ret.push(RuleParser.__parseValue(c.children[0]))
333
+ ret.push(RuleParser.__parseValue(c))
278
334
  }
279
335
  return ret;
280
336
  }
337
+ case 'dow': {
338
+ return normalizeDow(child.text)
339
+ }
281
340
  default:
282
341
  throw new Error(`Unknown value type ${type}`)
283
342
  }
@@ -287,7 +346,17 @@ class RuleParser {
287
346
 
288
347
  const type = child.type
289
348
  switch(type){
349
+ case 'value_atom': {
350
+ // New layer: unwrap value_atom to get the actual atomic type
351
+ const atomChild = child.children[0]
352
+ if (atomChild.type === 'time_period') {
353
+ const tp = atomChild.children[0]
354
+ return RuleParser._parseTimePeriod(tp)
355
+ }
356
+ return ['Value', RuleParser.__parseValue(atomChild)]
357
+ }
290
358
  case 'time_period': {
359
+ // Old structure (shouldn't happen with new EBNF)
291
360
  const tp = child.children[0]
292
361
  return RuleParser._parseTimePeriod(tp)
293
362
  }
@@ -314,6 +383,11 @@ class RuleParser {
314
383
  switch(type){
315
384
  case 'fcall':
316
385
  return RuleParser._parseFcall(child)
386
+ case 'number_atom':
387
+ case 'number_time_atom': {
388
+ // New layer: unwrap atom wrappers to get the actual leaf nodes
389
+ return ['Value', RuleParser.__parseValue(child.children[0])]
390
+ }
317
391
  case 'number':
318
392
  return ['Value', parseFloat(child.text)]
319
393
  case 'number_time':
@@ -406,7 +480,7 @@ class RuleParser {
406
480
  switch(rhs.type){
407
481
  case 'between_tod': {
408
482
  // Direct between_tod (without wrapping between node)
409
- // between_tod has: children[0] = first tod, children[1] = second tod, children[2] = optional dow_range
483
+ // between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
410
484
  const startTod = RuleParser.__parseValue(rhs.children[0])
411
485
  const endTod = RuleParser.__parseValue(rhs.children[1])
412
486
 
@@ -421,7 +495,7 @@ class RuleParser {
421
495
  // between wraps either between_number or between_tod
422
496
  const betweenChild = rhs.children[0]
423
497
  if (betweenChild.type === 'between_tod') {
424
- // between_tod has: children[0] = first tod, children[1] = second tod, children[2] = optional dow_range
498
+ // between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
425
499
  const startTod = RuleParser.__parseValue(betweenChild.children[0])
426
500
  const endTod = RuleParser.__parseValue(betweenChild.children[1])
427
501
 
@@ -432,12 +506,13 @@ class RuleParser {
432
506
 
433
507
  return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', startTod], ['Value', endTod]]
434
508
  } else {
435
- // between_number - no dow support
436
- return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', RuleParser.__parseValue(betweenChild.children[0])], ['Value', RuleParser.__parseValue(betweenChild.children[1])]]
509
+ // between_number has: children[0] = first number_inner, children[1] = separator, children[2] = second number_inner
510
+ return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', RuleParser.__parseValue(betweenChild.children[0])], ['Value', RuleParser.__parseValue(betweenChild.children[2])]]
437
511
  }
438
512
  }
439
513
  case 'between_number':
440
- return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', RuleParser.__parseValue(rhs.children[0].children[0])], ['Value', RuleParser.__parseValue(rhs.children[0].children[1])]]
514
+ // between_number has: children[0] = first number_inner, children[1] = separator, children[2] = second number_inner
515
+ return ['Between', RuleParser._parseResult(expr.children[0]), ['Value', RuleParser.__parseValue(rhs.children[0].children[0])], ['Value', RuleParser.__parseValue(rhs.children[0].children[2])]]
441
516
  case 'basic_rhs':
442
517
  return [OperatorFn[rhs.children[0].text], RuleParser._parseResult(expr.children[0]), RuleParser._parseResult(rhs.children[1])]
443
518
  case 'eq_approx': {
@@ -559,8 +634,6 @@ class RuleParser {
559
634
  // Extract the invalid time from the error message
560
635
  const match = e.message.match(/Invalid time of day[,:]?\s*([0-9:]+)/);
561
636
  const badTod = match ? match[1] : 'invalid';
562
- const { ParsingError } = require('ebnf');
563
- const { RuleParseError } = require('./errors/RuleParseError');
564
637
 
565
638
  // Calculate position (simplified - at end of input)
566
639
  const lines = txt.trim().split('\n');
@@ -585,7 +658,6 @@ class RuleParser {
585
658
  if (e.message && e.message.includes('Invalid day of week')) {
586
659
  const match = e.message.match(/Invalid day of week[,:]?\s*(\w+)/);
587
660
  const badDow = match ? match[1] : 'invalid';
588
- const { RuleParseError } = require('./errors/RuleParseError');
589
661
 
590
662
  const lines = txt.trim().split('\n');
591
663
  const position = {
@@ -611,5 +683,6 @@ class RuleParser {
611
683
  }
612
684
  }
613
685
  module.exports = RuleParser
614
- module.exports.ParsingError = require('ebnf').ParsingError
615
- module.exports.RuleParseError = require('./errors/RuleParseError').RuleParseError
686
+ module.exports.ParserRules = ParserRules
687
+ module.exports.ParsingError = ParsingError
688
+ module.exports.RuleParseError = RuleParseError
@@ -1,5 +1,5 @@
1
1
  const { ParsingError } = require('ebnf');
2
- const { RuleParseError } = require('./RuleParseError');
2
+ const RuleParseError = require('./RuleParseError');
3
3
 
4
4
  /**
5
5
  * Analyzes parsing errors and maps them to user-friendly error codes
@@ -61,4 +61,4 @@ class RuleParseError extends Error {
61
61
  }
62
62
  }
63
63
 
64
- module.exports = { RuleParseError };
64
+ module.exports = RuleParseError;