@wener/common 1.0.1 → 1.0.2

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.
@@ -0,0 +1,204 @@
1
+ /*
2
+ Grammar for advance search query
3
+
4
+ source: https://github.com/wenerme/wener/tree/master/tricks/languages/parser/peg/advance-search.peggy
5
+ ================================
6
+
7
+ ok OR yes AND NO AND NO
8
+ QUALIFIER.a:@me is:yes AND yes HELLO WORLD
9
+ start:>2019-09-12T12:20:30.123+08:00
10
+ a:[2, 1 ) -owner:@me AND YES
11
+ -a a yes OR KEY
12
+ NOT NOT AND AND OR OR
13
+ NOT -a
14
+ (NOT hello)
15
+ @AI:"Where is my car"
16
+ owner:@me
17
+ owner:!=@me
18
+ (a OR B)
19
+ ( a OR "B )" )
20
+ */
21
+
22
+ {
23
+ const OPERATORS = {
24
+ ":": "has",
25
+ ":=": "eq",
26
+ ":!=": "ne",
27
+ ":>": "gt",
28
+ ":>=": "gte",
29
+ ":<": "lt",
30
+ ":<=": "lte",
31
+ };
32
+ }
33
+
34
+ // todo make /**/b works
35
+ Main = @Exprs EOF
36
+
37
+ Exprs = _ @Expr|1.., __| _
38
+
39
+ Expr
40
+ = Comment
41
+ / OrExpr
42
+
43
+ Comment
44
+ = "/*" value:$[^*]* "*/" { return { type: "comment", value: value.trim() }; }
45
+
46
+ OrExpr
47
+ = head:AndExpr tail:(__ KW_OR __ @AndExpr)* {
48
+ return !tail.length
49
+ ? head
50
+ : { type: "logical", operator: "or", value: [head].concat(tail) };
51
+ }
52
+
53
+ AndExpr
54
+ = head:NotExpr tail:(__ KW_AND __ @NotExpr)* {
55
+ return !tail.length
56
+ ? head
57
+ : { type: "logical", operator: "and", value: [head].concat(tail) };
58
+ }
59
+
60
+ NotExpr
61
+ = KW_NOT __ value:NotExpr { return { type: "not", value }; }
62
+ / @ParenthesesExpr
63
+
64
+ ParenthesesExpr
65
+ = "(" _ value:Exprs _ ")" { return { type: "parentheses", value }; }
66
+ / @ComparisonExpr
67
+
68
+ ComparisonExpr
69
+ = modifier:(negative:"-" { return { negative: true }; } / "+" { return {}; })?
70
+ expr:(
71
+ field:field operator:":" value:range {
72
+ return { type: "compare", field, operator: "range", value };
73
+ }
74
+ / field:field operator:(":=" / ":!=" / ":") value:mention {
75
+ return {
76
+ type: "compare",
77
+ field,
78
+ operator: operator === ":!=" ? "ne" : "eq",
79
+ value,
80
+ };
81
+ }
82
+ / field:field
83
+ operator:(":=" / ":>" / ":<" / ":>=" / ":<=" / ":!=" / ":")
84
+ value:value {
85
+ return {
86
+ type: "compare",
87
+ field,
88
+ operator: OPERATORS[operator],
89
+ value,
90
+ };
91
+ }
92
+ ) { return { ...expr, ...modifier }; }
93
+ / "@" field:field ":" value:string {
94
+ return {
95
+ type: "compare",
96
+ field,
97
+ operator: "has",
98
+ value: { value },
99
+ mention: true,
100
+ };
101
+ }
102
+ / KeywordExpr
103
+
104
+ KeywordExpr
105
+ = negative:"-"? value:string {
106
+ return {
107
+ type: "keyword",
108
+ negative: Boolean(negative),
109
+ value,
110
+ exact: true,
111
+ };
112
+ }
113
+ / negative:"-"? value:keyword {
114
+ return { type: "keyword", negative: Boolean(negative), value };
115
+ }
116
+
117
+ keyword = [^-+,'" \r\n\t()] [^ \r\n\t)]* { return text(); }
118
+
119
+ // support field,
120
+ // support field.key
121
+ // MAYBE field.*, field.0
122
+ // MAYBE date(field)
123
+ field = $ident|1.., "."|
124
+
125
+ range
126
+ = minimum:(value / "*") ".." maximum:(value / "*") {
127
+ return {
128
+ type: "range",
129
+ minimum: minimum === "*" ? undefined : minimum,
130
+ maximum: maximum === "*" ? undefined : maximum,
131
+ };
132
+ }
133
+ / minimumBoundary:[\[(]
134
+ _
135
+ minimum:value?
136
+ _
137
+ ","
138
+ _
139
+ maximum:value?
140
+ _
141
+ maximumBoundary:[)\]] {
142
+ return {
143
+ type: "range",
144
+ minimum,
145
+ maximum,
146
+ minimumExclusive: minimumBoundary === "(",
147
+ maximumExclusive: maximumBoundary === ")",
148
+ };
149
+ }
150
+
151
+ mention = "@" value:ident { return { format: "mention", value }; }
152
+
153
+ value
154
+ = @date
155
+ / value:(ident / literal) { return { type: "literal", value }; }
156
+
157
+ // date-fns yyyy-MM-dd'T'HH:mm:ss.SSSXXX
158
+ // dayjs YYYY-MM-DDTHH:mm:ss.SSSZ
159
+ date
160
+ = ([1-9] [0-9]|3| "-" [0-9]|1..2| "-" [0-9]|1..2|) // date
161
+ time:(
162
+ "T"
163
+ ([0-9]|1..2| ":" [0-9]|1..2| ":" [0-9]|1..2|) // time
164
+ ("." [0-9]|1..3|)? // mills
165
+ ("Z" / "+" [0-9]|1..2| ":" [0-9]|1..2|)? // zone
166
+ )? { return { format: time ? "date-time" : "date", value: text() }; }
167
+
168
+ ident = ([a-zA-Z] [_a-zA-Z0-9]*) { return text(); }
169
+
170
+ literal
171
+ = string
172
+ / float
173
+ / int
174
+ / bool
175
+ / null
176
+
177
+ number = ([0-9]+ ("." [0-9]+)? / "." [0-9]+) { return parseFloat(text()); }
178
+
179
+ // todo escape
180
+ string = "\"" v:[^"]* "\"" { return v.join(""); }
181
+
182
+ bool = ("true" / "false") { return text().toLowerCase() === "true"; }
183
+
184
+ int = [0-9]+ { return parseInt(text()); }
185
+
186
+ float = [0-9]+ "." [0-9]+ { return parseFloat(text()); }
187
+
188
+ null = "null" { return null; }
189
+
190
+ ident_start = [A-Za-z_]
191
+
192
+ KW_OR = "OR" !ident_start
193
+
194
+ KW_AND = "AND" !ident_start
195
+
196
+ KW_NOT = "NOT" !ident_start
197
+
198
+ _ "whitespace" = white* { return ""; }
199
+
200
+ __ "whitespace" = white+ { return " "; }
201
+
202
+ white = [ \t\n\r]
203
+
204
+ EOF = !.
@@ -0,0 +1,71 @@
1
+ export type Exprs = Expr[];
2
+ export type Expr =
3
+ | CommentExpr
4
+ | ParenthesesExpr
5
+ | KeywordCondition
6
+ | LogicalCondition
7
+ | NotCondition
8
+ | CompareCondition;
9
+
10
+ export type CommentExpr = {
11
+ type: 'comment';
12
+ value: string;
13
+ };
14
+
15
+ export type ParenthesesExpr = {
16
+ type: 'parentheses';
17
+ value: Expr[];
18
+ };
19
+
20
+ export type KeywordCondition = {
21
+ type: 'keyword';
22
+ value: string;
23
+ negative?: boolean;
24
+ exact?: boolean;
25
+ };
26
+
27
+ export type LogicalCondition = {
28
+ type: 'logical';
29
+ operator: 'and' | 'or';
30
+ value: Expr[];
31
+ };
32
+
33
+ export type NotCondition = {
34
+ type: 'not';
35
+ value: Expr;
36
+ };
37
+
38
+ export type CompareCondition = {
39
+ type: 'compare';
40
+ field: string;
41
+ /**
42
+ * mention value for eq, ne only
43
+ * range require range value
44
+ */
45
+ operator: 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'range' | 'has';
46
+ negative?: boolean;
47
+ mention?: boolean;
48
+ value: Value;
49
+ };
50
+
51
+ export type Value = LiteralValue | RangeValue | MentionValue;
52
+
53
+ export type LiteralValue = {
54
+ type?: 'literal';
55
+ format?: 'date' | 'date-time';
56
+ value: string | number | null;
57
+ };
58
+
59
+ export type MentionValue = {
60
+ type?: 'literal';
61
+ format: 'mention';
62
+ value: string;
63
+ };
64
+
65
+ export type RangeValue = {
66
+ type: 'range';
67
+ minimum: LiteralValue | undefined;
68
+ maximum: LiteralValue | undefined;
69
+ minimumExclusive: boolean;
70
+ maximumExclusive: boolean;
71
+ };