@halleyassist/rule-parser 1.0.10 → 1.0.11
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/package.json +1 -1
- package/src/RuleParser.ebnf.js +2 -2
- package/src/RuleParser.js +46 -12
- package/src/RuleParser.production.ebnf.js +1 -1
- package/src/RuleParser.production.js +46 -12
package/package.json
CHANGED
package/src/RuleParser.ebnf.js
CHANGED
|
@@ -47,10 +47,10 @@ fname ::= [a-zA-z0-9]+
|
|
|
47
47
|
fcall ::= fname WS* BEGIN_ARGUMENT WS* arguments? END_ARGUMENT
|
|
48
48
|
|
|
49
49
|
between_number ||= (number_time | number) ((WS+ "AND" WS+) | (WS* "-" WS*)) (number_time | number)
|
|
50
|
-
between_number_time ||= number_time ((WS+ "AND" WS+) | (WS* "-" WS*)) number_time
|
|
50
|
+
between_number_time ||= number_time ((WS+ "AND" WS+) | (WS* "-" WS*)) number_time (WS+ dow_range)?
|
|
51
51
|
between_tod ||= number_tod ((WS+ "AND" WS+)) number_tod (WS+ dow_range)?
|
|
52
52
|
between ||= "BETWEEN" WS+ (between_number | between_tod)
|
|
53
|
-
dow ||= "MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY"
|
|
53
|
+
dow ||= "MONDAY" | "MON" | "TUESDAY" | "TUE" | "WEDNESDAY" | "WED" | "THURSDAY" | "THU" | "THUR" | "FRIDAY" | "FRI" | "SATURDAY" | "SAT" | "SUNDAY" | "SUN"
|
|
54
54
|
dow_range ||= "ON" WS+ dow (WS+ "TO" WS+ dow)?
|
|
55
55
|
between_time_only ||= "BETWEEN" WS+ between_number_time
|
|
56
56
|
between_tod_only ||= "BETWEEN" WS+ between_tod
|
package/src/RuleParser.js
CHANGED
|
@@ -30,6 +30,34 @@ const LogicalOperators = {
|
|
|
30
30
|
"OR": 'Or',
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// Map abbreviations to canonical uppercase full form
|
|
34
|
+
const DOW_MAP = {
|
|
35
|
+
'MON': 'MONDAY',
|
|
36
|
+
'TUE': 'TUESDAY',
|
|
37
|
+
'WED': 'WEDNESDAY',
|
|
38
|
+
'THU': 'THURSDAY',
|
|
39
|
+
'THUR': 'THURSDAY',
|
|
40
|
+
'FRI': 'FRIDAY',
|
|
41
|
+
'SAT': 'SATURDAY',
|
|
42
|
+
'SUN': 'SUNDAY',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Valid full day names
|
|
46
|
+
const VALID_DAYS = new Set(['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY']);
|
|
47
|
+
|
|
48
|
+
const normalizeDow = (text) => {
|
|
49
|
+
const upper = text.toUpperCase();
|
|
50
|
+
// Check if it's an abbreviation first
|
|
51
|
+
if (upper in DOW_MAP) {
|
|
52
|
+
return DOW_MAP[upper];
|
|
53
|
+
}
|
|
54
|
+
// Otherwise, check if it's a valid full name
|
|
55
|
+
if (VALID_DAYS.has(upper)) {
|
|
56
|
+
return upper;
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`Invalid day of week: ${text}`);
|
|
59
|
+
};
|
|
60
|
+
|
|
33
61
|
const Epsilon = 0.01
|
|
34
62
|
|
|
35
63
|
class RuleParser {
|
|
@@ -63,21 +91,19 @@ class RuleParser {
|
|
|
63
91
|
return ret
|
|
64
92
|
}
|
|
65
93
|
static _parseDowRange(dowRange) {
|
|
66
|
-
const dow = []
|
|
67
|
-
|
|
94
|
+
const dow = [];
|
|
68
95
|
// dow_range can have 1 or 2 children (single day or range)
|
|
69
96
|
if (dowRange.children.length === 1) {
|
|
70
97
|
// Single day: ON MONDAY
|
|
71
|
-
dow.push(dowRange.children[0].text
|
|
98
|
+
dow.push(normalizeDow(dowRange.children[0].text));
|
|
72
99
|
} else if (dowRange.children.length === 2) {
|
|
73
100
|
// Range: ON MONDAY TO WEDNESDAY
|
|
74
|
-
dow.push(dowRange.children[0].text
|
|
75
|
-
dow.push(dowRange.children[1].text
|
|
101
|
+
dow.push(normalizeDow(dowRange.children[0].text));
|
|
102
|
+
dow.push(normalizeDow(dowRange.children[1].text));
|
|
76
103
|
} else {
|
|
77
|
-
throw new Error(`Invalid dow_range with ${dowRange.children.length} children`)
|
|
104
|
+
throw new Error(`Invalid dow_range with ${dowRange.children.length} children`);
|
|
78
105
|
}
|
|
79
|
-
|
|
80
|
-
return dow
|
|
106
|
+
return dow;
|
|
81
107
|
}
|
|
82
108
|
static _addDowToTods(startTod, endTod, dowRange) {
|
|
83
109
|
if (dowRange && dowRange.type === 'dow_range') {
|
|
@@ -141,10 +167,18 @@ class RuleParser {
|
|
|
141
167
|
return ["TimePeriodBetween", startTod, endTod]
|
|
142
168
|
}
|
|
143
169
|
case 'between_time_only': {
|
|
144
|
-
//
|
|
145
|
-
const
|
|
146
|
-
const startValue = RuleParser.__parseValue(
|
|
147
|
-
const endValue = RuleParser.__parseValue(
|
|
170
|
+
// between_time_only has children[0] = between_number_time node
|
|
171
|
+
const betweenNumberTime = tp.children[0]
|
|
172
|
+
const startValue = RuleParser.__parseValue(betweenNumberTime.children[0])
|
|
173
|
+
const endValue = RuleParser.__parseValue(betweenNumberTime.children[1])
|
|
174
|
+
|
|
175
|
+
// Check if there's a dow_range at betweenNumberTime.children[2]
|
|
176
|
+
// If DOW filters are provided, append them as additional parameters
|
|
177
|
+
if (betweenNumberTime.children.length > 2 && betweenNumberTime.children[2].type === 'dow_range') {
|
|
178
|
+
const dow = RuleParser._parseDowRange(betweenNumberTime.children[2])
|
|
179
|
+
// Append DOW as additional arguments: ["TimePeriodBetween", start, end, "MONDAY"] or ["TimePeriodBetween", start, end, "MONDAY", "FRIDAY"]
|
|
180
|
+
return ["TimePeriodBetween", startValue, endValue, ...dow]
|
|
181
|
+
}
|
|
148
182
|
|
|
149
183
|
return ["TimePeriodBetween", startValue, endValue]
|
|
150
184
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports=[{"name":"statement_main","bnf":[["statement","EOF"]]},{"name":"logical_operator","bnf":[["AND"],["OR"]]},{"name":"%statement0","bnf":[["logical_operator","expression"]],"fragment":true},{"name":"statement","bnf":[["expression","%statement0*"]]},{"name":"expression","bnf":[["not_expression"],["standard_expression"],["parenthesis_expression"]]},{"name":"parenthesis_expression","bnf":[["BEGIN_PARENTHESIS","WS*","statement","WS*","END_PARENTHESIS"]]},{"name":"%not_expression1","bnf":[["result"],["parenthesis_expression"]],"fragment":true},{"name":"not_expression","bnf":[["NOT","%not_expression1"]]},{"name":"%%standard_expression23","bnf":[["WS*","eq_approx"]],"fragment":true},{"name":"%%standard_expression24","bnf":[["WS*","basic_rhs"]],"fragment":true},{"name":"%%%standard_expression256","bnf":[["WS+","IS"]],"fragment":true},{"name":"%%standard_expression25","bnf":[["%%%standard_expression256?","WS+","between"]],"fragment":true},{"name":"%standard_expression2","bnf":[["%%standard_expression23"],["%%standard_expression24"],["%%standard_expression25"]],"fragment":true},{"name":"standard_expression","bnf":[["result","%standard_expression2?"]]},{"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_result7","bnf":[["arithmetic_result"],["arithmetic_operand"]],"fragment":true},{"name":"arithmetic_result","bnf":[["arithmetic_operand","WS*","arithmetic_operator","WS*","%arithmetic_result7"]]},{"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":"%WS8","bnf":[[/[\x20\x09\x0A\x0D]/]]},{"name":"WS","bnf":[["%WS8+"]]},{"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":"%argument9","bnf":[["\",\"","WS*"]],"fragment":true},{"name":"argument","bnf":[["statement","WS*","%argument9?"]]},{"name":"arguments","bnf":[["argument*"]]},{"name":"%fname10","bnf":[[/[a-zA-z0-9]/]]},{"name":"fname","bnf":[["%fname10+"]]},{"name":"fcall","bnf":[["fname","WS*","BEGIN_ARGUMENT","WS*","arguments?","END_ARGUMENT"]]},{"name":"%between_number11","bnf":[["number_time"],["number"]],"fragment":true},{"name":"%%between_number1213","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%%between_number1214","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"%between_number12","bnf":[["%%between_number1213"],["%%between_number1214"]],"fragment":true},{"name":"%between_number15","bnf":[["number_time"],["number"]],"fragment":true},{"name":"between_number","bnf":[["%between_number11","%between_number12","%between_number15"]]},{"name":"%%between_number_time1617","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%%between_number_time1618","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"%between_number_time16","bnf":[["%%between_number_time1617"],["%%between_number_time1618"]],"fragment":true},{"name":"between_number_time","bnf":[["number_time","%between_number_time16","number_time"]]},{"name":"%%
|
|
1
|
+
module.exports=[{"name":"statement_main","bnf":[["statement","EOF"]]},{"name":"logical_operator","bnf":[["AND"],["OR"]]},{"name":"%statement0","bnf":[["logical_operator","expression"]],"fragment":true},{"name":"statement","bnf":[["expression","%statement0*"]]},{"name":"expression","bnf":[["not_expression"],["standard_expression"],["parenthesis_expression"]]},{"name":"parenthesis_expression","bnf":[["BEGIN_PARENTHESIS","WS*","statement","WS*","END_PARENTHESIS"]]},{"name":"%not_expression1","bnf":[["result"],["parenthesis_expression"]],"fragment":true},{"name":"not_expression","bnf":[["NOT","%not_expression1"]]},{"name":"%%standard_expression23","bnf":[["WS*","eq_approx"]],"fragment":true},{"name":"%%standard_expression24","bnf":[["WS*","basic_rhs"]],"fragment":true},{"name":"%%%standard_expression256","bnf":[["WS+","IS"]],"fragment":true},{"name":"%%standard_expression25","bnf":[["%%%standard_expression256?","WS+","between"]],"fragment":true},{"name":"%standard_expression2","bnf":[["%%standard_expression23"],["%%standard_expression24"],["%%standard_expression25"]],"fragment":true},{"name":"standard_expression","bnf":[["result","%standard_expression2?"]]},{"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_result7","bnf":[["arithmetic_result"],["arithmetic_operand"]],"fragment":true},{"name":"arithmetic_result","bnf":[["arithmetic_operand","WS*","arithmetic_operator","WS*","%arithmetic_result7"]]},{"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":"%WS8","bnf":[[/[\x20\x09\x0A\x0D]/]]},{"name":"WS","bnf":[["%WS8+"]]},{"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":"%argument9","bnf":[["\",\"","WS*"]],"fragment":true},{"name":"argument","bnf":[["statement","WS*","%argument9?"]]},{"name":"arguments","bnf":[["argument*"]]},{"name":"%fname10","bnf":[[/[a-zA-z0-9]/]]},{"name":"fname","bnf":[["%fname10+"]]},{"name":"fcall","bnf":[["fname","WS*","BEGIN_ARGUMENT","WS*","arguments?","END_ARGUMENT"]]},{"name":"%between_number11","bnf":[["number_time"],["number"]],"fragment":true},{"name":"%%between_number1213","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%%between_number1214","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"%between_number12","bnf":[["%%between_number1213"],["%%between_number1214"]],"fragment":true},{"name":"%between_number15","bnf":[["number_time"],["number"]],"fragment":true},{"name":"between_number","bnf":[["%between_number11","%between_number12","%between_number15"]]},{"name":"%%between_number_time1617","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%%between_number_time1618","bnf":[["WS*",/\-/,"WS*"]],"fragment":true},{"name":"%between_number_time16","bnf":[["%%between_number_time1617"],["%%between_number_time1618"]],"fragment":true},{"name":"%between_number_time19","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_number_time","bnf":[["number_time","%between_number_time16","number_time","%between_number_time19?"]]},{"name":"%%between_tod2021","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_tod20","bnf":[["%%between_tod2021"]],"fragment":true},{"name":"%between_tod22","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_tod","bnf":[["number_tod","%between_tod20","number_tod","%between_tod22?"]]},{"name":"%between23","bnf":[["between_number"],["between_tod"]],"fragment":true},{"name":"between","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","%between23"]]},{"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_range24","bnf":[["WS+",/[Tt]/,/[Oo]/,"WS+","dow"]],"fragment":true},{"name":"dow_range","bnf":[[/[Oo]/,/[Nn]/,"WS+","dow","%dow_range24?"]]},{"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":"%AND25","bnf":[["WS*",/&/,/&/,"WS*"]],"fragment":true},{"name":"%AND26","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"AND","bnf":[["%AND25"],["%AND26"]]},{"name":"%OR27","bnf":[["WS*",/\|/,/\|/,"WS*"]],"fragment":true},{"name":"%OR28","bnf":[["WS+",/[Oo]/,/[Rr]/,"WS+"]],"fragment":true},{"name":"OR","bnf":[["%OR27"],["%OR28"]]},{"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":"%NOT29","bnf":[[/!/,"WS*"]],"fragment":true},{"name":"%NOT30","bnf":[[/[Nn]/,/[Oo]/,/[Tt]/,"WS+"]],"fragment":true},{"name":"NOT","bnf":[["%NOT29"],["%NOT30"]]},{"name":"false","bnf":[[/[Ff]/,/[Aa]/,/[Ll]/,/[Ss]/,/[Ee]/]]},{"name":"null","bnf":[[/[Nn]/,/[Uu]/,/[Ll]/,/[Ll]/]]},{"name":"true","bnf":[[/[Tt]/,/[Rr]/,/[Uu]/,/[Ee]/]]},{"name":"%%array3132","bnf":[["VALUE_SEPARATOR","value"]],"fragment":true},{"name":"%array31","bnf":[["value","%%array3132*"]],"fragment":true},{"name":"array","bnf":[["BEGIN_ARRAY","%array31?","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":"%%number3334","bnf":[[/[0-9]/]]},{"name":"%number33","bnf":[["%%number3334+"]],"fragment":true},{"name":"%%number3536","bnf":[[/[0-9]/]]},{"name":"%number35","bnf":[["\".\"","%%number3536+"]],"fragment":true},{"name":"%%number3738","bnf":[["\"-\""],["\"+\""]],"fragment":true},{"name":"%%%number373940","bnf":[[/[0-9]/]]},{"name":"%%number3739","bnf":[["\"0\""],[/[1-9]/,"%%%number373940*"]],"fragment":true},{"name":"%number37","bnf":[["\"e\"","%%number3738?","%%number3739"]],"fragment":true},{"name":"number","bnf":[["\"-\"?","%number33","%number35?","%number37?"]]},{"name":"number_time","bnf":[["number","WS+","unit"]]},{"name":"%%number_tod4142","bnf":[[/[0-9]/]]},{"name":"%number_tod41","bnf":[["%%number_tod4142+"]],"fragment":true},{"name":"%%number_tod4344","bnf":[[/[0-9]/]]},{"name":"%number_tod43","bnf":[["%%number_tod4344+"]],"fragment":true},{"name":"number_tod","bnf":[["%number_tod41","\":\"","%number_tod43"]]},{"name":"%time_period_ago45","bnf":[["WS+","number_time"]],"fragment":true},{"name":"time_period_ago","bnf":[["number_time","%time_period_ago45*","WS+","AGO"]]},{"name":"%time_period_ago_between46","bnf":[["WS+","number_time"]],"fragment":true},{"name":"time_period_ago_between","bnf":[["number_time","%time_period_ago_between46*","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":"%%string4748","bnf":[[/[\x20-\x21]/],[/[\x23-\x5B]/],[/[\x5D-\uFFFF]/]],"fragment":true},{"name":"%%string4749","bnf":[[/\x22/],[/\x5C/],[/\x2F/],[/\x62/],[/\x66/],[/\x6E/],[/\x72/],[/\x74/],[/\x75/,"HEXDIG","HEXDIG","HEXDIG","HEXDIG"]],"fragment":true},{"name":"%string47","bnf":[["%%string4748"],[/\x5C/,"%%string4749"]],"fragment":true},{"name":"string","bnf":[["'\"'","%string47*","'\"'"]]},{"name":"HEXDIG","bnf":[[/[a-fA-F0-9]/]]}]
|
|
@@ -30,6 +30,34 @@ const LogicalOperators = {
|
|
|
30
30
|
"OR": 'Or',
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// Map abbreviations to canonical uppercase full form
|
|
34
|
+
const DOW_MAP = {
|
|
35
|
+
'MON': 'MONDAY',
|
|
36
|
+
'TUE': 'TUESDAY',
|
|
37
|
+
'WED': 'WEDNESDAY',
|
|
38
|
+
'THU': 'THURSDAY',
|
|
39
|
+
'THUR': 'THURSDAY',
|
|
40
|
+
'FRI': 'FRIDAY',
|
|
41
|
+
'SAT': 'SATURDAY',
|
|
42
|
+
'SUN': 'SUNDAY',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Valid full day names
|
|
46
|
+
const VALID_DAYS = new Set(['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY']);
|
|
47
|
+
|
|
48
|
+
const normalizeDow = (text) => {
|
|
49
|
+
const upper = text.toUpperCase();
|
|
50
|
+
// Check if it's an abbreviation first
|
|
51
|
+
if (upper in DOW_MAP) {
|
|
52
|
+
return DOW_MAP[upper];
|
|
53
|
+
}
|
|
54
|
+
// Otherwise, check if it's a valid full name
|
|
55
|
+
if (VALID_DAYS.has(upper)) {
|
|
56
|
+
return upper;
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`Invalid day of week: ${text}`);
|
|
59
|
+
};
|
|
60
|
+
|
|
33
61
|
const Epsilon = 0.01
|
|
34
62
|
|
|
35
63
|
class RuleParser {
|
|
@@ -63,21 +91,19 @@ class RuleParser {
|
|
|
63
91
|
return ret
|
|
64
92
|
}
|
|
65
93
|
static _parseDowRange(dowRange) {
|
|
66
|
-
const dow = []
|
|
67
|
-
|
|
94
|
+
const dow = [];
|
|
68
95
|
// dow_range can have 1 or 2 children (single day or range)
|
|
69
96
|
if (dowRange.children.length === 1) {
|
|
70
97
|
// Single day: ON MONDAY
|
|
71
|
-
dow.push(dowRange.children[0].text
|
|
98
|
+
dow.push(normalizeDow(dowRange.children[0].text));
|
|
72
99
|
} else if (dowRange.children.length === 2) {
|
|
73
100
|
// Range: ON MONDAY TO WEDNESDAY
|
|
74
|
-
dow.push(dowRange.children[0].text
|
|
75
|
-
dow.push(dowRange.children[1].text
|
|
101
|
+
dow.push(normalizeDow(dowRange.children[0].text));
|
|
102
|
+
dow.push(normalizeDow(dowRange.children[1].text));
|
|
76
103
|
} else {
|
|
77
|
-
throw new Error(`Invalid dow_range with ${dowRange.children.length} children`)
|
|
104
|
+
throw new Error(`Invalid dow_range with ${dowRange.children.length} children`);
|
|
78
105
|
}
|
|
79
|
-
|
|
80
|
-
return dow
|
|
106
|
+
return dow;
|
|
81
107
|
}
|
|
82
108
|
static _addDowToTods(startTod, endTod, dowRange) {
|
|
83
109
|
if (dowRange && dowRange.type === 'dow_range') {
|
|
@@ -141,10 +167,18 @@ class RuleParser {
|
|
|
141
167
|
return ["TimePeriodBetween", startTod, endTod]
|
|
142
168
|
}
|
|
143
169
|
case 'between_time_only': {
|
|
144
|
-
//
|
|
145
|
-
const
|
|
146
|
-
const startValue = RuleParser.__parseValue(
|
|
147
|
-
const endValue = RuleParser.__parseValue(
|
|
170
|
+
// between_time_only has children[0] = between_number_time node
|
|
171
|
+
const betweenNumberTime = tp.children[0]
|
|
172
|
+
const startValue = RuleParser.__parseValue(betweenNumberTime.children[0])
|
|
173
|
+
const endValue = RuleParser.__parseValue(betweenNumberTime.children[1])
|
|
174
|
+
|
|
175
|
+
// Check if there's a dow_range at betweenNumberTime.children[2]
|
|
176
|
+
// If DOW filters are provided, append them as additional parameters
|
|
177
|
+
if (betweenNumberTime.children.length > 2 && betweenNumberTime.children[2].type === 'dow_range') {
|
|
178
|
+
const dow = RuleParser._parseDowRange(betweenNumberTime.children[2])
|
|
179
|
+
// Append DOW as additional arguments: ["TimePeriodBetween", start, end, "MONDAY"] or ["TimePeriodBetween", start, end, "MONDAY", "FRIDAY"]
|
|
180
|
+
return ["TimePeriodBetween", startValue, endValue, ...dow]
|
|
181
|
+
}
|
|
148
182
|
|
|
149
183
|
return ["TimePeriodBetween", startValue, endValue]
|
|
150
184
|
}
|