@halleyassist/rule-templater 0.0.18 → 0.0.19
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.
- package/dist/rule-templater.browser.js +264 -39
- package/package.json +1 -1
- package/src/GeneralTemplate.js +6 -6
- package/src/RuleTemplate.ebnf.js +0 -9
- package/src/RuleTemplate.js +89 -13
- package/src/RuleTemplate.production.ebnf.js +1 -1
- package/src/RuleTemplate.production.js +89 -13
- package/src/RuleTemplater.production.js +71 -5
- package/src/VariableValidate.js +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.RuleTemplate = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
|
2
|
-
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]/]]}]
|
|
2
|
+
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"],["parenthesis_expression"],["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":"time_period_atom","bnf":[["between_tod_only"],["between_time_only"]]},{"name":"time_period_ago_atom","bnf":[["time_period_ago_between"]]},{"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_atom"],["time_period_const"],["time_period_atom"]]},{"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]/]]}]
|
|
3
3
|
},{}],2:[function(require,module,exports){
|
|
4
4
|
const {Parser} = require('ebnf/dist/Parser.js'), {ParsingError} = require('ebnf'), RuleParseError = require('./errors/RuleParseError');
|
|
5
5
|
let ParserRules = require('./RuleParser.production.ebnf.js');
|
|
@@ -28,6 +28,31 @@ const LogicalOperators = {
|
|
|
28
28
|
'||': 'Or',
|
|
29
29
|
'OR': 'Or'
|
|
30
30
|
};
|
|
31
|
+
const ILReservedNames = new Set([
|
|
32
|
+
'Value',
|
|
33
|
+
'Array',
|
|
34
|
+
'ArrayIn',
|
|
35
|
+
'Between',
|
|
36
|
+
'Not',
|
|
37
|
+
'And',
|
|
38
|
+
'Or',
|
|
39
|
+
'Gt',
|
|
40
|
+
'Lt',
|
|
41
|
+
'Gte',
|
|
42
|
+
'Lte',
|
|
43
|
+
'Eq',
|
|
44
|
+
'Neq',
|
|
45
|
+
'MathAdd',
|
|
46
|
+
'MathSub',
|
|
47
|
+
'MathDiv',
|
|
48
|
+
'MathMul',
|
|
49
|
+
'MathMod',
|
|
50
|
+
'Default',
|
|
51
|
+
'TimePeriodConst',
|
|
52
|
+
'TimePeriodConstAgo',
|
|
53
|
+
'TimePeriodBetween',
|
|
54
|
+
'TimePeriodBetweenAgo'
|
|
55
|
+
]);
|
|
31
56
|
const DOW_MAP = {
|
|
32
57
|
'MON': 'MONDAY',
|
|
33
58
|
'TUE': 'TUESDAY',
|
|
@@ -122,6 +147,9 @@ class RuleParser {
|
|
|
122
147
|
}
|
|
123
148
|
static _parseTimePeriod(tp) {
|
|
124
149
|
switch (tp.type) {
|
|
150
|
+
case 'time_period_atom':
|
|
151
|
+
case 'time_period_ago_atom':
|
|
152
|
+
return RuleParser._parseTimePeriod(tp.children[0]);
|
|
125
153
|
case 'time_period_const':
|
|
126
154
|
if (tp.children && tp.children.length > 0 && tp.children[0].type === 'time_period_ago') {
|
|
127
155
|
const timePeriodAgo = tp.children[0];
|
|
@@ -366,7 +394,7 @@ class RuleParser {
|
|
|
366
394
|
switch (type) {
|
|
367
395
|
case 'value_atom': {
|
|
368
396
|
const atomChild = child.children[0];
|
|
369
|
-
if (atomChild.type === 'time_period') {
|
|
397
|
+
if (atomChild.type === 'time_period' || atomChild.type === 'time_period_atom' || atomChild.type === 'time_period_ago_atom') {
|
|
370
398
|
const tp = atomChild.children[0];
|
|
371
399
|
return RuleParser._parseTimePeriod(tp);
|
|
372
400
|
}
|
|
@@ -379,6 +407,9 @@ class RuleParser {
|
|
|
379
407
|
const tp = child.children[0];
|
|
380
408
|
return RuleParser._parseTimePeriod(tp);
|
|
381
409
|
}
|
|
410
|
+
case 'time_period_atom':
|
|
411
|
+
case 'time_period_ago_atom':
|
|
412
|
+
return RuleParser._parseTimePeriod(child);
|
|
382
413
|
default:
|
|
383
414
|
return [
|
|
384
415
|
'Value',
|
|
@@ -403,6 +434,8 @@ class RuleParser {
|
|
|
403
434
|
switch (type) {
|
|
404
435
|
case 'fcall':
|
|
405
436
|
return RuleParser._parseFcall(child);
|
|
437
|
+
case 'parenthesis_expression':
|
|
438
|
+
return RuleParser._parseParenthesisExpression(child);
|
|
406
439
|
case 'number_atom':
|
|
407
440
|
case 'number_time_atom': {
|
|
408
441
|
return [
|
|
@@ -686,6 +719,29 @@ class RuleParser {
|
|
|
686
719
|
throw new Error(`unknown type of expression ${ eInner.type }`);
|
|
687
720
|
}
|
|
688
721
|
}
|
|
722
|
+
static _collectFunctions(il, names) {
|
|
723
|
+
if (!Array.isArray(il) || il.length === 0) {
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
const [head, ...tail] = il;
|
|
727
|
+
if (typeof head === 'string') {
|
|
728
|
+
if (!ILReservedNames.has(head)) {
|
|
729
|
+
names.add(head);
|
|
730
|
+
}
|
|
731
|
+
for (const child of tail) {
|
|
732
|
+
RuleParser._collectFunctions(child, names);
|
|
733
|
+
}
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
for (const child of il) {
|
|
737
|
+
RuleParser._collectFunctions(child, names);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
static getFunctions(il) {
|
|
741
|
+
const names = new Set();
|
|
742
|
+
RuleParser._collectFunctions(il, names);
|
|
743
|
+
return [...names];
|
|
744
|
+
}
|
|
689
745
|
static toIL(txt) {
|
|
690
746
|
try {
|
|
691
747
|
const ast = RuleParser.toAst(txt);
|
|
@@ -781,10 +837,14 @@ class ErrorAnalyzer {
|
|
|
781
837
|
|
|
782
838
|
// Get snippet (last 50 chars or the whole input if shorter)
|
|
783
839
|
const snippetStart = Math.max(0, trimmedInput.length - 50);
|
|
784
|
-
const
|
|
840
|
+
const snippetEnd = trimmedInput.length;
|
|
841
|
+
let snippet = this._buildSnippet(trimmedInput, snippetStart, snippetEnd);
|
|
785
842
|
|
|
786
843
|
// Analyze the error pattern
|
|
787
844
|
const errorInfo = this._detectErrorPattern(trimmedInput, position, snippet);
|
|
845
|
+
this._enrichBadFunctionCallError(trimmedInput, position, errorInfo, (value) => {
|
|
846
|
+
snippet = value;
|
|
847
|
+
}, snippetStart, snippetEnd);
|
|
788
848
|
|
|
789
849
|
return new RuleParseError(
|
|
790
850
|
errorInfo.code,
|
|
@@ -810,12 +870,13 @@ class ErrorAnalyzer {
|
|
|
810
870
|
// Get snippet around error position
|
|
811
871
|
const snippetStart = Math.max(0, position.offset - 20);
|
|
812
872
|
const snippetEnd = Math.min(input.length, position.offset + 30);
|
|
813
|
-
|
|
814
|
-
input.substring(snippetStart, snippetEnd) +
|
|
815
|
-
(snippetEnd < input.length ? '...' : '');
|
|
873
|
+
let snippet = this._buildSnippet(input, snippetStart, snippetEnd);
|
|
816
874
|
|
|
817
875
|
// Analyze what was expected to determine error type using failureTree
|
|
818
876
|
const errorInfo = this._detectErrorFromFailureTree(input, position, expected, found, failureTree);
|
|
877
|
+
this._enrichBadFunctionCallError(input, position, errorInfo, (value) => {
|
|
878
|
+
snippet = value;
|
|
879
|
+
}, snippetStart, snippetEnd);
|
|
819
880
|
|
|
820
881
|
return new RuleParseError(
|
|
821
882
|
errorInfo.code,
|
|
@@ -1329,6 +1390,109 @@ class ErrorAnalyzer {
|
|
|
1329
1390
|
};
|
|
1330
1391
|
}
|
|
1331
1392
|
|
|
1393
|
+
static _enrichBadFunctionCallError(input, position, errorInfo, setSnippet, snippetStart, snippetEnd) {
|
|
1394
|
+
if (!errorInfo || errorInfo.code !== "BAD_FUNCTION_CALL") {
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
const functionContext = this._findFunctionContext(input, position.offset);
|
|
1399
|
+
errorInfo.hint = this._getBadFunctionCallHint(input, position, functionContext);
|
|
1400
|
+
|
|
1401
|
+
if (!functionContext) {
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
errorInfo.message = `Invalid function call syntax for ${functionContext.name}.`;
|
|
1406
|
+
setSnippet(this._buildBadFunctionCallSnippet(input, functionContext, snippetStart, snippetEnd));
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
static _buildSnippet(input, start, end) {
|
|
1410
|
+
return (start > 0 ? '...' : '') +
|
|
1411
|
+
input.substring(start, end) +
|
|
1412
|
+
(end < input.length ? '...' : '');
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
static _getBadFunctionCallHint(input, position, functionContext) {
|
|
1416
|
+
const genericHint = "Function calls must have matching parentheses, e.g. func() or func(arg1, arg2).";
|
|
1417
|
+
|
|
1418
|
+
if (!functionContext || !this._isArgumentRelatedFunctionCallError(input, position, functionContext)) {
|
|
1419
|
+
return genericHint;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
return "Function calls must have matching parentheses, e.g. func() or func(arg1, arg2). Please check function arguments for invalid syntax.";
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
static _isArgumentRelatedFunctionCallError(input, position, functionContext) {
|
|
1426
|
+
const endOffset = Math.max(functionContext.openParenIndex + 1, Math.min(position.offset, input.length));
|
|
1427
|
+
const argumentText = input.substring(functionContext.openParenIndex + 1, endOffset).trim();
|
|
1428
|
+
return argumentText.length > 0;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
static _buildBadFunctionCallSnippet(input, functionContext, snippetStart, snippetEnd) {
|
|
1432
|
+
if (snippetStart <= functionContext.start) {
|
|
1433
|
+
return this._buildSnippet(input, snippetStart, snippetEnd);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
const functionPrefix = input.substring(functionContext.start, functionContext.openParenIndex + 1);
|
|
1437
|
+
const suffix = input.substring(snippetStart, snippetEnd);
|
|
1438
|
+
return functionPrefix + '...' + suffix + (snippetEnd < input.length ? '...' : '');
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
static _findFunctionContext(input, offset) {
|
|
1442
|
+
const scanLimit = Math.max(0, Math.min(typeof offset === 'number' ? offset : input.length, input.length));
|
|
1443
|
+
const stack = [];
|
|
1444
|
+
let inString = false;
|
|
1445
|
+
|
|
1446
|
+
for (let i = 0; i < scanLimit; i++) {
|
|
1447
|
+
const char = input[i];
|
|
1448
|
+
|
|
1449
|
+
if (char === '"') {
|
|
1450
|
+
if (!inString) {
|
|
1451
|
+
inString = true;
|
|
1452
|
+
} else {
|
|
1453
|
+
let backslashCount = 0;
|
|
1454
|
+
let j = i - 1;
|
|
1455
|
+
while (j >= 0 && input[j] === '\\') {
|
|
1456
|
+
backslashCount++;
|
|
1457
|
+
j--;
|
|
1458
|
+
}
|
|
1459
|
+
if (backslashCount % 2 === 0) {
|
|
1460
|
+
inString = false;
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
continue;
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
if (inString) {
|
|
1467
|
+
continue;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
if (char === '(') {
|
|
1471
|
+
const prefix = input.substring(0, i);
|
|
1472
|
+
const match = /([a-zA-Z_][a-zA-Z0-9_]*)\s*$/.exec(prefix);
|
|
1473
|
+
if (match) {
|
|
1474
|
+
stack.push({
|
|
1475
|
+
name: match[1],
|
|
1476
|
+
start: i - match[1].length,
|
|
1477
|
+
openParenIndex: i
|
|
1478
|
+
});
|
|
1479
|
+
} else {
|
|
1480
|
+
stack.push(null);
|
|
1481
|
+
}
|
|
1482
|
+
} else if (char === ')' && stack.length > 0) {
|
|
1483
|
+
stack.pop();
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
1488
|
+
if (stack[i]) {
|
|
1489
|
+
return stack[i];
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
return null;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1332
1496
|
/**
|
|
1333
1497
|
* Check if string is properly terminated
|
|
1334
1498
|
* @private
|
|
@@ -1700,12 +1864,6 @@ class RuleParseError extends Error {
|
|
|
1700
1864
|
if (this.hint) {
|
|
1701
1865
|
msg += ` Hint: ${this.hint}\n`;
|
|
1702
1866
|
}
|
|
1703
|
-
if (this.found) {
|
|
1704
|
-
msg += ` Found: ${this.found}\n`;
|
|
1705
|
-
}
|
|
1706
|
-
if (this.expected && this.expected.length) {
|
|
1707
|
-
msg += ` Expected: ${this.expected.join(', ')}`;
|
|
1708
|
-
}
|
|
1709
1867
|
return msg;
|
|
1710
1868
|
}
|
|
1711
1869
|
|
|
@@ -3671,18 +3829,9 @@ const grammar = `
|
|
|
3671
3829
|
|
|
3672
3830
|
template_filter_arg ::= value | template_value
|
|
3673
3831
|
|
|
3674
|
-
number_atom ::= number | template_value
|
|
3675
|
-
number_time_atom ::= number_time | template_value WS+ unit | template_value
|
|
3676
|
-
tod_atom ::= number_tod | template_value
|
|
3677
|
-
dow_atom ::= dow | template_value
|
|
3678
|
-
between_time_only_atom ::= between_time_only | template_value
|
|
3679
|
-
between_tod_only_atom ::= between_tod_only | template_value
|
|
3680
|
-
|
|
3681
3832
|
string_atom ::= string
|
|
3682
3833
|
boolean_atom ::= false | true
|
|
3683
3834
|
time_value_atom ::= number_tod
|
|
3684
|
-
time_period_atom ::= time_value_atom WS* "TO" WS* time_value_atom
|
|
3685
|
-
time_period_ago_atom ::= time_value_atom WS* "TO" WS* time_value_atom WS+ AGO WS+ number WS+ unit
|
|
3686
3835
|
|
|
3687
3836
|
object_atom ::= json_object
|
|
3688
3837
|
json_value ::= string | number | false | true | null | json_array | json_object
|
|
@@ -3699,7 +3848,7 @@ const grammar = `
|
|
|
3699
3848
|
module.exports = Grammars.W3C.getRules(grammar);
|
|
3700
3849
|
|
|
3701
3850
|
},{"ebnf":13}],16:[function(require,module,exports){
|
|
3702
|
-
module.exports=[{"name":"TEMPLATE_BEGIN","bnf":[["\"${\""]]},{"name":"TEMPLATE_END","bnf":[["\"}\""]]},{"name":"PIPE","bnf":[["\"|\""]]},{"name":"%IDENT[2]","bnf":[[/[A-Za-z0-9_]/]]},{"name":"IDENT","bnf":[[/[A-Za-z_]/,"%IDENT[2]*"]]},{"name":"DOT","bnf":[["\".\""]]},{"name":"template_value","bnf":[["TEMPLATE_BEGIN","WS*","template_expr","WS*","TEMPLATE_END"]]},{"name":"%template_expr[2]","bnf":[["WS*","template_pipe","WS*","template_filter_call"]],"fragment":true},{"name":"template_expr","bnf":[["template_path","%template_expr[2]*"]]},{"name":"template_pipe","bnf":[["PIPE"]]},{"name":"%template_path[2]","bnf":[["WS*","DOT","WS*","IDENT"]],"fragment":true},{"name":"template_path","bnf":[["IDENT","%template_path[2]*"]]},{"name":"%template_filter_call[2]","bnf":[["WS*","BEGIN_ARGUMENT","WS*","template_filter_args?","WS*","END_ARGUMENT"]],"fragment":true},{"name":"template_filter_call","bnf":[["template_filter_name","%template_filter_call[2]?"]]},{"name":"template_filter_name","bnf":[["IDENT"]]},{"name":"%template_filter_args[2]","bnf":[["WS*","\",\"","WS*","template_filter_arg"]],"fragment":true},{"name":"template_filter_args","bnf":[["template_filter_arg","%template_filter_args[2]*"]]},{"name":"template_filter_arg","bnf":[["value"],["template_value"]]},{"name":"
|
|
3851
|
+
module.exports=[{"name":"TEMPLATE_BEGIN","bnf":[["\"${\""]]},{"name":"TEMPLATE_END","bnf":[["\"}\""]]},{"name":"PIPE","bnf":[["\"|\""]]},{"name":"%IDENT[2]","bnf":[[/[A-Za-z0-9_]/]]},{"name":"IDENT","bnf":[[/[A-Za-z_]/,"%IDENT[2]*"]]},{"name":"DOT","bnf":[["\".\""]]},{"name":"template_value","bnf":[["TEMPLATE_BEGIN","WS*","template_expr","WS*","TEMPLATE_END"]]},{"name":"%template_expr[2]","bnf":[["WS*","template_pipe","WS*","template_filter_call"]],"fragment":true},{"name":"template_expr","bnf":[["template_path","%template_expr[2]*"]]},{"name":"template_pipe","bnf":[["PIPE"]]},{"name":"%template_path[2]","bnf":[["WS*","DOT","WS*","IDENT"]],"fragment":true},{"name":"template_path","bnf":[["IDENT","%template_path[2]*"]]},{"name":"%template_filter_call[2]","bnf":[["WS*","BEGIN_ARGUMENT","WS*","template_filter_args?","WS*","END_ARGUMENT"]],"fragment":true},{"name":"template_filter_call","bnf":[["template_filter_name","%template_filter_call[2]?"]]},{"name":"template_filter_name","bnf":[["IDENT"]]},{"name":"%template_filter_args[2]","bnf":[["WS*","\",\"","WS*","template_filter_arg"]],"fragment":true},{"name":"template_filter_args","bnf":[["template_filter_arg","%template_filter_args[2]*"]]},{"name":"template_filter_arg","bnf":[["value"],["template_value"]]},{"name":"string_atom","bnf":[["string"]]},{"name":"boolean_atom","bnf":[["false"],["true"]]},{"name":"time_value_atom","bnf":[["number_tod"]]},{"name":"object_atom","bnf":[["json_object"]]},{"name":"json_value","bnf":[["string"],["number"],["false"],["true"],["null"],["json_array"],["json_object"]]},{"name":"json_member","bnf":[["string","NAME_SEPARATOR","json_value"]]},{"name":"%json_object[2][2]","bnf":[["VALUE_SEPARATOR","json_member"]],"fragment":true},{"name":"%json_object[2]","bnf":[["json_member","%json_object[2][2]*"]],"fragment":true},{"name":"json_object","bnf":[["BEGIN_OBJECT","%json_object[2]?","END_OBJECT"]]},{"name":"%json_array[2][2]","bnf":[["VALUE_SEPARATOR","json_value"]],"fragment":true},{"name":"%json_array[2]","bnf":[["json_value","%json_array[2][2]*"]],"fragment":true},{"name":"json_array","bnf":[["BEGIN_ARRAY","%json_array[2]?","END_ARRAY"]]},{"name":"%string_array[2][2]","bnf":[["VALUE_SEPARATOR","string"]],"fragment":true},{"name":"%string_array[2]","bnf":[["string","%string_array[2][2]*"]],"fragment":true},{"name":"string_array","bnf":[["BEGIN_ARRAY","%string_array[2]?","END_ARRAY"]]},{"name":"%number_array[2][2]","bnf":[["VALUE_SEPARATOR","number"]],"fragment":true},{"name":"%number_array[2]","bnf":[["number","%number_array[2][2]*"]],"fragment":true},{"name":"number_array","bnf":[["BEGIN_ARRAY","%number_array[2]?","END_ARRAY"]]},{"name":"%boolean_array[2][2]","bnf":[["VALUE_SEPARATOR","boolean_atom"]],"fragment":true},{"name":"%boolean_array[2]","bnf":[["boolean_atom","%boolean_array[2][2]*"]],"fragment":true},{"name":"boolean_array","bnf":[["BEGIN_ARRAY","%boolean_array[2]?","END_ARRAY"]]},{"name":"%object_array[2][2]","bnf":[["VALUE_SEPARATOR","json_object"]],"fragment":true},{"name":"%object_array[2]","bnf":[["json_object","%object_array[2][2]*"]],"fragment":true},{"name":"object_array","bnf":[["BEGIN_ARRAY","%object_array[2]?","END_ARRAY"]]}]
|
|
3703
3852
|
},{}],17:[function(require,module,exports){
|
|
3704
3853
|
// Note: We are coupled closely with the ebnf grammar structure of rule-parser
|
|
3705
3854
|
const TemplateGrammar = require('./RuleTemplate.production.ebnf.js'),
|
|
@@ -3731,7 +3880,7 @@ const AllowedTypeMapping = {
|
|
|
3731
3880
|
'number': ['number_atom', 'math_expr'],
|
|
3732
3881
|
'boolean': ['boolean_atom', 'boolean_expr'],
|
|
3733
3882
|
'time period': ['time_period_atom'],
|
|
3734
|
-
'time period ago': ['
|
|
3883
|
+
'time period ago': ['time_period_ago_atom'],
|
|
3735
3884
|
'time value': ['time_value_atom', 'tod_atom'],
|
|
3736
3885
|
'number time': ['number_atom'],
|
|
3737
3886
|
'string array': ['string_array'],
|
|
@@ -3752,12 +3901,71 @@ for(const rule of TemplateGrammar){
|
|
|
3752
3901
|
}
|
|
3753
3902
|
}
|
|
3754
3903
|
|
|
3755
|
-
|
|
3756
|
-
const
|
|
3757
|
-
if (
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3904
|
+
const cloneRule = (ruleName) => {
|
|
3905
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
3906
|
+
if (idx === -1) {
|
|
3907
|
+
return null;
|
|
3908
|
+
}
|
|
3909
|
+
|
|
3910
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
3911
|
+
bnf: extendedGrammar[idx].bnf.map(alt => Array.isArray(alt) ? alt.slice() : alt)
|
|
3912
|
+
});
|
|
3913
|
+
|
|
3914
|
+
return extendedGrammar[idx];
|
|
3915
|
+
};
|
|
3916
|
+
|
|
3917
|
+
const appendAlternative = (ruleName, alternative) => {
|
|
3918
|
+
const rule = cloneRule(ruleName);
|
|
3919
|
+
if (!rule) {
|
|
3920
|
+
return;
|
|
3921
|
+
}
|
|
3922
|
+
|
|
3923
|
+
const exists = rule.bnf.some(existing => JSON.stringify(existing) === JSON.stringify(alternative));
|
|
3924
|
+
if (!exists) {
|
|
3925
|
+
rule.bnf.push(alternative);
|
|
3926
|
+
}
|
|
3927
|
+
};
|
|
3928
|
+
|
|
3929
|
+
const replaceRule = (ruleName, bnf) => {
|
|
3930
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
3931
|
+
if (idx === -1) {
|
|
3932
|
+
extendedGrammar.push({name: ruleName, bnf});
|
|
3933
|
+
return;
|
|
3934
|
+
}
|
|
3935
|
+
|
|
3936
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
3937
|
+
bnf: bnf.map(alt => alt.slice())
|
|
3938
|
+
});
|
|
3939
|
+
};
|
|
3940
|
+
|
|
3941
|
+
appendAlternative('number_atom', ['template_value']);
|
|
3942
|
+
appendAlternative('number_time_atom', ['template_value', 'WS+', 'unit']);
|
|
3943
|
+
appendAlternative('number_time_atom', ['template_value']);
|
|
3944
|
+
appendAlternative('tod_atom', ['template_value']);
|
|
3945
|
+
appendAlternative('dow_atom', ['template_value']);
|
|
3946
|
+
appendAlternative('between_time_only_atom', ['template_value']);
|
|
3947
|
+
appendAlternative('between_tod_only_atom', ['template_value']);
|
|
3948
|
+
appendAlternative('string_atom', ['template_value']);
|
|
3949
|
+
appendAlternative('boolean_atom', ['template_value']);
|
|
3950
|
+
appendAlternative('time_value_atom', ['template_value']);
|
|
3951
|
+
appendAlternative('time_period_atom', ['template_value']);
|
|
3952
|
+
appendAlternative('time_period_ago_atom', ['template_value']);
|
|
3953
|
+
appendAlternative('object_atom', ['template_value']);
|
|
3954
|
+
appendAlternative('string_array', ['template_value']);
|
|
3955
|
+
appendAlternative('number_array', ['template_value']);
|
|
3956
|
+
appendAlternative('boolean_array', ['template_value']);
|
|
3957
|
+
appendAlternative('object_array', ['template_value']);
|
|
3958
|
+
|
|
3959
|
+
replaceRule('argument', [
|
|
3960
|
+
['number_time_atom', 'WS*'],
|
|
3961
|
+
['statement', 'WS*']
|
|
3962
|
+
]);
|
|
3963
|
+
|
|
3964
|
+
replaceRule('simple_result', [
|
|
3965
|
+
['fcall'],
|
|
3966
|
+
['number_time_atom'],
|
|
3967
|
+
['value']
|
|
3968
|
+
]);
|
|
3761
3969
|
|
|
3762
3970
|
// Export the parser rules for potential external use
|
|
3763
3971
|
const ParserRules = extendedGrammar;
|
|
@@ -4054,6 +4262,23 @@ class RuleTemplate {
|
|
|
4054
4262
|
}
|
|
4055
4263
|
}
|
|
4056
4264
|
|
|
4265
|
+
const canValidatePreparedRule = errors.length === 0
|
|
4266
|
+
&& Array.from(seenVariables).every(varName => {
|
|
4267
|
+
const varData = variables[varName];
|
|
4268
|
+
return varData
|
|
4269
|
+
&& typeof varData === 'object'
|
|
4270
|
+
&& Object.prototype.hasOwnProperty.call(varData, 'type')
|
|
4271
|
+
&& Object.prototype.hasOwnProperty.call(varData, 'value');
|
|
4272
|
+
});
|
|
4273
|
+
|
|
4274
|
+
if (canValidatePreparedRule) {
|
|
4275
|
+
try {
|
|
4276
|
+
RuleParser.toAst(this.prepare(variables));
|
|
4277
|
+
} catch (error) {
|
|
4278
|
+
errors.push(`Prepared rule is invalid: ${error.message}`);
|
|
4279
|
+
}
|
|
4280
|
+
}
|
|
4281
|
+
|
|
4057
4282
|
if (functionBlob && typeof functionBlob.validate === 'function') {
|
|
4058
4283
|
for (const functionCall of this._extractFunctionCalls()) {
|
|
4059
4284
|
warnings.push(...functionBlob.validate(functionCall.name, functionCall.arguments));
|
|
@@ -4262,12 +4487,12 @@ class RuleTemplate {
|
|
|
4262
4487
|
return value ? 'true' : 'false';
|
|
4263
4488
|
}
|
|
4264
4489
|
|
|
4265
|
-
if (type === 'time period'
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
return
|
|
4490
|
+
if (type === 'time period') {
|
|
4491
|
+
return `BETWEEN ${value.from} AND ${value.to}`;
|
|
4492
|
+
}
|
|
4493
|
+
|
|
4494
|
+
if (type === 'time period ago') {
|
|
4495
|
+
return `${value.ago[0]} ${value.ago[1]} AGO BETWEEN ${value.from} AND ${value.to}`;
|
|
4271
4496
|
}
|
|
4272
4497
|
|
|
4273
4498
|
if (type === 'object' || type === 'string array' || type === 'number array' || type === 'boolean array' || type === 'object array') {
|
|
@@ -4762,7 +4987,7 @@ class VariableValidate {
|
|
|
4762
4987
|
return null;
|
|
4763
4988
|
}
|
|
4764
4989
|
|
|
4765
|
-
return
|
|
4990
|
+
return `BETWEEN ${value.from.trim()} AND ${value.to.trim()}`;
|
|
4766
4991
|
}
|
|
4767
4992
|
|
|
4768
4993
|
static _serializeTimePeriodAgo(value) {
|
|
@@ -4779,7 +5004,7 @@ class VariableValidate {
|
|
|
4779
5004
|
return null;
|
|
4780
5005
|
}
|
|
4781
5006
|
|
|
4782
|
-
return `${
|
|
5007
|
+
return `${amount} ${unit.trim()} AGO BETWEEN ${value.from.trim()} AND ${value.to.trim()}`;
|
|
4783
5008
|
}
|
|
4784
5009
|
|
|
4785
5010
|
static _serializeNumberTime(value) {
|
|
@@ -4896,7 +5121,7 @@ VariableValidate.validators = Object.freeze({
|
|
|
4896
5121
|
'time period': (value) => VariableValidate._validateWithRule(value, 'time_period_atom', {
|
|
4897
5122
|
normalize: VariableValidate._serializeTimePeriod,
|
|
4898
5123
|
emptyMessage: 'Time period variables must be objects with string from/to properties',
|
|
4899
|
-
parseMessage: 'Time period variables must serialize to FROM
|
|
5124
|
+
parseMessage: 'Time period variables must serialize to BETWEEN FROM AND TO syntax',
|
|
4900
5125
|
semanticCheck: (rawValue) => {
|
|
4901
5126
|
const fromError = VariableValidate._validateTimeOfDay(rawValue?.from);
|
|
4902
5127
|
if (fromError) return `Invalid time period from value: ${fromError}`;
|
|
@@ -4910,7 +5135,7 @@ VariableValidate.validators = Object.freeze({
|
|
|
4910
5135
|
'time period ago': (value) => VariableValidate._validateWithRule(value, 'time_period_ago_atom', {
|
|
4911
5136
|
normalize: VariableValidate._serializeTimePeriodAgo,
|
|
4912
5137
|
emptyMessage: 'Time period ago variables must be objects with from, to, and ago properties',
|
|
4913
|
-
parseMessage: 'Time period ago variables must serialize to
|
|
5138
|
+
parseMessage: 'Time period ago variables must serialize to AMOUNT UNIT AGO BETWEEN FROM AND TO syntax',
|
|
4914
5139
|
semanticCheck: (rawValue) => {
|
|
4915
5140
|
const fromError = VariableValidate._validateTimeOfDay(rawValue?.from);
|
|
4916
5141
|
if (fromError) return `Invalid time period ago from value: ${fromError}`;
|
package/package.json
CHANGED
package/src/GeneralTemplate.js
CHANGED
|
@@ -190,12 +190,12 @@ class GeneralTemplate {
|
|
|
190
190
|
return '';
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
if (varData.type === 'time period'
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return
|
|
193
|
+
if (varData.type === 'time period') {
|
|
194
|
+
return `BETWEEN ${varData.value.from} AND ${varData.value.to}`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (varData.type === 'time period ago') {
|
|
198
|
+
return `${varData.value.ago[0]} ${varData.value.ago[1]} AGO BETWEEN ${varData.value.from} AND ${varData.value.to}`;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
return String(varData.value);
|
package/src/RuleTemplate.ebnf.js
CHANGED
|
@@ -23,18 +23,9 @@ const grammar = `
|
|
|
23
23
|
|
|
24
24
|
template_filter_arg ::= value | template_value
|
|
25
25
|
|
|
26
|
-
number_atom ::= number | template_value
|
|
27
|
-
number_time_atom ::= number_time | template_value WS+ unit | template_value
|
|
28
|
-
tod_atom ::= number_tod | template_value
|
|
29
|
-
dow_atom ::= dow | template_value
|
|
30
|
-
between_time_only_atom ::= between_time_only | template_value
|
|
31
|
-
between_tod_only_atom ::= between_tod_only | template_value
|
|
32
|
-
|
|
33
26
|
string_atom ::= string
|
|
34
27
|
boolean_atom ::= false | true
|
|
35
28
|
time_value_atom ::= number_tod
|
|
36
|
-
time_period_atom ::= time_value_atom WS* "TO" WS* time_value_atom
|
|
37
|
-
time_period_ago_atom ::= time_value_atom WS* "TO" WS* time_value_atom WS+ AGO WS+ number WS+ unit
|
|
38
29
|
|
|
39
30
|
object_atom ::= json_object
|
|
40
31
|
json_value ::= string | number | false | true | null | json_array | json_object
|
package/src/RuleTemplate.js
CHANGED
|
@@ -28,7 +28,7 @@ const AllowedTypeMapping = {
|
|
|
28
28
|
'number': ['number_atom', 'math_expr'],
|
|
29
29
|
'boolean': ['boolean_atom', 'boolean_expr'],
|
|
30
30
|
'time period': ['time_period_atom'],
|
|
31
|
-
'time period ago': ['
|
|
31
|
+
'time period ago': ['time_period_ago_atom'],
|
|
32
32
|
'time value': ['time_value_atom', 'tod_atom'],
|
|
33
33
|
'number time': ['number_atom'],
|
|
34
34
|
'string array': ['string_array'],
|
|
@@ -49,12 +49,71 @@ for(const rule of TemplateGrammar){
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
const cloneRule = (ruleName) => {
|
|
53
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
54
|
+
if (idx === -1) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
59
|
+
bnf: extendedGrammar[idx].bnf.map(alt => Array.isArray(alt) ? alt.slice() : alt)
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return extendedGrammar[idx];
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const appendAlternative = (ruleName, alternative) => {
|
|
66
|
+
const rule = cloneRule(ruleName);
|
|
67
|
+
if (!rule) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const exists = rule.bnf.some(existing => JSON.stringify(existing) === JSON.stringify(alternative));
|
|
72
|
+
if (!exists) {
|
|
73
|
+
rule.bnf.push(alternative);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const replaceRule = (ruleName, bnf) => {
|
|
78
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
79
|
+
if (idx === -1) {
|
|
80
|
+
extendedGrammar.push({name: ruleName, bnf});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
85
|
+
bnf: bnf.map(alt => alt.slice())
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
appendAlternative('number_atom', ['template_value']);
|
|
90
|
+
appendAlternative('number_time_atom', ['template_value', 'WS+', 'unit']);
|
|
91
|
+
appendAlternative('number_time_atom', ['template_value']);
|
|
92
|
+
appendAlternative('tod_atom', ['template_value']);
|
|
93
|
+
appendAlternative('dow_atom', ['template_value']);
|
|
94
|
+
appendAlternative('between_time_only_atom', ['template_value']);
|
|
95
|
+
appendAlternative('between_tod_only_atom', ['template_value']);
|
|
96
|
+
appendAlternative('string_atom', ['template_value']);
|
|
97
|
+
appendAlternative('boolean_atom', ['template_value']);
|
|
98
|
+
appendAlternative('time_value_atom', ['template_value']);
|
|
99
|
+
appendAlternative('time_period_atom', ['template_value']);
|
|
100
|
+
appendAlternative('time_period_ago_atom', ['template_value']);
|
|
101
|
+
appendAlternative('object_atom', ['template_value']);
|
|
102
|
+
appendAlternative('string_array', ['template_value']);
|
|
103
|
+
appendAlternative('number_array', ['template_value']);
|
|
104
|
+
appendAlternative('boolean_array', ['template_value']);
|
|
105
|
+
appendAlternative('object_array', ['template_value']);
|
|
106
|
+
|
|
107
|
+
replaceRule('argument', [
|
|
108
|
+
['number_time_atom', 'WS*'],
|
|
109
|
+
['statement', 'WS*']
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
replaceRule('simple_result', [
|
|
113
|
+
['fcall'],
|
|
114
|
+
['number_time_atom'],
|
|
115
|
+
['value']
|
|
116
|
+
]);
|
|
58
117
|
|
|
59
118
|
// Export the parser rules for potential external use
|
|
60
119
|
const ParserRules = extendedGrammar;
|
|
@@ -351,6 +410,23 @@ class RuleTemplate {
|
|
|
351
410
|
}
|
|
352
411
|
}
|
|
353
412
|
|
|
413
|
+
const canValidatePreparedRule = errors.length === 0
|
|
414
|
+
&& Array.from(seenVariables).every(varName => {
|
|
415
|
+
const varData = variables[varName];
|
|
416
|
+
return varData
|
|
417
|
+
&& typeof varData === 'object'
|
|
418
|
+
&& Object.prototype.hasOwnProperty.call(varData, 'type')
|
|
419
|
+
&& Object.prototype.hasOwnProperty.call(varData, 'value');
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
if (canValidatePreparedRule) {
|
|
423
|
+
try {
|
|
424
|
+
RuleParser.toAst(this.prepare(variables));
|
|
425
|
+
} catch (error) {
|
|
426
|
+
errors.push(`Prepared rule is invalid: ${error.message}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
354
430
|
if (functionBlob && typeof functionBlob.validate === 'function') {
|
|
355
431
|
for (const functionCall of this._extractFunctionCalls()) {
|
|
356
432
|
warnings.push(...functionBlob.validate(functionCall.name, functionCall.arguments));
|
|
@@ -559,12 +635,12 @@ class RuleTemplate {
|
|
|
559
635
|
return value ? 'true' : 'false';
|
|
560
636
|
}
|
|
561
637
|
|
|
562
|
-
if (type === 'time period'
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
return
|
|
638
|
+
if (type === 'time period') {
|
|
639
|
+
return `BETWEEN ${value.from} AND ${value.to}`;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (type === 'time period ago') {
|
|
643
|
+
return `${value.ago[0]} ${value.ago[1]} AGO BETWEEN ${value.from} AND ${value.to}`;
|
|
568
644
|
}
|
|
569
645
|
|
|
570
646
|
if (type === 'object' || type === 'string array' || type === 'number array' || type === 'boolean array' || type === 'object array') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports=[{"name":"TEMPLATE_BEGIN","bnf":[["\"${\""]]},{"name":"TEMPLATE_END","bnf":[["\"}\""]]},{"name":"PIPE","bnf":[["\"|\""]]},{"name":"%IDENT[2]","bnf":[[/[A-Za-z0-9_]/]]},{"name":"IDENT","bnf":[[/[A-Za-z_]/,"%IDENT[2]*"]]},{"name":"DOT","bnf":[["\".\""]]},{"name":"template_value","bnf":[["TEMPLATE_BEGIN","WS*","template_expr","WS*","TEMPLATE_END"]]},{"name":"%template_expr[2]","bnf":[["WS*","template_pipe","WS*","template_filter_call"]],"fragment":true},{"name":"template_expr","bnf":[["template_path","%template_expr[2]*"]]},{"name":"template_pipe","bnf":[["PIPE"]]},{"name":"%template_path[2]","bnf":[["WS*","DOT","WS*","IDENT"]],"fragment":true},{"name":"template_path","bnf":[["IDENT","%template_path[2]*"]]},{"name":"%template_filter_call[2]","bnf":[["WS*","BEGIN_ARGUMENT","WS*","template_filter_args?","WS*","END_ARGUMENT"]],"fragment":true},{"name":"template_filter_call","bnf":[["template_filter_name","%template_filter_call[2]?"]]},{"name":"template_filter_name","bnf":[["IDENT"]]},{"name":"%template_filter_args[2]","bnf":[["WS*","\",\"","WS*","template_filter_arg"]],"fragment":true},{"name":"template_filter_args","bnf":[["template_filter_arg","%template_filter_args[2]*"]]},{"name":"template_filter_arg","bnf":[["value"],["template_value"]]},{"name":"
|
|
1
|
+
module.exports=[{"name":"TEMPLATE_BEGIN","bnf":[["\"${\""]]},{"name":"TEMPLATE_END","bnf":[["\"}\""]]},{"name":"PIPE","bnf":[["\"|\""]]},{"name":"%IDENT[2]","bnf":[[/[A-Za-z0-9_]/]]},{"name":"IDENT","bnf":[[/[A-Za-z_]/,"%IDENT[2]*"]]},{"name":"DOT","bnf":[["\".\""]]},{"name":"template_value","bnf":[["TEMPLATE_BEGIN","WS*","template_expr","WS*","TEMPLATE_END"]]},{"name":"%template_expr[2]","bnf":[["WS*","template_pipe","WS*","template_filter_call"]],"fragment":true},{"name":"template_expr","bnf":[["template_path","%template_expr[2]*"]]},{"name":"template_pipe","bnf":[["PIPE"]]},{"name":"%template_path[2]","bnf":[["WS*","DOT","WS*","IDENT"]],"fragment":true},{"name":"template_path","bnf":[["IDENT","%template_path[2]*"]]},{"name":"%template_filter_call[2]","bnf":[["WS*","BEGIN_ARGUMENT","WS*","template_filter_args?","WS*","END_ARGUMENT"]],"fragment":true},{"name":"template_filter_call","bnf":[["template_filter_name","%template_filter_call[2]?"]]},{"name":"template_filter_name","bnf":[["IDENT"]]},{"name":"%template_filter_args[2]","bnf":[["WS*","\",\"","WS*","template_filter_arg"]],"fragment":true},{"name":"template_filter_args","bnf":[["template_filter_arg","%template_filter_args[2]*"]]},{"name":"template_filter_arg","bnf":[["value"],["template_value"]]},{"name":"string_atom","bnf":[["string"]]},{"name":"boolean_atom","bnf":[["false"],["true"]]},{"name":"time_value_atom","bnf":[["number_tod"]]},{"name":"object_atom","bnf":[["json_object"]]},{"name":"json_value","bnf":[["string"],["number"],["false"],["true"],["null"],["json_array"],["json_object"]]},{"name":"json_member","bnf":[["string","NAME_SEPARATOR","json_value"]]},{"name":"%json_object[2][2]","bnf":[["VALUE_SEPARATOR","json_member"]],"fragment":true},{"name":"%json_object[2]","bnf":[["json_member","%json_object[2][2]*"]],"fragment":true},{"name":"json_object","bnf":[["BEGIN_OBJECT","%json_object[2]?","END_OBJECT"]]},{"name":"%json_array[2][2]","bnf":[["VALUE_SEPARATOR","json_value"]],"fragment":true},{"name":"%json_array[2]","bnf":[["json_value","%json_array[2][2]*"]],"fragment":true},{"name":"json_array","bnf":[["BEGIN_ARRAY","%json_array[2]?","END_ARRAY"]]},{"name":"%string_array[2][2]","bnf":[["VALUE_SEPARATOR","string"]],"fragment":true},{"name":"%string_array[2]","bnf":[["string","%string_array[2][2]*"]],"fragment":true},{"name":"string_array","bnf":[["BEGIN_ARRAY","%string_array[2]?","END_ARRAY"]]},{"name":"%number_array[2][2]","bnf":[["VALUE_SEPARATOR","number"]],"fragment":true},{"name":"%number_array[2]","bnf":[["number","%number_array[2][2]*"]],"fragment":true},{"name":"number_array","bnf":[["BEGIN_ARRAY","%number_array[2]?","END_ARRAY"]]},{"name":"%boolean_array[2][2]","bnf":[["VALUE_SEPARATOR","boolean_atom"]],"fragment":true},{"name":"%boolean_array[2]","bnf":[["boolean_atom","%boolean_array[2][2]*"]],"fragment":true},{"name":"boolean_array","bnf":[["BEGIN_ARRAY","%boolean_array[2]?","END_ARRAY"]]},{"name":"%object_array[2][2]","bnf":[["VALUE_SEPARATOR","json_object"]],"fragment":true},{"name":"%object_array[2]","bnf":[["json_object","%object_array[2][2]*"]],"fragment":true},{"name":"object_array","bnf":[["BEGIN_ARRAY","%object_array[2]?","END_ARRAY"]]}]
|
|
@@ -28,7 +28,7 @@ const AllowedTypeMapping = {
|
|
|
28
28
|
'number': ['number_atom', 'math_expr'],
|
|
29
29
|
'boolean': ['boolean_atom', 'boolean_expr'],
|
|
30
30
|
'time period': ['time_period_atom'],
|
|
31
|
-
'time period ago': ['
|
|
31
|
+
'time period ago': ['time_period_ago_atom'],
|
|
32
32
|
'time value': ['time_value_atom', 'tod_atom'],
|
|
33
33
|
'number time': ['number_atom'],
|
|
34
34
|
'string array': ['string_array'],
|
|
@@ -49,12 +49,71 @@ for(const rule of TemplateGrammar){
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
const cloneRule = (ruleName) => {
|
|
53
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
54
|
+
if (idx === -1) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
59
|
+
bnf: extendedGrammar[idx].bnf.map(alt => Array.isArray(alt) ? alt.slice() : alt)
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return extendedGrammar[idx];
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const appendAlternative = (ruleName, alternative) => {
|
|
66
|
+
const rule = cloneRule(ruleName);
|
|
67
|
+
if (!rule) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const exists = rule.bnf.some(existing => JSON.stringify(existing) === JSON.stringify(alternative));
|
|
72
|
+
if (!exists) {
|
|
73
|
+
rule.bnf.push(alternative);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const replaceRule = (ruleName, bnf) => {
|
|
78
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
79
|
+
if (idx === -1) {
|
|
80
|
+
extendedGrammar.push({name: ruleName, bnf});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
85
|
+
bnf: bnf.map(alt => alt.slice())
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
appendAlternative('number_atom', ['template_value']);
|
|
90
|
+
appendAlternative('number_time_atom', ['template_value', 'WS+', 'unit']);
|
|
91
|
+
appendAlternative('number_time_atom', ['template_value']);
|
|
92
|
+
appendAlternative('tod_atom', ['template_value']);
|
|
93
|
+
appendAlternative('dow_atom', ['template_value']);
|
|
94
|
+
appendAlternative('between_time_only_atom', ['template_value']);
|
|
95
|
+
appendAlternative('between_tod_only_atom', ['template_value']);
|
|
96
|
+
appendAlternative('string_atom', ['template_value']);
|
|
97
|
+
appendAlternative('boolean_atom', ['template_value']);
|
|
98
|
+
appendAlternative('time_value_atom', ['template_value']);
|
|
99
|
+
appendAlternative('time_period_atom', ['template_value']);
|
|
100
|
+
appendAlternative('time_period_ago_atom', ['template_value']);
|
|
101
|
+
appendAlternative('object_atom', ['template_value']);
|
|
102
|
+
appendAlternative('string_array', ['template_value']);
|
|
103
|
+
appendAlternative('number_array', ['template_value']);
|
|
104
|
+
appendAlternative('boolean_array', ['template_value']);
|
|
105
|
+
appendAlternative('object_array', ['template_value']);
|
|
106
|
+
|
|
107
|
+
replaceRule('argument', [
|
|
108
|
+
['number_time_atom', 'WS*'],
|
|
109
|
+
['statement', 'WS*']
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
replaceRule('simple_result', [
|
|
113
|
+
['fcall'],
|
|
114
|
+
['number_time_atom'],
|
|
115
|
+
['value']
|
|
116
|
+
]);
|
|
58
117
|
|
|
59
118
|
// Export the parser rules for potential external use
|
|
60
119
|
const ParserRules = extendedGrammar;
|
|
@@ -351,6 +410,23 @@ class RuleTemplate {
|
|
|
351
410
|
}
|
|
352
411
|
}
|
|
353
412
|
|
|
413
|
+
const canValidatePreparedRule = errors.length === 0
|
|
414
|
+
&& Array.from(seenVariables).every(varName => {
|
|
415
|
+
const varData = variables[varName];
|
|
416
|
+
return varData
|
|
417
|
+
&& typeof varData === 'object'
|
|
418
|
+
&& Object.prototype.hasOwnProperty.call(varData, 'type')
|
|
419
|
+
&& Object.prototype.hasOwnProperty.call(varData, 'value');
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
if (canValidatePreparedRule) {
|
|
423
|
+
try {
|
|
424
|
+
RuleParser.toAst(this.prepare(variables));
|
|
425
|
+
} catch (error) {
|
|
426
|
+
errors.push(`Prepared rule is invalid: ${error.message}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
354
430
|
if (functionBlob && typeof functionBlob.validate === 'function') {
|
|
355
431
|
for (const functionCall of this._extractFunctionCalls()) {
|
|
356
432
|
warnings.push(...functionBlob.validate(functionCall.name, functionCall.arguments));
|
|
@@ -559,12 +635,12 @@ class RuleTemplate {
|
|
|
559
635
|
return value ? 'true' : 'false';
|
|
560
636
|
}
|
|
561
637
|
|
|
562
|
-
if (type === 'time period'
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
return
|
|
638
|
+
if (type === 'time period') {
|
|
639
|
+
return `BETWEEN ${value.from} AND ${value.to}`;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (type === 'time period ago') {
|
|
643
|
+
return `${value.ago[0]} ${value.ago[1]} AGO BETWEEN ${value.from} AND ${value.to}`;
|
|
568
644
|
}
|
|
569
645
|
|
|
570
646
|
if (type === 'object' || type === 'string array' || type === 'number array' || type === 'boolean array' || type === 'object array') {
|
|
@@ -13,6 +13,7 @@ const VariableTypes = [
|
|
|
13
13
|
'boolean',
|
|
14
14
|
'object',
|
|
15
15
|
'time period',
|
|
16
|
+
'time period ago',
|
|
16
17
|
'time value',
|
|
17
18
|
'string array',
|
|
18
19
|
'number array',
|
|
@@ -25,6 +26,7 @@ const AllowedTypeMapping = {
|
|
|
25
26
|
'number': ['number_atom', 'math_expr'],
|
|
26
27
|
'boolean': ['boolean_atom', 'boolean_expr'],
|
|
27
28
|
'time period': ['time_period_atom'],
|
|
29
|
+
'time period ago': ['time_period_ago_atom'],
|
|
28
30
|
'time value': ['time_value_atom', 'tod_atom'],
|
|
29
31
|
'string array': ['string_array'],
|
|
30
32
|
'number array': ['number_array'],
|
|
@@ -44,11 +46,71 @@ for(const rule of TemplateGrammar){
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
}
|
|
49
|
+
const cloneRule = (ruleName) => {
|
|
50
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
51
|
+
if (idx === -1) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
56
|
+
bnf: extendedGrammar[idx].bnf.map(alt => Array.isArray(alt) ? alt.slice() : alt)
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return extendedGrammar[idx];
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const appendAlternative = (ruleName, alternative) => {
|
|
63
|
+
const rule = cloneRule(ruleName);
|
|
64
|
+
if (!rule) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const exists = rule.bnf.some(existing => JSON.stringify(existing) === JSON.stringify(alternative));
|
|
69
|
+
if (!exists) {
|
|
70
|
+
rule.bnf.push(alternative);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const replaceRule = (ruleName, bnf) => {
|
|
75
|
+
const idx = extendedGrammar.findIndex(rule => rule.name === ruleName);
|
|
76
|
+
if (idx === -1) {
|
|
77
|
+
extendedGrammar.push({name: ruleName, bnf});
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
extendedGrammar[idx] = Object.assign({}, extendedGrammar[idx], {
|
|
82
|
+
bnf: bnf.map(alt => alt.slice())
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
appendAlternative('number_atom', ['template_value']);
|
|
87
|
+
appendAlternative('number_time_atom', ['template_value', 'WS+', 'unit']);
|
|
88
|
+
appendAlternative('number_time_atom', ['template_value']);
|
|
89
|
+
appendAlternative('tod_atom', ['template_value']);
|
|
90
|
+
appendAlternative('dow_atom', ['template_value']);
|
|
91
|
+
appendAlternative('between_time_only_atom', ['template_value']);
|
|
92
|
+
appendAlternative('between_tod_only_atom', ['template_value']);
|
|
93
|
+
appendAlternative('string_atom', ['template_value']);
|
|
94
|
+
appendAlternative('boolean_atom', ['template_value']);
|
|
95
|
+
appendAlternative('time_value_atom', ['template_value']);
|
|
96
|
+
appendAlternative('time_period_atom', ['template_value']);
|
|
97
|
+
appendAlternative('time_period_ago_atom', ['template_value']);
|
|
98
|
+
appendAlternative('object_atom', ['template_value']);
|
|
99
|
+
appendAlternative('string_array', ['template_value']);
|
|
100
|
+
appendAlternative('number_array', ['template_value']);
|
|
101
|
+
appendAlternative('boolean_array', ['template_value']);
|
|
102
|
+
appendAlternative('object_array', ['template_value']);
|
|
103
|
+
|
|
104
|
+
replaceRule('argument', [
|
|
105
|
+
['number_time_atom', 'WS*'],
|
|
106
|
+
['statement', 'WS*']
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
replaceRule('simple_result', [
|
|
110
|
+
['fcall'],
|
|
111
|
+
['number_time_atom'],
|
|
112
|
+
['value']
|
|
113
|
+
]);
|
|
52
114
|
|
|
53
115
|
// Export the parser rules for potential external use
|
|
54
116
|
const ParserRules = extendedGrammar;
|
|
@@ -374,6 +436,10 @@ class RuleTemplate {
|
|
|
374
436
|
return String(value);
|
|
375
437
|
} else if (type === 'boolean') {
|
|
376
438
|
return value ? 'true' : 'false';
|
|
439
|
+
} else if (type === 'time period') {
|
|
440
|
+
return `BETWEEN ${value.from} AND ${value.to}`;
|
|
441
|
+
} else if (type === 'time period ago') {
|
|
442
|
+
return `${value.ago[0]} ${value.ago[1]} AGO BETWEEN ${value.from} AND ${value.to}`;
|
|
377
443
|
} else {
|
|
378
444
|
// Default behavior - just insert the value as-is
|
|
379
445
|
return String(value);
|
package/src/VariableValidate.js
CHANGED
|
@@ -207,7 +207,7 @@ class VariableValidate {
|
|
|
207
207
|
return null;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
return
|
|
210
|
+
return `BETWEEN ${value.from.trim()} AND ${value.to.trim()}`;
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
static _serializeTimePeriodAgo(value) {
|
|
@@ -224,7 +224,7 @@ class VariableValidate {
|
|
|
224
224
|
return null;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
return `${
|
|
227
|
+
return `${amount} ${unit.trim()} AGO BETWEEN ${value.from.trim()} AND ${value.to.trim()}`;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
static _serializeNumberTime(value) {
|
|
@@ -341,7 +341,7 @@ VariableValidate.validators = Object.freeze({
|
|
|
341
341
|
'time period': (value) => VariableValidate._validateWithRule(value, 'time_period_atom', {
|
|
342
342
|
normalize: VariableValidate._serializeTimePeriod,
|
|
343
343
|
emptyMessage: 'Time period variables must be objects with string from/to properties',
|
|
344
|
-
parseMessage: 'Time period variables must serialize to FROM
|
|
344
|
+
parseMessage: 'Time period variables must serialize to BETWEEN FROM AND TO syntax',
|
|
345
345
|
semanticCheck: (rawValue) => {
|
|
346
346
|
const fromError = VariableValidate._validateTimeOfDay(rawValue?.from);
|
|
347
347
|
if (fromError) return `Invalid time period from value: ${fromError}`;
|
|
@@ -355,7 +355,7 @@ VariableValidate.validators = Object.freeze({
|
|
|
355
355
|
'time period ago': (value) => VariableValidate._validateWithRule(value, 'time_period_ago_atom', {
|
|
356
356
|
normalize: VariableValidate._serializeTimePeriodAgo,
|
|
357
357
|
emptyMessage: 'Time period ago variables must be objects with from, to, and ago properties',
|
|
358
|
-
parseMessage: 'Time period ago variables must serialize to
|
|
358
|
+
parseMessage: 'Time period ago variables must serialize to AMOUNT UNIT AGO BETWEEN FROM AND TO syntax',
|
|
359
359
|
semanticCheck: (rawValue) => {
|
|
360
360
|
const fromError = VariableValidate._validateTimeOfDay(rawValue?.from);
|
|
361
361
|
if (fromError) return `Invalid time period ago from value: ${fromError}`;
|