@halleyassist/rule-templater 0.0.8 → 0.0.9
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 +584 -543
- package/package.json +1 -1
|
@@ -1,43 +1,33 @@
|
|
|
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.RuleTemplater = 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
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]/]]}]
|
|
3
3
|
},{}],2:[function(require,module,exports){
|
|
4
|
-
const {Parser} = require('ebnf/dist/Parser.js'),
|
|
5
|
-
|
|
6
|
-
assert = require('assert'),
|
|
7
|
-
RuleParseError = require('./errors/RuleParseError')
|
|
8
|
-
|
|
9
|
-
let ParserRules = require('./RuleParser.production.ebnf.js')
|
|
4
|
+
const {Parser} = require('ebnf/dist/Parser.js'), {ParsingError} = require('ebnf'), RuleParseError = require('./errors/RuleParseError');
|
|
5
|
+
let ParserRules = require('./RuleParser.production.ebnf.js');
|
|
10
6
|
let ParserCache;
|
|
11
|
-
|
|
12
|
-
const { ErrorAnalyzer } = require('./errors/ErrorAnalyzer');
|
|
13
|
-
|
|
7
|
+
const {ErrorAnalyzer} = require('./errors/ErrorAnalyzer');
|
|
14
8
|
const ArithmeticOperators = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
9
|
+
'+': 'MathAdd',
|
|
10
|
+
'-': 'MathSub',
|
|
11
|
+
'/': 'MathDiv',
|
|
12
|
+
'*': 'MathMul',
|
|
13
|
+
'%': 'MathMod',
|
|
14
|
+
'??': 'Default'
|
|
15
|
+
};
|
|
23
16
|
const OperatorFn = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
17
|
+
'>': 'Gt',
|
|
18
|
+
'<': 'Lt',
|
|
19
|
+
'>=': 'Gte',
|
|
20
|
+
'<=': 'Lte',
|
|
21
|
+
'==': 'Eq',
|
|
22
|
+
'=': 'Eq',
|
|
23
|
+
'!=': 'Neq'
|
|
24
|
+
};
|
|
33
25
|
const LogicalOperators = {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Map abbreviations to canonical uppercase full form
|
|
26
|
+
'&&': 'And',
|
|
27
|
+
'AND': 'And',
|
|
28
|
+
'||': 'Or',
|
|
29
|
+
'OR': 'Or'
|
|
30
|
+
};
|
|
41
31
|
const DOW_MAP = {
|
|
42
32
|
'MON': 'MONDAY',
|
|
43
33
|
'TUE': 'TUESDAY',
|
|
@@ -46,654 +36,705 @@ const DOW_MAP = {
|
|
|
46
36
|
'THUR': 'THURSDAY',
|
|
47
37
|
'FRI': 'FRIDAY',
|
|
48
38
|
'SAT': 'SATURDAY',
|
|
49
|
-
'SUN': 'SUNDAY'
|
|
39
|
+
'SUN': 'SUNDAY'
|
|
50
40
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
41
|
+
const VALID_DAYS = new Set([
|
|
42
|
+
'MONDAY',
|
|
43
|
+
'TUESDAY',
|
|
44
|
+
'WEDNESDAY',
|
|
45
|
+
'THURSDAY',
|
|
46
|
+
'FRIDAY',
|
|
47
|
+
'SATURDAY',
|
|
48
|
+
'SUNDAY'
|
|
49
|
+
]);
|
|
50
|
+
const normalizeDow = text => {
|
|
56
51
|
const upper = text.toUpperCase();
|
|
57
|
-
// Check if it's an abbreviation first
|
|
58
52
|
if (upper in DOW_MAP) {
|
|
59
53
|
return DOW_MAP[upper];
|
|
60
54
|
}
|
|
61
|
-
// Otherwise, check if it's a valid full name
|
|
62
55
|
if (VALID_DAYS.has(upper)) {
|
|
63
56
|
return upper;
|
|
64
57
|
}
|
|
65
|
-
throw new Error(`Invalid day of week: ${text}`);
|
|
58
|
+
throw new Error(`Invalid day of week: ${ text }`);
|
|
66
59
|
};
|
|
67
|
-
|
|
68
|
-
const Epsilon = 0.01
|
|
69
|
-
|
|
60
|
+
const Epsilon = 0.01;
|
|
70
61
|
class RuleParser {
|
|
71
|
-
static toAst(txt, parser = null){
|
|
72
|
-
let ret
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
ParserCache = new Parser(ParserRules, {debug: false})
|
|
62
|
+
static toAst(txt, parser = null) {
|
|
63
|
+
let ret;
|
|
64
|
+
if (!parser) {
|
|
65
|
+
if (!ParserCache) {
|
|
66
|
+
ParserCache = new Parser(ParserRules, { debug: false });
|
|
77
67
|
}
|
|
78
|
-
parser = ParserCache
|
|
68
|
+
parser = ParserCache;
|
|
79
69
|
}
|
|
80
|
-
|
|
81
70
|
try {
|
|
82
71
|
ret = parser.getAST(txt.trim(), 'statement_main');
|
|
83
72
|
} catch (e) {
|
|
84
|
-
// If ebnf throws ParsingError, convert it to RuleParseError with helpful error code
|
|
85
73
|
if (e instanceof ParsingError) {
|
|
86
74
|
throw ErrorAnalyzer.analyzeParseFailure(txt, e);
|
|
87
75
|
}
|
|
88
76
|
throw e;
|
|
89
77
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return ret.children[0]
|
|
78
|
+
if (ret) {
|
|
79
|
+
return ret.children[0];
|
|
93
80
|
}
|
|
94
|
-
|
|
95
|
-
// If parsing failed without throwing (shouldn't happen with new ebnf), throw error
|
|
96
81
|
throw ErrorAnalyzer.analyzeParseFailure(txt);
|
|
97
82
|
}
|
|
98
|
-
static _parseArgument(argument){
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
ret.push(RuleParser._parseArgument(a))
|
|
83
|
+
static _parseArgument(argument) {
|
|
84
|
+
const child = argument.children[0];
|
|
85
|
+
return RuleParser._buildExpressionGroup(child);
|
|
86
|
+
}
|
|
87
|
+
static _parseFcall(fcall) {
|
|
88
|
+
const fname = fcall.children[0];
|
|
89
|
+
const ret = [fname.text];
|
|
90
|
+
if (fcall.children.length != 1) {
|
|
91
|
+
const args = fcall.children[1];
|
|
92
|
+
for (const a of args.children) {
|
|
93
|
+
ret.push(RuleParser._parseArgument(a));
|
|
110
94
|
}
|
|
111
95
|
}
|
|
112
|
-
return ret
|
|
96
|
+
return ret;
|
|
113
97
|
}
|
|
114
98
|
static _parseDowRange(dowRange) {
|
|
115
|
-
// dow_range can have 1 or 2 children (single day or range)
|
|
116
99
|
if (dowRange.children.length === 1) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
100
|
+
const dayText = RuleParser.__parseValue(dowRange.children[0]);
|
|
101
|
+
return {
|
|
102
|
+
start: dayText,
|
|
103
|
+
end: dayText
|
|
104
|
+
};
|
|
121
105
|
} else if (dowRange.children.length === 2) {
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
106
|
+
const startDay = RuleParser.__parseValue(dowRange.children[0]);
|
|
107
|
+
const endDay = RuleParser.__parseValue(dowRange.children[1]);
|
|
108
|
+
return {
|
|
109
|
+
start: startDay,
|
|
110
|
+
end: endDay
|
|
111
|
+
};
|
|
126
112
|
} else {
|
|
127
|
-
throw new Error(`Invalid dow_range with ${dowRange.children.length} children`);
|
|
113
|
+
throw new Error(`Invalid dow_range with ${ dowRange.children.length } children`);
|
|
128
114
|
}
|
|
129
115
|
}
|
|
130
116
|
static _addDowToTods(startTod, endTod, dowRange) {
|
|
131
117
|
if (dowRange && dowRange.type === 'dow_range') {
|
|
132
|
-
const dow = RuleParser._parseDowRange(dowRange)
|
|
133
|
-
startTod.dow = dow.start
|
|
134
|
-
endTod.dow = dow.end
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
static _parseTimePeriod(tp){
|
|
138
|
-
switch(tp.type){
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
totalSeconds += RuleParser.__parseValue(numberTime)
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
// If there's only one component, use its number and unit
|
|
158
|
-
// Otherwise, use the total in seconds and "SECONDS" as the unit
|
|
159
|
-
if (components.length === 1) {
|
|
160
|
-
return ["TimePeriodConstAgo", components[0][0], components[0][1]]
|
|
161
|
-
} else {
|
|
162
|
-
return ["TimePeriodConstAgo", totalSeconds, "SECONDS"]
|
|
118
|
+
const dow = RuleParser._parseDowRange(dowRange);
|
|
119
|
+
startTod.dow = dow.start;
|
|
120
|
+
endTod.dow = dow.end;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
static _parseTimePeriod(tp) {
|
|
124
|
+
switch (tp.type) {
|
|
125
|
+
case 'time_period_const':
|
|
126
|
+
if (tp.children && tp.children.length > 0 && tp.children[0].type === 'time_period_ago') {
|
|
127
|
+
const timePeriodAgo = tp.children[0];
|
|
128
|
+
let totalSeconds = 0;
|
|
129
|
+
const components = [];
|
|
130
|
+
for (const child of timePeriodAgo.children) {
|
|
131
|
+
if (child.type === 'number_time_atom') {
|
|
132
|
+
const numberTime = child.children[0];
|
|
133
|
+
const number = parseFloat(numberTime.children[0].text);
|
|
134
|
+
const unit = numberTime.children[1].text.toUpperCase();
|
|
135
|
+
components.push([
|
|
136
|
+
number,
|
|
137
|
+
unit
|
|
138
|
+
]);
|
|
139
|
+
totalSeconds += RuleParser.__parseValue(numberTime);
|
|
163
140
|
}
|
|
164
141
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
142
|
+
if (components.length === 1) {
|
|
143
|
+
return [
|
|
144
|
+
'TimePeriodConstAgo',
|
|
145
|
+
components[0][0],
|
|
146
|
+
components[0][1]
|
|
147
|
+
];
|
|
148
|
+
} else {
|
|
149
|
+
return [
|
|
150
|
+
'TimePeriodConstAgo',
|
|
151
|
+
totalSeconds,
|
|
152
|
+
'SECONDS'
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return [
|
|
157
|
+
'TimePeriodConst',
|
|
158
|
+
tp.text
|
|
159
|
+
];
|
|
160
|
+
case 'time_period_ago_between': {
|
|
161
|
+
let totalSeconds = 0;
|
|
162
|
+
let betweenNode = null;
|
|
163
|
+
let isBetweenTod = false;
|
|
174
164
|
for (let i = 0; i < tp.children.length; i++) {
|
|
175
165
|
if (tp.children[i].type === 'number_time_atom') {
|
|
176
|
-
|
|
177
|
-
totalSeconds += RuleParser.__parseValue(tp.children[i].children[0])
|
|
166
|
+
totalSeconds += RuleParser.__parseValue(tp.children[i].children[0]);
|
|
178
167
|
} else if (tp.children[i].type === 'between_time_only' || tp.children[i].type === 'between_time_only_atom') {
|
|
179
|
-
betweenNode = tp.children[i].type === 'between_time_only_atom' ? tp.children[i].children[0] : tp.children[i]
|
|
180
|
-
isBetweenTod = false
|
|
168
|
+
betweenNode = tp.children[i].type === 'between_time_only_atom' ? tp.children[i].children[0] : tp.children[i];
|
|
169
|
+
isBetweenTod = false;
|
|
181
170
|
} else if (tp.children[i].type === 'between_tod_only' || tp.children[i].type === 'between_tod_only_atom') {
|
|
182
|
-
betweenNode = tp.children[i].type === 'between_tod_only_atom' ? tp.children[i].children[0] : tp.children[i]
|
|
183
|
-
isBetweenTod = true
|
|
171
|
+
betweenNode = tp.children[i].type === 'between_tod_only_atom' ? tp.children[i].children[0] : tp.children[i];
|
|
172
|
+
isBetweenTod = true;
|
|
184
173
|
}
|
|
185
174
|
}
|
|
186
|
-
|
|
187
|
-
// This should always be present based on the grammar, but check defensively
|
|
188
175
|
if (!betweenNode) {
|
|
189
|
-
throw new Error('time_period_ago_between requires between_time_only or between_tod_only child')
|
|
176
|
+
throw new Error('time_period_ago_between requires between_time_only or between_tod_only child');
|
|
190
177
|
}
|
|
191
|
-
|
|
192
178
|
if (isBetweenTod) {
|
|
193
|
-
const betweenTod = betweenNode.children[0]
|
|
194
|
-
|
|
195
|
-
let
|
|
196
|
-
let endTod = RuleParser.__parseValue(betweenTod.children[1])
|
|
197
|
-
|
|
198
|
-
// Check if there's a dow_range at betweenTod.children[2]
|
|
199
|
-
// Note: startTod and endTod should always be objects from number_tod parsing
|
|
179
|
+
const betweenTod = betweenNode.children[0];
|
|
180
|
+
let startTod = RuleParser.__parseValue(betweenTod.children[0]);
|
|
181
|
+
let endTod = RuleParser.__parseValue(betweenTod.children[1]);
|
|
200
182
|
if (betweenTod.children.length > 2) {
|
|
201
|
-
RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2])
|
|
183
|
+
RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2]);
|
|
202
184
|
}
|
|
203
|
-
|
|
204
|
-
|
|
185
|
+
return [
|
|
186
|
+
'TimePeriodBetweenAgo',
|
|
187
|
+
totalSeconds,
|
|
188
|
+
startTod,
|
|
189
|
+
endTod
|
|
190
|
+
];
|
|
205
191
|
} else {
|
|
206
|
-
const betweenNumberTime = betweenNode.children[0]
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
const endValue = RuleParser.__parseValue(betweenNumberTime.children[2])
|
|
210
|
-
|
|
211
|
-
// Check if there's a dow_range at betweenNumberTime.children[3]
|
|
192
|
+
const betweenNumberTime = betweenNode.children[0];
|
|
193
|
+
const startValue = RuleParser.__parseValue(betweenNumberTime.children[0]);
|
|
194
|
+
const endValue = RuleParser.__parseValue(betweenNumberTime.children[2]);
|
|
212
195
|
if (betweenNumberTime.children.length > 3 && betweenNumberTime.children[3].type === 'dow_range') {
|
|
213
|
-
const dow = RuleParser._parseDowRange(betweenNumberTime.children[3])
|
|
196
|
+
const dow = RuleParser._parseDowRange(betweenNumberTime.children[3]);
|
|
214
197
|
if (dow.start === dow.end) {
|
|
215
|
-
|
|
216
|
-
|
|
198
|
+
return [
|
|
199
|
+
'TimePeriodBetweenAgo',
|
|
200
|
+
totalSeconds,
|
|
201
|
+
startValue,
|
|
202
|
+
endValue,
|
|
203
|
+
dow.start
|
|
204
|
+
];
|
|
217
205
|
} else {
|
|
218
|
-
|
|
219
|
-
|
|
206
|
+
return [
|
|
207
|
+
'TimePeriodBetweenAgo',
|
|
208
|
+
totalSeconds,
|
|
209
|
+
startValue,
|
|
210
|
+
endValue,
|
|
211
|
+
dow.start,
|
|
212
|
+
dow.end
|
|
213
|
+
];
|
|
220
214
|
}
|
|
221
215
|
}
|
|
222
|
-
|
|
223
|
-
|
|
216
|
+
return [
|
|
217
|
+
'TimePeriodBetweenAgo',
|
|
218
|
+
totalSeconds,
|
|
219
|
+
startValue,
|
|
220
|
+
endValue
|
|
221
|
+
];
|
|
224
222
|
}
|
|
225
223
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
let startTod = RuleParser.__parseValue(betweenTod.children[0])
|
|
231
|
-
let endTod = RuleParser.__parseValue(betweenTod.children[1])
|
|
232
|
-
|
|
233
|
-
// Check if there's a dow_range at betweenTod.children[2]
|
|
224
|
+
case 'between_tod_only': {
|
|
225
|
+
const betweenTod = tp.children[0];
|
|
226
|
+
let startTod = RuleParser.__parseValue(betweenTod.children[0]);
|
|
227
|
+
let endTod = RuleParser.__parseValue(betweenTod.children[1]);
|
|
234
228
|
if (betweenTod.children.length > 2) {
|
|
235
|
-
if(typeof startTod === 'number')
|
|
236
|
-
|
|
237
|
-
|
|
229
|
+
if (typeof startTod === 'number')
|
|
230
|
+
startTod = {
|
|
231
|
+
seconds: startTod,
|
|
232
|
+
dow: null
|
|
233
|
+
};
|
|
234
|
+
if (typeof endTod === 'number')
|
|
235
|
+
endTod = {
|
|
236
|
+
seconds: endTod,
|
|
237
|
+
dow: null
|
|
238
|
+
};
|
|
239
|
+
RuleParser._addDowToTods(startTod, endTod, betweenTod.children[2]);
|
|
238
240
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
// Check if there's a dow_range at betweenNumberTime.children[3]
|
|
250
|
-
// If DOW filters are provided, append them as additional parameters
|
|
241
|
+
return [
|
|
242
|
+
'TimePeriodBetween',
|
|
243
|
+
startTod,
|
|
244
|
+
endTod
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
case 'between_time_only': {
|
|
248
|
+
const betweenNumberTime = tp.children[0];
|
|
249
|
+
const startValue = RuleParser.__parseValue(betweenNumberTime.children[0]);
|
|
250
|
+
const endValue = RuleParser.__parseValue(betweenNumberTime.children[2]);
|
|
251
251
|
if (betweenNumberTime.children.length > 3 && betweenNumberTime.children[3].type === 'dow_range') {
|
|
252
|
-
const dow = RuleParser._parseDowRange(betweenNumberTime.children[3])
|
|
252
|
+
const dow = RuleParser._parseDowRange(betweenNumberTime.children[3]);
|
|
253
253
|
if (dow.start === dow.end) {
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
return [
|
|
255
|
+
'TimePeriodBetween',
|
|
256
|
+
startValue,
|
|
257
|
+
endValue,
|
|
258
|
+
dow.start
|
|
259
|
+
];
|
|
256
260
|
} else {
|
|
257
|
-
|
|
258
|
-
|
|
261
|
+
return [
|
|
262
|
+
'TimePeriodBetween',
|
|
263
|
+
startValue,
|
|
264
|
+
endValue,
|
|
265
|
+
dow.start,
|
|
266
|
+
dow.end
|
|
267
|
+
];
|
|
259
268
|
}
|
|
260
269
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return RuleParser.__parseValue(child.children[0])
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const str = child.text
|
|
290
|
-
return str.slice(1, -1)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const tokens = child.text.split(':')
|
|
270
|
+
return [
|
|
271
|
+
'TimePeriodBetween',
|
|
272
|
+
startValue,
|
|
273
|
+
endValue
|
|
274
|
+
];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
static __parseValue(child) {
|
|
279
|
+
const type = child.type;
|
|
280
|
+
switch (type) {
|
|
281
|
+
case 'value': {
|
|
282
|
+
return RuleParser.__parseValue(child.children[0]);
|
|
283
|
+
}
|
|
284
|
+
case 'value_atom': {
|
|
285
|
+
return RuleParser.__parseValue(child.children[0]);
|
|
286
|
+
}
|
|
287
|
+
case 'number_atom':
|
|
288
|
+
case 'number_time_atom':
|
|
289
|
+
case 'tod_atom':
|
|
290
|
+
case 'dow_atom':
|
|
291
|
+
case 'between_tod_inner':
|
|
292
|
+
case 'between_number_inner':
|
|
293
|
+
case 'between_number_time_inner':
|
|
294
|
+
case 'dow_range_inner': {
|
|
295
|
+
return RuleParser.__parseValue(child.children[0]);
|
|
296
|
+
}
|
|
297
|
+
case 'string': {
|
|
298
|
+
const str = child.text;
|
|
299
|
+
return str.slice(1, -1);
|
|
300
|
+
}
|
|
301
|
+
case 'number':
|
|
302
|
+
return parseFloat(child.text);
|
|
303
|
+
case 'number_tod': {
|
|
304
|
+
const tokens = child.text.split(':');
|
|
296
305
|
if (tokens.length !== 2) {
|
|
297
|
-
throw new Error(`Invalid time of day, ${child.text} should be ##:##`)
|
|
306
|
+
throw new Error(`Invalid time of day, ${ child.text } should be ##:##`);
|
|
298
307
|
}
|
|
299
|
-
const hours = parseInt(tokens[0])
|
|
300
|
-
const minutes = parseInt(tokens[1])
|
|
301
|
-
const tod = hours * 100 + minutes
|
|
302
|
-
const ret = {
|
|
308
|
+
const hours = parseInt(tokens[0]);
|
|
309
|
+
const minutes = parseInt(tokens[1]);
|
|
310
|
+
const tod = hours * 100 + minutes;
|
|
311
|
+
const ret = {
|
|
312
|
+
hours,
|
|
313
|
+
minutes,
|
|
314
|
+
tod
|
|
315
|
+
};
|
|
303
316
|
if (!isNaN(tod) && ret.hours >= 0 && ret.hours < 24 && ret.minutes >= 0 && ret.minutes < 60) {
|
|
304
|
-
return ret
|
|
317
|
+
return ret;
|
|
305
318
|
}
|
|
306
|
-
throw new Error(`Invalid time of day, ${child.text} -> [${tokens.join(', ')}] -> ${hours}h${minutes}m -> ${tod}`)
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const nt = child
|
|
310
|
-
const mult = parseFloat(nt.children[0].text)
|
|
311
|
-
switch(nt.children[1].text.toUpperCase()){
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
319
|
+
throw new Error(`Invalid time of day, ${ child.text } -> [${ tokens.join(', ') }] -> ${ hours }h${ minutes }m -> ${ tod }`);
|
|
320
|
+
}
|
|
321
|
+
case 'number_time': {
|
|
322
|
+
const nt = child;
|
|
323
|
+
const mult = parseFloat(nt.children[0].text);
|
|
324
|
+
switch (nt.children[1].text.toUpperCase()) {
|
|
325
|
+
case 'SECONDS':
|
|
326
|
+
case 'SECOND':
|
|
327
|
+
return mult;
|
|
328
|
+
case 'MINUTES':
|
|
329
|
+
case 'MINUTE':
|
|
330
|
+
case 'MINS':
|
|
331
|
+
case 'MIN':
|
|
332
|
+
return mult * 60;
|
|
333
|
+
case 'HOURS':
|
|
334
|
+
case 'HOUR':
|
|
335
|
+
return mult * 60 * 60;
|
|
336
|
+
case 'DAYS':
|
|
337
|
+
case 'DAY':
|
|
338
|
+
return mult * 60 * 60 * 24;
|
|
339
|
+
case 'WEEKS':
|
|
340
|
+
case 'WEEK':
|
|
341
|
+
return mult * 60 * 60 * 24 * 7;
|
|
329
342
|
}
|
|
330
|
-
throw new Error(`Invalid exponent ${nt.children[1].text}`)
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const ret = []
|
|
338
|
-
for(const c of child.children){
|
|
339
|
-
ret.push(RuleParser.__parseValue(c))
|
|
343
|
+
throw new Error(`Invalid exponent ${ nt.children[1].text }`);
|
|
344
|
+
}
|
|
345
|
+
case 'true':
|
|
346
|
+
return true;
|
|
347
|
+
case 'false':
|
|
348
|
+
return false;
|
|
349
|
+
case 'array': {
|
|
350
|
+
const ret = [];
|
|
351
|
+
for (const c of child.children) {
|
|
352
|
+
ret.push(RuleParser.__parseValue(c));
|
|
340
353
|
}
|
|
341
354
|
return ret;
|
|
342
355
|
}
|
|
343
|
-
|
|
344
|
-
return normalizeDow(child.text)
|
|
356
|
+
case 'dow': {
|
|
357
|
+
return normalizeDow(child.text);
|
|
345
358
|
}
|
|
346
|
-
|
|
347
|
-
|
|
359
|
+
default:
|
|
360
|
+
throw new Error(`Unknown value type ${ type }`);
|
|
348
361
|
}
|
|
349
362
|
}
|
|
350
|
-
static _parseValue(value){
|
|
351
|
-
const child = value.children[0]
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
// New layer: unwrap value_atom to get the actual atomic type
|
|
357
|
-
const atomChild = child.children[0]
|
|
363
|
+
static _parseValue(value) {
|
|
364
|
+
const child = value.children[0];
|
|
365
|
+
const type = child.type;
|
|
366
|
+
switch (type) {
|
|
367
|
+
case 'value_atom': {
|
|
368
|
+
const atomChild = child.children[0];
|
|
358
369
|
if (atomChild.type === 'time_period') {
|
|
359
|
-
const tp = atomChild.children[0]
|
|
360
|
-
return RuleParser._parseTimePeriod(tp)
|
|
370
|
+
const tp = atomChild.children[0];
|
|
371
|
+
return RuleParser._parseTimePeriod(tp);
|
|
361
372
|
}
|
|
362
|
-
return [
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
switch(type){
|
|
378
|
-
case 'fcall':
|
|
379
|
-
return RuleParser._parseFcall(child)
|
|
380
|
-
case 'value':
|
|
381
|
-
return RuleParser._parseValue(child)
|
|
382
|
-
}
|
|
383
|
-
return null
|
|
384
|
-
}
|
|
385
|
-
static _parseArithmeticOperand(operand){
|
|
386
|
-
assert(operand.children.length == 1)
|
|
387
|
-
const child = operand.children[0]
|
|
388
|
-
const type = child.type
|
|
389
|
-
switch(type){
|
|
390
|
-
case 'fcall':
|
|
391
|
-
return RuleParser._parseFcall(child)
|
|
392
|
-
case 'number_atom':
|
|
393
|
-
case 'number_time_atom': {
|
|
394
|
-
// New layer: unwrap atom wrappers to get the actual leaf nodes
|
|
395
|
-
return ['Value', RuleParser.__parseValue(child.children[0])]
|
|
396
|
-
}
|
|
397
|
-
case 'number':
|
|
398
|
-
return ['Value', parseFloat(child.text)]
|
|
399
|
-
case 'number_time':
|
|
400
|
-
return ['Value', RuleParser.__parseValue(child)]
|
|
401
|
-
}
|
|
402
|
-
throw new Error(`Unknown arithmetic operand type ${type}`)
|
|
403
|
-
}
|
|
404
|
-
static _isConstantValue(expr){
|
|
405
|
-
// Check if an expression is a constant value (not just numbers, but any literal)
|
|
406
|
-
return Array.isArray(expr) && expr.length === 2 && expr[0] === 'Value'
|
|
373
|
+
return [
|
|
374
|
+
'Value',
|
|
375
|
+
RuleParser.__parseValue(atomChild)
|
|
376
|
+
];
|
|
377
|
+
}
|
|
378
|
+
case 'time_period': {
|
|
379
|
+
const tp = child.children[0];
|
|
380
|
+
return RuleParser._parseTimePeriod(tp);
|
|
381
|
+
}
|
|
382
|
+
default:
|
|
383
|
+
return [
|
|
384
|
+
'Value',
|
|
385
|
+
RuleParser.__parseValue(child)
|
|
386
|
+
];
|
|
387
|
+
}
|
|
407
388
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
389
|
+
static _parseSimpleResult(result) {
|
|
390
|
+
const child = result.children[0];
|
|
391
|
+
const type = child.type;
|
|
392
|
+
switch (type) {
|
|
393
|
+
case 'fcall':
|
|
394
|
+
return RuleParser._parseFcall(child);
|
|
395
|
+
case 'value':
|
|
396
|
+
return RuleParser._parseValue(child);
|
|
397
|
+
}
|
|
398
|
+
return null;
|
|
412
399
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
switch(
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
400
|
+
static _parseArithmeticOperand(operand) {
|
|
401
|
+
const child = operand.children[0];
|
|
402
|
+
const type = child.type;
|
|
403
|
+
switch (type) {
|
|
404
|
+
case 'fcall':
|
|
405
|
+
return RuleParser._parseFcall(child);
|
|
406
|
+
case 'number_atom':
|
|
407
|
+
case 'number_time_atom': {
|
|
408
|
+
return [
|
|
409
|
+
'Value',
|
|
410
|
+
RuleParser.__parseValue(child.children[0])
|
|
411
|
+
];
|
|
412
|
+
}
|
|
413
|
+
case 'number':
|
|
414
|
+
return [
|
|
415
|
+
'Value',
|
|
416
|
+
parseFloat(child.text)
|
|
417
|
+
];
|
|
418
|
+
case 'number_time':
|
|
419
|
+
return [
|
|
420
|
+
'Value',
|
|
421
|
+
RuleParser.__parseValue(child)
|
|
422
|
+
];
|
|
423
|
+
}
|
|
424
|
+
throw new Error(`Unknown arithmetic operand type ${ type }`);
|
|
425
|
+
}
|
|
426
|
+
static _isConstantValue(expr) {
|
|
427
|
+
return Array.isArray(expr) && expr.length === 2 && expr[0] === 'Value';
|
|
428
|
+
}
|
|
429
|
+
static _isConstantNumberValue(expr) {
|
|
430
|
+
return Array.isArray(expr) && expr.length === 2 && expr[0] === 'Value' && typeof expr[1] === 'number';
|
|
431
|
+
}
|
|
432
|
+
static _evaluateConstantArithmetic(operator, leftValue, rightValue) {
|
|
433
|
+
switch (operator) {
|
|
434
|
+
case 'MathAdd':
|
|
435
|
+
return leftValue + rightValue;
|
|
436
|
+
case 'MathSub':
|
|
437
|
+
return leftValue - rightValue;
|
|
438
|
+
case 'MathMul':
|
|
439
|
+
return leftValue * rightValue;
|
|
440
|
+
case 'MathDiv':
|
|
441
|
+
return leftValue / rightValue;
|
|
442
|
+
case 'MathMod':
|
|
443
|
+
return leftValue % rightValue;
|
|
444
|
+
default:
|
|
445
|
+
return null;
|
|
429
446
|
}
|
|
430
447
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
const
|
|
435
|
-
const operatorFn = ArithmeticOperators[result.children[1].text]
|
|
436
|
-
const partB = RuleParser.__parseArithmeticResult(result, 2)
|
|
437
|
-
|
|
438
|
-
// Compile out constant expressions
|
|
448
|
+
static _parseArithmeticResult(result) {
|
|
449
|
+
const partA = RuleParser._parseArithmeticOperand(result.children[0]);
|
|
450
|
+
const operatorFn = ArithmeticOperators[result.children[1].text];
|
|
451
|
+
const partB = RuleParser.__parseArithmeticResult(result, 2);
|
|
439
452
|
if (RuleParser._isConstantNumberValue(partA) && RuleParser._isConstantNumberValue(partB)) {
|
|
440
|
-
const result = RuleParser._evaluateConstantArithmetic(operatorFn, partA[1], partB[1])
|
|
453
|
+
const result = RuleParser._evaluateConstantArithmetic(operatorFn, partA[1], partB[1]);
|
|
441
454
|
if (result !== null) {
|
|
442
|
-
return [
|
|
455
|
+
return [
|
|
456
|
+
'Value',
|
|
457
|
+
result
|
|
458
|
+
];
|
|
443
459
|
}
|
|
444
460
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
461
|
+
return [
|
|
462
|
+
operatorFn,
|
|
463
|
+
partA,
|
|
464
|
+
partB
|
|
465
|
+
];
|
|
466
|
+
}
|
|
467
|
+
static __parseArithmeticResult(result, idx) {
|
|
468
|
+
const child = result.children[idx];
|
|
469
|
+
const type = child.type;
|
|
470
|
+
switch (type) {
|
|
471
|
+
case 'arithmetic_operand':
|
|
472
|
+
return RuleParser._parseArithmeticOperand(child);
|
|
473
|
+
case 'arithmetic_result':
|
|
474
|
+
return RuleParser._parseArithmeticResult(child);
|
|
457
475
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
case 'arithmetic_result':
|
|
469
|
-
return RuleParser._parseArithmeticResult(child)
|
|
476
|
+
throw new Error(`Unknown arithmetic result node ${ type }`);
|
|
477
|
+
}
|
|
478
|
+
static __parseResult(result, idx) {
|
|
479
|
+
const child = result.children[idx];
|
|
480
|
+
const type = child.type;
|
|
481
|
+
switch (type) {
|
|
482
|
+
case 'simple_result':
|
|
483
|
+
return RuleParser._parseSimpleResult(child);
|
|
484
|
+
case 'arithmetic_result':
|
|
485
|
+
return RuleParser._parseArithmeticResult(child);
|
|
470
486
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
switch(rhs.type){
|
|
487
|
-
case 'between_tod': {
|
|
488
|
-
// Direct between_tod (without wrapping between node)
|
|
489
|
-
// between_tod has inline separator, so: children[0] = first tod_inner, children[1] = second tod_inner, children[2] = optional dow_range
|
|
490
|
-
const startTod = RuleParser.__parseValue(rhs.children[0])
|
|
491
|
-
const endTod = RuleParser.__parseValue(rhs.children[1])
|
|
492
|
-
|
|
493
|
-
// Check if there's a dow_range (children[2])
|
|
487
|
+
throw new Error(`Unknown result node ${ type }`);
|
|
488
|
+
}
|
|
489
|
+
static _parseResult(result) {
|
|
490
|
+
return RuleParser.__parseResult(result, 0);
|
|
491
|
+
}
|
|
492
|
+
static _parseStdExpression(expr) {
|
|
493
|
+
switch (expr.children.length) {
|
|
494
|
+
case 1:
|
|
495
|
+
return RuleParser._parseResult(expr.children[0]);
|
|
496
|
+
case 2: {
|
|
497
|
+
const rhs = expr.children[1];
|
|
498
|
+
switch (rhs.type) {
|
|
499
|
+
case 'between_tod': {
|
|
500
|
+
const startTod = RuleParser.__parseValue(rhs.children[0]);
|
|
501
|
+
const endTod = RuleParser.__parseValue(rhs.children[1]);
|
|
494
502
|
if (rhs.children.length > 2) {
|
|
495
|
-
RuleParser._addDowToTods(startTod, endTod, rhs.children[2])
|
|
503
|
+
RuleParser._addDowToTods(startTod, endTod, rhs.children[2]);
|
|
496
504
|
}
|
|
497
|
-
|
|
498
|
-
|
|
505
|
+
return [
|
|
506
|
+
'Between',
|
|
507
|
+
RuleParser._parseResult(expr.children[0]),
|
|
508
|
+
[
|
|
509
|
+
'Value',
|
|
510
|
+
startTod
|
|
511
|
+
],
|
|
512
|
+
[
|
|
513
|
+
'Value',
|
|
514
|
+
endTod
|
|
515
|
+
]
|
|
516
|
+
];
|
|
499
517
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
const betweenChild = rhs.children[0]
|
|
518
|
+
case 'between': {
|
|
519
|
+
const betweenChild = rhs.children[0];
|
|
503
520
|
if (betweenChild.type === 'between_tod') {
|
|
504
|
-
|
|
505
|
-
const
|
|
506
|
-
const endTod = RuleParser.__parseValue(betweenChild.children[1])
|
|
507
|
-
|
|
508
|
-
// Check if there's a dow_range (children[2])
|
|
521
|
+
const startTod = RuleParser.__parseValue(betweenChild.children[0]);
|
|
522
|
+
const endTod = RuleParser.__parseValue(betweenChild.children[1]);
|
|
509
523
|
if (betweenChild.children.length > 2) {
|
|
510
|
-
RuleParser._addDowToTods(startTod, endTod, betweenChild.children[2])
|
|
524
|
+
RuleParser._addDowToTods(startTod, endTod, betweenChild.children[2]);
|
|
511
525
|
}
|
|
512
|
-
|
|
513
|
-
|
|
526
|
+
return [
|
|
527
|
+
'Between',
|
|
528
|
+
RuleParser._parseResult(expr.children[0]),
|
|
529
|
+
[
|
|
530
|
+
'Value',
|
|
531
|
+
startTod
|
|
532
|
+
],
|
|
533
|
+
[
|
|
534
|
+
'Value',
|
|
535
|
+
endTod
|
|
536
|
+
]
|
|
537
|
+
];
|
|
514
538
|
} else {
|
|
515
|
-
|
|
516
|
-
|
|
539
|
+
return [
|
|
540
|
+
'Between',
|
|
541
|
+
RuleParser._parseResult(expr.children[0]),
|
|
542
|
+
[
|
|
543
|
+
'Value',
|
|
544
|
+
RuleParser.__parseValue(betweenChild.children[0])
|
|
545
|
+
],
|
|
546
|
+
[
|
|
547
|
+
'Value',
|
|
548
|
+
RuleParser.__parseValue(betweenChild.children[2])
|
|
549
|
+
]
|
|
550
|
+
];
|
|
517
551
|
}
|
|
518
552
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
553
|
+
case 'between_number':
|
|
554
|
+
return [
|
|
555
|
+
'Between',
|
|
556
|
+
RuleParser._parseResult(expr.children[0]),
|
|
557
|
+
[
|
|
558
|
+
'Value',
|
|
559
|
+
RuleParser.__parseValue(rhs.children[0].children[0])
|
|
560
|
+
],
|
|
561
|
+
[
|
|
562
|
+
'Value',
|
|
563
|
+
RuleParser.__parseValue(rhs.children[0].children[2])
|
|
564
|
+
]
|
|
565
|
+
];
|
|
566
|
+
case 'basic_rhs':
|
|
567
|
+
return [
|
|
568
|
+
OperatorFn[rhs.children[0].text],
|
|
569
|
+
RuleParser._parseResult(expr.children[0]),
|
|
570
|
+
RuleParser._parseResult(rhs.children[1])
|
|
571
|
+
];
|
|
572
|
+
case 'eq_approx': {
|
|
573
|
+
const rhsValue = RuleParser._parseResult(rhs.children[1]);
|
|
574
|
+
const ret = [
|
|
575
|
+
'Between',
|
|
576
|
+
RuleParser._parseResult(expr.children[0]),
|
|
577
|
+
[
|
|
578
|
+
'Value',
|
|
579
|
+
rhsValue[1] - Epsilon
|
|
580
|
+
],
|
|
581
|
+
[
|
|
582
|
+
'Value',
|
|
583
|
+
rhsValue[1] + Epsilon
|
|
584
|
+
]
|
|
585
|
+
];
|
|
586
|
+
if (rhs.children[0].text === '!=') {
|
|
587
|
+
return [
|
|
588
|
+
'Not',
|
|
589
|
+
ret
|
|
590
|
+
];
|
|
530
591
|
}
|
|
531
|
-
return ret
|
|
592
|
+
return ret;
|
|
532
593
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const args = rhs.children[0]
|
|
539
|
-
const haystack = []
|
|
540
|
-
for(const a of args.children){
|
|
541
|
-
haystack.push(RuleParser._parseArgument(a))
|
|
594
|
+
case 'in_expr': {
|
|
595
|
+
const args = rhs.children[0];
|
|
596
|
+
const haystack = [];
|
|
597
|
+
for (const a of args.children) {
|
|
598
|
+
haystack.push(RuleParser._parseArgument(a));
|
|
542
599
|
}
|
|
543
|
-
const needle = RuleParser._parseResult(expr.children[0])
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
const allConstants = haystack.every(item => RuleParser._isConstantValue(item))
|
|
547
|
-
|
|
548
|
-
let haystackExpr
|
|
600
|
+
const needle = RuleParser._parseResult(expr.children[0]);
|
|
601
|
+
const allConstants = haystack.every(item => RuleParser._isConstantValue(item));
|
|
602
|
+
let haystackExpr;
|
|
549
603
|
if (allConstants) {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
604
|
+
const constantArray = haystack.map(item => item[1]);
|
|
605
|
+
haystackExpr = [
|
|
606
|
+
'Value',
|
|
607
|
+
constantArray
|
|
608
|
+
];
|
|
553
609
|
} else {
|
|
554
|
-
|
|
555
|
-
|
|
610
|
+
haystackExpr = [
|
|
611
|
+
'Array',
|
|
612
|
+
...haystack
|
|
613
|
+
];
|
|
556
614
|
}
|
|
557
|
-
|
|
558
|
-
|
|
615
|
+
return [
|
|
616
|
+
'ArrayIn',
|
|
617
|
+
haystackExpr,
|
|
618
|
+
needle
|
|
619
|
+
];
|
|
559
620
|
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
throw new Error(`unable to parse std expression, unknown rhs type ${rhs.type}`)
|
|
621
|
+
default:
|
|
622
|
+
throw new Error(`unable to parse std expression, unknown rhs type ${ rhs.type }`);
|
|
563
623
|
}
|
|
564
624
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
625
|
+
default:
|
|
626
|
+
throw new Error(`unable to parse std expression, unknown number of children ${ expr.children.length }`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
static buildLogical(members, fn) {
|
|
630
|
+
return [
|
|
631
|
+
fn,
|
|
632
|
+
...members
|
|
633
|
+
];
|
|
634
|
+
}
|
|
635
|
+
static _buildExpressionGroup(ast) {
|
|
636
|
+
let ret = [];
|
|
637
|
+
let currentLogical = null;
|
|
638
|
+
for (const expr of ast.children) {
|
|
639
|
+
if (expr.type == 'logical_operator') {
|
|
640
|
+
const logicalOperator = expr.text.trim();
|
|
641
|
+
const operatorFn = LogicalOperators[logicalOperator.toUpperCase()];
|
|
642
|
+
if (currentLogical === null || currentLogical !== operatorFn) {
|
|
643
|
+
if (ret.length > 1) {
|
|
644
|
+
ret = [RuleParser.buildLogical(ret, currentLogical)];
|
|
584
645
|
}
|
|
585
|
-
currentLogical = operatorFn
|
|
646
|
+
currentLogical = operatorFn;
|
|
586
647
|
}
|
|
587
|
-
}else{
|
|
588
|
-
ret.push(RuleParser._exprToIL(expr))
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
if(ret.length == 0){
|
|
592
|
-
throw new Error('invalid rule')
|
|
593
|
-
}
|
|
594
|
-
if(ret.length == 1){
|
|
595
|
-
return ret[0]
|
|
596
|
-
}
|
|
597
|
-
return RuleParser.buildLogical(ret, currentLogical)
|
|
598
|
-
}
|
|
599
|
-
static _parseParenthesisExpression(expr){
|
|
600
|
-
return RuleParser._buildExpressionGroup(expr.children[0])
|
|
601
|
-
}
|
|
602
|
-
static _exprToIL(expr){
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
default:
|
|
617
|
-
result = RuleParser._parseResult(child)
|
|
648
|
+
} else {
|
|
649
|
+
ret.push(RuleParser._exprToIL(expr));
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
if (ret.length == 0) {
|
|
653
|
+
throw new Error('invalid rule');
|
|
654
|
+
}
|
|
655
|
+
if (ret.length == 1) {
|
|
656
|
+
return ret[0];
|
|
657
|
+
}
|
|
658
|
+
return RuleParser.buildLogical(ret, currentLogical);
|
|
659
|
+
}
|
|
660
|
+
static _parseParenthesisExpression(expr) {
|
|
661
|
+
return RuleParser._buildExpressionGroup(expr.children[0]);
|
|
662
|
+
}
|
|
663
|
+
static _exprToIL(expr) {
|
|
664
|
+
const eInner = expr.children[0];
|
|
665
|
+
switch (eInner.type) {
|
|
666
|
+
case 'standard_expression':
|
|
667
|
+
return RuleParser._parseStdExpression(eInner);
|
|
668
|
+
case 'not_expression': {
|
|
669
|
+
const child = eInner.children[0];
|
|
670
|
+
let result;
|
|
671
|
+
switch (child.type) {
|
|
672
|
+
case 'parenthesis_expression':
|
|
673
|
+
result = RuleParser._parseParenthesisExpression(child);
|
|
674
|
+
break;
|
|
675
|
+
default:
|
|
676
|
+
result = RuleParser._parseResult(child);
|
|
618
677
|
}
|
|
619
|
-
return [
|
|
678
|
+
return [
|
|
679
|
+
'Not',
|
|
680
|
+
result
|
|
681
|
+
];
|
|
620
682
|
}
|
|
621
|
-
|
|
622
|
-
return RuleParser._parseParenthesisExpression(eInner)
|
|
623
|
-
|
|
624
|
-
|
|
683
|
+
case 'parenthesis_expression':
|
|
684
|
+
return RuleParser._parseParenthesisExpression(eInner);
|
|
685
|
+
default:
|
|
686
|
+
throw new Error(`unknown type of expression ${ eInner.type }`);
|
|
625
687
|
}
|
|
626
688
|
}
|
|
627
|
-
static toIL(txt){
|
|
689
|
+
static toIL(txt) {
|
|
628
690
|
try {
|
|
629
|
-
const ast = RuleParser.toAst(txt)
|
|
630
|
-
if(!ast)
|
|
631
|
-
|
|
691
|
+
const ast = RuleParser.toAst(txt);
|
|
692
|
+
if (!ast)
|
|
693
|
+
throw new Error(`failed to parse ${ txt }`);
|
|
694
|
+
return RuleParser._buildExpressionGroup(ast);
|
|
632
695
|
} catch (e) {
|
|
633
|
-
// If it's already a RuleParseError, just re-throw it
|
|
634
696
|
if (e.name === 'RuleParseError') {
|
|
635
697
|
throw e;
|
|
636
698
|
}
|
|
637
|
-
|
|
638
|
-
// Check if it's a validation error we can map to a specific code
|
|
639
699
|
if (e.message && e.message.includes('Invalid time of day')) {
|
|
640
|
-
// Extract the invalid time from the error message
|
|
641
700
|
const match = e.message.match(/Invalid time of day[,:]?\s*([0-9:]+)/);
|
|
642
701
|
const badTod = match ? match[1] : 'invalid';
|
|
643
|
-
|
|
644
|
-
// Calculate position (simplified - at end of input)
|
|
645
702
|
const lines = txt.trim().split('\n');
|
|
646
703
|
const position = {
|
|
647
704
|
line: lines.length,
|
|
648
705
|
column: lines[lines.length - 1].length + 1,
|
|
649
706
|
offset: txt.trim().length
|
|
650
707
|
};
|
|
651
|
-
|
|
652
|
-
throw new RuleParseError(
|
|
653
|
-
"BAD_TOD",
|
|
654
|
-
`Invalid time of day: ${badTod}`,
|
|
655
|
-
"Time of day must be in HH:MM format with hours 0-23 and minutes 0-59, e.g. 08:30, 14:00, 23:59.",
|
|
656
|
-
position,
|
|
657
|
-
badTod,
|
|
658
|
-
["HH:MM"],
|
|
659
|
-
txt.trim().substring(Math.max(0, txt.trim().length - 50))
|
|
660
|
-
);
|
|
708
|
+
throw new RuleParseError('BAD_TOD', `Invalid time of day: ${ badTod }`, 'Time of day must be in HH:MM format with hours 0-23 and minutes 0-59, e.g. 08:30, 14:00, 23:59.', position, badTod, ['HH:MM'], txt.trim().substring(Math.max(0, txt.trim().length - 50)));
|
|
661
709
|
}
|
|
662
|
-
|
|
663
|
-
// Check if it's a day of week error
|
|
664
710
|
if (e.message && e.message.includes('Invalid day of week')) {
|
|
665
711
|
const match = e.message.match(/Invalid day of week[,:]?\s*(\w+)/);
|
|
666
712
|
const badDow = match ? match[1] : 'invalid';
|
|
667
|
-
|
|
668
713
|
const lines = txt.trim().split('\n');
|
|
669
714
|
const position = {
|
|
670
715
|
line: lines.length,
|
|
671
716
|
column: lines[lines.length - 1].length + 1,
|
|
672
717
|
offset: txt.trim().length
|
|
673
718
|
};
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
);
|
|
719
|
+
throw new RuleParseError('BAD_DOW', `Invalid day of week: ${ badDow }`, 'Valid days are: MONDAY/MON, TUESDAY/TUE, WEDNESDAY/WED, THURSDAY/THU, FRIDAY/FRI, SATURDAY/SAT, SUNDAY/SUN.', position, badDow, [
|
|
720
|
+
'MONDAY',
|
|
721
|
+
'TUESDAY',
|
|
722
|
+
'WEDNESDAY',
|
|
723
|
+
'THURSDAY',
|
|
724
|
+
'FRIDAY',
|
|
725
|
+
'SATURDAY',
|
|
726
|
+
'SUNDAY'
|
|
727
|
+
], txt.trim().substring(Math.max(0, txt.trim().length - 50)));
|
|
684
728
|
}
|
|
685
|
-
|
|
686
|
-
// For other errors, re-throw
|
|
687
729
|
throw e;
|
|
688
730
|
}
|
|
689
731
|
}
|
|
690
732
|
}
|
|
691
|
-
module.exports = RuleParser
|
|
692
|
-
module.exports.ParserRules = ParserRules
|
|
693
|
-
module.exports.ParsingError = ParsingError
|
|
694
|
-
module.exports.RuleParseError = RuleParseError
|
|
695
|
-
|
|
696
|
-
},{"./RuleParser.production.ebnf.js":1,"./errors/ErrorAnalyzer":3,"./errors/RuleParseError":4,"assert":undefined,"ebnf":13,"ebnf/dist/Parser.js":9}],3:[function(require,module,exports){
|
|
733
|
+
module.exports = RuleParser;
|
|
734
|
+
module.exports.ParserRules = ParserRules;
|
|
735
|
+
module.exports.ParsingError = ParsingError;
|
|
736
|
+
module.exports.RuleParseError = RuleParseError;
|
|
737
|
+
},{"./RuleParser.production.ebnf.js":1,"./errors/ErrorAnalyzer":3,"./errors/RuleParseError":4,"ebnf":13,"ebnf/dist/Parser.js":9}],3:[function(require,module,exports){
|
|
697
738
|
const { ParsingError } = require('ebnf');
|
|
698
739
|
const RuleParseError = require('./RuleParseError');
|
|
699
740
|
|