fable 3.1.32 → 3.1.34
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/fable.js +471 -371
- package/dist/fable.js.map +1 -1
- package/dist/fable.min.js +2 -2
- package/dist/fable.min.js.map +1 -1
- package/example_applications/mathematical_playground/README.md +27 -0
- package/package.json +2 -2
- package/source/Fable.js +0 -1
- package/source/services/Fable-Service-CSVParser.js +177 -177
- package/source/services/Fable-Service-DataFormat.js +22 -22
- package/source/services/Fable-Service-DataGeneration.js +161 -161
- package/source/services/Fable-Service-DateManipulation.js +209 -209
- package/source/services/Fable-Service-EnvironmentData-Web.js +3 -3
- package/source/services/Fable-Service-EnvironmentData.js +3 -3
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer-DirectiveMutation.js +136 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js +6 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +39 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js +2 -2
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json +9 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ValueMarshal.js +3 -3
- package/source/services/Fable-Service-ExpressionParser.js +154 -22
- package/source/services/Fable-Service-FilePersistence.js +2 -2
- package/source/services/Fable-Service-Logic.js +1 -1
- package/source/services/Fable-Service-Math.js +293 -57
- package/source/services/Fable-Service-MetaTemplate.js +2 -2
- package/source/services/Fable-Service-Operation.js +7 -7
- package/source/services/Fable-Service-ProgressTime.js +3 -3
- package/source/services/Fable-Service-RestClient.js +2 -2
- package/source/services/Fable-Service-Template.js +4 -4
- package/source/services/Fable-Service-Utility.js +6 -6
- package/test/ExpressionParser_tests.js +67 -0
- package/test/Math_test.js +81 -1
- package/source/services/Fable-Service-ExpressionParser/RNI_Randy.json +0 -1
- package/source/services/Fable-Service-ExpressionParser/RNI_Tool.json +0 -1
|
@@ -6,225 +6,225 @@ const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
|
6
6
|
*/
|
|
7
7
|
class DateManipulation extends libFableServiceProviderBase
|
|
8
8
|
{
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
10
|
+
{
|
|
11
|
+
super(pFable, pOptions, pServiceHash)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
this.serviceType = 'Dates';
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
this.dayJS = require('dayjs');
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
17
|
+
// Include the `weekOfYear` plugin
|
|
18
|
+
this.plugin_weekOfYear = require('dayjs/plugin/weekOfYear');
|
|
19
|
+
this.dayJS.extend(this.plugin_weekOfYear);
|
|
20
|
+
// Include the `weekday` plugin
|
|
21
|
+
this.plugin_weekday = require('dayjs/plugin/weekday');
|
|
22
|
+
this.dayJS.extend(this.plugin_weekday);
|
|
23
|
+
// Include the `isoWeek` plugin
|
|
24
|
+
this.plugin_isoWeek = require('dayjs/plugin/isoWeek');
|
|
25
|
+
this.dayJS.extend(this.plugin_isoWeek);
|
|
26
|
+
// Include the `timezone` plugin
|
|
27
|
+
this.plugin_timezone = require('dayjs/plugin/timezone');
|
|
28
|
+
this.dayJS.extend(this.plugin_timezone);
|
|
29
|
+
// Include the `relativetime` plugin
|
|
30
|
+
this.plugin_relativetime = require('dayjs/plugin/relativeTime');
|
|
31
|
+
this.dayJS.extend(this.plugin_relativetime);
|
|
32
|
+
// Include the `utc` plugin
|
|
33
|
+
this.plugin_utc = require('dayjs/plugin/utc');
|
|
34
|
+
this.dayJS.extend(this.plugin_utc);
|
|
35
|
+
// Include the `advancedFormat` plugin
|
|
36
|
+
this.plugin_advancedFormat = require('dayjs/plugin/advancedFormat');
|
|
37
|
+
this.dayJS.extend(this.plugin_advancedFormat);
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
// A developer can include locales if they want
|
|
40
|
+
// You would do the following:
|
|
41
|
+
// const localeDE = require('dayjs/locale/de');
|
|
42
|
+
// _Fable.Dates.dayJS.locale('de');
|
|
43
|
+
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Calculates the difference in milliseconds between two dates.
|
|
47
|
+
*
|
|
48
|
+
* @param {string|Date|number} pDateStart - The start date. Can be a string, Date object, or timestamp.
|
|
49
|
+
* @param {string|Date|number} pDateEnd - The end date. Can be a string, Date object, or timestamp. Defaults to the current date if not provided.
|
|
50
|
+
* @param {boolean} pRequireEndDate - If true, the end date must be provided; otherwise, it defaults to the current date.
|
|
51
|
+
* @returns {number} The difference in milliseconds between the start and end dates. Returns NaN if the start date is invalid.
|
|
52
|
+
*/
|
|
53
|
+
dateMillisecondDifference(pDateStart, pDateEnd, pRequireEndDate = false)
|
|
54
|
+
{
|
|
55
|
+
if ((pDateStart === undefined) || (pDateStart === null) || (pDateStart === ''))
|
|
56
|
+
{
|
|
57
|
+
return NaN;
|
|
58
|
+
}
|
|
59
|
+
if ((pRequireEndDate || (pRequireEndDate == 1) || (pRequireEndDate == '1')) && ((pDateEnd === undefined) || (pDateEnd === null) || (pDateEnd === '')))
|
|
60
|
+
{
|
|
61
|
+
return NaN;
|
|
62
|
+
}
|
|
63
|
+
let tmpStartDate = this.dayJS(pDateStart);
|
|
64
|
+
let tmpEndDate = this.dayJS(pDateEnd);
|
|
65
|
+
return tmpEndDate.diff(tmpStartDate, 'millisecond');
|
|
66
|
+
}
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Calculates the difference in seconds between two dates.
|
|
70
|
+
*
|
|
71
|
+
* @param {string|Date|number} pDateStart - The start date. Can be a string, Date object, or timestamp.
|
|
72
|
+
* @param {string|Date|number} pDateEnd - The end date. Can be a string, Date object, or timestamp. Defaults to the current date if not provided.
|
|
73
|
+
* @param {boolean} pRequireEndDate - If true, the end date must be provided; otherwise, it defaults to the current date.
|
|
74
|
+
* @returns {number} The difference in seconds between the start and end dates. Returns NaN if the start date is invalid.
|
|
75
|
+
*/
|
|
76
|
+
dateSecondDifference(pDateStart, pDateEnd, pRequireEndDate = false)
|
|
77
|
+
{
|
|
78
|
+
if ((pDateStart === undefined) || (pDateStart === null) || (pDateStart === ''))
|
|
79
|
+
{
|
|
80
|
+
return NaN;
|
|
81
|
+
}
|
|
82
|
+
if ((pRequireEndDate || (pRequireEndDate == 1) || (pRequireEndDate == '1')) && ((pDateEnd === undefined) || (pDateEnd === null) || (pDateEnd === '')))
|
|
83
|
+
{
|
|
84
|
+
return NaN;
|
|
85
|
+
}
|
|
86
|
+
let tmpStartDate = this.dayJS(pDateStart);
|
|
87
|
+
let tmpEndDate = this.dayJS(pDateEnd);
|
|
88
|
+
return tmpEndDate.diff(tmpStartDate, 'second');
|
|
89
|
+
}
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Calculates the difference in minutes between two dates.
|
|
93
|
+
*
|
|
94
|
+
* @param {string|Date|number} pDateStart - The start date. Can be a string, Date object, or timestamp.
|
|
95
|
+
* @param {string|Date|number} pDateEnd - The end date. Can be a string, Date object, or timestamp. Defaults to the current date if not provided.
|
|
96
|
+
* @param {boolean} pRequireEndDate - If true, the end date must be provided; otherwise, it defaults to the current date.
|
|
97
|
+
* @returns {number} The difference in minutes between the start and end dates. Returns NaN if the start date is invalid.
|
|
98
|
+
*/
|
|
99
|
+
dateMinuteDifference(pDateStart, pDateEnd, pRequireEndDate = false)
|
|
100
|
+
{
|
|
101
|
+
if ((pDateStart === undefined) || (pDateStart === null) || (pDateStart === ''))
|
|
102
|
+
{
|
|
103
|
+
return NaN;
|
|
104
|
+
}
|
|
105
|
+
if ((pRequireEndDate || (pRequireEndDate == 1) || (pRequireEndDate == '1')) && ((pDateEnd === undefined) || (pDateEnd === null) || (pDateEnd === '')))
|
|
106
|
+
{
|
|
107
|
+
return NaN;
|
|
108
|
+
}
|
|
109
|
+
let tmpStartDate = this.dayJS(pDateStart);
|
|
110
|
+
let tmpEndDate = this.dayJS(pDateEnd);
|
|
111
|
+
return tmpEndDate.diff(tmpStartDate, 'minute');
|
|
112
|
+
}
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Calculates the difference in hours between two dates.
|
|
116
|
+
*
|
|
117
|
+
* @param {string|Date|number} pDateStart - The start date. Can be a string, Date object, or timestamp.
|
|
118
|
+
* @param {string|Date|number} pDateEnd - The end date. Can be a string, Date object, or timestamp. Defaults to the current date if not provided.
|
|
119
|
+
* @param {boolean} pRequireEndDate - If true, the end date must be provided; otherwise, it defaults to the current date.
|
|
120
|
+
* @returns {number} The difference in hours between the start and end dates. Returns NaN if the start date is invalid.
|
|
121
|
+
*/
|
|
122
|
+
dateHourDifference(pDateStart, pDateEnd, pRequireEndDate = false)
|
|
123
|
+
{
|
|
124
|
+
if ((pDateStart === undefined) || (pDateStart === null) || (pDateStart === ''))
|
|
125
|
+
{
|
|
126
|
+
return NaN;
|
|
127
|
+
}
|
|
128
|
+
if ((pRequireEndDate || (pRequireEndDate == 1) || (pRequireEndDate == '1')) && ((pDateEnd === undefined) || (pDateEnd === null) || (pDateEnd === '')))
|
|
129
|
+
{
|
|
130
|
+
return NaN;
|
|
131
|
+
}
|
|
132
|
+
let tmpStartDate = this.dayJS(pDateStart);
|
|
133
|
+
let tmpEndDate = this.dayJS(pDateEnd);
|
|
134
|
+
return tmpEndDate.diff(tmpStartDate, 'hour');
|
|
135
|
+
}
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Calculates the difference in days between two dates.
|
|
139
|
+
*
|
|
140
|
+
* @param {string|Date|number} pDateStart - The start date. Can be a string, Date object, or timestamp.
|
|
141
|
+
* @param {string|Date|number} pDateEnd - The end date. Can be a string, Date object, or timestamp. Defaults to the current date if not provided.
|
|
142
|
+
* @param {boolean} pRequireEndDate - If true, the end date must be provided; otherwise, it defaults to the current date.
|
|
143
|
+
* @returns {number} The difference in days between the start and end dates. Returns NaN if the start date is invalid.
|
|
144
|
+
*/
|
|
145
|
+
dateDayDifference(pDateStart, pDateEnd, pRequireEndDate = false)
|
|
146
|
+
{
|
|
147
|
+
if ((pDateStart === undefined) || (pDateStart === null) || (pDateStart === ''))
|
|
148
|
+
{
|
|
149
|
+
return NaN;
|
|
150
|
+
}
|
|
151
|
+
if ((pRequireEndDate || (pRequireEndDate == 1) || (pRequireEndDate == '1')) && ((pDateEnd === undefined) || (pDateEnd === null) || (pDateEnd === '')))
|
|
152
|
+
{
|
|
153
|
+
return NaN;
|
|
154
|
+
}
|
|
155
|
+
let tmpStartDate = this.dayJS(pDateStart);
|
|
156
|
+
let tmpEndDate = this.dayJS(pDateEnd);
|
|
157
|
+
return tmpEndDate.diff(tmpStartDate, 'day');
|
|
158
|
+
}
|
|
159
159
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
160
|
+
/**
|
|
161
|
+
* Calculates the difference in weeks between two dates.
|
|
162
|
+
*
|
|
163
|
+
* @param {string|Date|number} pDateStart - The start date. Can be a string, Date object, or timestamp.
|
|
164
|
+
* @param {string|Date|number} pDateEnd - The end date. Can be a string, Date object, or timestamp. Defaults to the current date if not provided.
|
|
165
|
+
* @param {boolean} pRequireEndDate - If true, the end date must be provided; otherwise, it defaults to the current date.
|
|
166
|
+
* @returns {number} The difference in weeks between the two dates. Returns NaN if the start date is invalid.
|
|
167
|
+
*/
|
|
168
|
+
dateWeekDifference(pDateStart, pDateEnd, pRequireEndDate = false)
|
|
169
|
+
{
|
|
170
|
+
if ((pDateStart === undefined) || (pDateStart === null) || (pDateStart === ''))
|
|
171
|
+
{
|
|
172
|
+
return NaN;
|
|
173
|
+
}
|
|
174
|
+
if ((pRequireEndDate || (pRequireEndDate == 1) || (pRequireEndDate == '1')) && ((pDateEnd === undefined) || (pDateEnd === null) || (pDateEnd === '')))
|
|
175
|
+
{
|
|
176
|
+
return NaN;
|
|
177
|
+
}
|
|
178
|
+
let tmpStartDate = this.dayJS(pDateStart);
|
|
179
|
+
let tmpEndDate = this.dayJS(pDateEnd);
|
|
180
|
+
return tmpEndDate.diff(tmpStartDate, 'week');
|
|
181
|
+
}
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Calculates the difference in months between two dates.
|
|
185
|
+
*
|
|
186
|
+
* @param {string|Date|number} pDateStart - The start date. Can be a string, Date object, or timestamp.
|
|
187
|
+
* @param {string|Date|number} pDateEnd - The end date. Can be a string, Date object, or timestamp. Defaults to the current date if not provided.
|
|
188
|
+
* @param {boolean} pRequireEndDate - If true, the end date must be provided; otherwise, it defaults to the current date.
|
|
189
|
+
* @returns {number} The difference in months between the two dates. Returns NaN if the start date is invalid.
|
|
190
|
+
*/
|
|
191
|
+
dateMonthDifference(pDateStart, pDateEnd, pRequireEndDate = false)
|
|
192
|
+
{
|
|
193
|
+
if ((pDateStart === undefined) || (pDateStart === null) || (pDateStart === ''))
|
|
194
|
+
{
|
|
195
|
+
return NaN;
|
|
196
|
+
}
|
|
197
|
+
if ((pRequireEndDate || (pRequireEndDate == 1) || (pRequireEndDate == '1')) && ((pDateEnd === undefined) || (pDateEnd === null) || (pDateEnd === '')))
|
|
198
|
+
{
|
|
199
|
+
return NaN;
|
|
200
|
+
}
|
|
201
|
+
let tmpStartDate = this.dayJS(pDateStart);
|
|
202
|
+
let tmpEndDate = this.dayJS(pDateEnd);
|
|
203
|
+
return tmpEndDate.diff(tmpStartDate, 'month');
|
|
204
|
+
}
|
|
205
205
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
206
|
+
/**
|
|
207
|
+
* Calculates the difference in years between two dates.
|
|
208
|
+
*
|
|
209
|
+
* @param {string|Date|number} pDateStart - The start date. Can be a string, Date object, or timestamp.
|
|
210
|
+
* @param {string|Date|number} pDateEnd - The end date. Can be a string, Date object, or timestamp. Defaults to the current date if not provided.
|
|
211
|
+
* @param {boolean} pRequireEndDate - If true, the end date must be provided; otherwise, it defaults to the current date.
|
|
212
|
+
* @returns {number} The difference in years between the two dates. Returns NaN if the start date is invalid.
|
|
213
|
+
*/
|
|
214
|
+
dateYearDifference(pDateStart, pDateEnd, pRequireEndDate = false)
|
|
215
|
+
{
|
|
216
|
+
if ((pDateStart === undefined) || (pDateStart === null) || (pDateStart === ''))
|
|
217
|
+
{
|
|
218
|
+
return NaN;
|
|
219
|
+
}
|
|
220
|
+
if ((pRequireEndDate || (pRequireEndDate == 1) || (pRequireEndDate == '1')) && ((pDateEnd === undefined) || (pDateEnd === null) || (pDateEnd === '')))
|
|
221
|
+
{
|
|
222
|
+
return NaN;
|
|
223
|
+
}
|
|
224
|
+
let tmpStartDate = this.dayJS(pDateStart);
|
|
225
|
+
let tmpEndDate = this.dayJS(pDateEnd);
|
|
226
|
+
return tmpEndDate.diff(tmpStartDate, 'year');
|
|
227
|
+
}
|
|
228
228
|
|
|
229
229
|
dateAddMilliseconds(pDate, pAmount)
|
|
230
230
|
{
|
|
@@ -255,7 +255,7 @@ class DateManipulation extends libFableServiceProviderBase
|
|
|
255
255
|
{
|
|
256
256
|
return this.dateMath(pDate, pAmount, 'week', 'add');
|
|
257
257
|
}
|
|
258
|
-
|
|
258
|
+
|
|
259
259
|
dateAddMonths(pDate, pAmount)
|
|
260
260
|
{
|
|
261
261
|
return this.dateMath(pDate, pAmount, 'month', 'add');
|
|
@@ -302,4 +302,4 @@ class DateManipulation extends libFableServiceProviderBase
|
|
|
302
302
|
}
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
module.exports = DateManipulation;
|
|
305
|
+
module.exports = DateManipulation;
|
|
@@ -4,12 +4,12 @@ class FableServiceEnvironmentData extends libFableServiceBase
|
|
|
4
4
|
{
|
|
5
5
|
constructor(pFable, pOptions, pServiceHash)
|
|
6
6
|
{
|
|
7
|
-
|
|
7
|
+
super(pFable, pOptions, pServiceHash);
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
this.serviceType = 'EnvironmentData';
|
|
10
10
|
|
|
11
11
|
this.Environment = `web`;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
module.exports = FableServiceEnvironmentData;
|
|
15
|
+
module.exports = FableServiceEnvironmentData;
|
|
@@ -4,12 +4,12 @@ class FableServiceEnvironmentData extends libFableServiceBase
|
|
|
4
4
|
{
|
|
5
5
|
constructor(pFable, pOptions, pServiceHash)
|
|
6
6
|
{
|
|
7
|
-
|
|
7
|
+
super(pFable, pOptions, pServiceHash);
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
this.serviceType = 'EnvironmentData';
|
|
10
10
|
|
|
11
11
|
this.Environment = `node.js`;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
module.exports = FableServiceEnvironmentData;
|
|
15
|
+
module.exports = FableServiceEnvironmentData;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
const libExpressionParserOperationBase = require('./Fable-Service-ExpressionParser-Base.js');
|
|
2
|
+
|
|
3
|
+
class ExpressionTokenizerDirectiveMutation extends libExpressionParserOperationBase
|
|
4
|
+
{
|
|
5
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
6
|
+
{
|
|
7
|
+
super(pFable, pOptions, pServiceHash);
|
|
8
|
+
this.serviceType = 'ExpressionParser-TokenizerDirectiveMutation';
|
|
9
|
+
|
|
10
|
+
this.directiveTypes = (
|
|
11
|
+
{
|
|
12
|
+
'SOLVE': { Name: 'Solve Expression', Code: 'SOLVE' },
|
|
13
|
+
'SERIES': { Name: 'Series', Code: 'SERIES', From: null, To: null, Step: null },
|
|
14
|
+
'MONTECARLO': { Name: 'Monte Carlo Simulation', Code: 'MONTECARLO', Iterations: null, Values: {} }
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
this.defaultDirective = this.directiveTypes.SOLVE;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
parseSeriesDirective(pTokens)
|
|
21
|
+
{
|
|
22
|
+
// This isn't a fancy real parse it's just taking words and stealing values after them.
|
|
23
|
+
let tmpNewSeriesDirectiveDescription = Object.assign({}, this.directiveTypes.SERIES);
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < pTokens.length; i++)
|
|
26
|
+
{
|
|
27
|
+
let tmpToken = pTokens[i].toUpperCase();
|
|
28
|
+
switch(tmpToken)
|
|
29
|
+
{
|
|
30
|
+
case 'FROM':
|
|
31
|
+
if ((i + 1) < pTokens.length)
|
|
32
|
+
{
|
|
33
|
+
tmpNewSeriesDirectiveDescription.From = pTokens[i + 1];
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
case 'TO':
|
|
38
|
+
if ((i + 1) < pTokens.length)
|
|
39
|
+
{
|
|
40
|
+
tmpNewSeriesDirectiveDescription.To = pTokens[i + 1];
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
|
|
44
|
+
case 'STEP':
|
|
45
|
+
if ((i + 1) < pTokens.length)
|
|
46
|
+
{
|
|
47
|
+
tmpNewSeriesDirectiveDescription.Step = pTokens[i + 1];
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
|
|
51
|
+
default:
|
|
52
|
+
// Ignore other tokens
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return tmpNewSeriesDirectiveDescription;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
parseDirectives(pResultObject)
|
|
61
|
+
{
|
|
62
|
+
let tmpResults = (typeof(pResultObject) === 'object') ? pResultObject : { ExpressionParserLog: [] };
|
|
63
|
+
|
|
64
|
+
tmpResults.SolverDirectives = this.defaultDirective;
|
|
65
|
+
tmpResults.SolverDirectiveTokens = [];
|
|
66
|
+
|
|
67
|
+
if (tmpResults.RawTokens.length < 2)
|
|
68
|
+
{
|
|
69
|
+
tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenizeDirectiveMutation postprocessor received insufficient tokens to process directives.`);
|
|
70
|
+
this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
71
|
+
return tmpResults.SolverDirectives;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Enumerate each of the tmpResults.RawTokens to see if one of the values in the directiveTypeMap exists and is either at the beginning or after the assignment (= or ?=) operator
|
|
75
|
+
for (let i = 0; i < tmpResults.RawTokens.length; i++)
|
|
76
|
+
{
|
|
77
|
+
let tmpToken = tmpResults.RawTokens[i].toUpperCase();
|
|
78
|
+
if (tmpToken in this.directiveTypes)
|
|
79
|
+
{
|
|
80
|
+
// Check if it's at the beginning or after an assignment operator
|
|
81
|
+
// FIXME: This is hard coded assignment operators which is bad juju
|
|
82
|
+
if ((i === 0) || (tmpResults.RawTokens[i-1] === '=') || (tmpResults.RawTokens[i-1] === '?='))
|
|
83
|
+
{
|
|
84
|
+
// We have a directive!
|
|
85
|
+
tmpResults.SolverDirectives.Type = this.directiveTypes[tmpToken];
|
|
86
|
+
|
|
87
|
+
tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenizeDirectiveMutation identified solver directive: ${tmpToken}`);
|
|
88
|
+
this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
89
|
+
|
|
90
|
+
// Extract the Directive name and everything else from it up until the : token
|
|
91
|
+
let tmpDirectiveTokenStartIndex = i;
|
|
92
|
+
let tmpDirectiveTokenEndIndex = -1;
|
|
93
|
+
for (let j = tmpDirectiveTokenStartIndex + 1; j < tmpResults.RawTokens.length; j++)
|
|
94
|
+
{
|
|
95
|
+
if (tmpResults.RawTokens[j] === ':')
|
|
96
|
+
{
|
|
97
|
+
tmpDirectiveTokenEndIndex = j;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// If the directive token end is not in the expression we don't know what to do
|
|
103
|
+
if (tmpDirectiveTokenEndIndex === -1)
|
|
104
|
+
{
|
|
105
|
+
tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenizeDirectiveMutation could not find the end of the directive token set for directive: ${tmpToken}`);
|
|
106
|
+
this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Set the tmpResults.SolverDirectiveTokens to the slice of tokens that represent the directive
|
|
111
|
+
tmpResults.SolverDirectiveTokens = tmpResults.RawTokens.slice(tmpDirectiveTokenStartIndex, tmpDirectiveTokenEndIndex);
|
|
112
|
+
|
|
113
|
+
// Remove the directive tokens and the assignment to the left of it from the array of raw tokens
|
|
114
|
+
// the colonoscopy if you will
|
|
115
|
+
tmpResults.RawTokens.splice(0, tmpDirectiveTokenEndIndex + 1);
|
|
116
|
+
|
|
117
|
+
// Further parsing based on directive type could go here
|
|
118
|
+
// e.g. parseSeriesDirective for SERIES, etc.
|
|
119
|
+
switch(tmpToken)
|
|
120
|
+
{
|
|
121
|
+
case 'SERIES':
|
|
122
|
+
tmpResults.SolverDirectives = this.parseSeriesDirective(tmpResults.SolverDirectiveTokens);
|
|
123
|
+
break;
|
|
124
|
+
default:
|
|
125
|
+
// No further parsing needed
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return tmpResults.SolverDirectives;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = ExpressionTokenizerDirectiveMutation;
|
|
@@ -13,6 +13,7 @@ class ExpressionTokenizer extends libExpressionParserOperationBase
|
|
|
13
13
|
let tmpResults = (typeof(pResultObject) === 'object') ? pResultObject : { ExpressionParserLog: [] };
|
|
14
14
|
|
|
15
15
|
tmpResults.RawExpression = pExpression;
|
|
16
|
+
tmpResults.SolverDirectives = {};
|
|
16
17
|
tmpResults.RawTokens = [];
|
|
17
18
|
tmpResults.ExpressionParserLog = [];
|
|
18
19
|
|
|
@@ -203,6 +204,11 @@ class ExpressionTokenizer extends libExpressionParserOperationBase
|
|
|
203
204
|
tmpResults.RawTokens.push(tmpCurrentToken);
|
|
204
205
|
}
|
|
205
206
|
|
|
207
|
+
tmpResults.OriginalRawTokens = Array.from(tmpResults.RawTokens);
|
|
208
|
+
|
|
209
|
+
// Potentially mutate the tokens based on directives in the tokenized expression
|
|
210
|
+
this.TokenizerDirectiveMutation.parseDirectives(tmpResults);
|
|
211
|
+
|
|
206
212
|
return tmpResults.RawTokens;
|
|
207
213
|
}
|
|
208
214
|
}
|