@malloydata/malloy-filter 0.0.237-dev250224215546 → 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 -114
- 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.js +135 -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 +32 -25
- package/dist/generate_samples.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- 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 +1 -1
- 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 +136 -118
- package/src/date_serializer.ts +27 -20
- package/src/date_types.ts +42 -34
- package/src/generate_samples.ts +33 -25
- package/src/index.ts +7 -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,12 +94,12 @@ 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',
|
|
93
104
|
'2020-08-12 03:12:56.57',
|
|
94
105
|
'2020-08-12T03:12:56[PST]',
|
|
@@ -167,8 +178,8 @@ class GenerateSamples {
|
|
|
167
178
|
if (response.clauses && response.clauses.length > 0) {
|
|
168
179
|
GenerateSamples.writeJson(fp, 'Output: ', ...response.clauses);
|
|
169
180
|
}
|
|
170
|
-
if (response.
|
|
171
|
-
GenerateSamples.writeJson(fp, '
|
|
181
|
+
if (response.logs && response.logs.length > 0) {
|
|
182
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
172
183
|
}
|
|
173
184
|
GenerateSamples.writeRaw(fp, '');
|
|
174
185
|
}
|
|
@@ -181,8 +192,8 @@ class GenerateSamples {
|
|
|
181
192
|
if (response.clauses && response.clauses.length > 0) {
|
|
182
193
|
GenerateSamples.writeJson(fp, 'Output: ', ...response.clauses);
|
|
183
194
|
}
|
|
184
|
-
if (response.
|
|
185
|
-
GenerateSamples.writeJson(fp, '
|
|
195
|
+
if (response.logs && response.logs.length > 0) {
|
|
196
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
186
197
|
}
|
|
187
198
|
GenerateSamples.writeRaw(fp, '');
|
|
188
199
|
}
|
|
@@ -195,8 +206,8 @@ class GenerateSamples {
|
|
|
195
206
|
if (response.clauses && response.clauses.length > 0) {
|
|
196
207
|
GenerateSamples.writeJson(fp, 'Output: ', ...response.clauses);
|
|
197
208
|
}
|
|
198
|
-
if (response.
|
|
199
|
-
GenerateSamples.writeJson(fp, '
|
|
209
|
+
if (response.logs && response.logs.length > 0) {
|
|
210
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
200
211
|
}
|
|
201
212
|
GenerateSamples.writeRaw(fp, '');
|
|
202
213
|
}
|
|
@@ -209,11 +220,8 @@ class GenerateSamples {
|
|
|
209
220
|
if (response.clauses && response.clauses.length > 0) {
|
|
210
221
|
GenerateSamples.writeJson(fp, 'Output: ', ...response.clauses);
|
|
211
222
|
}
|
|
212
|
-
if (response.
|
|
213
|
-
GenerateSamples.writeJson(fp, '
|
|
214
|
-
}
|
|
215
|
-
if (response.errors && response.errors.length > 0) {
|
|
216
|
-
GenerateSamples.writeJson(fp, 'Errors: ', ...response.errors);
|
|
223
|
+
if (response.logs && response.logs.length > 0) {
|
|
224
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
217
225
|
}
|
|
218
226
|
GenerateSamples.writeRaw(fp, '');
|
|
219
227
|
}
|
|
@@ -226,8 +234,8 @@ class GenerateSamples {
|
|
|
226
234
|
const result = new BooleanSerializer(response.clauses || []).serialize();
|
|
227
235
|
GenerateSamples.writeRaw(fp, 'Output: ' + result);
|
|
228
236
|
}
|
|
229
|
-
if (response.
|
|
230
|
-
GenerateSamples.writeJson(fp, '
|
|
237
|
+
if (response.logs && response.logs.length > 0) {
|
|
238
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
231
239
|
}
|
|
232
240
|
GenerateSamples.writeRaw(fp, '');
|
|
233
241
|
}
|
|
@@ -240,8 +248,8 @@ class GenerateSamples {
|
|
|
240
248
|
const result = new DateSerializer(response.clauses || []).serialize();
|
|
241
249
|
GenerateSamples.writeRaw(fp, 'Output: ' + result);
|
|
242
250
|
}
|
|
243
|
-
if (response.
|
|
244
|
-
GenerateSamples.writeJson(fp, '
|
|
251
|
+
if (response.logs && response.logs.length > 0) {
|
|
252
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
245
253
|
}
|
|
246
254
|
GenerateSamples.writeRaw(fp, '');
|
|
247
255
|
}
|
|
@@ -254,8 +262,8 @@ class GenerateSamples {
|
|
|
254
262
|
const result = new NumberSerializer(response.clauses || []).serialize();
|
|
255
263
|
GenerateSamples.writeRaw(fp, 'Output: ' + result);
|
|
256
264
|
}
|
|
257
|
-
if (response.
|
|
258
|
-
GenerateSamples.writeJson(fp, '
|
|
265
|
+
if (response.logs && response.logs.length > 0) {
|
|
266
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
259
267
|
}
|
|
260
268
|
GenerateSamples.writeRaw(fp, '');
|
|
261
269
|
}
|
|
@@ -268,8 +276,8 @@ class GenerateSamples {
|
|
|
268
276
|
const result = new StringSerializer(response.clauses || []).serialize();
|
|
269
277
|
GenerateSamples.writeRaw(fp, 'Output: ' + result);
|
|
270
278
|
}
|
|
271
|
-
if (response.
|
|
272
|
-
GenerateSamples.writeJson(fp, '
|
|
279
|
+
if (response.logs && response.logs.length > 0) {
|
|
280
|
+
GenerateSamples.writeJson(fp, 'Logs: ', ...response.logs);
|
|
273
281
|
}
|
|
274
282
|
GenerateSamples.writeRaw(fp, '');
|
|
275
283
|
}
|
package/src/index.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
|
export {BooleanParser} from './boolean_parser';
|
|
2
9
|
export {DateParser} from './date_parser';
|
|
3
10
|
export {NumberParser} from './number_parser';
|
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) {
|