@malloydata/malloy-filter 0.0.237-dev250222012247 → 0.0.237-dev250222034547
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/a_simple_parser.js +12 -9
- package/dist/a_simple_parser.js.map +1 -1
- package/dist/base_parser.d.ts +0 -2
- package/dist/base_parser.js.map +1 -1
- package/dist/boolean_parser.d.ts +2 -2
- package/dist/boolean_parser.js.map +1 -1
- package/dist/boolean_serializer.d.ts +4 -4
- package/dist/boolean_serializer.js +3 -3
- package/dist/boolean_serializer.js.map +1 -1
- package/dist/clause_types.d.ts +15 -41
- package/dist/date_parser.d.ts +13 -11
- package/dist/date_parser.js +187 -130
- package/dist/date_parser.js.map +1 -1
- package/dist/date_serializer.d.ts +6 -5
- package/dist/date_serializer.js +53 -71
- package/dist/date_serializer.js.map +1 -1
- package/dist/date_types.d.ts +69 -0
- package/dist/{filter_types.js → date_types.js} +1 -1
- package/dist/date_types.js.map +1 -0
- package/dist/generate_samples.js +154 -85
- package/dist/generate_samples.js.map +1 -1
- package/dist/number_parser.d.ts +2 -2
- package/dist/number_parser.js.map +1 -1
- package/dist/number_serializer.d.ts +4 -4
- package/dist/number_serializer.js +3 -3
- package/dist/number_serializer.js.map +1 -1
- package/dist/string_parser.d.ts +2 -2
- package/dist/string_parser.js.map +1 -1
- package/dist/string_serializer.d.ts +5 -5
- package/dist/string_serializer.js +5 -5
- package/dist/string_serializer.js.map +1 -1
- package/package.json +1 -2
- package/src/a_simple_parser.ts +12 -9
- package/src/base_parser.ts +0 -3
- package/src/boolean_parser.ts +7 -3
- package/src/boolean_serializer.ts +5 -6
- package/src/clause_types.ts +15 -97
- package/src/date_parser.ts +224 -191
- package/src/date_serializer.ts +55 -87
- package/src/date_types.ts +149 -0
- package/src/generate_samples.ts +170 -107
- package/src/number_parser.ts +5 -5
- package/src/number_serializer.ts +5 -6
- package/src/string_parser.ts +14 -9
- package/src/string_serializer.ts +8 -9
- package/tsconfig.json +1 -6
- package/dist/a_simple_serializer.d.ts +0 -1
- package/dist/a_simple_serializer.js +0 -31
- package/dist/a_simple_serializer.js.map +0 -1
- package/dist/base_serializer.d.ts +0 -6
- package/dist/base_serializer.js +0 -11
- package/dist/base_serializer.js.map +0 -1
- package/dist/filter_parser.d.ts +0 -12
- package/dist/filter_parser.js +0 -66
- package/dist/filter_parser.js.map +0 -1
- package/dist/filter_serializer.d.ts +0 -13
- package/dist/filter_serializer.js +0 -43
- package/dist/filter_serializer.js.map +0 -1
- package/dist/filter_types.d.ts +0 -10
- package/dist/filter_types.js.map +0 -1
- package/src/a_simple_serializer.ts +0 -40
- package/src/base_serializer.ts +0 -9
- package/src/filter_parser.ts +0 -68
- package/src/filter_serializer.ts +0 -49
- package/src/filter_types.ts +0 -12
package/dist/a_simple_parser.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const
|
|
3
|
+
const boolean_parser_1 = require("./boolean_parser");
|
|
4
|
+
const string_parser_1 = require("./string_parser");
|
|
5
|
+
const number_parser_1 = require("./number_parser");
|
|
6
|
+
const date_parser_1 = require("./date_parser");
|
|
4
7
|
/* eslint-disable no-console */
|
|
5
8
|
function aSimpleParser() {
|
|
6
9
|
let str = 'CAT,DOG';
|
|
7
|
-
|
|
8
|
-
console.log(str, '\n', ...
|
|
10
|
+
const stringResponse = new string_parser_1.StringParser(str).parse();
|
|
11
|
+
console.log(str, '\n', ...stringResponse.clauses, '\n');
|
|
9
12
|
str = '-5.5, 10, 2.3e7';
|
|
10
|
-
|
|
11
|
-
console.log(str, '\n', ...
|
|
13
|
+
const numberResponse = new number_parser_1.NumberParser(str).parse();
|
|
14
|
+
console.log(str, '\n', ...numberResponse.clauses, '\n');
|
|
12
15
|
str = 'null, false';
|
|
13
|
-
|
|
14
|
-
console.log(str, '\n', ...
|
|
16
|
+
const booleanResponse = new boolean_parser_1.BooleanParser(str).parse();
|
|
17
|
+
console.log(str, '\n', ...booleanResponse.clauses, '\n');
|
|
15
18
|
str = 'after 2025-10-05';
|
|
16
|
-
|
|
17
|
-
console.log(str, '\n', ...
|
|
19
|
+
const dateResponse = new date_parser_1.DateParser(str).parse();
|
|
20
|
+
console.log(str, '\n', ...dateResponse.clauses, '\n');
|
|
18
21
|
}
|
|
19
22
|
aSimpleParser();
|
|
20
23
|
//# sourceMappingURL=a_simple_parser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a_simple_parser.js","sourceRoot":"","sources":["../src/a_simple_parser.ts"],"names":[],"mappings":";;AAAA,mDAA6C;
|
|
1
|
+
{"version":3,"file":"a_simple_parser.js","sourceRoot":"","sources":["../src/a_simple_parser.ts"],"names":[],"mappings":";;AAAA,qDAA+C;AAC/C,mDAA6C;AAC7C,mDAA6C;AAC7C,+CAAyC;AAEzC,+BAA+B;AAC/B,SAAS,aAAa;IACpB,IAAI,GAAG,GAAG,SAAS,CAAC;IACpB,MAAM,cAAc,GAAG,IAAI,4BAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAExD,GAAG,GAAG,iBAAiB,CAAC;IACxB,MAAM,cAAc,GAAG,IAAI,4BAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAExD,GAAG,GAAG,aAAa,CAAC;IACpB,MAAM,eAAe,GAAG,IAAI,8BAAa,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAEzD,GAAG,GAAG,kBAAkB,CAAC;IACzB,MAAM,YAAY,GAAG,IAAI,wBAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACxD,CAAC;AAED,aAAa,EAAE,CAAC"}
|
package/dist/base_parser.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { Token } from './token_types';
|
|
2
|
-
import { FilterParserResponse } from './filter_types';
|
|
3
2
|
export declare abstract class BaseParser {
|
|
4
3
|
protected inputString: string;
|
|
5
4
|
protected index: number;
|
|
6
5
|
protected tokens: Token[];
|
|
7
6
|
constructor(inputString: string);
|
|
8
7
|
getTokens(): Token[];
|
|
9
|
-
abstract parse(): FilterParserResponse;
|
|
10
8
|
protected getAt(index: number): Token;
|
|
11
9
|
protected getNext(): Token;
|
|
12
10
|
protected static matchTokenTypes(candidates: string[], index: number, tokens: Token[]): boolean;
|
package/dist/base_parser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base_parser.js","sourceRoot":"","sources":["../src/base_parser.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"base_parser.js","sourceRoot":"","sources":["../src/base_parser.ts"],"names":[],"mappings":";;;AAEA,MAAsB,UAAU;IAK9B,YAAY,WAAmB;QAC7B,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAEM,SAAS;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAES,KAAK,CAAC,KAAa;QAC3B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAES,OAAO;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAES,MAAM,CAAC,eAAe,CAC9B,UAAoB,EACpB,KAAa,EACb,MAAe;QAEf,MAAM,QAAQ,GAAG,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC;QAC3C,IAAI,KAAK,GAAG,CAAC,IAAI,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE;YACzC,OAAO,KAAK,CAAC;SACd;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC1C,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE;gBAC5C,OAAO,KAAK,CAAC;aACd;SACF;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAvCD,gCAuCC"}
|
package/dist/boolean_parser.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { BooleanParserResponse } from './clause_types';
|
|
1
2
|
import { BaseParser } from './base_parser';
|
|
2
|
-
import { FilterParserResponse } from './filter_types';
|
|
3
3
|
export declare class BooleanParser extends BaseParser {
|
|
4
4
|
constructor(input: string);
|
|
5
5
|
private tokenize;
|
|
6
|
-
parse():
|
|
6
|
+
parse(): BooleanParserResponse;
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boolean_parser.js","sourceRoot":"","sources":["../src/boolean_parser.ts"],"names":[],"mappings":";;;AAAA,2CAAqE;
|
|
1
|
+
{"version":3,"file":"boolean_parser.js","sourceRoot":"","sources":["../src/boolean_parser.ts"],"names":[],"mappings":";;;AAAA,2CAAqE;AAOrE,+CAAyC;AAEzC,MAAa,aAAc,SAAQ,wBAAU;IAC3C,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAEO,QAAQ;QACd,MAAM,iBAAiB,GAAmB,CAAC,EAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAC,CAAC,CAAC;QACpE,MAAM,YAAY,GAAmB;YACnC,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAC;YAC/C,EAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAC;YACnD,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAC;YAC/C,EAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAC;SAClD,CAAC;QACF,MAAM,MAAM,GAAoB;YAC9B,kBAAkB,EAAE,IAAI;YACxB,iBAAiB,EAAE,IAAI;YACvB,iBAAiB;YACjB,YAAY,EAAE,YAAY;SAC3B,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,qBAAS,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,qBAAS,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACzE,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,MAAM,MAAM,GAAkB,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,GAAG,EAAE;gBACtB,IAAI,CAAC,KAAK,EAAE,CAAC;aACd;iBAAM,IACL,KAAK,CAAC,IAAI,KAAK,MAAM;gBACrB,KAAK,CAAC,IAAI,KAAK,MAAM;gBACrB,KAAK,CAAC,IAAI,KAAK,OAAO;gBACtB,KAAK,CAAC,IAAI,KAAK,SAAS,EACxB;gBACA,MAAM,MAAM,GAAkB,EAAC,QAAQ,EAAE,KAAK,CAAC,IAAuB,EAAC,CAAC;gBACxE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACrB,IAAI,CAAC,KAAK,EAAE,CAAC;aACd;iBAAM;gBACL,MAAM,CAAC,IAAI,CAAC;oBACV,OAAO,EAAE,gBAAgB,GAAG,KAAK,CAAC,KAAK;oBACvC,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;iBACzB,CAAC,CAAC;gBACH,IAAI,CAAC,KAAK,EAAE,CAAC;aACd;SACF;QACD,OAAO,EAAC,OAAO,EAAE,MAAM,EAAC,CAAC;IAC3B,CAAC;CACF;AAtDD,sCAsDC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
constructor(clauses:
|
|
1
|
+
import { BooleanClause } from './clause_types';
|
|
2
|
+
export declare class BooleanSerializer {
|
|
3
|
+
private clauses;
|
|
4
|
+
constructor(clauses: BooleanClause[]);
|
|
5
5
|
serialize(): string;
|
|
6
6
|
private static booleanClauseToString;
|
|
7
7
|
private static clauseToString;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BooleanSerializer = void 0;
|
|
4
|
-
|
|
5
|
-
class BooleanSerializer extends base_serializer_1.BaseSerializer {
|
|
4
|
+
class BooleanSerializer {
|
|
6
5
|
constructor(clauses) {
|
|
7
|
-
|
|
6
|
+
this.clauses = clauses;
|
|
7
|
+
this.clauses = clauses;
|
|
8
8
|
}
|
|
9
9
|
serialize() {
|
|
10
10
|
const result = BooleanSerializer.clauseToString(this.clauses);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boolean_serializer.js","sourceRoot":"","sources":["../src/boolean_serializer.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"boolean_serializer.js","sourceRoot":"","sources":["../src/boolean_serializer.ts"],"names":[],"mappings":";;;AAEA,MAAa,iBAAiB;IAC5B,YAAoB,OAAwB;QAAxB,YAAO,GAAP,OAAO,CAAiB;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAEM,SAAS;QACd,MAAM,MAAM,GAAG,iBAAiB,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9D,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAEO,MAAM,CAAC,qBAAqB,CAAC,MAAqB;QACxD,OAAO,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;IACnE,CAAC;IAEO,MAAM,CAAC,cAAc,CAAC,OAAwB;QACpD,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;YAC5B,IAAI,UAAU,IAAI,MAAM,EAAE;gBACxB,MAAM,IAAI,iBAAiB,CAAC,qBAAqB,CAC/C,MAAuB,CACxB,CAAC;aACH;iBAAM;gBACL,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;aACrE;YACD,MAAM,IAAI,IAAI,CAAC;SAChB;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA5BD,8CA4BC"}
|
package/dist/clause_types.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface NumberRange {
|
|
|
15
15
|
export type QuoteType = 'SINGLE' | 'DOUBLE' | 'BACKTICK' | 'TRIPLESINGLE' | 'TRIPLEDOUBLE' | 'ESCAPEDSINGLE' | 'ESCAPEDDOUBLE' | 'ESCAPEDBACKTICK';
|
|
16
16
|
export type StringOperator = 'EMPTY' | 'NOTEMPTY' | 'starts' | 'ends' | 'contains' | 'notStarts' | 'notEnds' | 'notContains' | '~' | '=' | '!~' | '!=';
|
|
17
17
|
export type StringValue = string | null;
|
|
18
|
-
export interface
|
|
18
|
+
export interface StringClause {
|
|
19
19
|
operator: StringOperator;
|
|
20
20
|
values: StringValue[];
|
|
21
21
|
quotes?: QuoteType[];
|
|
@@ -24,47 +24,21 @@ export type BooleanOperator = 'TRUE' | 'FALSE' | 'NULL' | 'NOTNULL';
|
|
|
24
24
|
export interface BooleanClause {
|
|
25
25
|
operator: BooleanOperator;
|
|
26
26
|
}
|
|
27
|
-
export type
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
prefix?: DatePrefix;
|
|
33
|
-
operator: DateMomentNowOperator;
|
|
34
|
-
}
|
|
35
|
-
export type DateMomentIntervalOperator = 'LAST' | 'THIS' | 'NEXT';
|
|
36
|
-
export interface DateMomentInterval {
|
|
37
|
-
prefix?: DatePrefix;
|
|
38
|
-
operator: DateMomentIntervalOperator;
|
|
39
|
-
unit: DateTimeUnit | DateWeekday;
|
|
40
|
-
}
|
|
41
|
-
export type DateMomentNumberIntervalOperator = 'LASTN' | 'NEXTN' | 'AGO' | 'FROMNOW';
|
|
42
|
-
export interface DateMomentNumberInterval {
|
|
43
|
-
prefix?: DatePrefix;
|
|
44
|
-
operator: DateMomentNumberIntervalOperator;
|
|
45
|
-
unit: DateTimeUnit;
|
|
46
|
-
value: string;
|
|
27
|
+
export type NumberClause = NumberCondition | NumberRange;
|
|
28
|
+
export interface FilterError {
|
|
29
|
+
message: string;
|
|
30
|
+
startIndex: number;
|
|
31
|
+
endIndex: number;
|
|
47
32
|
}
|
|
48
|
-
export
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
operator: DateMomentNumberUnitOperator;
|
|
52
|
-
unit: DateTimeUnit;
|
|
53
|
-
value: string;
|
|
33
|
+
export interface BooleanParserResponse {
|
|
34
|
+
clauses: BooleanClause[];
|
|
35
|
+
errors: FilterError[];
|
|
54
36
|
}
|
|
55
|
-
export
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
operator: DateMomentNumberOperator;
|
|
59
|
-
date: string;
|
|
60
|
-
time?: string;
|
|
37
|
+
export interface NumberParserResponse {
|
|
38
|
+
clauses: NumberClause[];
|
|
39
|
+
errors: FilterError[];
|
|
61
40
|
}
|
|
62
|
-
export
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
operator: 'TO' | 'FOR';
|
|
66
|
-
end: DateMoment;
|
|
41
|
+
export interface StringParserResponse {
|
|
42
|
+
clauses: StringClause[];
|
|
43
|
+
errors: FilterError[];
|
|
67
44
|
}
|
|
68
|
-
export type NumberClause = NumberCondition | NumberRange;
|
|
69
|
-
export type DateClause = DateMoment | DateRange;
|
|
70
|
-
export type Clause = NumberClause | StringCondition | BooleanClause | DateClause;
|
package/dist/date_parser.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { DateParserResponse } from './date_types';
|
|
1
2
|
import { BaseParser } from './base_parser';
|
|
2
|
-
import { FilterParserResponse } from './filter_types';
|
|
3
3
|
export declare class DateParser extends BaseParser {
|
|
4
4
|
private static readonly yearRegex;
|
|
5
5
|
private static readonly negatedStartRegex;
|
|
@@ -7,16 +7,18 @@ export declare class DateParser extends BaseParser {
|
|
|
7
7
|
private tokenize;
|
|
8
8
|
private mergeMomentTokens;
|
|
9
9
|
private matchAndMerge;
|
|
10
|
-
parse():
|
|
11
|
-
private static
|
|
12
|
-
private static
|
|
13
|
-
private static
|
|
14
|
-
private static
|
|
15
|
-
private static
|
|
16
|
-
private static
|
|
17
|
-
private static
|
|
18
|
-
private static
|
|
10
|
+
parse(): DateParserResponse;
|
|
11
|
+
private static createMomentClause;
|
|
12
|
+
private static createIntervalMoment;
|
|
13
|
+
private static createOffsetMoment;
|
|
14
|
+
private static createSpanMoment;
|
|
15
|
+
private static createDateDuration;
|
|
16
|
+
private static createAbsoluteMoment;
|
|
17
|
+
private static createNamedMoment;
|
|
18
|
+
private static isValidNumber;
|
|
19
|
+
private static createDurationFromMerged;
|
|
20
|
+
private static createClauseFromMerged;
|
|
19
21
|
private isMatchingToken;
|
|
20
22
|
private handleRange;
|
|
21
|
-
private
|
|
23
|
+
private handleMerged;
|
|
22
24
|
}
|
package/dist/date_parser.js
CHANGED
|
@@ -39,7 +39,7 @@ class DateParser extends base_parser_1.BaseParser {
|
|
|
39
39
|
{ type: 'FROM', value: 'from', ignoreCase: true },
|
|
40
40
|
{ type: 'FOR', value: 'for', ignoreCase: true },
|
|
41
41
|
{ type: 'TO', value: 'to', ignoreCase: true },
|
|
42
|
-
{ type: '
|
|
42
|
+
{ type: 'YEAR', value: /^\d\d\d\d$/ },
|
|
43
43
|
{ type: 'NUMBER', value: /^[\d.]+/, ignoreCase: true },
|
|
44
44
|
];
|
|
45
45
|
const params = {
|
|
@@ -57,28 +57,28 @@ class DateParser extends base_parser_1.BaseParser {
|
|
|
57
57
|
const output = [];
|
|
58
58
|
this.index = 0;
|
|
59
59
|
while (this.index < this.tokens.length) {
|
|
60
|
-
if (this.matchAndMerge('LAST|UNITOFTIME',
|
|
61
|
-
this.matchAndMerge('LAST|DAYOFWEEK',
|
|
62
|
-
this.matchAndMerge('LAST|NUMBER|UNITOFTIME',
|
|
63
|
-
this.matchAndMerge('LAST|
|
|
64
|
-
this.matchAndMerge('THIS|UNITOFTIME',
|
|
65
|
-
this.matchAndMerge('NEXT|UNITOFTIME',
|
|
66
|
-
this.matchAndMerge('NEXT|DAYOFWEEK',
|
|
67
|
-
this.matchAndMerge('NEXT|NUMBER|UNITOFTIME',
|
|
68
|
-
this.matchAndMerge('NEXT|
|
|
69
|
-
this.matchAndMerge('NUMBER|UNITOFTIME|AGO',
|
|
70
|
-
this.matchAndMerge('
|
|
71
|
-
this.matchAndMerge('NUMBER|UNITOFTIME|FROM|NOW',
|
|
72
|
-
this.matchAndMerge('
|
|
73
|
-
this.matchAndMerge('NUMBER|UNITOFTIME',
|
|
74
|
-
this.matchAndMerge('
|
|
75
|
-
this.matchAndMerge('DATE|TIME',
|
|
76
|
-
this.matchAndMerge('TODAY',
|
|
77
|
-
this.matchAndMerge('YESTERDAY',
|
|
78
|
-
this.matchAndMerge('TOMORROW',
|
|
79
|
-
this.matchAndMerge('DATE',
|
|
80
|
-
this.matchAndMerge('
|
|
81
|
-
this.matchAndMerge('NOW',
|
|
60
|
+
if (this.matchAndMerge('LAST|UNITOFTIME', output) ||
|
|
61
|
+
this.matchAndMerge('LAST|DAYOFWEEK', output) ||
|
|
62
|
+
this.matchAndMerge('LAST|NUMBER|UNITOFTIME', output) ||
|
|
63
|
+
this.matchAndMerge('LAST|YEAR|UNITOFTIME', output) ||
|
|
64
|
+
this.matchAndMerge('THIS|UNITOFTIME', output) ||
|
|
65
|
+
this.matchAndMerge('NEXT|UNITOFTIME', output) ||
|
|
66
|
+
this.matchAndMerge('NEXT|DAYOFWEEK', output) ||
|
|
67
|
+
this.matchAndMerge('NEXT|NUMBER|UNITOFTIME', output) ||
|
|
68
|
+
this.matchAndMerge('NEXT|YEAR|UNITOFTIME', output) ||
|
|
69
|
+
this.matchAndMerge('NUMBER|UNITOFTIME|AGO', output) ||
|
|
70
|
+
this.matchAndMerge('YEAR|UNITOFTIME|AGO', output) ||
|
|
71
|
+
this.matchAndMerge('NUMBER|UNITOFTIME|FROM|NOW', output) ||
|
|
72
|
+
this.matchAndMerge('YEAR|UNITOFTIME|FROM|NOW', output) ||
|
|
73
|
+
this.matchAndMerge('NUMBER|UNITOFTIME', output) ||
|
|
74
|
+
this.matchAndMerge('YEAR|UNITOFTIME', output) ||
|
|
75
|
+
this.matchAndMerge('DATE|TIME', output) ||
|
|
76
|
+
this.matchAndMerge('TODAY', output) ||
|
|
77
|
+
this.matchAndMerge('YESTERDAY', output) ||
|
|
78
|
+
this.matchAndMerge('TOMORROW', output) ||
|
|
79
|
+
this.matchAndMerge('DATE', output) ||
|
|
80
|
+
this.matchAndMerge('YEAR', output) ||
|
|
81
|
+
this.matchAndMerge('NOW', output)) {
|
|
82
82
|
continue;
|
|
83
83
|
}
|
|
84
84
|
else {
|
|
@@ -88,12 +88,12 @@ class DateParser extends base_parser_1.BaseParser {
|
|
|
88
88
|
}
|
|
89
89
|
return output;
|
|
90
90
|
}
|
|
91
|
-
matchAndMerge(types,
|
|
91
|
+
matchAndMerge(types, output) {
|
|
92
92
|
const idx = this.index;
|
|
93
|
-
const matchedTokens = tokenizer_1.Tokenizer.matchTypes(types, tokens, idx);
|
|
93
|
+
const matchedTokens = tokenizer_1.Tokenizer.matchTypes(types, this.tokens, idx);
|
|
94
94
|
if (matchedTokens) {
|
|
95
95
|
output.push({
|
|
96
|
-
type: '
|
|
96
|
+
type: 'MERGE:' + types,
|
|
97
97
|
value: '',
|
|
98
98
|
values: matchedTokens,
|
|
99
99
|
startIndex: matchedTokens[0].startIndex,
|
|
@@ -136,7 +136,7 @@ class DateParser extends base_parser_1.BaseParser {
|
|
|
136
136
|
this.index++;
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
-
else if (this.
|
|
139
|
+
else if (this.handleMerged(prefix, clauses)) {
|
|
140
140
|
prefix = undefined;
|
|
141
141
|
}
|
|
142
142
|
else {
|
|
@@ -151,116 +151,154 @@ class DateParser extends base_parser_1.BaseParser {
|
|
|
151
151
|
}
|
|
152
152
|
return { clauses, errors };
|
|
153
153
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
.type;
|
|
158
|
-
const unit = tokens[1].value;
|
|
159
|
-
const moment = { operator, unit };
|
|
160
|
-
if (prefix) {
|
|
161
|
-
moment.prefix = prefix;
|
|
154
|
+
static createMomentClause(prefix, moment) {
|
|
155
|
+
if (!prefix) {
|
|
156
|
+
return { operator: 'ON', moment }; // DateOnClause
|
|
162
157
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const operator = type0 === 'LAST' ? 'LASTN' : 'NEXTN';
|
|
169
|
-
const value = tokens[1].value;
|
|
170
|
-
const unit = tokens[2].value;
|
|
171
|
-
const moment = { operator, value, unit };
|
|
172
|
-
if (prefix) {
|
|
173
|
-
moment.prefix = prefix;
|
|
158
|
+
else if (prefix === 'BEFORE') {
|
|
159
|
+
return { operator: 'BEFORE', moment }; // DateBeforeClause
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return { operator: 'AFTER', moment }; // DateAfterClause
|
|
174
163
|
}
|
|
175
|
-
return moment;
|
|
176
164
|
}
|
|
177
|
-
//
|
|
178
|
-
static
|
|
179
|
-
const
|
|
180
|
-
|
|
165
|
+
// (BEFORE|AFTER) LAST|DAYOFWEEK
|
|
166
|
+
static createIntervalMoment(prefix, tokens) {
|
|
167
|
+
const kind = tokens[0]
|
|
168
|
+
.type;
|
|
181
169
|
const unit = tokens[1].value;
|
|
182
|
-
const moment = {
|
|
183
|
-
|
|
184
|
-
moment.prefix = prefix;
|
|
185
|
-
}
|
|
186
|
-
return moment;
|
|
170
|
+
const moment = { type: 'INTERVAL', kind, unit };
|
|
171
|
+
return DateParser.createMomentClause(prefix, moment);
|
|
187
172
|
}
|
|
173
|
+
// NUMBER|UNITOFTIME|AGO
|
|
188
174
|
// NUMBER|UNITOFTIME|FROM|NOW
|
|
189
|
-
static
|
|
190
|
-
const
|
|
191
|
-
const value = tokens[0].value;
|
|
175
|
+
static createOffsetMoment(prefix, tokens) {
|
|
176
|
+
const amount = Number(tokens[0].value);
|
|
192
177
|
const unit = tokens[1].value;
|
|
193
|
-
const
|
|
194
|
-
if (
|
|
195
|
-
|
|
178
|
+
const direction = tokens[2].type === 'AGO' ? 'AGO' : 'FROMNOW';
|
|
179
|
+
if (!DateParser.isValidNumber(amount)) {
|
|
180
|
+
return undefined;
|
|
196
181
|
}
|
|
197
|
-
|
|
182
|
+
const moment = {
|
|
183
|
+
type: 'OFFSET_FROM_NOW',
|
|
184
|
+
direction,
|
|
185
|
+
amount,
|
|
186
|
+
unit,
|
|
187
|
+
};
|
|
188
|
+
return DateParser.createMomentClause(prefix, moment);
|
|
198
189
|
}
|
|
199
|
-
// NUMBER|UNITOFTIME
|
|
200
|
-
static
|
|
201
|
-
const
|
|
202
|
-
const value = tokens[0].value;
|
|
190
|
+
// (LAST|NEXT)|NUMBER|UNITOFTIME
|
|
191
|
+
static createSpanMoment(prefix, tokens) {
|
|
192
|
+
const amount = Number(tokens[0].value);
|
|
203
193
|
const unit = tokens[1].value;
|
|
204
|
-
const
|
|
194
|
+
const direction = tokens[2].type === 'LAST' ? 'LAST' : 'NEXT';
|
|
195
|
+
if (!DateParser.isValidNumber(amount)) {
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
const moment = { type: 'SPAN_FROM_NOW', direction, amount, unit };
|
|
199
|
+
return DateParser.createMomentClause(prefix, moment);
|
|
200
|
+
}
|
|
201
|
+
// (NUMBER|YEAR)|UNITOFTIME
|
|
202
|
+
static createDateDuration(prefix, tokens) {
|
|
205
203
|
if (prefix) {
|
|
206
|
-
|
|
204
|
+
return undefined; // before 7 hours is ambiguous, not allowed.
|
|
205
|
+
}
|
|
206
|
+
const operator = 'DURATION';
|
|
207
|
+
const amount = Number(tokens[0].value);
|
|
208
|
+
const unit = tokens[1].value;
|
|
209
|
+
if (!DateParser.isValidNumber(amount)) {
|
|
210
|
+
return undefined;
|
|
207
211
|
}
|
|
208
|
-
|
|
212
|
+
const clause = { operator, duration: { amount, unit } };
|
|
213
|
+
return clause;
|
|
209
214
|
}
|
|
210
|
-
// DATE DATE|TIME
|
|
211
|
-
static
|
|
212
|
-
|
|
213
|
-
|
|
215
|
+
// (BEFORE|AFTER) DATE DATE|TIME
|
|
216
|
+
static createAbsoluteMoment(prefix, tokens) {
|
|
217
|
+
let unit = 'YEAR';
|
|
218
|
+
let date = tokens[0].value;
|
|
214
219
|
if (tokens.length === 2) {
|
|
215
|
-
|
|
220
|
+
const timeStr = tokens[1].value;
|
|
221
|
+
date += ' ' + timeStr;
|
|
222
|
+
if (timeStr.length > 5)
|
|
223
|
+
unit = 'SECOND';
|
|
224
|
+
else
|
|
225
|
+
unit = 'MINUTE';
|
|
216
226
|
}
|
|
217
|
-
if (
|
|
218
|
-
|
|
227
|
+
else if (date.length > 7) {
|
|
228
|
+
unit = 'DAY';
|
|
219
229
|
}
|
|
220
|
-
|
|
230
|
+
else if (date.length > 4) {
|
|
231
|
+
unit = 'MONTH';
|
|
232
|
+
}
|
|
233
|
+
const moment = { type: 'ABSOLUTE', date, unit };
|
|
234
|
+
return DateParser.createMomentClause(prefix, moment);
|
|
221
235
|
}
|
|
222
236
|
// NOW YESTERDAY TODAY TOMORROW
|
|
223
|
-
static
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
237
|
+
static createNamedMoment(prefix, tokens) {
|
|
238
|
+
let momentName = 'NOW';
|
|
239
|
+
switch (tokens[0].type) {
|
|
240
|
+
case 'TODAY':
|
|
241
|
+
momentName = 'TODAY';
|
|
242
|
+
break;
|
|
243
|
+
case 'YESTERDAY':
|
|
244
|
+
momentName = 'YESTERDAY';
|
|
245
|
+
break;
|
|
246
|
+
case 'TOMORROW':
|
|
247
|
+
momentName = 'TOMORROW';
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
const moment = { type: 'NAMED', name: momentName };
|
|
251
|
+
return DateParser.createMomentClause(prefix, moment);
|
|
252
|
+
}
|
|
253
|
+
static isValidNumber(value) {
|
|
254
|
+
return Number.isNaN(value) === false;
|
|
255
|
+
}
|
|
256
|
+
static createDurationFromMerged(token) {
|
|
257
|
+
if (!token.values || token.values.length !== 2) {
|
|
258
|
+
return undefined;
|
|
229
259
|
}
|
|
230
|
-
|
|
260
|
+
if (token.type === 'MERGE:NUMBER|UNITOFTIME' ||
|
|
261
|
+
token.type === 'MERGE:YEAR|UNITOFTIME') {
|
|
262
|
+
const value = Number(token.values[0].value);
|
|
263
|
+
if (!DateParser.isValidNumber(value)) {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
const unit = token.values[1].value;
|
|
267
|
+
return { amount: value, unit: unit };
|
|
268
|
+
}
|
|
269
|
+
return undefined;
|
|
231
270
|
}
|
|
232
|
-
static
|
|
271
|
+
static createClauseFromMerged(prefix, token) {
|
|
233
272
|
const tokens = token.values || [];
|
|
234
273
|
switch (token.type) {
|
|
235
|
-
case '
|
|
236
|
-
case '
|
|
237
|
-
case '
|
|
238
|
-
case '
|
|
239
|
-
case '
|
|
240
|
-
return this.
|
|
241
|
-
case '
|
|
242
|
-
case '
|
|
243
|
-
case '
|
|
244
|
-
case '
|
|
245
|
-
return this.
|
|
246
|
-
case '
|
|
247
|
-
case '
|
|
248
|
-
|
|
249
|
-
case '
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
case '
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
case '
|
|
256
|
-
case '
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
case '
|
|
260
|
-
case '
|
|
261
|
-
case '
|
|
262
|
-
|
|
263
|
-
return this.createMomentNow(prefix, tokens);
|
|
274
|
+
case 'MERGE:LAST|UNITOFTIME':
|
|
275
|
+
case 'MERGE:LAST|DAYOFWEEK':
|
|
276
|
+
case 'MERGE:THIS|UNITOFTIME':
|
|
277
|
+
case 'MERGE:NEXT|UNITOFTIME':
|
|
278
|
+
case 'MERGE:NEXT|DAYOFWEEK':
|
|
279
|
+
return this.createIntervalMoment(prefix, tokens);
|
|
280
|
+
case 'MERGE:LAST|NUMBER|UNITOFTIME':
|
|
281
|
+
case 'MERGE:LAST|YEAR|UNITOFTIME':
|
|
282
|
+
case 'MERGE:NEXT|NUMBER|UNITOFTIME':
|
|
283
|
+
case 'MERGE:NEXT|YEAR|UNITOFTIME':
|
|
284
|
+
return this.createSpanMoment(prefix, tokens);
|
|
285
|
+
case 'MERGE:NUMBER|UNITOFTIME|AGO':
|
|
286
|
+
case 'MERGE:YEAR|UNITOFTIME|AGO':
|
|
287
|
+
case 'MERGE:NUMBER|UNITOFTIME|FROM|NOW':
|
|
288
|
+
case 'MERGE:YEAR|UNITOFTIME|FROM|NOW':
|
|
289
|
+
return this.createOffsetMoment(prefix, tokens);
|
|
290
|
+
case 'MERGE:NUMBER|UNITOFTIME':
|
|
291
|
+
case 'MERGE:YEAR|UNITOFTIME':
|
|
292
|
+
return this.createDateDuration(prefix, tokens);
|
|
293
|
+
case 'MERGE:DATE|TIME':
|
|
294
|
+
case 'MERGE:DATE':
|
|
295
|
+
case 'MERGE:YEAR':
|
|
296
|
+
return this.createAbsoluteMoment(prefix, tokens);
|
|
297
|
+
case 'MERGE:NOW':
|
|
298
|
+
case 'MERGE:TODAY':
|
|
299
|
+
case 'MERGE:YESTERDAY':
|
|
300
|
+
case 'MERGE:TOMORROW':
|
|
301
|
+
return this.createNamedMoment(prefix, tokens);
|
|
264
302
|
default:
|
|
265
303
|
return undefined;
|
|
266
304
|
}
|
|
@@ -274,31 +312,50 @@ class DateParser extends base_parser_1.BaseParser {
|
|
|
274
312
|
: this.tokens[position].type.startsWith(value);
|
|
275
313
|
}
|
|
276
314
|
handleRange(clauses) {
|
|
277
|
-
if (this.isMatchingToken(this.index, '
|
|
315
|
+
if (this.isMatchingToken(this.index, 'MERGE', false) &&
|
|
278
316
|
(this.isMatchingToken(this.index + 1, 'TO', true) ||
|
|
279
317
|
this.isMatchingToken(this.index + 1, 'FOR', true)) &&
|
|
280
|
-
this.isMatchingToken(this.index + 2, '
|
|
281
|
-
const
|
|
282
|
-
const
|
|
283
|
-
const
|
|
318
|
+
this.isMatchingToken(this.index + 2, 'MERGE', false)) {
|
|
319
|
+
const startToken = this.tokens[this.index];
|
|
320
|
+
const operator = this.tokens[this.index + 1].type; // TO | FOR
|
|
321
|
+
const endToken = this.tokens[this.index + 2];
|
|
322
|
+
const startClause = DateParser.createClauseFromMerged(undefined, startToken);
|
|
284
323
|
this.index += 3;
|
|
285
|
-
if (
|
|
324
|
+
if (startClause === undefined || !('moment' in startClause)) {
|
|
286
325
|
return false;
|
|
287
326
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
327
|
+
if (operator === 'TO') {
|
|
328
|
+
const endClause = DateParser.createClauseFromMerged(undefined, endToken);
|
|
329
|
+
if (endClause === undefined || !('moment' in endClause)) {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
const clause = {
|
|
333
|
+
operator: 'TO_RANGE',
|
|
334
|
+
from: startClause.moment,
|
|
335
|
+
to: endClause.moment,
|
|
336
|
+
};
|
|
337
|
+
clauses.push(clause);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
const endDuration = DateParser.createDurationFromMerged(endToken);
|
|
341
|
+
if (endDuration === undefined) {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
const clause = {
|
|
345
|
+
operator: 'FOR_RANGE',
|
|
346
|
+
from: startClause.moment,
|
|
347
|
+
duration: endDuration,
|
|
348
|
+
};
|
|
349
|
+
clauses.push(clause);
|
|
350
|
+
}
|
|
294
351
|
return true;
|
|
295
352
|
}
|
|
296
353
|
return false;
|
|
297
354
|
}
|
|
298
|
-
|
|
355
|
+
handleMerged(prefix, clauses) {
|
|
299
356
|
const token = this.getNext();
|
|
300
|
-
if (token.type.startsWith('
|
|
301
|
-
const clause = DateParser.
|
|
357
|
+
if (token.type.startsWith('MERGE')) {
|
|
358
|
+
const clause = DateParser.createClauseFromMerged(prefix, token);
|
|
302
359
|
this.index++;
|
|
303
360
|
if (clause === undefined) {
|
|
304
361
|
return false;
|