@malloydata/malloy-filter 0.0.237-dev250224203840 → 0.0.237-dev250225015031
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/SAMPLES.md +336 -116
- package/SERIALIZE_SAMPLES.md +268 -64
- package/dist/a_simple_parser.js +6 -0
- package/dist/a_simple_parser.js.map +1 -1
- package/dist/base_parser.js +6 -0
- package/dist/base_parser.js.map +1 -1
- package/dist/boolean_parser.js +28 -13
- package/dist/boolean_parser.js.map +1 -1
- package/dist/boolean_serializer.js +12 -6
- package/dist/boolean_serializer.js.map +1 -1
- package/dist/clause_types.d.ts +20 -15
- package/dist/clause_types.js +6 -0
- package/dist/clause_types.js.map +1 -1
- package/dist/date_parser.d.ts +1 -0
- package/dist/date_parser.js +174 -116
- package/dist/date_parser.js.map +1 -1
- package/dist/date_serializer.js +26 -20
- package/dist/date_serializer.js.map +1 -1
- package/dist/date_types.d.ts +21 -21
- package/dist/date_types.js +6 -0
- package/dist/date_types.js.map +1 -1
- package/dist/generate_samples.js +41 -26
- package/dist/generate_samples.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/number_parser.js +43 -25
- package/dist/number_parser.js.map +1 -1
- package/dist/number_serializer.js +10 -4
- package/dist/number_serializer.js.map +1 -1
- package/dist/string_parser.d.ts +0 -1
- package/dist/string_parser.js +47 -79
- package/dist/string_parser.js.map +1 -1
- package/dist/string_serializer.d.ts +1 -0
- package/dist/string_serializer.js +49 -33
- package/dist/string_serializer.js.map +1 -1
- package/dist/token_types.js +6 -0
- package/dist/token_types.js.map +1 -1
- package/dist/tokenizer.js +9 -3
- package/dist/tokenizer.js.map +1 -1
- package/dist/tokenizer.spec.js +13 -7
- package/dist/tokenizer.spec.js.map +1 -1
- package/package.json +2 -2
- package/src/a_simple_parser.ts +7 -0
- package/src/base_parser.ts +7 -0
- package/src/boolean_parser.ts +30 -18
- package/src/boolean_serializer.ts +13 -6
- package/src/clause_types.ts +36 -31
- package/src/date_parser.ts +177 -115
- package/src/date_serializer.ts +27 -20
- package/src/date_types.ts +42 -34
- package/src/generate_samples.ts +42 -26
- package/src/index.ts +17 -0
- package/src/number_parser.ts +45 -26
- package/src/number_serializer.ts +11 -4
- package/src/string_parser.ts +51 -79
- package/src/string_serializer.ts +65 -39
- package/src/token_types.ts +7 -0
- package/src/tokenizer.spec.ts +14 -7
- package/src/tokenizer.ts +10 -3
package/src/date_types.ts
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {FilterLog} from './clause_types';
|
|
2
9
|
|
|
3
10
|
export type DateTimeUnit =
|
|
4
|
-
| '
|
|
5
|
-
| '
|
|
6
|
-
| '
|
|
7
|
-
| '
|
|
8
|
-
| '
|
|
9
|
-
| '
|
|
10
|
-
| '
|
|
11
|
-
| '
|
|
11
|
+
| 'year'
|
|
12
|
+
| 'quarter'
|
|
13
|
+
| 'month'
|
|
14
|
+
| 'week'
|
|
15
|
+
| 'day'
|
|
16
|
+
| 'hour'
|
|
17
|
+
| 'minute'
|
|
18
|
+
| 'second'
|
|
19
|
+
| 'instant';
|
|
12
20
|
|
|
13
21
|
export type DateWeekday =
|
|
14
|
-
| '
|
|
15
|
-
| '
|
|
16
|
-
| '
|
|
17
|
-
| '
|
|
18
|
-
| '
|
|
19
|
-
| '
|
|
20
|
-
| '
|
|
22
|
+
| 'monday'
|
|
23
|
+
| 'tuesday'
|
|
24
|
+
| 'wednesday'
|
|
25
|
+
| 'thursday'
|
|
26
|
+
| 'friday'
|
|
27
|
+
| 'saturday'
|
|
28
|
+
| 'sunday';
|
|
21
29
|
|
|
22
30
|
// 7 weeks, 32 hours
|
|
23
31
|
export interface Duration {
|
|
@@ -25,45 +33,45 @@ export interface Duration {
|
|
|
25
33
|
unit: DateTimeUnit;
|
|
26
34
|
}
|
|
27
35
|
|
|
28
|
-
export type DateMomentName = '
|
|
36
|
+
export type DateMomentName = 'now' | 'today' | 'yesterday' | 'tomorrow';
|
|
29
37
|
|
|
30
38
|
// now, today, yesterday, tomorrow
|
|
31
39
|
export interface NamedMoment {
|
|
32
|
-
type: '
|
|
40
|
+
type: 'named';
|
|
33
41
|
name: DateMomentName;
|
|
34
42
|
}
|
|
35
43
|
|
|
36
|
-
export type DateMomentIntervalOperator = '
|
|
44
|
+
export type DateMomentIntervalOperator = 'last' | 'this' | 'next';
|
|
37
45
|
|
|
38
46
|
// LAST|UNITOFTIME, LAST|DAYOFWEEK
|
|
39
47
|
// THIS|UNITOFTIME
|
|
40
48
|
// NEXT|UNITOFTIME, NEXT|DAYOFWEEK
|
|
41
49
|
// last month, next tuesday, this month
|
|
42
50
|
export interface IntervalMoment {
|
|
43
|
-
type: '
|
|
51
|
+
type: 'interval';
|
|
44
52
|
kind: DateMomentIntervalOperator;
|
|
45
53
|
unit: DateTimeUnit | DateWeekday;
|
|
46
54
|
}
|
|
47
55
|
|
|
48
|
-
export type DateMomentOffsetFromNowDirection = '
|
|
56
|
+
export type DateMomentOffsetFromNowDirection = 'ago' | 'from_now';
|
|
49
57
|
|
|
50
58
|
// NUMBER|UNITOFTIME|AGO
|
|
51
59
|
// NUMBER|UNITOFTIME|FROM|NOW
|
|
52
60
|
// 3 hours ago, 6 weeks from now
|
|
53
61
|
export interface OffsetMoment {
|
|
54
|
-
type: '
|
|
62
|
+
type: 'offset_from_now';
|
|
55
63
|
direction: DateMomentOffsetFromNowDirection;
|
|
56
64
|
unit: DateTimeUnit;
|
|
57
65
|
amount: number;
|
|
58
66
|
}
|
|
59
67
|
|
|
60
|
-
export type DateMomentSpanFromNowDirection = '
|
|
68
|
+
export type DateMomentSpanFromNowDirection = 'last' | 'next';
|
|
61
69
|
|
|
62
70
|
// LAST|NUMBER|UNITOFTIME
|
|
63
71
|
// NEXT|NUMBER|UNITOFTIME
|
|
64
72
|
// last 3 hours, next 2025 seconds, last 6 weeks
|
|
65
73
|
export interface SpanMoment {
|
|
66
|
-
type: '
|
|
74
|
+
type: 'span_from_now';
|
|
67
75
|
direction: DateMomentSpanFromNowDirection;
|
|
68
76
|
unit: DateTimeUnit;
|
|
69
77
|
amount: number;
|
|
@@ -71,7 +79,7 @@ export interface SpanMoment {
|
|
|
71
79
|
|
|
72
80
|
// 2005, 2005-01, 2005-01-01, 2005-01-01 00:00, 2005-01-01 00:00:01
|
|
73
81
|
export interface AbsoluteMoment {
|
|
74
|
-
type: '
|
|
82
|
+
type: 'absolute';
|
|
75
83
|
date: string;
|
|
76
84
|
unit: DateTimeUnit;
|
|
77
85
|
}
|
|
@@ -99,47 +107,47 @@ export type DateMoment =
|
|
|
99
107
|
|
|
100
108
|
// after 2005-01, after 3 hours ago
|
|
101
109
|
export interface DateAfterClause {
|
|
102
|
-
operator: '
|
|
110
|
+
operator: 'after';
|
|
103
111
|
moment: DateMoment;
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
// before 2005-01, before 3 hours ago
|
|
107
115
|
export interface DateBeforeClause {
|
|
108
|
-
operator: '
|
|
116
|
+
operator: 'before';
|
|
109
117
|
moment: DateMoment;
|
|
110
118
|
}
|
|
111
119
|
|
|
112
120
|
// next week, last 3 weeks, 3 days ago
|
|
113
121
|
export interface DateOnClause {
|
|
114
|
-
operator: '
|
|
122
|
+
operator: 'on';
|
|
115
123
|
moment: DateMoment;
|
|
116
124
|
}
|
|
117
125
|
|
|
118
126
|
// 2015 to next month
|
|
119
127
|
export interface DateBetweenClause {
|
|
120
|
-
operator: '
|
|
128
|
+
operator: 'to_range';
|
|
121
129
|
from: DateMoment;
|
|
122
130
|
to: DateMoment;
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
// 2025-01-01 12:00:00 for 3 days
|
|
126
134
|
export interface DateForClause {
|
|
127
|
-
operator: '
|
|
135
|
+
operator: 'for_range';
|
|
128
136
|
from: DateMoment;
|
|
129
137
|
duration: Duration;
|
|
130
138
|
}
|
|
131
139
|
|
|
132
140
|
export interface DateNullClause {
|
|
133
|
-
operator: '
|
|
141
|
+
operator: 'null';
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
export interface DateNotNullClause {
|
|
137
|
-
operator: '
|
|
145
|
+
operator: 'not_null';
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
// 3 days
|
|
141
149
|
export interface DateDurationClause {
|
|
142
|
-
operator: '
|
|
150
|
+
operator: 'duration';
|
|
143
151
|
duration: Duration;
|
|
144
152
|
}
|
|
145
153
|
|
|
@@ -155,5 +163,5 @@ export type DateClause =
|
|
|
155
163
|
|
|
156
164
|
export interface DateParserResponse {
|
|
157
165
|
clauses: DateClause[];
|
|
158
|
-
|
|
166
|
+
logs: FilterLog[];
|
|
159
167
|
}
|
package/src/generate_samples.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
import * as fs from 'fs';
|
|
2
9
|
import {BooleanParser} from './boolean_parser';
|
|
3
10
|
import {StringParser} from './string_parser';
|
|
@@ -12,6 +19,7 @@ const numberExamples = [
|
|
|
12
19
|
'5',
|
|
13
20
|
'!=5',
|
|
14
21
|
'1, 3, 5, null',
|
|
22
|
+
'1, 3, , 5,',
|
|
15
23
|
'<1, >=100 ',
|
|
16
24
|
'>=1',
|
|
17
25
|
' <= 10 ',
|
|
@@ -45,6 +53,8 @@ const stringExamples = [
|
|
|
45
53
|
'CAT,-NULL',
|
|
46
54
|
'CAT,-"NULL"',
|
|
47
55
|
'CAT,NULL',
|
|
56
|
+
'CAT,,',
|
|
57
|
+
'CAT, , DOG',
|
|
48
58
|
'EMPTY',
|
|
49
59
|
'-EMPTY',
|
|
50
60
|
'CAT,-EMPTY',
|
|
@@ -69,7 +79,8 @@ const booleanExamples = [
|
|
|
69
79
|
'=false',
|
|
70
80
|
'null',
|
|
71
81
|
'-NULL',
|
|
72
|
-
'
|
|
82
|
+
'null,',
|
|
83
|
+
' True , , faLSE,=false,NULl,-null',
|
|
73
84
|
"-'null'",
|
|
74
85
|
'10',
|
|
75
86
|
'nnull',
|
|
@@ -83,14 +94,21 @@ const dateExamples = [
|
|
|
83
94
|
'3 months ago for 2 days',
|
|
84
95
|
'2025 weeks ago',
|
|
85
96
|
'before 3 days ago',
|
|
86
|
-
'
|
|
87
|
-
'
|
|
97
|
+
'Before 2025-08-30 08:30:20',
|
|
98
|
+
'AFTER 2025-10-05',
|
|
88
99
|
'2025-08-30 12:00 to 2025-09-18 14:30',
|
|
89
|
-
'this
|
|
90
|
-
'
|
|
91
|
-
'7 years from
|
|
100
|
+
'this YEAR',
|
|
101
|
+
'Next Tuesday',
|
|
102
|
+
'7 years from Now',
|
|
92
103
|
'2025-01-01 12:00:00 for 3 days',
|
|
104
|
+
'2020-08-12 03:12:56.57',
|
|
105
|
+
'2020-08-12T03:12:56[PST]',
|
|
106
|
+
'2020-08-12 03:12:56',
|
|
107
|
+
'2020-08-12 03:22',
|
|
108
|
+
'2020-08-12 03',
|
|
93
109
|
'2020-08-12',
|
|
110
|
+
'2020-Q3',
|
|
111
|
+
'2020-08-07-wK',
|
|
94
112
|
'2020-08',
|
|
95
113
|
'today',
|
|
96
114
|
'yesterday',
|
|
@@ -105,9 +123,10 @@ const dateExamples = [
|
|
|
105
123
|
' yyesterday ', // Typo
|
|
106
124
|
'before', // Bad syntax
|
|
107
125
|
'for', // Bad syntax
|
|
108
|
-
'
|
|
126
|
+
'12', // Bad syntax
|
|
109
127
|
'from now', // Bad syntax
|
|
110
128
|
'2025-12-25 12:32:', // Bad syntax
|
|
129
|
+
'12:22',
|
|
111
130
|
'after 2025 seconds', // Bad syntax
|
|
112
131
|
'',
|
|
113
132
|
];
|
|
@@ -159,8 +178,8 @@ class GenerateSamples {
|
|
|
159
178
|
if (response.clauses && response.clauses.length > 0) {
|
|
160
179
|
GenerateSamples.writeJson(fp, 'Output: ', ...response.clauses);
|
|
161
180
|
}
|
|
162
|
-
if (response.
|
|
163
|
-
GenerateSamples.writeJson(fp, '
|
|
181
|
+
if (response.logs && response.logs.length > 0) {
|
|
182
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
164
183
|
}
|
|
165
184
|
GenerateSamples.writeRaw(fp, '');
|
|
166
185
|
}
|
|
@@ -173,8 +192,8 @@ class GenerateSamples {
|
|
|
173
192
|
if (response.clauses && response.clauses.length > 0) {
|
|
174
193
|
GenerateSamples.writeJson(fp, 'Output: ', ...response.clauses);
|
|
175
194
|
}
|
|
176
|
-
if (response.
|
|
177
|
-
GenerateSamples.writeJson(fp, '
|
|
195
|
+
if (response.logs && response.logs.length > 0) {
|
|
196
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
178
197
|
}
|
|
179
198
|
GenerateSamples.writeRaw(fp, '');
|
|
180
199
|
}
|
|
@@ -187,8 +206,8 @@ class GenerateSamples {
|
|
|
187
206
|
if (response.clauses && response.clauses.length > 0) {
|
|
188
207
|
GenerateSamples.writeJson(fp, 'Output: ', ...response.clauses);
|
|
189
208
|
}
|
|
190
|
-
if (response.
|
|
191
|
-
GenerateSamples.writeJson(fp, '
|
|
209
|
+
if (response.logs && response.logs.length > 0) {
|
|
210
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
192
211
|
}
|
|
193
212
|
GenerateSamples.writeRaw(fp, '');
|
|
194
213
|
}
|
|
@@ -201,11 +220,8 @@ class GenerateSamples {
|
|
|
201
220
|
if (response.clauses && response.clauses.length > 0) {
|
|
202
221
|
GenerateSamples.writeJson(fp, 'Output: ', ...response.clauses);
|
|
203
222
|
}
|
|
204
|
-
if (response.
|
|
205
|
-
GenerateSamples.writeJson(fp, '
|
|
206
|
-
}
|
|
207
|
-
if (response.errors && response.errors.length > 0) {
|
|
208
|
-
GenerateSamples.writeJson(fp, 'Errors: ', ...response.errors);
|
|
223
|
+
if (response.logs && response.logs.length > 0) {
|
|
224
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
209
225
|
}
|
|
210
226
|
GenerateSamples.writeRaw(fp, '');
|
|
211
227
|
}
|
|
@@ -218,8 +234,8 @@ class GenerateSamples {
|
|
|
218
234
|
const result = new BooleanSerializer(response.clauses || []).serialize();
|
|
219
235
|
GenerateSamples.writeRaw(fp, 'Output: ' + result);
|
|
220
236
|
}
|
|
221
|
-
if (response.
|
|
222
|
-
GenerateSamples.writeJson(fp, '
|
|
237
|
+
if (response.logs && response.logs.length > 0) {
|
|
238
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
223
239
|
}
|
|
224
240
|
GenerateSamples.writeRaw(fp, '');
|
|
225
241
|
}
|
|
@@ -232,8 +248,8 @@ class GenerateSamples {
|
|
|
232
248
|
const result = new DateSerializer(response.clauses || []).serialize();
|
|
233
249
|
GenerateSamples.writeRaw(fp, 'Output: ' + result);
|
|
234
250
|
}
|
|
235
|
-
if (response.
|
|
236
|
-
GenerateSamples.writeJson(fp, '
|
|
251
|
+
if (response.logs && response.logs.length > 0) {
|
|
252
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
237
253
|
}
|
|
238
254
|
GenerateSamples.writeRaw(fp, '');
|
|
239
255
|
}
|
|
@@ -246,8 +262,8 @@ class GenerateSamples {
|
|
|
246
262
|
const result = new NumberSerializer(response.clauses || []).serialize();
|
|
247
263
|
GenerateSamples.writeRaw(fp, 'Output: ' + result);
|
|
248
264
|
}
|
|
249
|
-
if (response.
|
|
250
|
-
GenerateSamples.writeJson(fp, '
|
|
265
|
+
if (response.logs && response.logs.length > 0) {
|
|
266
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
251
267
|
}
|
|
252
268
|
GenerateSamples.writeRaw(fp, '');
|
|
253
269
|
}
|
|
@@ -260,8 +276,8 @@ class GenerateSamples {
|
|
|
260
276
|
const result = new StringSerializer(response.clauses || []).serialize();
|
|
261
277
|
GenerateSamples.writeRaw(fp, 'Output: ' + result);
|
|
262
278
|
}
|
|
263
|
-
if (response.
|
|
264
|
-
GenerateSamples.writeJson(fp, '
|
|
279
|
+
if (response.logs && response.logs.length > 0) {
|
|
280
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
265
281
|
}
|
|
266
282
|
GenerateSamples.writeRaw(fp, '');
|
|
267
283
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export {BooleanParser} from './boolean_parser';
|
|
9
|
+
export {DateParser} from './date_parser';
|
|
10
|
+
export {NumberParser} from './number_parser';
|
|
11
|
+
export {StringParser} from './string_parser';
|
|
12
|
+
export {BooleanSerializer} from './boolean_serializer';
|
|
13
|
+
export {DateSerializer} from './date_serializer';
|
|
14
|
+
export {NumberSerializer} from './number_serializer';
|
|
15
|
+
export {StringSerializer} from './string_serializer';
|
|
16
|
+
export * from './clause_types';
|
|
17
|
+
export * from './date_types';
|
package/src/number_parser.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
import {SpecialToken, Tokenizer, TokenizerParams} from './tokenizer';
|
|
2
9
|
import {
|
|
3
10
|
NumberCondition,
|
|
@@ -6,7 +13,7 @@ import {
|
|
|
6
13
|
NumberRangeOperator,
|
|
7
14
|
NumberClause,
|
|
8
15
|
NumberParserResponse,
|
|
9
|
-
|
|
16
|
+
FilterLog,
|
|
10
17
|
} from './clause_types';
|
|
11
18
|
import {BaseParser} from './base_parser';
|
|
12
19
|
import {Token} from './token_types';
|
|
@@ -31,8 +38,8 @@ export class NumberParser extends BaseParser {
|
|
|
31
38
|
{type: '<', value: '<'},
|
|
32
39
|
];
|
|
33
40
|
const specialWords = [
|
|
34
|
-
{type: '
|
|
35
|
-
{type: '
|
|
41
|
+
{type: 'not_null', value: '-null', ignoreCase: true},
|
|
42
|
+
{type: 'null', value: 'null', ignoreCase: true},
|
|
36
43
|
];
|
|
37
44
|
const params: TokenizerParams = {
|
|
38
45
|
trimWordWhitespace: true,
|
|
@@ -50,16 +57,24 @@ export class NumberParser extends BaseParser {
|
|
|
50
57
|
this.index = 0;
|
|
51
58
|
this.tokenize();
|
|
52
59
|
let clauses: NumberClause[] = [];
|
|
53
|
-
const
|
|
60
|
+
const logs: FilterLog[] = [];
|
|
54
61
|
while (this.index < this.tokens.length) {
|
|
55
62
|
const token = this.getNext();
|
|
56
63
|
if (token.type === ',') {
|
|
64
|
+
if (this.index > 0 && this.tokens[this.index - 1].type === ',') {
|
|
65
|
+
logs.push({
|
|
66
|
+
severity: 'warn',
|
|
67
|
+
message: 'Empty clause',
|
|
68
|
+
startIndex: token.startIndex,
|
|
69
|
+
endIndex: token.endIndex,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
57
72
|
this.index++;
|
|
58
73
|
} else if (this.isRangeStart(this.index)) {
|
|
59
|
-
clauses = this.checkRange(token, false, clauses,
|
|
74
|
+
clauses = this.checkRange(token, false, clauses, logs);
|
|
60
75
|
} else if (token.type === '!=' && this.isRangeStart(this.index + 1)) {
|
|
61
76
|
this.index++;
|
|
62
|
-
clauses = this.checkRange(token, true, clauses,
|
|
77
|
+
clauses = this.checkRange(token, true, clauses, logs);
|
|
63
78
|
} else if (this.checkNull(clauses)) {
|
|
64
79
|
this.index++;
|
|
65
80
|
} else if (
|
|
@@ -74,15 +89,16 @@ export class NumberParser extends BaseParser {
|
|
|
74
89
|
} else if (this.checkSimpleNumber(clauses)) {
|
|
75
90
|
this.index++;
|
|
76
91
|
} else {
|
|
77
|
-
|
|
78
|
-
|
|
92
|
+
logs.push({
|
|
93
|
+
severity: 'error',
|
|
94
|
+
message: 'Invalid expression: ' + token.value,
|
|
79
95
|
startIndex: token.startIndex,
|
|
80
96
|
endIndex: token.endIndex,
|
|
81
97
|
});
|
|
82
98
|
this.index++;
|
|
83
99
|
}
|
|
84
100
|
}
|
|
85
|
-
return {clauses: NumberParser.groupClauses(clauses),
|
|
101
|
+
return {clauses: NumberParser.groupClauses(clauses), logs};
|
|
86
102
|
}
|
|
87
103
|
|
|
88
104
|
private static groupClauses(clauses: NumberClause[]): NumberClause[] {
|
|
@@ -119,26 +135,27 @@ export class NumberParser extends BaseParser {
|
|
|
119
135
|
token: Token,
|
|
120
136
|
negated: boolean,
|
|
121
137
|
clauses: NumberClause[],
|
|
122
|
-
|
|
138
|
+
logs: FilterLog[]
|
|
123
139
|
): NumberClause[] {
|
|
124
140
|
if (this.matchTokens(['[', 'word', ',', 'word', ']'])) {
|
|
125
141
|
return negated
|
|
126
|
-
? this.consumeRange('<', '>', clauses,
|
|
127
|
-
: this.consumeRange('>=', '<=', clauses,
|
|
142
|
+
? this.consumeRange('<', '>', clauses, logs)
|
|
143
|
+
: this.consumeRange('>=', '<=', clauses, logs);
|
|
128
144
|
} else if (this.matchTokens(['[', 'word', ',', 'word', ')'])) {
|
|
129
145
|
return negated
|
|
130
|
-
? this.consumeRange('<', '>=', clauses,
|
|
131
|
-
: this.consumeRange('>=', '<', clauses,
|
|
146
|
+
? this.consumeRange('<', '>=', clauses, logs)
|
|
147
|
+
: this.consumeRange('>=', '<', clauses, logs);
|
|
132
148
|
} else if (this.matchTokens(['(', 'word', ',', 'word', ']'])) {
|
|
133
149
|
return negated
|
|
134
|
-
? this.consumeRange('<=', '>', clauses,
|
|
135
|
-
: this.consumeRange('>', '<=', clauses,
|
|
150
|
+
? this.consumeRange('<=', '>', clauses, logs)
|
|
151
|
+
: this.consumeRange('>', '<=', clauses, logs);
|
|
136
152
|
} else if (this.matchTokens(['(', 'word', ',', 'word', ')'])) {
|
|
137
153
|
return negated
|
|
138
|
-
? this.consumeRange('<=', '>=', clauses,
|
|
139
|
-
: this.consumeRange('>', '<', clauses,
|
|
154
|
+
? this.consumeRange('<=', '>=', clauses, logs)
|
|
155
|
+
: this.consumeRange('>', '<', clauses, logs);
|
|
140
156
|
} else {
|
|
141
|
-
|
|
157
|
+
logs.push({
|
|
158
|
+
severity: 'error',
|
|
142
159
|
message: 'Invalid range expression',
|
|
143
160
|
startIndex: token.startIndex,
|
|
144
161
|
endIndex: token.endIndex,
|
|
@@ -174,20 +191,22 @@ export class NumberParser extends BaseParser {
|
|
|
174
191
|
startOperator: NumberRangeOperator,
|
|
175
192
|
endOperator: NumberRangeOperator,
|
|
176
193
|
clauses: NumberClause[],
|
|
177
|
-
|
|
194
|
+
logs: FilterLog[]
|
|
178
195
|
): NumberClause[] {
|
|
179
196
|
const startToken = this.getAt(this.index + 1);
|
|
180
197
|
const endToken = this.getAt(this.index + 3);
|
|
181
198
|
const startValue: number = NumberParser.parseNumber(startToken.value);
|
|
182
199
|
const endValue: number = NumberParser.parseNumber(endToken.value);
|
|
183
200
|
if (!NumberParser.isValidNumber(startValue)) {
|
|
184
|
-
|
|
201
|
+
logs.push({
|
|
202
|
+
severity: 'error',
|
|
185
203
|
message: 'Invalid number',
|
|
186
204
|
startIndex: startToken.startIndex,
|
|
187
205
|
endIndex: startToken.endIndex,
|
|
188
206
|
});
|
|
189
207
|
} else if (!NumberParser.isValidNumber(endValue)) {
|
|
190
|
-
|
|
208
|
+
logs.push({
|
|
209
|
+
severity: 'error',
|
|
191
210
|
message: 'Invalid number',
|
|
192
211
|
startIndex: endToken.startIndex,
|
|
193
212
|
endIndex: endToken.endIndex,
|
|
@@ -247,11 +266,11 @@ export class NumberParser extends BaseParser {
|
|
|
247
266
|
|
|
248
267
|
private checkNull(clauses: NumberClause[]): boolean {
|
|
249
268
|
const type = this.getNext().type;
|
|
250
|
-
if (type === '
|
|
251
|
-
clauses.push({operator: '
|
|
269
|
+
if (type === 'null') {
|
|
270
|
+
clauses.push({operator: 'null'});
|
|
252
271
|
return true;
|
|
253
|
-
} else if (type === '
|
|
254
|
-
clauses.push({operator: '
|
|
272
|
+
} else if (type === 'not_null') {
|
|
273
|
+
clauses.push({operator: 'not_null'});
|
|
255
274
|
return true;
|
|
256
275
|
}
|
|
257
276
|
return false;
|
package/src/number_serializer.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
import {
|
|
2
9
|
NumberCondition,
|
|
3
10
|
NumberRange,
|
|
@@ -75,10 +82,10 @@ export class NumberSerializer {
|
|
|
75
82
|
if (clause.operator === 'range') {
|
|
76
83
|
result += NumberSerializer.rangeToString(clause);
|
|
77
84
|
result += ', ';
|
|
78
|
-
} else if (clause.operator === '
|
|
79
|
-
result += '
|
|
80
|
-
} else if (clause.operator === '
|
|
81
|
-
result += '-
|
|
85
|
+
} else if (clause.operator === 'null') {
|
|
86
|
+
result += 'null, ';
|
|
87
|
+
} else if (clause.operator === 'not_null') {
|
|
88
|
+
result += '-null, ';
|
|
82
89
|
} else if (NumberSerializer.isNumberOperator(clause.operator)) {
|
|
83
90
|
const numberClause: NumberCondition = clause as NumberCondition;
|
|
84
91
|
for (const value of numberClause.values) {
|