@tekki-forge/expression 0.0.0-stage → 0.2.0

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/parser.js ADDED
@@ -0,0 +1,323 @@
1
+ import { ExpressionError, MAX_DEPTH, MAX_SOURCE_LENGTH } from "./ast.js";
2
+ const TWO_CHAR_OPS = new Set(["==", "!=", "<=", ">=", "&&", "||"]);
3
+ const ONE_CHAR_OPS = new Set(["(", ")", ",", ".", "+", "-", "*", "/", "%", "<", ">", "!"]);
4
+ const KEYWORDS = new Set(["and", "or", "not", "true", "false", "null"]);
5
+ const AGGREGATE_ONLY = new Set(["sum", "avg", "count"]);
6
+ function isDigit(c) {
7
+ return c >= "0" && c <= "9";
8
+ }
9
+ function isIdentStart(c) {
10
+ return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || c === "_";
11
+ }
12
+ function isIdentPart(c) {
13
+ return isIdentStart(c) || isDigit(c);
14
+ }
15
+ function tokenize(src) {
16
+ const tokens = [];
17
+ let i = 0;
18
+ const n = src.length;
19
+ while (i < n) {
20
+ const c = src[i];
21
+ if (c === " " || c === "\t" || c === "\n" || c === "\r") {
22
+ i++;
23
+ continue;
24
+ }
25
+ const start = i;
26
+ if (isDigit(c)) {
27
+ while (i < n && isDigit(src[i]))
28
+ i++;
29
+ if (src[i] === ".") {
30
+ i++;
31
+ if (i >= n || !isDigit(src[i])) {
32
+ throw new ExpressionError(`Invalid number literal at ${start} — expected digits after "."`, start);
33
+ }
34
+ while (i < n && isDigit(src[i]))
35
+ i++;
36
+ }
37
+ if (i < n && isIdentPart(src[i])) {
38
+ throw new ExpressionError(`Invalid number literal at ${start}`, start);
39
+ }
40
+ const text = src.slice(start, i);
41
+ const v = Number(text);
42
+ if (!Number.isFinite(v))
43
+ throw new ExpressionError(`Number literal out of range at ${start}`, start);
44
+ tokens.push({ t: "num", v, pos: start });
45
+ continue;
46
+ }
47
+ if (isIdentStart(c)) {
48
+ while (i < n && isIdentPart(src[i]))
49
+ i++;
50
+ tokens.push({ t: "ident", v: src.slice(start, i), pos: start });
51
+ continue;
52
+ }
53
+ if (c === '"' || c === "'") {
54
+ i++;
55
+ let out = "";
56
+ let closed = false;
57
+ while (i < n) {
58
+ const ch = src[i];
59
+ if (ch === c) {
60
+ closed = true;
61
+ i++;
62
+ break;
63
+ }
64
+ if (ch === "\\") {
65
+ const nx = src[i + 1];
66
+ if (nx === undefined)
67
+ break;
68
+ switch (nx) {
69
+ case "\\":
70
+ case "'":
71
+ case '"':
72
+ out += nx;
73
+ break;
74
+ case "n":
75
+ out += "\n";
76
+ break;
77
+ case "t":
78
+ out += "\t";
79
+ break;
80
+ case "r":
81
+ out += "\r";
82
+ break;
83
+ default:
84
+ throw new ExpressionError(`Invalid escape sequence "\\${nx}" at ${i}`, i);
85
+ }
86
+ i += 2;
87
+ continue;
88
+ }
89
+ out += ch;
90
+ i++;
91
+ }
92
+ if (!closed)
93
+ throw new ExpressionError(`Unterminated string literal starting at ${start}`, start);
94
+ tokens.push({ t: "str", v: out, pos: start });
95
+ continue;
96
+ }
97
+ const two = src.slice(i, i + 2);
98
+ if (TWO_CHAR_OPS.has(two)) {
99
+ tokens.push({ t: "op", v: two, pos: i });
100
+ i += 2;
101
+ continue;
102
+ }
103
+ if (ONE_CHAR_OPS.has(c)) {
104
+ tokens.push({ t: "op", v: c, pos: i });
105
+ i++;
106
+ continue;
107
+ }
108
+ if (c === "=")
109
+ throw new ExpressionError(`Unexpected "=" at ${i} — use "==" for equality`, i);
110
+ if (c === "&")
111
+ throw new ExpressionError(`Unexpected "&" at ${i} — use "&&" or "and"`, i);
112
+ if (c === "|")
113
+ throw new ExpressionError(`Unexpected "|" at ${i} — use "||" or "or"`, i);
114
+ throw new ExpressionError(`Unexpected character "${c}" at ${i}`, i);
115
+ }
116
+ tokens.push({ t: "eof", pos: n });
117
+ return tokens;
118
+ }
119
+ function describe(tok) {
120
+ switch (tok.t) {
121
+ case "eof":
122
+ return "end of expression";
123
+ case "str":
124
+ return "string literal";
125
+ case "num":
126
+ return `"${tok.v}"`;
127
+ default:
128
+ return `"${tok.v}"`;
129
+ }
130
+ }
131
+ class Parser {
132
+ tokens;
133
+ i = 0;
134
+ depth = 0;
135
+ constructor(tokens) {
136
+ this.tokens = tokens;
137
+ }
138
+ peek(offset = 0) {
139
+ return this.tokens[Math.min(this.i + offset, this.tokens.length - 1)];
140
+ }
141
+ next() {
142
+ const t = this.peek();
143
+ if (t.t !== "eof")
144
+ this.i++;
145
+ return t;
146
+ }
147
+ isOp(v, offset = 0) {
148
+ const t = this.peek(offset);
149
+ return t.t === "op" && t.v === v;
150
+ }
151
+ isKw(kw) {
152
+ const t = this.peek();
153
+ return t.t === "ident" && t.v.toLowerCase() === kw;
154
+ }
155
+ expectOp(v) {
156
+ const t = this.peek();
157
+ if (t.t === "op" && t.v === v)
158
+ return this.next();
159
+ throw new ExpressionError(`Expected "${v}" at ${t.pos}`, t.pos);
160
+ }
161
+ enter(pos) {
162
+ if (++this.depth > MAX_DEPTH) {
163
+ throw new ExpressionError(`Expression is nested too deeply (max depth ${MAX_DEPTH}) at ${pos}`, pos);
164
+ }
165
+ }
166
+ leave() {
167
+ this.depth--;
168
+ }
169
+ parseTop() {
170
+ const e = this.parseOr();
171
+ const t = this.peek();
172
+ if (t.t !== "eof")
173
+ throw new ExpressionError(`Unexpected ${describe(t)} at ${t.pos}`, t.pos);
174
+ return e;
175
+ }
176
+ parseOr() {
177
+ this.enter(this.peek().pos);
178
+ let left = this.parseAnd();
179
+ while (this.isOp("||") || this.isKw("or")) {
180
+ const pos = this.next().pos;
181
+ const right = this.parseAnd();
182
+ left = { kind: "binary", op: "or", left, right, pos };
183
+ }
184
+ this.leave();
185
+ return left;
186
+ }
187
+ parseAnd() {
188
+ let left = this.parseEquality();
189
+ while (this.isOp("&&") || this.isKw("and")) {
190
+ const pos = this.next().pos;
191
+ const right = this.parseEquality();
192
+ left = { kind: "binary", op: "and", left, right, pos };
193
+ }
194
+ return left;
195
+ }
196
+ parseBinaryLevel(ops, nextLevel) {
197
+ let left = nextLevel();
198
+ for (;;) {
199
+ const t = this.peek();
200
+ if (t.t !== "op" || !ops.includes(t.v))
201
+ return left;
202
+ this.next();
203
+ const right = nextLevel();
204
+ left = { kind: "binary", op: t.v, left, right, pos: t.pos };
205
+ }
206
+ }
207
+ parseEquality() {
208
+ return this.parseBinaryLevel(["==", "!="], () => this.parseComparison());
209
+ }
210
+ parseComparison() {
211
+ return this.parseBinaryLevel(["<", "<=", ">", ">="], () => this.parseAdditive());
212
+ }
213
+ parseAdditive() {
214
+ return this.parseBinaryLevel(["+", "-"], () => this.parseMultiplicative());
215
+ }
216
+ parseMultiplicative() {
217
+ return this.parseBinaryLevel(["*", "/", "%"], () => this.parseUnary());
218
+ }
219
+ parseUnary() {
220
+ const t = this.peek();
221
+ const isNeg = t.t === "op" && t.v === "-";
222
+ const isNot = (t.t === "op" && t.v === "!") || this.isKw("not");
223
+ if (!isNeg && !isNot)
224
+ return this.parsePrimary();
225
+ this.next();
226
+ this.enter(t.pos);
227
+ const operand = this.parseUnary();
228
+ this.leave();
229
+ return { kind: "unary", op: isNeg ? "-" : "not", operand, pos: t.pos };
230
+ }
231
+ parsePrimary() {
232
+ const t = this.peek();
233
+ switch (t.t) {
234
+ case "num":
235
+ this.next();
236
+ return { kind: "literal", value: t.v, pos: t.pos };
237
+ case "str":
238
+ this.next();
239
+ return { kind: "literal", value: t.v, pos: t.pos };
240
+ case "ident": {
241
+ const lower = t.v.toLowerCase();
242
+ if (lower === "true" || lower === "false") {
243
+ this.next();
244
+ return { kind: "literal", value: lower === "true", pos: t.pos };
245
+ }
246
+ if (lower === "null") {
247
+ this.next();
248
+ return { kind: "literal", value: null, pos: t.pos };
249
+ }
250
+ if (KEYWORDS.has(lower))
251
+ throw new ExpressionError(`Unexpected "${t.v}" at ${t.pos}`, t.pos);
252
+ if (this.isOp("(", 1))
253
+ return this.parseCall();
254
+ if (this.isOp(".", 1)) {
255
+ const prop = this.peek(2);
256
+ const shown = prop.t === "ident" ? `${t.v}.${prop.v}` : `${t.v}.`;
257
+ throw new ExpressionError(`Member access "${shown}" is only allowed inside aggregate functions such as sum(lines.amount) at ${t.pos}`, t.pos);
258
+ }
259
+ this.next();
260
+ return { kind: "field", name: t.v, pos: t.pos };
261
+ }
262
+ case "op":
263
+ if (t.v === "(") {
264
+ this.next();
265
+ const e = this.parseOr();
266
+ this.expectOp(")");
267
+ return e;
268
+ }
269
+ throw new ExpressionError(`Unexpected "${t.v}" at ${t.pos}`, t.pos);
270
+ case "eof":
271
+ throw new ExpressionError(`Unexpected end of expression at ${t.pos}`, t.pos);
272
+ }
273
+ }
274
+ parseCall() {
275
+ const nameTok = this.next();
276
+ const name = nameTok.v.toLowerCase();
277
+ const pos = nameTok.pos;
278
+ this.expectOp("(");
279
+ if (AGGREGATE_ONLY.has(name) || name === "min" || name === "max") {
280
+ const a = this.peek();
281
+ // relation.field )
282
+ if (a.t === "ident" && this.isOp(".", 1) && this.peek(2).t === "ident" && this.isOp(")", 3)) {
283
+ const f = this.peek(2);
284
+ this.i += 4;
285
+ return { kind: "aggregate", fn: name, relation: a.v, field: f.v, pos };
286
+ }
287
+ if (name === "count" && a.t === "ident" && this.isOp(")", 1) && !KEYWORDS.has(a.v.toLowerCase())) {
288
+ this.i += 2;
289
+ return { kind: "aggregate", fn: "count", relation: a.v, field: null, pos };
290
+ }
291
+ if (AGGREGATE_ONLY.has(name)) {
292
+ const example = name === "count" ? `count(lines) or count(lines.id)` : `${name}(lines.amount)`;
293
+ throw new ExpressionError(`Aggregate ${name} expects a relation field argument, e.g. ${example}, at ${a.pos}`, a.pos);
294
+ }
295
+ // scalar min/max: fall through to a normal call
296
+ }
297
+ const args = [];
298
+ if (!this.isOp(")")) {
299
+ for (;;) {
300
+ args.push(this.parseOr());
301
+ if (this.isOp(",")) {
302
+ this.next();
303
+ continue;
304
+ }
305
+ break;
306
+ }
307
+ }
308
+ this.expectOp(")");
309
+ return { kind: "call", name, args, pos };
310
+ }
311
+ }
312
+ /** Parse source text into a JSON-serializable AST. Throws ExpressionError with position. */
313
+ export function parseExpression(source) {
314
+ if (typeof source !== "string")
315
+ throw new ExpressionError("Expression source must be a string");
316
+ if (source.length > MAX_SOURCE_LENGTH) {
317
+ throw new ExpressionError(`Expression is too long (${source.length} characters, max ${MAX_SOURCE_LENGTH})`, MAX_SOURCE_LENGTH);
318
+ }
319
+ if (source.trim() === "")
320
+ throw new ExpressionError("Expression is empty at 0", 0);
321
+ return new Parser(tokenize(source)).parseTop();
322
+ }
323
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Expr } from "./ast.js";
2
+ export interface References {
3
+ fields: string[];
4
+ aggregates: {
5
+ fn: string;
6
+ relation: string;
7
+ field: string | null;
8
+ }[];
9
+ }
10
+ /** Collect the (deduplicated) scalar fields and aggregates an expression depends on. */
11
+ export declare function references(expr: Expr): References;
@@ -0,0 +1,42 @@
1
+ /** Collect the (deduplicated) scalar fields and aggregates an expression depends on. */
2
+ export function references(expr) {
3
+ const fields = new Set();
4
+ const aggKeys = new Set();
5
+ const aggregates = [];
6
+ const stack = [expr];
7
+ const order = [];
8
+ // Iterative pre-order traversal (left to right) to avoid deep recursion.
9
+ while (stack.length) {
10
+ const e = stack.pop();
11
+ if (typeof e !== "object" || e === null)
12
+ continue;
13
+ order.push(e);
14
+ switch (e.kind) {
15
+ case "unary":
16
+ stack.push(e.operand);
17
+ break;
18
+ case "binary":
19
+ stack.push(e.right, e.left);
20
+ break;
21
+ case "call":
22
+ if (Array.isArray(e.args))
23
+ for (let i = e.args.length - 1; i >= 0; i--)
24
+ stack.push(e.args[i]);
25
+ break;
26
+ }
27
+ }
28
+ for (const e of order) {
29
+ if (e.kind === "field")
30
+ fields.add(e.name);
31
+ else if (e.kind === "aggregate") {
32
+ const field = e.field ?? null;
33
+ const key = JSON.stringify([e.fn, e.relation, field]);
34
+ if (!aggKeys.has(key)) {
35
+ aggKeys.add(key);
36
+ aggregates.push({ fn: e.fn, relation: e.relation, field });
37
+ }
38
+ }
39
+ }
40
+ return { fields: [...fields], aggregates };
41
+ }
42
+ //# sourceMappingURL=references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.js","sourceRoot":"","sources":["../src/references.ts"],"names":[],"mappings":"AAOA,wFAAwF;AACxF,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,UAAU,GAA6B,EAAE,CAAC;IAChD,MAAM,KAAK,GAAW,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,yEAAyE;IACzE,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QACvB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;YAAE,SAAS;QAClD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACd,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,OAAO;gBACV,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;gBACtB,MAAM;YACR,KAAK,QAAQ;gBACX,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC5B,MAAM;YACR,KAAK,MAAM;gBACT,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;oBAAE,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;wBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;gBAC/F,MAAM;QACV,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;YAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aACtC,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC;YAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;YACtD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACjB,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { CallExpr, Expr, ExprType } from "./ast.js";
2
+ export interface TypeEnv {
3
+ /** Scalar fields of the entity. */
4
+ fields: Record<string, ExprType>;
5
+ /** One-to-many relation name -> its fields' types. */
6
+ relations?: Record<string, Record<string, ExprType>>;
7
+ }
8
+ /** Common type of two types, or null when incompatible. */
9
+ export declare function unify(a: ExprType, b: ExprType): ExprType | null;
10
+ interface FnSpec {
11
+ min: number;
12
+ max: number;
13
+ check(args: ExprType[], node: CallExpr): ExprType;
14
+ }
15
+ export declare const FUNCTIONS: ReadonlyMap<string, FnSpec>;
16
+ /**
17
+ * Infer (and validate) the static type of an expression.
18
+ * Side effect: annotates every node with its `type`, which `evaluate()` then uses to pick
19
+ * decimal vs. number arithmetic and date handling.
20
+ */
21
+ export declare function inferType(expr: Expr, env: TypeEnv): ExprType;
22
+ export {};