@dra2020/baseclient 1.0.10 → 1.0.13
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/package.json +16 -15
- package/LICENSE +0 -21
- package/README.md +0 -26
- package/dist/all/all.d.ts +0 -20
- package/dist/baseclient.js +0 -10103
- package/dist/baseclient.js.map +0 -1
- package/dist/context/all.d.ts +0 -1
- package/dist/context/context.d.ts +0 -13
- package/dist/filterexpr/all.d.ts +0 -1
- package/dist/filterexpr/filterexpr.d.ts +0 -67
- package/dist/fsm/all.d.ts +0 -1
- package/dist/fsm/fsm.d.ts +0 -119
- package/dist/geo/all.d.ts +0 -2
- package/dist/geo/geo.d.ts +0 -67
- package/dist/geo/vfeature.d.ts +0 -4
- package/dist/logabstract/all.d.ts +0 -1
- package/dist/logabstract/log.d.ts +0 -26
- package/dist/logclient/all.d.ts +0 -1
- package/dist/logclient/log.d.ts +0 -6
- package/dist/ot-editutil/all.d.ts +0 -2
- package/dist/ot-editutil/oteditutil.d.ts +0 -14
- package/dist/ot-editutil/otmaputil.d.ts +0 -21
- package/dist/ot-js/all.d.ts +0 -9
- package/dist/ot-js/otarray.d.ts +0 -111
- package/dist/ot-js/otclientengine.d.ts +0 -38
- package/dist/ot-js/otcomposite.d.ts +0 -37
- package/dist/ot-js/otcounter.d.ts +0 -17
- package/dist/ot-js/otengine.d.ts +0 -22
- package/dist/ot-js/otmap.d.ts +0 -19
- package/dist/ot-js/otserverengine.d.ts +0 -38
- package/dist/ot-js/otsession.d.ts +0 -113
- package/dist/ot-js/ottypes.d.ts +0 -29
- package/dist/poly/all.d.ts +0 -15
- package/dist/poly/blend.d.ts +0 -1
- package/dist/poly/boundbox.d.ts +0 -16
- package/dist/poly/cartesian.d.ts +0 -5
- package/dist/poly/graham-scan.d.ts +0 -8
- package/dist/poly/hash.d.ts +0 -1
- package/dist/poly/matrix.d.ts +0 -24
- package/dist/poly/minbound.d.ts +0 -1
- package/dist/poly/poly.d.ts +0 -52
- package/dist/poly/polybin.d.ts +0 -5
- package/dist/poly/polylabel.d.ts +0 -7
- package/dist/poly/polypack.d.ts +0 -30
- package/dist/poly/polyround.d.ts +0 -1
- package/dist/poly/polysimplify.d.ts +0 -1
- package/dist/poly/quad.d.ts +0 -48
- package/dist/poly/selfintersect.d.ts +0 -1
- package/dist/poly/shamos.d.ts +0 -1
- package/dist/poly/simplify.d.ts +0 -2
- package/dist/poly/topo.d.ts +0 -46
- package/dist/poly/union.d.ts +0 -49
- package/dist/util/all.d.ts +0 -5
- package/dist/util/bintrie.d.ts +0 -93
- package/dist/util/countedhash.d.ts +0 -19
- package/dist/util/gradient.d.ts +0 -15
- package/dist/util/indexedarray.d.ts +0 -15
- package/dist/util/util.d.ts +0 -68
- package/docs/context.md +0 -2
- package/docs/filterexpr.md +0 -22
- package/docs/fsm.md +0 -243
- package/docs/logabstract.md +0 -2
- package/docs/logclient.md +0 -2
- package/docs/ot-editutil.md +0 -2
- package/docs/ot-js.md +0 -95
- package/docs/poly.md +0 -103
- package/docs/util.md +0 -2
- package/lib/all/all.ts +0 -21
- package/lib/context/all.ts +0 -1
- package/lib/context/context.ts +0 -82
- package/lib/filterexpr/all.ts +0 -1
- package/lib/filterexpr/filterexpr.ts +0 -699
- package/lib/fsm/all.ts +0 -1
- package/lib/fsm/fsm.ts +0 -559
- package/lib/geo/all.ts +0 -2
- package/lib/geo/geo.ts +0 -452
- package/lib/geo/vfeature.ts +0 -34
- package/lib/logabstract/all.ts +0 -1
- package/lib/logabstract/log.ts +0 -55
- package/lib/logclient/all.ts +0 -1
- package/lib/logclient/log.ts +0 -105
- package/lib/ot-editutil/all.ts +0 -2
- package/lib/ot-editutil/oteditutil.ts +0 -180
- package/lib/ot-editutil/otmaputil.ts +0 -209
- package/lib/ot-js/all.ts +0 -9
- package/lib/ot-js/otarray.ts +0 -1168
- package/lib/ot-js/otclientengine.ts +0 -327
- package/lib/ot-js/otcomposite.ts +0 -247
- package/lib/ot-js/otcounter.ts +0 -145
- package/lib/ot-js/otengine.ts +0 -71
- package/lib/ot-js/otmap.ts +0 -144
- package/lib/ot-js/otserverengine.ts +0 -329
- package/lib/ot-js/otsession.ts +0 -201
- package/lib/ot-js/ottypes.ts +0 -98
- package/lib/poly/all.ts +0 -15
- package/lib/poly/blend.ts +0 -27
- package/lib/poly/boundbox.ts +0 -102
- package/lib/poly/cartesian.ts +0 -130
- package/lib/poly/graham-scan.ts +0 -401
- package/lib/poly/hash.ts +0 -15
- package/lib/poly/matrix.ts +0 -309
- package/lib/poly/minbound.ts +0 -211
- package/lib/poly/poly.ts +0 -767
- package/lib/poly/polybin.ts +0 -218
- package/lib/poly/polylabel.ts +0 -204
- package/lib/poly/polypack.ts +0 -458
- package/lib/poly/polyround.ts +0 -30
- package/lib/poly/polysimplify.ts +0 -24
- package/lib/poly/quad.ts +0 -272
- package/lib/poly/selfintersect.ts +0 -87
- package/lib/poly/shamos.ts +0 -297
- package/lib/poly/simplify.ts +0 -119
- package/lib/poly/topo.ts +0 -499
- package/lib/poly/union.ts +0 -388
- package/lib/util/all.ts +0 -5
- package/lib/util/bintrie.ts +0 -603
- package/lib/util/countedhash.ts +0 -83
- package/lib/util/gradient.ts +0 -108
- package/lib/util/indexedarray.ts +0 -80
- package/lib/util/util.ts +0 -695
|
@@ -1,699 +0,0 @@
|
|
|
1
|
-
import * as Util from '../util/all';
|
|
2
|
-
|
|
3
|
-
const Space = 32;
|
|
4
|
-
const Tab = 9;
|
|
5
|
-
const Newline = 10;
|
|
6
|
-
const CR = 13;
|
|
7
|
-
const OpenParen = 40;
|
|
8
|
-
const CloseParen = 41;
|
|
9
|
-
const Colon = 58;
|
|
10
|
-
const SingleQuote = 39;
|
|
11
|
-
const DoubleQuote = 34;
|
|
12
|
-
const BackSlash = 92;
|
|
13
|
-
const Exclamation = 33;
|
|
14
|
-
const LessThan = 60;
|
|
15
|
-
const Equal = 61;
|
|
16
|
-
const GreaterThan = 62;
|
|
17
|
-
const LowerA = 97;
|
|
18
|
-
const UpperA = 65;
|
|
19
|
-
const LowerN = 110;
|
|
20
|
-
const UpperN = 78;
|
|
21
|
-
const LowerD = 100;
|
|
22
|
-
const UpperD = 68;
|
|
23
|
-
const LowerO = 111;
|
|
24
|
-
const UpperO = 79;
|
|
25
|
-
const LowerT = 97;
|
|
26
|
-
const UpperT = 65;
|
|
27
|
-
const LowerR = 114;
|
|
28
|
-
const UpperR = 82;
|
|
29
|
-
|
|
30
|
-
function isWhite(c: number): boolean
|
|
31
|
-
{
|
|
32
|
-
return c === Space || c === Newline || c === Tab || c == CR;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
enum TokType
|
|
36
|
-
{
|
|
37
|
-
Text,
|
|
38
|
-
OpenParen,
|
|
39
|
-
CloseParen,
|
|
40
|
-
Not,
|
|
41
|
-
And,
|
|
42
|
-
Or,
|
|
43
|
-
Colon,
|
|
44
|
-
GreaterThan,
|
|
45
|
-
GreaterThanEqual,
|
|
46
|
-
Equal,
|
|
47
|
-
LessThan,
|
|
48
|
-
LessThanEqual,
|
|
49
|
-
NotEqual,
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function tokToText(tt: TokType): string
|
|
53
|
-
{
|
|
54
|
-
switch (tt)
|
|
55
|
-
{
|
|
56
|
-
case TokType.Text: return 'text';
|
|
57
|
-
case TokType.OpenParen: return '(';
|
|
58
|
-
case TokType.CloseParen: return ')';
|
|
59
|
-
case TokType.Not: return 'not';
|
|
60
|
-
case TokType.And: return 'and';
|
|
61
|
-
case TokType.Or: return 'or';
|
|
62
|
-
case TokType.Colon: return ':';
|
|
63
|
-
case TokType.GreaterThan: return '>';
|
|
64
|
-
case TokType.GreaterThanEqual: return '>=';
|
|
65
|
-
case TokType.Equal: return '=';
|
|
66
|
-
case TokType.LessThan: return '<';
|
|
67
|
-
case TokType.LessThanEqual: return '<=';
|
|
68
|
-
case TokType.NotEqual: return '!=';
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function tokIsUnary(tt: TokType): boolean
|
|
73
|
-
{
|
|
74
|
-
switch (tt)
|
|
75
|
-
{
|
|
76
|
-
case TokType.Text: return false;
|
|
77
|
-
case TokType.OpenParen: return false;
|
|
78
|
-
case TokType.CloseParen: return false;
|
|
79
|
-
case TokType.Not: return true;
|
|
80
|
-
case TokType.And: return false;
|
|
81
|
-
case TokType.Or: return false;
|
|
82
|
-
case TokType.Colon: return false;
|
|
83
|
-
// Nominally binary, but written as "prop: < 3" so appears as unary operator where test is comparative to prop value
|
|
84
|
-
case TokType.GreaterThan: return true;
|
|
85
|
-
case TokType.GreaterThanEqual: return true;
|
|
86
|
-
case TokType.Equal: return true;
|
|
87
|
-
case TokType.LessThan: return true;
|
|
88
|
-
case TokType.LessThanEqual: return true;
|
|
89
|
-
case TokType.NotEqual: return true;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function tokIsBinary(tt: TokType): boolean
|
|
94
|
-
{
|
|
95
|
-
switch (tt)
|
|
96
|
-
{
|
|
97
|
-
case TokType.Text: return false;
|
|
98
|
-
case TokType.OpenParen: return false;
|
|
99
|
-
case TokType.CloseParen: return false;
|
|
100
|
-
case TokType.Not: return false;
|
|
101
|
-
case TokType.And: return true;
|
|
102
|
-
case TokType.Or: return true;
|
|
103
|
-
case TokType.Colon: return true;
|
|
104
|
-
// Nominally binary, but written as "prop: < 3" so appears as unary operator where test is comparative to prop value
|
|
105
|
-
case TokType.GreaterThan: return false;
|
|
106
|
-
case TokType.GreaterThanEqual: return false;
|
|
107
|
-
case TokType.Equal: return false;
|
|
108
|
-
case TokType.LessThan: return false;
|
|
109
|
-
case TokType.LessThanEqual: return false;
|
|
110
|
-
case TokType.NotEqual: return false;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
interface Token
|
|
115
|
-
{
|
|
116
|
-
tt: TokType;
|
|
117
|
-
text?: string;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
interface Clause
|
|
121
|
-
{
|
|
122
|
-
op: Token;
|
|
123
|
-
operand1?: Clause;
|
|
124
|
-
operand2?: Clause;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
enum ParseState
|
|
128
|
-
{
|
|
129
|
-
Start,
|
|
130
|
-
InString,
|
|
131
|
-
Ended
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
class Lexer
|
|
135
|
-
{
|
|
136
|
-
coder: Util.Coder;
|
|
137
|
-
tokens: Token[];
|
|
138
|
-
buf: Uint8Array;
|
|
139
|
-
tok: Uint8Array;
|
|
140
|
-
toklen: number;
|
|
141
|
-
n: number;
|
|
142
|
-
|
|
143
|
-
constructor(coder: Util.Coder, expr?: string)
|
|
144
|
-
{
|
|
145
|
-
this.coder = coder;
|
|
146
|
-
if (expr)
|
|
147
|
-
this.set(expr);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
set(expr: string): void
|
|
151
|
-
{
|
|
152
|
-
this.tokens = [];
|
|
153
|
-
this.buf = Util.s2u8(this.coder, expr);
|
|
154
|
-
this.tok = new Uint8Array(new ArrayBuffer(this.buf.length));
|
|
155
|
-
this.toklen = 0;
|
|
156
|
-
this.n = 0;
|
|
157
|
-
this.lex();
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
pushString(s: string): void
|
|
161
|
-
{
|
|
162
|
-
this.tokens.push({ tt: TokType.Text, text: s });
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
pushText(bForce: boolean = false): void
|
|
166
|
-
{
|
|
167
|
-
if (this.toklen > 0)
|
|
168
|
-
{
|
|
169
|
-
let text = Util.u82s(this.coder, this.tok, 0, this.toklen).toLowerCase();
|
|
170
|
-
this.toklen = 0;
|
|
171
|
-
if (!bForce && text === 'or')
|
|
172
|
-
this.tokens.push({ tt: TokType.Or });
|
|
173
|
-
else if (!bForce && text === 'and')
|
|
174
|
-
this.tokens.push({ tt: TokType.And });
|
|
175
|
-
else if (!bForce && text === 'not')
|
|
176
|
-
this.tokens.push({ tt: TokType.Not });
|
|
177
|
-
else
|
|
178
|
-
this.pushString(text);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
pushSpecial(tt: TokType): void
|
|
183
|
-
{
|
|
184
|
-
this.pushText();
|
|
185
|
-
this.tokens.push({ tt: tt });
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
lex(): void
|
|
189
|
-
{
|
|
190
|
-
while (this.n < this.buf.length)
|
|
191
|
-
{
|
|
192
|
-
let c: number = this.buf[this.n++];
|
|
193
|
-
if (c == Colon)
|
|
194
|
-
this.pushSpecial(TokType.Colon);
|
|
195
|
-
else if (c == OpenParen)
|
|
196
|
-
this.pushSpecial(TokType.OpenParen);
|
|
197
|
-
else if (c == CloseParen)
|
|
198
|
-
this.pushSpecial(TokType.CloseParen);
|
|
199
|
-
else if (c == SingleQuote || c == DoubleQuote)
|
|
200
|
-
{
|
|
201
|
-
this.pushText();
|
|
202
|
-
while (this.n < this.buf.length)
|
|
203
|
-
{
|
|
204
|
-
let cc = this.buf[this.n++];
|
|
205
|
-
if (cc === c)
|
|
206
|
-
break;
|
|
207
|
-
else
|
|
208
|
-
this.tok[this.toklen++] = cc;
|
|
209
|
-
}
|
|
210
|
-
this.pushText(true);
|
|
211
|
-
}
|
|
212
|
-
else if (isWhite(c))
|
|
213
|
-
this.pushText();
|
|
214
|
-
else if (c === GreaterThan)
|
|
215
|
-
{
|
|
216
|
-
if (this.n < this.buf.length && this.buf[this.n] === Equal)
|
|
217
|
-
{
|
|
218
|
-
this.n++;
|
|
219
|
-
this.pushSpecial(TokType.GreaterThanEqual)
|
|
220
|
-
}
|
|
221
|
-
else
|
|
222
|
-
this.pushSpecial(TokType.GreaterThan)
|
|
223
|
-
}
|
|
224
|
-
else if (c === LessThan)
|
|
225
|
-
{
|
|
226
|
-
if (this.n < this.buf.length && this.buf[this.n] === Equal)
|
|
227
|
-
{
|
|
228
|
-
this.n++;
|
|
229
|
-
this.pushSpecial(TokType.LessThanEqual)
|
|
230
|
-
}
|
|
231
|
-
else
|
|
232
|
-
this.pushSpecial(TokType.LessThan)
|
|
233
|
-
}
|
|
234
|
-
else if (c === Equal)
|
|
235
|
-
this.pushSpecial(TokType.Equal)
|
|
236
|
-
else if (c === Exclamation)
|
|
237
|
-
{
|
|
238
|
-
if (this.n < this.buf.length && this.buf[this.n] === Equal)
|
|
239
|
-
{
|
|
240
|
-
this.n++;
|
|
241
|
-
this.pushSpecial(TokType.NotEqual)
|
|
242
|
-
}
|
|
243
|
-
else
|
|
244
|
-
this.tok[this.toklen++] = c;
|
|
245
|
-
}
|
|
246
|
-
else
|
|
247
|
-
this.tok[this.toklen++] = c;
|
|
248
|
-
}
|
|
249
|
-
this.pushText();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
class Parser
|
|
255
|
-
{
|
|
256
|
-
clauses: Clause[];
|
|
257
|
-
|
|
258
|
-
constructor() { }
|
|
259
|
-
|
|
260
|
-
get clause(): Clause { return this.clauses && this.clauses.length == 1 ? this.clauses[0] : undefined }
|
|
261
|
-
|
|
262
|
-
initFromTokens(tokens: Token[])
|
|
263
|
-
{
|
|
264
|
-
this.clausesFromTokens(tokens);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
initFromClauses(clauses: Clause[])
|
|
268
|
-
{
|
|
269
|
-
this.clauses = clauses;
|
|
270
|
-
this.combineParenthetical();
|
|
271
|
-
this.convertOpToText();
|
|
272
|
-
this.combineUnary();
|
|
273
|
-
this.convertOpToText();
|
|
274
|
-
this.combineBinary(TokType.Colon);
|
|
275
|
-
this.convertOpToText();
|
|
276
|
-
this.combineBinary(TokType.And);
|
|
277
|
-
this.convertOpToText();
|
|
278
|
-
this.combineBinary(TokType.Or);
|
|
279
|
-
this.convertOpToText();
|
|
280
|
-
this.combineImplicitAnd();
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
convertOpToText(): void
|
|
284
|
-
{
|
|
285
|
-
// walk through and convert naked ops to simple text matches (so "state: or" matches oregon rather than being invalid)
|
|
286
|
-
this.clauses.forEach((c, i) => {
|
|
287
|
-
let bad = false;
|
|
288
|
-
switch (c.op.tt)
|
|
289
|
-
{
|
|
290
|
-
case TokType.And:
|
|
291
|
-
case TokType.Or:
|
|
292
|
-
case TokType.Colon:
|
|
293
|
-
if (c.operand1 == null)
|
|
294
|
-
{
|
|
295
|
-
if (i == 0 || i == this.clauses.length-1)
|
|
296
|
-
bad = true;
|
|
297
|
-
else
|
|
298
|
-
{
|
|
299
|
-
let cBefore = this.clauses[i-1];
|
|
300
|
-
if (cBefore.operand1 == null && tokIsBinary(cBefore.op.tt))
|
|
301
|
-
bad = true;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
break;
|
|
305
|
-
case TokType.Not:
|
|
306
|
-
case TokType.GreaterThan:
|
|
307
|
-
case TokType.LessThan:
|
|
308
|
-
case TokType.GreaterThanEqual:
|
|
309
|
-
case TokType.LessThanEqual:
|
|
310
|
-
case TokType.Equal:
|
|
311
|
-
case TokType.NotEqual:
|
|
312
|
-
if (c.operand1 == null && i == this.clauses.length-1)
|
|
313
|
-
bad = true;
|
|
314
|
-
break;
|
|
315
|
-
}
|
|
316
|
-
if (bad)
|
|
317
|
-
c.op = { tt: TokType.Text, text: tokToText(c.op.tt) };
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
combineParenthetical(): void
|
|
322
|
-
{
|
|
323
|
-
for (let i: number = 0; i < this.clauses.length; i++)
|
|
324
|
-
{
|
|
325
|
-
let c = this.clauses[i];
|
|
326
|
-
if (c.op.tt === TokType.OpenParen)
|
|
327
|
-
{
|
|
328
|
-
let depth = 1;
|
|
329
|
-
let j = i+1;
|
|
330
|
-
for (; j < this.clauses.length; j++)
|
|
331
|
-
{
|
|
332
|
-
let c1 = this.clauses[j];
|
|
333
|
-
if (c1.op.tt === TokType.OpenParen)
|
|
334
|
-
depth++;
|
|
335
|
-
else if (c1.op.tt === TokType.CloseParen)
|
|
336
|
-
depth--;
|
|
337
|
-
if (depth == 0)
|
|
338
|
-
break;
|
|
339
|
-
}
|
|
340
|
-
// Pull out stuff inside parens
|
|
341
|
-
let clauses = this.clauses.splice(i+1, j-(i+1));
|
|
342
|
-
// Parse it
|
|
343
|
-
let parser = new Parser();
|
|
344
|
-
parser.initFromClauses(clauses);
|
|
345
|
-
// Insert it back, deleting parens along the way
|
|
346
|
-
if (parser.clause)
|
|
347
|
-
this.clauses.splice(i, 2, parser.clause);
|
|
348
|
-
else
|
|
349
|
-
this.clauses.splice(i, 2);
|
|
350
|
-
}
|
|
351
|
-
else if (c.op.tt === TokType.CloseParen) // malformed - extra paren
|
|
352
|
-
{
|
|
353
|
-
this.clauses.splice(i, 1);
|
|
354
|
-
i--;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
combineUnary(): void
|
|
360
|
-
{
|
|
361
|
-
// go backwards to handle not not
|
|
362
|
-
for (let i: number = this.clauses.length-1; i >= 0; i--)
|
|
363
|
-
{
|
|
364
|
-
let c = this.clauses[i];
|
|
365
|
-
if (tokIsUnary(c.op.tt))
|
|
366
|
-
{
|
|
367
|
-
let notclause = (i < this.clauses.length-1) ? { op: c.op, operand1: this.clauses[i+1] } : undefined;
|
|
368
|
-
if (notclause)
|
|
369
|
-
this.clauses.splice(i, 2, notclause);
|
|
370
|
-
else
|
|
371
|
-
this.clauses.splice(i, 1);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
combineColon(): void
|
|
377
|
-
{
|
|
378
|
-
for (let i: number = 0; i < this.clauses.length; i++)
|
|
379
|
-
{
|
|
380
|
-
let c = this.clauses[i];
|
|
381
|
-
|
|
382
|
-
if (c.op.tt === TokType.Colon && c.operand1 == null)
|
|
383
|
-
{
|
|
384
|
-
if (i === 0) // malformed, but ignore
|
|
385
|
-
this.clauses.splice(i, 1);
|
|
386
|
-
else
|
|
387
|
-
{
|
|
388
|
-
c = { op: c.op, operand1: this.clauses[i-1], operand2: null };
|
|
389
|
-
this.clauses.splice(i-1, 2, c);
|
|
390
|
-
i--;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
combineBinary(tt: TokType): void
|
|
397
|
-
{
|
|
398
|
-
for (let i: number = 0; i < this.clauses.length; i++)
|
|
399
|
-
{
|
|
400
|
-
let c = this.clauses[i];
|
|
401
|
-
|
|
402
|
-
if (c.op.tt === tt)
|
|
403
|
-
if (c.operand1 == null)
|
|
404
|
-
{
|
|
405
|
-
if (i === 0 || i === this.clauses.length-1) // malformed, but ignore
|
|
406
|
-
this.clauses.splice(i, 1);
|
|
407
|
-
else
|
|
408
|
-
{
|
|
409
|
-
c = { op: c.op, operand1: this.clauses[i-1], operand2: this.clauses[i+1] };
|
|
410
|
-
this.clauses.splice(i-1, 3, c);
|
|
411
|
-
i--;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
else if (c.operand2 == null) // just colon where name binds earlier in combineColon
|
|
415
|
-
{
|
|
416
|
-
if (i === this.clauses.length-1) // malformed, but ignore
|
|
417
|
-
this.clauses.splice(i, 1);
|
|
418
|
-
else
|
|
419
|
-
{
|
|
420
|
-
c.operand2 = this.clauses[i+1];
|
|
421
|
-
this.clauses.splice(i+1, 1);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
combineImplicitAnd(): void
|
|
428
|
-
{
|
|
429
|
-
while (this.clauses.length > 1)
|
|
430
|
-
{
|
|
431
|
-
let c: Clause = { op: { tt: TokType.And }, operand1: this.clauses[0], operand2: this.clauses[1] };
|
|
432
|
-
this.clauses.splice(0, 2, c);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
clausesFromTokens(tokens: Token[]): void
|
|
437
|
-
{
|
|
438
|
-
let clauses: Clause[] = [];
|
|
439
|
-
// combine sequential text tokens into AND clauses, push rest as distinct clauses
|
|
440
|
-
for (let i: number = 0; i < tokens.length; i++)
|
|
441
|
-
{
|
|
442
|
-
let t = tokens[i];
|
|
443
|
-
if (t.tt === TokType.Text)
|
|
444
|
-
{
|
|
445
|
-
let c: Clause = { op: t };
|
|
446
|
-
let j = i+1;
|
|
447
|
-
for (; j < tokens.length; j++)
|
|
448
|
-
{
|
|
449
|
-
let jt = tokens[j];
|
|
450
|
-
if (jt.tt === TokType.Text)
|
|
451
|
-
c = { op: { tt: TokType.And }, operand1: c, operand2: { op: jt } };
|
|
452
|
-
else
|
|
453
|
-
break;
|
|
454
|
-
}
|
|
455
|
-
clauses.push(c);
|
|
456
|
-
i = j-1;
|
|
457
|
-
}
|
|
458
|
-
else
|
|
459
|
-
clauses.push({ op: t });
|
|
460
|
-
}
|
|
461
|
-
this.initFromClauses(clauses);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
function wordyDate(s: string): string
|
|
466
|
-
{
|
|
467
|
-
let d = new Date(s);
|
|
468
|
-
let now = new Date();
|
|
469
|
-
let yyyyNow = now.getFullYear();
|
|
470
|
-
let mmmNow = now.getMonth();
|
|
471
|
-
let ddNow = now.getDate();
|
|
472
|
-
|
|
473
|
-
let mmm = d.getMonth();
|
|
474
|
-
let dd = d.getDate();
|
|
475
|
-
let yyyy = d.getFullYear();
|
|
476
|
-
|
|
477
|
-
s = Util.prettyDate(d);
|
|
478
|
-
if (yyyyNow === yyyy && mmmNow === mmm && ddNow === dd)
|
|
479
|
-
s = 'today ' + s;
|
|
480
|
-
|
|
481
|
-
// If I get ambitious, could add "yesterday", "this week", "last week", "this month", "last month", "this year"
|
|
482
|
-
// But this is close enough to match what gets displayed by "prettyDate" while also letting selection by month year
|
|
483
|
-
|
|
484
|
-
return s;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
function clauseEqual(c1: Clause, c2: Clause): boolean
|
|
488
|
-
{
|
|
489
|
-
if (c1 == null && c2 == null) return true;
|
|
490
|
-
if (c1 == null || c2 == null) return false;
|
|
491
|
-
if (c1.op.tt === c2.op.tt)
|
|
492
|
-
{
|
|
493
|
-
if (c1.op.tt === TokType.Text)
|
|
494
|
-
return c1.op.text === c2.op.text;
|
|
495
|
-
else
|
|
496
|
-
return clauseEqual(c1.operand1, c2.operand1) && clauseEqual(c1.operand2, c2.operand2);
|
|
497
|
-
}
|
|
498
|
-
else
|
|
499
|
-
return false;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
function containsClause(c: Clause, s: Clause): boolean
|
|
503
|
-
{
|
|
504
|
-
if (clauseEqual(c, s))
|
|
505
|
-
return true;
|
|
506
|
-
if (c == null || s == null) return false;
|
|
507
|
-
return containsClause(c.operand1, s) || containsClause(c.operand2, s);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
function removeClause(c: Clause, s: Clause): Clause
|
|
511
|
-
{
|
|
512
|
-
if (c == null || (c.op.tt === TokType.Text && c.op.tt !== s.op.tt))
|
|
513
|
-
return c;
|
|
514
|
-
else if (clauseEqual(c, s))
|
|
515
|
-
return null;
|
|
516
|
-
else
|
|
517
|
-
{
|
|
518
|
-
c.operand1 = removeClause(c.operand1, s);
|
|
519
|
-
c.operand2 = removeClause(c.operand2, s);
|
|
520
|
-
if ((c.op.tt === TokType.And || c.op.tt === TokType.Or) && (c.operand1 == null || c.operand2 == null))
|
|
521
|
-
return c.operand1 || c.operand2;
|
|
522
|
-
return c;
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
export class FilterExpr
|
|
527
|
-
{
|
|
528
|
-
lexer: Lexer;
|
|
529
|
-
parser: Parser;
|
|
530
|
-
|
|
531
|
-
constructor(coder: Util.Coder, expr?: string)
|
|
532
|
-
{
|
|
533
|
-
this.lexer = new Lexer(coder);
|
|
534
|
-
this.parser = new Parser;
|
|
535
|
-
if (expr) this.set(expr);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
set(expr: string): void
|
|
539
|
-
{
|
|
540
|
-
this.lexer.set(expr);
|
|
541
|
-
this.parser.initFromTokens(this.lexer.tokens);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
test(o: any, types?: any): boolean
|
|
545
|
-
{
|
|
546
|
-
return this.testClause(o, types, this.parser.clause);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
asString(): string
|
|
550
|
-
{
|
|
551
|
-
return this.asStringClause(this.parser.clause);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
containsClause(expr: string): boolean
|
|
555
|
-
{
|
|
556
|
-
let sub = new FilterExpr(this.lexer.coder, expr);
|
|
557
|
-
return containsClause(this.parser.clause, sub.parser.clause);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
addClause(expr: string): void
|
|
561
|
-
{
|
|
562
|
-
let sub = new FilterExpr(this.lexer.coder, expr);
|
|
563
|
-
if (! containsClause(this.parser.clause, sub.parser.clause))
|
|
564
|
-
{
|
|
565
|
-
if (this.parser.clause)
|
|
566
|
-
this.parser.clauses = [ { op: { tt: TokType.And }, operand1: this.parser.clause, operand2: sub.parser.clause } ];
|
|
567
|
-
else
|
|
568
|
-
this.parser.clauses = [ sub.parser.clause ];
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
removeClause(expr: string): void
|
|
573
|
-
{
|
|
574
|
-
if (this.containsClause(expr))
|
|
575
|
-
{
|
|
576
|
-
let sub = new FilterExpr(this.lexer.coder, expr);
|
|
577
|
-
this.parser.clauses = [ removeClause(this.parser.clause, sub.parser.clause) ];
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
asStringClause(clause: Clause): string
|
|
582
|
-
{
|
|
583
|
-
if (clause == null) return '';
|
|
584
|
-
if (clause.op.tt == TokType.Text)
|
|
585
|
-
{
|
|
586
|
-
this.lexer.set(clause.op.text);
|
|
587
|
-
if (this.lexer.tokens.length == 1 && this.lexer.tokens[0].tt === TokType.Text)
|
|
588
|
-
return clause.op.text;
|
|
589
|
-
else
|
|
590
|
-
return `'${clause.op.text}'`;
|
|
591
|
-
}
|
|
592
|
-
let a: string[] = [];
|
|
593
|
-
if (clause !== this.parser.clause)
|
|
594
|
-
a.push('(');
|
|
595
|
-
switch (clause.op.tt)
|
|
596
|
-
{
|
|
597
|
-
case TokType.And:
|
|
598
|
-
a.push(this.asStringClause(clause.operand1));
|
|
599
|
-
a.push('and');
|
|
600
|
-
a.push(this.asStringClause(clause.operand2));
|
|
601
|
-
break;
|
|
602
|
-
case TokType.Or:
|
|
603
|
-
a.push(this.asStringClause(clause.operand1));
|
|
604
|
-
a.push('or');
|
|
605
|
-
a.push(this.asStringClause(clause.operand2));
|
|
606
|
-
break;
|
|
607
|
-
case TokType.Not:
|
|
608
|
-
a.push('not');
|
|
609
|
-
a.push(this.asStringClause(clause.operand1));
|
|
610
|
-
break;
|
|
611
|
-
case TokType.Colon:
|
|
612
|
-
a.push(`${this.asStringClause(clause.operand1)}:`);
|
|
613
|
-
a.push(this.asStringClause(clause.operand2));
|
|
614
|
-
break;
|
|
615
|
-
case TokType.Equal:
|
|
616
|
-
case TokType.LessThan:
|
|
617
|
-
case TokType.GreaterThan:
|
|
618
|
-
case TokType.LessThanEqual:
|
|
619
|
-
case TokType.GreaterThanEqual:
|
|
620
|
-
case TokType.NotEqual:
|
|
621
|
-
a.push(tokToText(clause.op.tt));
|
|
622
|
-
a.push(this.asStringClause(clause.operand1));
|
|
623
|
-
break;
|
|
624
|
-
default:
|
|
625
|
-
throw 'Unexpected token in asString';
|
|
626
|
-
}
|
|
627
|
-
if (clause !== this.parser.clause)
|
|
628
|
-
a.push(')');
|
|
629
|
-
return a.join(' ');
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
testClause(o: any, types: any, clause: Clause, prop?: string, relation?: TokType): boolean
|
|
633
|
-
{
|
|
634
|
-
if (clause == null) return true;
|
|
635
|
-
switch (clause.op.tt)
|
|
636
|
-
{
|
|
637
|
-
case TokType.Text:
|
|
638
|
-
for (let p in o) if (o.hasOwnProperty(p) && (prop == null || p.toLowerCase() === prop))
|
|
639
|
-
{
|
|
640
|
-
let s = String(o[p]);
|
|
641
|
-
if (s)
|
|
642
|
-
{
|
|
643
|
-
let t = types ? types[p] : undefined;
|
|
644
|
-
if (t === 'skip')
|
|
645
|
-
continue;
|
|
646
|
-
if (t && t === 'date')
|
|
647
|
-
s = wordyDate(s);
|
|
648
|
-
s = s.toLowerCase();
|
|
649
|
-
if (relation === undefined)
|
|
650
|
-
{
|
|
651
|
-
if (s.indexOf(clause.op.text) >= 0)
|
|
652
|
-
return true;
|
|
653
|
-
}
|
|
654
|
-
else
|
|
655
|
-
{
|
|
656
|
-
let op2: any = isNaN(Number(clause.op.text)) ? clause.op.text : Number(clause.op.text);
|
|
657
|
-
let op1: any = typeof op2 === 'number' ? Number(s) : s;
|
|
658
|
-
switch (relation)
|
|
659
|
-
{
|
|
660
|
-
case TokType.Equal: return op1 === op2;
|
|
661
|
-
case TokType.LessThan: return op1 < op2;
|
|
662
|
-
case TokType.LessThanEqual: return op1 <= op2;
|
|
663
|
-
case TokType.GreaterThanEqual: return op1 >= op2;
|
|
664
|
-
case TokType.GreaterThan: return op1 > op2;
|
|
665
|
-
case TokType.NotEqual: return op1 !== op2;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
return false;
|
|
671
|
-
|
|
672
|
-
case TokType.Colon:
|
|
673
|
-
if (clause.operand1 && clause.operand1.op.tt === TokType.Text)
|
|
674
|
-
prop = clause.operand1.op.text;
|
|
675
|
-
return this.testClause(o, types, clause.operand2, prop);
|
|
676
|
-
|
|
677
|
-
case TokType.Not:
|
|
678
|
-
return ! this.testClause(o, types, clause.operand1, prop);
|
|
679
|
-
|
|
680
|
-
case TokType.Equal:
|
|
681
|
-
case TokType.LessThan:
|
|
682
|
-
case TokType.GreaterThan:
|
|
683
|
-
case TokType.LessThanEqual:
|
|
684
|
-
case TokType.GreaterThanEqual:
|
|
685
|
-
case TokType.NotEqual:
|
|
686
|
-
return this.testClause(o, types, clause.operand1, prop, clause.op.tt);
|
|
687
|
-
|
|
688
|
-
case TokType.And:
|
|
689
|
-
return this.testClause(o, types, clause.operand1, prop) && this.testClause(o, types, clause.operand2, prop);
|
|
690
|
-
|
|
691
|
-
case TokType.Or:
|
|
692
|
-
return this.testClause(o, types, clause.operand1, prop) || this.testClause(o, types, clause.operand2, prop);
|
|
693
|
-
|
|
694
|
-
default:
|
|
695
|
-
throw 'Unexpected token in clause';
|
|
696
|
-
}
|
|
697
|
-
// NOTREACHED
|
|
698
|
-
}
|
|
699
|
-
}
|
package/lib/fsm/all.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './fsm';
|