@fieldia/core 0.9.1 → 0.10.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/package.json +1 -1
- package/schema/page.schema.json +1128 -89
- package/src/lib/expression/evaluator.d.mts +6 -5
- package/src/lib/expression/evaluator.d.ts +6 -5
- package/src/lib/expression/evaluator.js +37 -22
- package/src/lib/expression/evaluator.js.map +1 -1
- package/src/lib/expression/evaluator.mjs +32 -18
- package/src/lib/expression/evaluator.mjs.map +1 -1
- package/src/lib/expression/expression.d.mts +21 -0
- package/src/lib/expression/expression.d.ts +21 -0
- package/src/lib/expression/expression.js +29 -0
- package/src/lib/expression/expression.js.map +1 -0
- package/src/lib/expression/expression.mjs +26 -0
- package/src/lib/expression/expression.mjs.map +1 -0
- package/src/lib/expression/extractFieldNames.js +6 -1
- package/src/lib/expression/extractFieldNames.js.map +1 -1
- package/src/lib/expression/extractFieldNames.mjs +6 -1
- package/src/lib/expression/extractFieldNames.mjs.map +1 -1
- package/src/lib/expression/functions.d.mts +35 -0
- package/src/lib/expression/functions.d.ts +35 -0
- package/src/lib/expression/functions.js +129 -0
- package/src/lib/expression/functions.js.map +1 -0
- package/src/lib/expression/functions.mjs +124 -0
- package/src/lib/expression/functions.mjs.map +1 -0
- package/src/lib/expression/modifier.d.mts +3 -1
- package/src/lib/expression/modifier.d.ts +3 -1
- package/src/lib/expression/modifier.js +4 -27
- package/src/lib/expression/modifier.js.map +1 -1
- package/src/lib/expression/modifier.mjs +3 -26
- package/src/lib/expression/modifier.mjs.map +1 -1
- package/src/lib/expression/operations.d.mts +25 -0
- package/src/lib/expression/operations.d.ts +25 -0
- package/src/lib/expression/operations.js +81 -0
- package/src/lib/expression/operations.js.map +1 -0
- package/src/lib/expression/operations.mjs +72 -0
- package/src/lib/expression/operations.mjs.map +1 -0
- package/src/lib/expression/order.d.mts +11 -0
- package/src/lib/expression/order.d.ts +11 -0
- package/src/lib/expression/order.js +36 -0
- package/src/lib/expression/order.js.map +1 -0
- package/src/lib/expression/order.mjs +33 -0
- package/src/lib/expression/order.mjs.map +1 -0
- package/src/lib/expression/parser.d.mts +34 -4
- package/src/lib/expression/parser.d.ts +34 -4
- package/src/lib/expression/parser.js +72 -6
- package/src/lib/expression/parser.js.map +1 -1
- package/src/lib/expression/parser.mjs +72 -6
- package/src/lib/expression/parser.mjs.map +1 -1
- package/src/lib/expression/reads.d.mts +8 -0
- package/src/lib/expression/reads.d.ts +8 -0
- package/src/lib/expression/reads.js +48 -0
- package/src/lib/expression/reads.js.map +1 -0
- package/src/lib/expression/reads.mjs +44 -0
- package/src/lib/expression/reads.mjs.map +1 -0
- package/src/lib/expression/tokenizer.d.mts +7 -6
- package/src/lib/expression/tokenizer.d.ts +7 -6
- package/src/lib/expression/tokenizer.js +28 -18
- package/src/lib/expression/tokenizer.js.map +1 -1
- package/src/lib/expression/tokenizer.mjs +28 -18
- package/src/lib/expression/tokenizer.mjs.map +1 -1
- package/src/lib/format/field.d.mts +686 -5
- package/src/lib/format/field.d.ts +686 -5
- package/src/lib/format/field.js +115 -13
- package/src/lib/format/field.js.map +1 -1
- package/src/lib/format/field.mjs +114 -12
- package/src/lib/format/field.mjs.map +1 -1
- package/src/lib/format/layout.d.mts +388 -10
- package/src/lib/format/layout.d.ts +388 -10
- package/src/lib/format/layout.js +50 -3
- package/src/lib/format/layout.js.map +1 -1
- package/src/lib/format/layout.mjs +49 -2
- package/src/lib/format/layout.mjs.map +1 -1
- package/src/lib/format/names.d.mts +1 -1
- package/src/lib/format/names.d.ts +1 -1
- package/src/lib/format/names.js +1 -0
- package/src/lib/format/names.js.map +1 -1
- package/src/lib/format/names.mjs +1 -0
- package/src/lib/format/names.mjs.map +1 -1
- package/src/lib/format/page.d.mts +391 -4
- package/src/lib/format/page.d.ts +391 -4
- package/src/lib/format/page.js +13 -0
- package/src/lib/format/page.js.map +1 -1
- package/src/lib/format/page.mjs +13 -0
- package/src/lib/format/page.mjs.map +1 -1
- package/src/lib/format/references.d.mts +14 -1
- package/src/lib/format/references.d.ts +14 -1
- package/src/lib/format/references.js +96 -8
- package/src/lib/format/references.js.map +1 -1
- package/src/lib/format/references.mjs +96 -8
- package/src/lib/format/references.mjs.map +1 -1
- package/src/lib/format/translate.d.mts +20 -0
- package/src/lib/format/translate.d.ts +20 -0
- package/src/lib/format/translate.js +79 -21
- package/src/lib/format/translate.js.map +1 -1
- package/src/lib/format/translate.mjs +76 -21
- package/src/lib/format/translate.mjs.map +1 -1
- package/src/lib/record/check.d.mts +19 -1
- package/src/lib/record/check.d.ts +19 -1
- package/src/lib/record/check.js +84 -21
- package/src/lib/record/check.js.map +1 -1
- package/src/lib/record/check.mjs +82 -21
- package/src/lib/record/check.mjs.map +1 -1
- package/src/lib/record/compute.d.mts +24 -0
- package/src/lib/record/compute.d.ts +24 -0
- package/src/lib/record/compute.js +107 -0
- package/src/lib/record/compute.js.map +1 -0
- package/src/lib/record/compute.mjs +103 -0
- package/src/lib/record/compute.mjs.map +1 -0
- package/src/lib/record/data-source.d.mts +9 -1
- package/src/lib/record/data-source.d.ts +9 -1
- package/src/lib/record/data-source.js.map +1 -1
- package/src/lib/record/data-source.mjs.map +1 -1
- package/src/lib/record/env.d.mts +9 -0
- package/src/lib/record/env.d.ts +9 -0
- package/src/lib/record/env.js +28 -0
- package/src/lib/record/env.js.map +1 -0
- package/src/lib/record/env.mjs +25 -0
- package/src/lib/record/env.mjs.map +1 -0
- package/src/lib/record/form.d.mts +24 -0
- package/src/lib/record/form.d.ts +24 -0
- package/src/lib/record/form.js +160 -32
- package/src/lib/record/form.js.map +1 -1
- package/src/lib/record/form.mjs +160 -32
- package/src/lib/record/form.mjs.map +1 -1
- package/src/lib/record/inputs.d.mts +5 -0
- package/src/lib/record/inputs.d.ts +5 -0
- package/src/lib/record/inputs.js +47 -0
- package/src/lib/record/inputs.js.map +1 -0
- package/src/lib/record/inputs.mjs +44 -0
- package/src/lib/record/inputs.mjs.map +1 -0
- package/src/lib/record/limits.d.mts +13 -0
- package/src/lib/record/limits.d.ts +13 -0
- package/src/lib/record/limits.js +45 -0
- package/src/lib/record/limits.js.map +1 -0
- package/src/lib/record/limits.mjs +41 -0
- package/src/lib/record/limits.mjs.map +1 -0
- package/src/lib/record/locales/all.d.mts +7 -0
- package/src/lib/record/locales/all.d.ts +7 -0
- package/src/lib/record/locales/all.js +13 -0
- package/src/lib/record/locales/all.js.map +1 -0
- package/src/lib/record/locales/all.mjs +10 -0
- package/src/lib/record/locales/all.mjs.map +1 -0
- package/src/lib/record/locales/ar.d.mts +3 -0
- package/src/lib/record/locales/ar.d.ts +3 -0
- package/src/lib/record/locales/ar.js +55 -0
- package/src/lib/record/locales/ar.js.map +1 -0
- package/src/lib/record/locales/ar.mjs +52 -0
- package/src/lib/record/locales/ar.mjs.map +1 -0
- package/src/lib/record/locales/de.d.mts +3 -0
- package/src/lib/record/locales/de.d.ts +3 -0
- package/src/lib/record/locales/de.js +55 -0
- package/src/lib/record/locales/de.js.map +1 -0
- package/src/lib/record/locales/de.mjs +52 -0
- package/src/lib/record/locales/de.mjs.map +1 -0
- package/src/lib/record/locales/fr.d.mts +3 -0
- package/src/lib/record/locales/fr.d.ts +3 -0
- package/src/lib/record/locales/fr.js +55 -0
- package/src/lib/record/locales/fr.js.map +1 -0
- package/src/lib/record/locales/fr.mjs +52 -0
- package/src/lib/record/locales/fr.mjs.map +1 -0
- package/src/lib/record/memory-data-source.d.mts +3 -0
- package/src/lib/record/memory-data-source.d.ts +3 -0
- package/src/lib/record/memory-data-source.js +8 -0
- package/src/lib/record/memory-data-source.js.map +1 -1
- package/src/lib/record/memory-data-source.mjs +8 -0
- package/src/lib/record/memory-data-source.mjs.map +1 -1
- package/src/lib/record/messages.d.mts +46 -0
- package/src/lib/record/messages.d.ts +46 -0
- package/src/lib/record/messages.js +58 -101
- package/src/lib/record/messages.js.map +1 -1
- package/src/lib/record/messages.mjs +58 -101
- package/src/lib/record/messages.mjs.map +1 -1
- package/src/lib/record/rules.d.mts +33 -0
- package/src/lib/record/rules.d.ts +33 -0
- package/src/lib/record/rules.js +83 -0
- package/src/lib/record/rules.js.map +1 -0
- package/src/lib/record/rules.mjs +79 -0
- package/src/lib/record/rules.mjs.map +1 -0
- package/src/lib/record/score.d.mts +16 -0
- package/src/lib/record/score.d.ts +16 -0
- package/src/lib/record/score.js +35 -0
- package/src/lib/record/score.js.map +1 -0
- package/src/lib/record/score.mjs +32 -0
- package/src/lib/record/score.mjs.map +1 -0
- package/src/lib/record/set-when.d.mts +24 -0
- package/src/lib/record/set-when.d.ts +24 -0
- package/src/lib/record/set-when.js +68 -0
- package/src/lib/record/set-when.js.map +1 -0
- package/src/lib/record/set-when.mjs +65 -0
- package/src/lib/record/set-when.mjs.map +1 -0
- package/src/lib/record/structures.d.mts +14 -0
- package/src/lib/record/structures.d.ts +14 -0
- package/src/lib/record/structures.js +32 -0
- package/src/lib/record/structures.js.map +1 -0
- package/src/lib/record/structures.mjs +28 -0
- package/src/lib/record/structures.mjs.map +1 -0
- package/src/lib/record/values.d.mts +10 -5
- package/src/lib/record/values.d.ts +10 -5
- package/src/lib/record/values.js +20 -6
- package/src/lib/record/values.js.map +1 -1
- package/src/lib/record/values.mjs +19 -6
- package/src/lib/record/values.mjs.map +1 -1
- package/src/runtime.d.mts +10 -7
- package/src/runtime.d.ts +10 -7
- package/src/runtime.js +12 -1
- package/src/runtime.js.map +1 -1
- package/src/runtime.mjs +5 -2
- package/src/runtime.mjs.map +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Every node of an expression, each visited once, the outer before the inner. */
|
|
2
|
+
function walk(ast, visit) {
|
|
3
|
+
visit(ast);
|
|
4
|
+
switch (ast.type) {
|
|
5
|
+
case 'BinaryOp':
|
|
6
|
+
walk(ast.left, visit);
|
|
7
|
+
walk(ast.right, visit);
|
|
8
|
+
return;
|
|
9
|
+
case 'UnaryOp':
|
|
10
|
+
walk(ast.operand, visit);
|
|
11
|
+
return;
|
|
12
|
+
case 'Call':
|
|
13
|
+
for (const arg of ast.args)
|
|
14
|
+
walk(arg, visit);
|
|
15
|
+
return;
|
|
16
|
+
default:
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** The fields an expression reads, by their first name, once each, in order of appearance. Functions are not fields. */
|
|
21
|
+
export function fieldsRead(ast) {
|
|
22
|
+
const names = [];
|
|
23
|
+
walk(ast, (node) => {
|
|
24
|
+
if (node.type !== 'Identifier')
|
|
25
|
+
return;
|
|
26
|
+
const root = node.name.split('.')[0];
|
|
27
|
+
if (!names.includes(root))
|
|
28
|
+
names.push(root);
|
|
29
|
+
});
|
|
30
|
+
return names;
|
|
31
|
+
}
|
|
32
|
+
/** The line fields an expression adds up, as `sum(lines, 'subtotal')` names them. */
|
|
33
|
+
export function sumsRead(ast) {
|
|
34
|
+
const sums = [];
|
|
35
|
+
walk(ast, (node) => {
|
|
36
|
+
if (node.type !== 'Call' || node.name !== 'sum')
|
|
37
|
+
return;
|
|
38
|
+
const [lines, field] = node.args;
|
|
39
|
+
if (lines.type === 'Identifier' && field?.type === 'Literal')
|
|
40
|
+
sums.push({ lines: lines.name, field: field.value });
|
|
41
|
+
});
|
|
42
|
+
return sums;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=reads.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reads.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/reads.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,SAAS,IAAI,CAAC,GAAY,EAAE,KAA8B;IACxD,KAAK,CAAC,GAAG,CAAC,CAAC;IACX,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACvB,OAAO;QACT,KAAK,SAAS;YACZ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACzB,OAAO;QACT,KAAK,MAAM;YACT,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI;gBAAE,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7C,OAAO;QACT;YACE,OAAO;IACX,CAAC;AACH,CAAC;AAED,wHAAwH;AACxH,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;QACjB,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY;YAAE,OAAO;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,QAAQ,CAAC,GAAY;IACnC,MAAM,IAAI,GAAuC,EAAE,CAAC;IACpD,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;QACjB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO;QACxD,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAe,EAAE,CAAC,CAAC;IAC/H,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tokenizer for
|
|
2
|
+
* Tokenizer for expressions: modifiers, and values worked out from others.
|
|
3
3
|
*
|
|
4
4
|
* Ported from the React form engine, with one change in behaviour: a
|
|
5
5
|
* character the language does not know is an error, not something to skip.
|
|
6
6
|
* The React version dropped it silently, so `amount > -5` read as
|
|
7
|
-
* `amount > 5` and `a && b` read as `a b`.
|
|
7
|
+
* `amount > 5` and `a && b` read as `a b`. A minus sign is a token of its
|
|
8
|
+
* own, so `a-5` is a subtraction; the parser reads `-5` as a negative number.
|
|
8
9
|
*/
|
|
9
|
-
export type TokenType = 'IDENTIFIER' | 'NUMBER' | 'STRING' | 'LIST' | 'OPERATOR' | 'LOGICAL' | 'CONSTANT' | 'PAREN';
|
|
10
|
+
export type TokenType = 'IDENTIFIER' | 'NUMBER' | 'STRING' | 'LIST' | 'OPERATOR' | 'LOGICAL' | 'CONSTANT' | 'ARITHMETIC' | 'COMMA' | 'PAREN';
|
|
10
11
|
export interface Token {
|
|
11
12
|
type: TokenType;
|
|
12
13
|
value: string;
|
|
13
14
|
position: number;
|
|
14
15
|
}
|
|
16
|
+
/** The words that are values, not field names. */
|
|
17
|
+
export declare const CONSTANTS: ReadonlyMap<string, boolean | null>;
|
|
15
18
|
/**
|
|
16
|
-
* Tokenizes a Flectra modifier
|
|
19
|
+
* Tokenizes an expression: a Flectra modifier, or a value worked out from others.
|
|
17
20
|
*
|
|
18
21
|
* @param expr - The expression string to tokenize
|
|
19
22
|
* @returns Array of tokens
|
|
@@ -26,6 +29,4 @@ export interface Token {
|
|
|
26
29
|
* // { type: 'STRING', value: "'draft'", position: 2 }
|
|
27
30
|
* // ]
|
|
28
31
|
*/
|
|
29
|
-
/** The words that are values, not field names. */
|
|
30
|
-
export declare const CONSTANTS: ReadonlyMap<string, boolean | null>;
|
|
31
32
|
export declare function tokenize(expr: string): Token[];
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tokenizer for
|
|
2
|
+
* Tokenizer for expressions: modifiers, and values worked out from others.
|
|
3
3
|
*
|
|
4
4
|
* Ported from the React form engine, with one change in behaviour: a
|
|
5
5
|
* character the language does not know is an error, not something to skip.
|
|
6
6
|
* The React version dropped it silently, so `amount > -5` read as
|
|
7
|
-
* `amount > 5` and `a && b` read as `a b`.
|
|
7
|
+
* `amount > 5` and `a && b` read as `a b`. A minus sign is a token of its
|
|
8
|
+
* own, so `a-5` is a subtraction; the parser reads `-5` as a negative number.
|
|
8
9
|
*/
|
|
9
|
-
export type TokenType = 'IDENTIFIER' | 'NUMBER' | 'STRING' | 'LIST' | 'OPERATOR' | 'LOGICAL' | 'CONSTANT' | 'PAREN';
|
|
10
|
+
export type TokenType = 'IDENTIFIER' | 'NUMBER' | 'STRING' | 'LIST' | 'OPERATOR' | 'LOGICAL' | 'CONSTANT' | 'ARITHMETIC' | 'COMMA' | 'PAREN';
|
|
10
11
|
export interface Token {
|
|
11
12
|
type: TokenType;
|
|
12
13
|
value: string;
|
|
13
14
|
position: number;
|
|
14
15
|
}
|
|
16
|
+
/** The words that are values, not field names. */
|
|
17
|
+
export declare const CONSTANTS: ReadonlyMap<string, boolean | null>;
|
|
15
18
|
/**
|
|
16
|
-
* Tokenizes a Flectra modifier
|
|
19
|
+
* Tokenizes an expression: a Flectra modifier, or a value worked out from others.
|
|
17
20
|
*
|
|
18
21
|
* @param expr - The expression string to tokenize
|
|
19
22
|
* @returns Array of tokens
|
|
@@ -26,6 +29,4 @@ export interface Token {
|
|
|
26
29
|
* // { type: 'STRING', value: "'draft'", position: 2 }
|
|
27
30
|
* // ]
|
|
28
31
|
*/
|
|
29
|
-
/** The words that are values, not field names. */
|
|
30
|
-
export declare const CONSTANTS: ReadonlyMap<string, boolean | null>;
|
|
31
32
|
export declare function tokenize(expr: string): Token[];
|
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Tokenizer for
|
|
3
|
+
* Tokenizer for expressions: modifiers, and values worked out from others.
|
|
4
4
|
*
|
|
5
5
|
* Ported from the React form engine, with one change in behaviour: a
|
|
6
6
|
* character the language does not know is an error, not something to skip.
|
|
7
7
|
* The React version dropped it silently, so `amount > -5` read as
|
|
8
|
-
* `amount > 5` and `a && b` read as `a b`.
|
|
8
|
+
* `amount > 5` and `a && b` read as `a b`. A minus sign is a token of its
|
|
9
|
+
* own, so `a-5` is a subtraction; the parser reads `-5` as a negative number.
|
|
9
10
|
*/
|
|
10
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
12
|
exports.CONSTANTS = void 0;
|
|
12
13
|
exports.tokenize = tokenize;
|
|
14
|
+
/** The words that are values, not field names. */
|
|
15
|
+
exports.CONSTANTS = new Map([
|
|
16
|
+
['True', true],
|
|
17
|
+
['False', false],
|
|
18
|
+
['None', null],
|
|
19
|
+
['true', true],
|
|
20
|
+
['false', false],
|
|
21
|
+
['null', null],
|
|
22
|
+
]);
|
|
23
|
+
/** The operators that work out numbers, and join text. */
|
|
24
|
+
const ARITHMETIC = new Set(['+', '-', '*', '/', '%']);
|
|
13
25
|
/**
|
|
14
|
-
* Tokenizes a Flectra modifier
|
|
26
|
+
* Tokenizes an expression: a Flectra modifier, or a value worked out from others.
|
|
15
27
|
*
|
|
16
28
|
* @param expr - The expression string to tokenize
|
|
17
29
|
* @returns Array of tokens
|
|
@@ -24,24 +36,15 @@ exports.tokenize = tokenize;
|
|
|
24
36
|
* // { type: 'STRING', value: "'draft'", position: 2 }
|
|
25
37
|
* // ]
|
|
26
38
|
*/
|
|
27
|
-
/** The words that are values, not field names. */
|
|
28
|
-
exports.CONSTANTS = new Map([
|
|
29
|
-
['True', true],
|
|
30
|
-
['False', false],
|
|
31
|
-
['None', null],
|
|
32
|
-
['true', true],
|
|
33
|
-
['false', false],
|
|
34
|
-
['null', null],
|
|
35
|
-
]);
|
|
36
39
|
function tokenize(expr) {
|
|
37
40
|
const tokens = [];
|
|
38
41
|
if (!expr)
|
|
39
42
|
return tokens;
|
|
40
43
|
// Alternatives in priority order: "not in" before "not", operators of two
|
|
41
|
-
// characters before one, a
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
const token = /(\(|\)
|
|
44
|
+
// characters before one, a number before anything else that could start
|
|
45
|
+
// with a digit. Sticky (`y`), so a position nothing matches is an error
|
|
46
|
+
// instead of a gap.
|
|
47
|
+
const token = /(\(|\)|,|==|!=|<=|>=|<>|<|>|[-+*/%]|not\s+in\b|in\b|and\b|or\b|not\b|\[[^\]]*\]|'[^']*'|"[^"]*"|\d+\.?\d*|\w+(?:\.\w+)*)/iy;
|
|
45
48
|
const space = /\s*/y;
|
|
46
49
|
let at = 0;
|
|
47
50
|
for (;;) {
|
|
@@ -82,6 +85,13 @@ function getTokenType(text) {
|
|
|
82
85
|
if (text === '(' || text === ')') {
|
|
83
86
|
return 'PAREN';
|
|
84
87
|
}
|
|
88
|
+
// Arithmetic, and the comma between a function's values
|
|
89
|
+
if (ARITHMETIC.has(text)) {
|
|
90
|
+
return 'ARITHMETIC';
|
|
91
|
+
}
|
|
92
|
+
if (text === ',') {
|
|
93
|
+
return 'COMMA';
|
|
94
|
+
}
|
|
85
95
|
// Lists (start with '[')
|
|
86
96
|
if (text.startsWith('[')) {
|
|
87
97
|
return 'LIST';
|
|
@@ -90,8 +100,8 @@ function getTokenType(text) {
|
|
|
90
100
|
if (text.startsWith("'") || text.startsWith('"')) {
|
|
91
101
|
return 'STRING';
|
|
92
102
|
}
|
|
93
|
-
// Numbers (
|
|
94
|
-
if (
|
|
103
|
+
// Numbers (integer or float; a minus sign before one is its own token)
|
|
104
|
+
if (/^\d+\.?\d*$/.test(text)) {
|
|
95
105
|
return 'NUMBER';
|
|
96
106
|
}
|
|
97
107
|
// Default to identifier
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/tokenizer.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/tokenizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tokenizer for
|
|
2
|
+
* Tokenizer for expressions: modifiers, and values worked out from others.
|
|
3
3
|
*
|
|
4
4
|
* Ported from the React form engine, with one change in behaviour: a
|
|
5
5
|
* character the language does not know is an error, not something to skip.
|
|
6
6
|
* The React version dropped it silently, so `amount > -5` read as
|
|
7
|
-
* `amount > 5` and `a && b` read as `a b`.
|
|
7
|
+
* `amount > 5` and `a && b` read as `a b`. A minus sign is a token of its
|
|
8
|
+
* own, so `a-5` is a subtraction; the parser reads `-5` as a negative number.
|
|
8
9
|
*/
|
|
10
|
+
/** The words that are values, not field names. */
|
|
11
|
+
export const CONSTANTS = new Map([
|
|
12
|
+
['True', true],
|
|
13
|
+
['False', false],
|
|
14
|
+
['None', null],
|
|
15
|
+
['true', true],
|
|
16
|
+
['false', false],
|
|
17
|
+
['null', null],
|
|
18
|
+
]);
|
|
19
|
+
/** The operators that work out numbers, and join text. */
|
|
20
|
+
const ARITHMETIC = new Set(['+', '-', '*', '/', '%']);
|
|
9
21
|
/**
|
|
10
|
-
* Tokenizes a Flectra modifier
|
|
22
|
+
* Tokenizes an expression: a Flectra modifier, or a value worked out from others.
|
|
11
23
|
*
|
|
12
24
|
* @param expr - The expression string to tokenize
|
|
13
25
|
* @returns Array of tokens
|
|
@@ -20,24 +32,15 @@
|
|
|
20
32
|
* // { type: 'STRING', value: "'draft'", position: 2 }
|
|
21
33
|
* // ]
|
|
22
34
|
*/
|
|
23
|
-
/** The words that are values, not field names. */
|
|
24
|
-
export const CONSTANTS = new Map([
|
|
25
|
-
['True', true],
|
|
26
|
-
['False', false],
|
|
27
|
-
['None', null],
|
|
28
|
-
['true', true],
|
|
29
|
-
['false', false],
|
|
30
|
-
['null', null],
|
|
31
|
-
]);
|
|
32
35
|
export function tokenize(expr) {
|
|
33
36
|
const tokens = [];
|
|
34
37
|
if (!expr)
|
|
35
38
|
return tokens;
|
|
36
39
|
// Alternatives in priority order: "not in" before "not", operators of two
|
|
37
|
-
// characters before one, a
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
const token = /(\(|\)
|
|
40
|
+
// characters before one, a number before anything else that could start
|
|
41
|
+
// with a digit. Sticky (`y`), so a position nothing matches is an error
|
|
42
|
+
// instead of a gap.
|
|
43
|
+
const token = /(\(|\)|,|==|!=|<=|>=|<>|<|>|[-+*/%]|not\s+in\b|in\b|and\b|or\b|not\b|\[[^\]]*\]|'[^']*'|"[^"]*"|\d+\.?\d*|\w+(?:\.\w+)*)/iy;
|
|
41
44
|
const space = /\s*/y;
|
|
42
45
|
let at = 0;
|
|
43
46
|
for (;;) {
|
|
@@ -78,6 +81,13 @@ function getTokenType(text) {
|
|
|
78
81
|
if (text === '(' || text === ')') {
|
|
79
82
|
return 'PAREN';
|
|
80
83
|
}
|
|
84
|
+
// Arithmetic, and the comma between a function's values
|
|
85
|
+
if (ARITHMETIC.has(text)) {
|
|
86
|
+
return 'ARITHMETIC';
|
|
87
|
+
}
|
|
88
|
+
if (text === ',') {
|
|
89
|
+
return 'COMMA';
|
|
90
|
+
}
|
|
81
91
|
// Lists (start with '[')
|
|
82
92
|
if (text.startsWith('[')) {
|
|
83
93
|
return 'LIST';
|
|
@@ -86,8 +96,8 @@ function getTokenType(text) {
|
|
|
86
96
|
if (text.startsWith("'") || text.startsWith('"')) {
|
|
87
97
|
return 'STRING';
|
|
88
98
|
}
|
|
89
|
-
// Numbers (
|
|
90
|
-
if (
|
|
99
|
+
// Numbers (integer or float; a minus sign before one is its own token)
|
|
100
|
+
if (/^\d+\.?\d*$/.test(text)) {
|
|
91
101
|
return 'NUMBER';
|
|
92
102
|
}
|
|
93
103
|
// Default to identifier
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokenizer.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/tokenizer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tokenizer.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/expression/tokenizer.ts"],"names":[],"mappings":"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"}
|