@halleyassist/rule-parser 1.0.9 → 1.0.10
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
CHANGED
package/src/RuleParser.ebnf.js
CHANGED
|
@@ -18,11 +18,12 @@ DIVIDE ::= "/"
|
|
|
18
18
|
MODULUS ::= "%"
|
|
19
19
|
DEFAULT_VAL ::= "??"
|
|
20
20
|
arithmetic_operator ::= PLUS | MINUS | MULTIPLY | DIVIDE | MODULUS | DEFAULT_VAL
|
|
21
|
-
|
|
21
|
+
arithmetic_operand ::= fcall | number_time | number
|
|
22
|
+
arithmetic_result ::= arithmetic_operand WS* arithmetic_operator WS* ( arithmetic_result | arithmetic_operand )
|
|
22
23
|
|
|
23
24
|
simple_result ::= fcall | value
|
|
24
25
|
result ::= arithmetic_result | simple_result
|
|
25
|
-
value ::= false | true | array | number_time | number | number_tod |
|
|
26
|
+
value ::= false | true | array | time_period | number_time | number | number_tod | string
|
|
26
27
|
BEGIN_ARRAY ::= WS* #x5B WS* /* [ left square bracket */
|
|
27
28
|
BEGIN_OBJECT ::= WS* #x7B WS* /* { left curly bracket */
|
|
28
29
|
END_ARRAY ::= WS* #x5D WS* /* ] right square bracket */
|
|
@@ -46,15 +47,17 @@ fname ::= [a-zA-z0-9]+
|
|
|
46
47
|
fcall ::= fname WS* BEGIN_ARGUMENT WS* arguments? END_ARGUMENT
|
|
47
48
|
|
|
48
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
|
|
49
51
|
between_tod ||= number_tod ((WS+ "AND" WS+)) number_tod (WS+ dow_range)?
|
|
50
52
|
between ||= "BETWEEN" WS+ (between_number | between_tod)
|
|
51
53
|
dow ||= "MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY"
|
|
52
54
|
dow_range ||= "ON" WS+ dow (WS+ "TO" WS+ dow)?
|
|
53
|
-
|
|
55
|
+
between_time_only ||= "BETWEEN" WS+ between_number_time
|
|
54
56
|
between_tod_only ||= "BETWEEN" WS+ between_tod
|
|
55
57
|
|
|
56
58
|
AND ||= (WS* "&&" WS*) | (WS+ "AND" WS+)
|
|
57
59
|
OR ||= (WS* "||" WS*) | (WS+ "OR" WS+)
|
|
60
|
+
AGO ||= "AGO"
|
|
58
61
|
GT ::= ">"
|
|
59
62
|
LT ::= "<"
|
|
60
63
|
GTE ::= ">="
|
|
@@ -68,13 +71,15 @@ null ||= "null"
|
|
|
68
71
|
true ||= "TRUE"
|
|
69
72
|
array ::= BEGIN_ARRAY (value (VALUE_SEPARATOR value)*)? END_ARRAY
|
|
70
73
|
|
|
71
|
-
unit ||= "seconds" | "
|
|
74
|
+
unit ||= "seconds" | "minutes" | "hours" | "weeks" | "days" | "second" | "minute" | "week" | "hour" | "day" | "mins" | "min"
|
|
72
75
|
number ::= "-"? ([0-9]+) ("." [0-9]+)? ("e" ( "-" | "+" )? ("0" | [1-9] [0-9]*))?
|
|
73
76
|
number_time ::= number WS+ unit
|
|
74
77
|
number_tod ::= ([0-9]+) ":" ([0-9]+)
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
time_period_ago ||= number_time (WS+ number_time)* WS+ AGO
|
|
80
|
+
time_period_ago_between ||= number_time (WS+ number_time)* WS+ AGO WS+ between_tod_only
|
|
81
|
+
time_period_const ||= "today" | time_period_ago
|
|
82
|
+
time_period ::= time_period_ago_between | time_period_const | between_tod_only | between_time_only
|
|
78
83
|
|
|
79
84
|
string ::= '"' (([#x20-#x21] | [#x23-#x5B] | [#x5D-#xFFFF]) | #x5C (#x22 | #x5C | #x2F | #x62 | #x66 | #x6E | #x72 | #x74 | #x75 HEXDIG HEXDIG HEXDIG HEXDIG))* '"'
|
|
80
85
|
HEXDIG ::= [a-fA-F0-9]
|
package/src/RuleParser.js
CHANGED
|
@@ -89,7 +89,44 @@ class RuleParser {
|
|
|
89
89
|
static _parseTimePeriod(tp){
|
|
90
90
|
switch(tp.type){
|
|
91
91
|
case 'time_period_const':
|
|
92
|
+
// Check if this is a time_period_ago (has children)
|
|
93
|
+
if (tp.children && tp.children.length > 0 && tp.children[0].type === 'time_period_ago') {
|
|
94
|
+
const timePeriodAgo = tp.children[0]
|
|
95
|
+
// Extract all number_time children and sum them up
|
|
96
|
+
let totalSeconds = 0
|
|
97
|
+
const components = []
|
|
98
|
+
for (const child of timePeriodAgo.children) {
|
|
99
|
+
if (child.type === 'number_time') {
|
|
100
|
+
const number = parseFloat(child.children[0].text)
|
|
101
|
+
const unit = child.children[1].text.toUpperCase()
|
|
102
|
+
components.push([number, unit])
|
|
103
|
+
// Parse the value to get seconds
|
|
104
|
+
totalSeconds += RuleParser.__parseValue(child)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// If there's only one component, use its number and unit
|
|
108
|
+
// Otherwise, use the total in seconds and "SECONDS" as the unit
|
|
109
|
+
if (components.length === 1) {
|
|
110
|
+
return ["TimePeriodConstAgo", components[0][0], components[0][1]]
|
|
111
|
+
} else {
|
|
112
|
+
return ["TimePeriodConstAgo", totalSeconds, "SECONDS"]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
92
115
|
return ["TimePeriodConst", tp.text]
|
|
116
|
+
case 'time_period_ago_between': {
|
|
117
|
+
// time_period_ago_between has children[0] = number_time, children[1] = between_tod_only
|
|
118
|
+
const betweenTodOnly = tp.children[1]
|
|
119
|
+
const betweenTod = betweenTodOnly.children[0]
|
|
120
|
+
const startTod = RuleParser.__parseValue(betweenTod.children[0])
|
|
121
|
+
const endTod = RuleParser.__parseValue(betweenTod.children[1])
|
|
122
|
+
|
|
123
|
+
// Check if there's a dow_range at betweenTod.children[2]
|
|
124
|
+
if (betweenTod.children.length > 2) {
|
|
125
|
+
RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2])
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return ["TimePeriodBetween", startTod, endTod]
|
|
129
|
+
}
|
|
93
130
|
case 'between_tod_only': {
|
|
94
131
|
// between_tod_only has children[0] = between_tod node
|
|
95
132
|
const betweenTod = tp.children[0]
|
|
@@ -103,7 +140,7 @@ class RuleParser {
|
|
|
103
140
|
|
|
104
141
|
return ["TimePeriodBetween", startTod, endTod]
|
|
105
142
|
}
|
|
106
|
-
case '
|
|
143
|
+
case 'between_time_only': {
|
|
107
144
|
// between_number_only has children[0] = between_number node
|
|
108
145
|
const betweenNumber = tp.children[0]
|
|
109
146
|
const startValue = RuleParser.__parseValue(betweenNumber.children[0])
|
|
@@ -200,15 +237,42 @@ class RuleParser {
|
|
|
200
237
|
}
|
|
201
238
|
return null
|
|
202
239
|
}
|
|
240
|
+
static _parseArithmeticOperand(operand){
|
|
241
|
+
assert(operand.children.length == 1)
|
|
242
|
+
const child = operand.children[0]
|
|
243
|
+
const type = child.type
|
|
244
|
+
switch(type){
|
|
245
|
+
case 'fcall':
|
|
246
|
+
return RuleParser._parseFcall(child)
|
|
247
|
+
case 'number':
|
|
248
|
+
return ['Value', parseFloat(child.text)]
|
|
249
|
+
case 'number_time':
|
|
250
|
+
return ['Value', RuleParser.__parseValue(child)]
|
|
251
|
+
}
|
|
252
|
+
throw new Error(`Unknown arithmetic operand type ${type}`)
|
|
253
|
+
}
|
|
203
254
|
static _parseArithmeticResult(result){
|
|
204
255
|
assert(result.children.length == 3)
|
|
205
|
-
const partA =
|
|
256
|
+
const partA = RuleParser._parseArithmeticOperand(result.children[0])
|
|
206
257
|
const operatorFn = ArithmeticOperators[result.children[1].text]
|
|
207
|
-
const partB =
|
|
258
|
+
const partB = RuleParser.__parseArithmeticResult(result, 2)
|
|
208
259
|
|
|
209
260
|
return [operatorFn, partA, partB]
|
|
210
261
|
}
|
|
211
262
|
|
|
263
|
+
static __parseArithmeticResult(result, idx){
|
|
264
|
+
const child = result.children[idx]
|
|
265
|
+
const type = child.type
|
|
266
|
+
switch(type){
|
|
267
|
+
case 'arithmetic_operand':
|
|
268
|
+
return RuleParser._parseArithmeticOperand(child)
|
|
269
|
+
case 'arithmetic_result':
|
|
270
|
+
return RuleParser._parseArithmeticResult(child)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
throw new Error(`Unknown arithmetic result node ${type}`)
|
|
274
|
+
}
|
|
275
|
+
|
|
212
276
|
static __parseResult(result, idx){
|
|
213
277
|
const child = result.children[idx]
|
|
214
278
|
const type = child.type
|
|
@@ -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_result7","bnf":[["arithmetic_result"],["
|
|
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":"%%between_tod1920","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"%between_tod19","bnf":[["%%between_tod1920"]],"fragment":true},{"name":"%between_tod21","bnf":[["WS+","dow_range"]],"fragment":true},{"name":"between_tod","bnf":[["number_tod","%between_tod19","number_tod","%between_tod21?"]]},{"name":"%between22","bnf":[["between_number"],["between_tod"]],"fragment":true},{"name":"between","bnf":[[/[Bb]/,/[Ee]/,/[Tt]/,/[Ww]/,/[Ee]/,/[Ee]/,/[Nn]/,"WS+","%between22"]]},{"name":"dow","bnf":[[/[Mm]/,/[Oo]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Uu]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ww]/,/[Ee]/,/[Dd]/,/[Nn]/,/[Ee]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Tt]/,/[Hh]/,/[Uu]/,/[Rr]/,/[Ss]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ff]/,/[Rr]/,/[Ii]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Aa]/,/[Tt]/,/[Uu]/,/[Rr]/,/[Dd]/,/[Aa]/,/[Yy]/],[/[Ss]/,/[Uu]/,/[Nn]/,/[Dd]/,/[Aa]/,/[Yy]/]]},{"name":"%dow_range23","bnf":[["WS+",/[Tt]/,/[Oo]/,"WS+","dow"]],"fragment":true},{"name":"dow_range","bnf":[[/[Oo]/,/[Nn]/,"WS+","dow","%dow_range23?"]]},{"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":"%AND24","bnf":[["WS*",/&/,/&/,"WS*"]],"fragment":true},{"name":"%AND25","bnf":[["WS+",/[Aa]/,/[Nn]/,/[Dd]/,"WS+"]],"fragment":true},{"name":"AND","bnf":[["%AND24"],["%AND25"]]},{"name":"%OR26","bnf":[["WS*",/\|/,/\|/,"WS*"]],"fragment":true},{"name":"%OR27","bnf":[["WS+",/[Oo]/,/[Rr]/,"WS+"]],"fragment":true},{"name":"OR","bnf":[["%OR26"],["%OR27"]]},{"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":"%NOT28","bnf":[[/!/,"WS*"]],"fragment":true},{"name":"%NOT29","bnf":[[/[Nn]/,/[Oo]/,/[Tt]/,"WS+"]],"fragment":true},{"name":"NOT","bnf":[["%NOT28"],["%NOT29"]]},{"name":"false","bnf":[[/[Ff]/,/[Aa]/,/[Ll]/,/[Ss]/,/[Ee]/]]},{"name":"null","bnf":[[/[Nn]/,/[Uu]/,/[Ll]/,/[Ll]/]]},{"name":"true","bnf":[[/[Tt]/,/[Rr]/,/[Uu]/,/[Ee]/]]},{"name":"%%array3031","bnf":[["VALUE_SEPARATOR","value"]],"fragment":true},{"name":"%array30","bnf":[["value","%%array3031*"]],"fragment":true},{"name":"array","bnf":[["BEGIN_ARRAY","%array30?","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":"%%number3233","bnf":[[/[0-9]/]]},{"name":"%number32","bnf":[["%%number3233+"]],"fragment":true},{"name":"%%number3435","bnf":[[/[0-9]/]]},{"name":"%number34","bnf":[["\".\"","%%number3435+"]],"fragment":true},{"name":"%%number3637","bnf":[["\"-\""],["\"+\""]],"fragment":true},{"name":"%%%number363839","bnf":[[/[0-9]/]]},{"name":"%%number3638","bnf":[["\"0\""],[/[1-9]/,"%%%number363839*"]],"fragment":true},{"name":"%number36","bnf":[["\"e\"","%%number3637?","%%number3638"]],"fragment":true},{"name":"number","bnf":[["\"-\"?","%number32","%number34?","%number36?"]]},{"name":"number_time","bnf":[["number","WS+","unit"]]},{"name":"%%number_tod4041","bnf":[[/[0-9]/]]},{"name":"%number_tod40","bnf":[["%%number_tod4041+"]],"fragment":true},{"name":"%%number_tod4243","bnf":[[/[0-9]/]]},{"name":"%number_tod42","bnf":[["%%number_tod4243+"]],"fragment":true},{"name":"number_tod","bnf":[["%number_tod40","\":\"","%number_tod42"]]},{"name":"%time_period_ago44","bnf":[["WS+","number_time"]],"fragment":true},{"name":"time_period_ago","bnf":[["number_time","%time_period_ago44*","WS+","AGO"]]},{"name":"%time_period_ago_between45","bnf":[["WS+","number_time"]],"fragment":true},{"name":"time_period_ago_between","bnf":[["number_time","%time_period_ago_between45*","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":"%%string4647","bnf":[[/[\x20-\x21]/],[/[\x23-\x5B]/],[/[\x5D-\uFFFF]/]],"fragment":true},{"name":"%%string4648","bnf":[[/\x22/],[/\x5C/],[/\x2F/],[/\x62/],[/\x66/],[/\x6E/],[/\x72/],[/\x74/],[/\x75/,"HEXDIG","HEXDIG","HEXDIG","HEXDIG"]],"fragment":true},{"name":"%string46","bnf":[["%%string4647"],[/\x5C/,"%%string4648"]],"fragment":true},{"name":"string","bnf":[["'\"'","%string46*","'\"'"]]},{"name":"HEXDIG","bnf":[[/[a-fA-F0-9]/]]}]
|
|
@@ -89,7 +89,44 @@ class RuleParser {
|
|
|
89
89
|
static _parseTimePeriod(tp){
|
|
90
90
|
switch(tp.type){
|
|
91
91
|
case 'time_period_const':
|
|
92
|
+
// Check if this is a time_period_ago (has children)
|
|
93
|
+
if (tp.children && tp.children.length > 0 && tp.children[0].type === 'time_period_ago') {
|
|
94
|
+
const timePeriodAgo = tp.children[0]
|
|
95
|
+
// Extract all number_time children and sum them up
|
|
96
|
+
let totalSeconds = 0
|
|
97
|
+
const components = []
|
|
98
|
+
for (const child of timePeriodAgo.children) {
|
|
99
|
+
if (child.type === 'number_time') {
|
|
100
|
+
const number = parseFloat(child.children[0].text)
|
|
101
|
+
const unit = child.children[1].text.toUpperCase()
|
|
102
|
+
components.push([number, unit])
|
|
103
|
+
// Parse the value to get seconds
|
|
104
|
+
totalSeconds += RuleParser.__parseValue(child)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// If there's only one component, use its number and unit
|
|
108
|
+
// Otherwise, use the total in seconds and "SECONDS" as the unit
|
|
109
|
+
if (components.length === 1) {
|
|
110
|
+
return ["TimePeriodConstAgo", components[0][0], components[0][1]]
|
|
111
|
+
} else {
|
|
112
|
+
return ["TimePeriodConstAgo", totalSeconds, "SECONDS"]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
92
115
|
return ["TimePeriodConst", tp.text]
|
|
116
|
+
case 'time_period_ago_between': {
|
|
117
|
+
// time_period_ago_between has children[0] = number_time, children[1] = between_tod_only
|
|
118
|
+
const betweenTodOnly = tp.children[1]
|
|
119
|
+
const betweenTod = betweenTodOnly.children[0]
|
|
120
|
+
const startTod = RuleParser.__parseValue(betweenTod.children[0])
|
|
121
|
+
const endTod = RuleParser.__parseValue(betweenTod.children[1])
|
|
122
|
+
|
|
123
|
+
// Check if there's a dow_range at betweenTod.children[2]
|
|
124
|
+
if (betweenTod.children.length > 2) {
|
|
125
|
+
RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2])
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return ["TimePeriodBetween", startTod, endTod]
|
|
129
|
+
}
|
|
93
130
|
case 'between_tod_only': {
|
|
94
131
|
// between_tod_only has children[0] = between_tod node
|
|
95
132
|
const betweenTod = tp.children[0]
|
|
@@ -103,7 +140,7 @@ class RuleParser {
|
|
|
103
140
|
|
|
104
141
|
return ["TimePeriodBetween", startTod, endTod]
|
|
105
142
|
}
|
|
106
|
-
case '
|
|
143
|
+
case 'between_time_only': {
|
|
107
144
|
// between_number_only has children[0] = between_number node
|
|
108
145
|
const betweenNumber = tp.children[0]
|
|
109
146
|
const startValue = RuleParser.__parseValue(betweenNumber.children[0])
|
|
@@ -200,15 +237,42 @@ class RuleParser {
|
|
|
200
237
|
}
|
|
201
238
|
return null
|
|
202
239
|
}
|
|
240
|
+
static _parseArithmeticOperand(operand){
|
|
241
|
+
assert(operand.children.length == 1)
|
|
242
|
+
const child = operand.children[0]
|
|
243
|
+
const type = child.type
|
|
244
|
+
switch(type){
|
|
245
|
+
case 'fcall':
|
|
246
|
+
return RuleParser._parseFcall(child)
|
|
247
|
+
case 'number':
|
|
248
|
+
return ['Value', parseFloat(child.text)]
|
|
249
|
+
case 'number_time':
|
|
250
|
+
return ['Value', RuleParser.__parseValue(child)]
|
|
251
|
+
}
|
|
252
|
+
throw new Error(`Unknown arithmetic operand type ${type}`)
|
|
253
|
+
}
|
|
203
254
|
static _parseArithmeticResult(result){
|
|
204
255
|
assert(result.children.length == 3)
|
|
205
|
-
const partA =
|
|
256
|
+
const partA = RuleParser._parseArithmeticOperand(result.children[0])
|
|
206
257
|
const operatorFn = ArithmeticOperators[result.children[1].text]
|
|
207
|
-
const partB =
|
|
258
|
+
const partB = RuleParser.__parseArithmeticResult(result, 2)
|
|
208
259
|
|
|
209
260
|
return [operatorFn, partA, partB]
|
|
210
261
|
}
|
|
211
262
|
|
|
263
|
+
static __parseArithmeticResult(result, idx){
|
|
264
|
+
const child = result.children[idx]
|
|
265
|
+
const type = child.type
|
|
266
|
+
switch(type){
|
|
267
|
+
case 'arithmetic_operand':
|
|
268
|
+
return RuleParser._parseArithmeticOperand(child)
|
|
269
|
+
case 'arithmetic_result':
|
|
270
|
+
return RuleParser._parseArithmeticResult(child)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
throw new Error(`Unknown arithmetic result node ${type}`)
|
|
274
|
+
}
|
|
275
|
+
|
|
212
276
|
static __parseResult(result, idx){
|
|
213
277
|
const child = result.children[idx]
|
|
214
278
|
const type = child.type
|