pacc 8.9.3 → 8.11.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/README.md +21 -30
- package/package.json +1 -1
- package/src/ast.mjs +1 -41
- package/src/expression.mjs +30 -126
- package/src/filter.mjs +4 -1
- package/src/settergetter.mjs +7 -17
- package/src/tokens.mjs +186 -29
- package/types/ast.d.mts +4 -2
- package/types/tokens.d.mts +5 -2
package/README.md
CHANGED
|
@@ -32,16 +32,14 @@ const result = expand("${a + 1}",{ root: { a: 2 }});
|
|
|
32
32
|
|
|
33
33
|
* [AST](#ast)
|
|
34
34
|
* [Properties](#properties)
|
|
35
|
-
* [binopError](#binoperror)
|
|
36
|
-
* [Parameters](#parameters)
|
|
37
35
|
* [prepareAttributesDefinitions](#prepareattributesdefinitions)
|
|
38
|
-
* [Parameters](#parameters
|
|
36
|
+
* [Parameters](#parameters)
|
|
39
37
|
* [mergeAttributeDefinitions](#mergeattributedefinitions)
|
|
40
|
-
* [Parameters](#parameters-
|
|
38
|
+
* [Parameters](#parameters-1)
|
|
41
39
|
* [attributeIterator](#attributeiterator)
|
|
42
|
-
* [Parameters](#parameters-
|
|
40
|
+
* [Parameters](#parameters-2)
|
|
43
41
|
* [parseBytes](#parsebytes)
|
|
44
|
-
* [Parameters](#parameters-
|
|
42
|
+
* [Parameters](#parameters-3)
|
|
45
43
|
* [AttributeDefinition](#attributedefinition)
|
|
46
44
|
* [Properties](#properties-1)
|
|
47
45
|
* [default\_attribute](#default_attribute)
|
|
@@ -99,40 +97,40 @@ const result = expand("${a + 1}",{ root: { a: 2 }});
|
|
|
99
97
|
* [timeout\_attribute](#timeout_attribute)
|
|
100
98
|
* [language\_attribute](#language_attribute)
|
|
101
99
|
* [environmentValues](#environmentvalues)
|
|
102
|
-
* [Parameters](#parameters-
|
|
100
|
+
* [Parameters](#parameters-4)
|
|
103
101
|
* [expandContextDefault](#expandcontextdefault)
|
|
104
102
|
* [expandContextDoubbleCurly](#expandcontextdoubblecurly)
|
|
105
103
|
* [expand](#expand)
|
|
106
|
-
* [Parameters](#parameters-
|
|
104
|
+
* [Parameters](#parameters-5)
|
|
107
105
|
* [promises](#promises)
|
|
108
106
|
* [filter](#filter)
|
|
109
|
-
* [Parameters](#parameters-
|
|
107
|
+
* [Parameters](#parameters-6)
|
|
110
108
|
* [setAttributes](#setattributes)
|
|
111
|
-
* [Parameters](#parameters-
|
|
109
|
+
* [Parameters](#parameters-7)
|
|
112
110
|
* [getAttributes](#getattributes)
|
|
113
|
-
* [Parameters](#parameters-
|
|
111
|
+
* [Parameters](#parameters-8)
|
|
114
112
|
* [getAttributesJSON](#getattributesjson)
|
|
115
|
-
* [Parameters](#parameters-
|
|
113
|
+
* [Parameters](#parameters-9)
|
|
116
114
|
* [tokens](#tokens)
|
|
117
115
|
* [tokens](#tokens-1)
|
|
118
|
-
* [Parameters](#parameters-
|
|
116
|
+
* [Parameters](#parameters-10)
|
|
119
117
|
* [setAttribute](#setattribute)
|
|
120
|
-
* [Parameters](#parameters-
|
|
118
|
+
* [Parameters](#parameters-11)
|
|
121
119
|
* [getAttribute](#getattribute)
|
|
122
|
-
* [Parameters](#parameters-
|
|
120
|
+
* [Parameters](#parameters-12)
|
|
123
121
|
* [getAttributeAndOperator](#getattributeandoperator)
|
|
124
|
-
* [Parameters](#parameters-
|
|
122
|
+
* [Parameters](#parameters-13)
|
|
125
123
|
* [parseDuration](#parseduration)
|
|
126
|
-
* [Parameters](#parameters-
|
|
124
|
+
* [Parameters](#parameters-14)
|
|
127
125
|
* [formatDuration](#formatduration)
|
|
128
|
-
* [Parameters](#parameters-
|
|
126
|
+
* [Parameters](#parameters-15)
|
|
129
127
|
* [formatDurationISO](#formatdurationiso)
|
|
130
|
-
* [Parameters](#parameters-
|
|
128
|
+
* [Parameters](#parameters-16)
|
|
131
129
|
* [lookup](#lookup)
|
|
132
130
|
* [Token](#token)
|
|
133
131
|
* [Properties](#properties-2)
|
|
134
132
|
* [createToken](#createtoken)
|
|
135
|
-
* [Parameters](#parameters-
|
|
133
|
+
* [Parameters](#parameters-17)
|
|
136
134
|
* [PLUS](#plus)
|
|
137
135
|
* [MINUS](#minus)
|
|
138
136
|
* [STAR](#star)
|
|
@@ -164,7 +162,7 @@ const result = expand("${a + 1}",{ root: { a: 2 }});
|
|
|
164
162
|
* [Type](#type)
|
|
165
163
|
* [Properties](#properties-3)
|
|
166
164
|
* [raiseOnUnknownType](#raiseonunknowntype)
|
|
167
|
-
* [Parameters](#parameters-
|
|
165
|
+
* [Parameters](#parameters-18)
|
|
168
166
|
|
|
169
167
|
## AST
|
|
170
168
|
|
|
@@ -174,14 +172,6 @@ Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Globa
|
|
|
174
172
|
|
|
175
173
|
* `eval` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** 
|
|
176
174
|
|
|
177
|
-
## binopError
|
|
178
|
-
|
|
179
|
-
### Parameters
|
|
180
|
-
|
|
181
|
-
* `token` **[Token](#token)** 
|
|
182
|
-
* `left` **[AST](#ast)** 
|
|
183
|
-
* `right` **[AST](#ast)** 
|
|
184
|
-
|
|
185
175
|
## prepareAttributesDefinitions
|
|
186
176
|
|
|
187
177
|
Create attributes from its definition.
|
|
@@ -661,7 +651,8 @@ Type: [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Globa
|
|
|
661
651
|
* `str` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
662
652
|
* `precedence` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** (optional, default `0`)
|
|
663
653
|
* `type` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** 
|
|
664
|
-
* `led` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)
|
|
654
|
+
* `led` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** (optional, default `()=>{}`)
|
|
655
|
+
* `nud` (optional, default `()=>{}`)
|
|
665
656
|
|
|
666
657
|
Returns **[Token](#token)** 
|
|
667
658
|
|
package/package.json
CHANGED
package/src/ast.mjs
CHANGED
|
@@ -1,49 +1,9 @@
|
|
|
1
|
+
|
|
1
2
|
/**
|
|
2
3
|
* @typedef {Object} AST
|
|
3
4
|
* @property {Function} [eval]
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
* @param {Token} token
|
|
9
|
-
* @param {AST} left
|
|
10
|
-
* @param {AST} right
|
|
11
|
-
*
|
|
12
|
-
*/
|
|
13
|
-
function binopError(token, left, right) {
|
|
14
|
-
throw new Error(`Unexpected '${token.str || token}'`, { cause: token });
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function binop(token, left, right, fallback) {
|
|
18
|
-
if(token.led) { return token.led(left,right); }
|
|
19
|
-
|
|
20
|
-
return fallback(token, left, right);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function binopEval(node, current, context) {
|
|
24
|
-
return binop(
|
|
25
|
-
node.token,
|
|
26
|
-
node.left.eval ? node.left.eval(node.left, current, context) : node.left,
|
|
27
|
-
node.right.eval
|
|
28
|
-
? node.right.eval(node.right, current, context)
|
|
29
|
-
: node.right,
|
|
30
|
-
binopError
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function ASTBinop(token, left, right) {
|
|
35
|
-
if (!left.eval && !right.eval) {
|
|
36
|
-
return binop(token, left, right, binopError);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
eval: binopEval,
|
|
41
|
-
token,
|
|
42
|
-
left,
|
|
43
|
-
right
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
7
|
export function pathEval(node, current, context) {
|
|
48
8
|
let collection = false;
|
|
49
9
|
let first = true;
|
package/src/expression.mjs
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
tokens,
|
|
3
|
-
DOT,
|
|
4
|
-
OPEN_ROUND,
|
|
5
|
-
CLOSE_ROUND,
|
|
6
|
-
OPEN_BRACKET,
|
|
7
|
-
CLOSE_BRACKET,
|
|
8
|
-
IDENTIFIER,
|
|
9
|
-
COMMA,
|
|
10
|
-
EOF
|
|
11
|
-
} from "./tokens.mjs";
|
|
12
|
-
import { pathEval, functionEval, ASTTrue, ASTBinop } from "./ast.mjs";
|
|
1
|
+
import { tokens, EOF } from "./tokens.mjs";
|
|
13
2
|
|
|
14
3
|
export function parseOnly(input, context = {}) {
|
|
15
4
|
context.getGlobal ||= a => globals[a];
|
|
@@ -30,129 +19,44 @@ export function parseOnly(input, context = {}) {
|
|
|
30
19
|
}
|
|
31
20
|
}
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (token === COMMA) {
|
|
51
|
-
advance();
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
expect(CLOSE_ROUND);
|
|
55
|
-
|
|
56
|
-
// TODO always a sequence ?
|
|
57
|
-
return sequence.length > 1 ? sequence : sequence[0];
|
|
58
|
-
}
|
|
59
|
-
case OPEN_BRACKET: {
|
|
60
|
-
if (token === CLOSE_BRACKET) {
|
|
61
|
-
advance();
|
|
62
|
-
return ASTTrue;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const node = expression(0);
|
|
66
|
-
expect(CLOSE_BRACKET);
|
|
67
|
-
|
|
68
|
-
switch (typeof node) {
|
|
69
|
-
case "string":
|
|
70
|
-
case "number":
|
|
71
|
-
return { eval: pathEval, path: [node] };
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return node;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
case IDENTIFIER:
|
|
78
|
-
return { eval: pathEval, path: [value] };
|
|
79
|
-
|
|
80
|
-
case EOF:
|
|
81
|
-
throw new Error("unexpected EOF");
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (last.type === "prefix") {
|
|
85
|
-
return { token: last, left, right: expression(last.precedence) };
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return last;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function led(last, left) {
|
|
92
|
-
switch (last.type) {
|
|
93
|
-
case "infixr":
|
|
94
|
-
return ASTBinop(last, left, expression(last.precedence - 1));
|
|
95
|
-
|
|
96
|
-
case "infix": {
|
|
97
|
-
const right = expression(last.precedence);
|
|
98
|
-
|
|
99
|
-
if (last === DOT) {
|
|
100
|
-
return last.led(left, right);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return ASTBinop(last, left, right);
|
|
22
|
+
const parser = {
|
|
23
|
+
get node() {
|
|
24
|
+
return node;
|
|
25
|
+
},
|
|
26
|
+
get token() {
|
|
27
|
+
return token;
|
|
28
|
+
},
|
|
29
|
+
get value() {
|
|
30
|
+
return value;
|
|
31
|
+
},
|
|
32
|
+
advance,
|
|
33
|
+
expect(expected) {
|
|
34
|
+
if (token !== expected) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`unexpected '${token?.str || token}' expecting '${expected.str}'`,
|
|
37
|
+
{ cause: token }
|
|
38
|
+
);
|
|
104
39
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
args.push(expression(0));
|
|
112
|
-
if (token === COMMA) {
|
|
113
|
-
advance();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
left.args = args;
|
|
117
|
-
left.eval = functionEval;
|
|
40
|
+
advance();
|
|
41
|
+
},
|
|
42
|
+
expression(precedence) {
|
|
43
|
+
const last = token;
|
|
44
|
+
advance();
|
|
45
|
+
node = last.nud ? last.nud(parser) : last;
|
|
118
46
|
|
|
47
|
+
while (token.precedence > precedence) {
|
|
48
|
+
const last = token;
|
|
119
49
|
advance();
|
|
120
|
-
|
|
121
|
-
return left;
|
|
50
|
+
node = last.led(parser, node);
|
|
122
51
|
}
|
|
123
|
-
case OPEN_BRACKET: {
|
|
124
|
-
if (token === CLOSE_BRACKET) {
|
|
125
|
-
advance();
|
|
126
|
-
left.path.push(ASTTrue);
|
|
127
|
-
} else {
|
|
128
|
-
const predicate = expression(0);
|
|
129
|
-
expect(CLOSE_BRACKET);
|
|
130
|
-
left.path.push(predicate);
|
|
131
|
-
}
|
|
132
|
-
return left;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return { token };
|
|
137
|
-
}
|
|
138
52
|
|
|
139
|
-
|
|
140
|
-
const last = token;
|
|
141
|
-
advance();
|
|
142
|
-
node = nud(last, node);
|
|
143
|
-
|
|
144
|
-
while (token.precedence > precedence) {
|
|
145
|
-
const last = token;
|
|
146
|
-
advance();
|
|
147
|
-
node = led(last, node);
|
|
53
|
+
return node;
|
|
148
54
|
}
|
|
149
|
-
|
|
150
|
-
return node;
|
|
151
|
-
}
|
|
55
|
+
};
|
|
152
56
|
|
|
153
57
|
advance();
|
|
154
58
|
|
|
155
|
-
return expression(token.precedence ?? 0);
|
|
59
|
+
return parser.expression(token.precedence ?? 0);
|
|
156
60
|
}
|
|
157
61
|
|
|
158
62
|
export function parse(input, context) {
|
package/src/filter.mjs
CHANGED
|
@@ -7,7 +7,10 @@ import {
|
|
|
7
7
|
GREATER,
|
|
8
8
|
GREATER_EQUAL
|
|
9
9
|
} from "pacc";
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
function binop(token, left, right) {
|
|
12
|
+
return token.binop(left, right);
|
|
13
|
+
}
|
|
11
14
|
|
|
12
15
|
function dateOp(op, value, against) {
|
|
13
16
|
return binop(op, value.getTime(), against.getTime());
|
package/src/settergetter.mjs
CHANGED
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
GREATER,
|
|
15
15
|
GREATER_EQUAL,
|
|
16
16
|
STAR,
|
|
17
|
-
IDENTIFIER
|
|
17
|
+
IDENTIFIER,
|
|
18
|
+
STRING,
|
|
19
|
+
NUMBER,
|
|
20
|
+
BOOLEAN
|
|
18
21
|
} from "./tokens.mjs";
|
|
19
22
|
import { parseOnly } from "./expression.mjs";
|
|
20
23
|
import { toInternal } from "./attributes.mjs";
|
|
@@ -146,6 +149,9 @@ export function getAttributeAndOperator(object, expression) {
|
|
|
146
149
|
predicateTokens.push(token[0]);
|
|
147
150
|
break;
|
|
148
151
|
|
|
152
|
+
case STRING:
|
|
153
|
+
case NUMBER:
|
|
154
|
+
case BOOLEAN:
|
|
149
155
|
case IDENTIFIER:
|
|
150
156
|
if (object !== undefined) {
|
|
151
157
|
switch (typeof object[token[1]]) {
|
|
@@ -163,22 +169,6 @@ export function getAttributeAndOperator(object, expression) {
|
|
|
163
169
|
}
|
|
164
170
|
}
|
|
165
171
|
break;
|
|
166
|
-
default:
|
|
167
|
-
if (object !== undefined) {
|
|
168
|
-
switch (typeof object[token[0]]) {
|
|
169
|
-
case "function":
|
|
170
|
-
object = object[token[0]]();
|
|
171
|
-
if (typeof object[Symbol.iterator] === "function") {
|
|
172
|
-
object = [...object];
|
|
173
|
-
}
|
|
174
|
-
break;
|
|
175
|
-
default:
|
|
176
|
-
object = object[token[0]];
|
|
177
|
-
break;
|
|
178
|
-
case "undefined":
|
|
179
|
-
return [undefined, op];
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
172
|
}
|
|
183
173
|
}
|
|
184
174
|
|
package/src/tokens.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { pathEval, ASTTrue, functionEval } from "./ast.mjs";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Token lookup
|
|
3
5
|
*/
|
|
@@ -8,6 +10,8 @@ const lookup = {};
|
|
|
8
10
|
* @property {string} str
|
|
9
11
|
*/
|
|
10
12
|
|
|
13
|
+
function infix() {}
|
|
14
|
+
|
|
11
15
|
/**
|
|
12
16
|
*
|
|
13
17
|
* @param {string} str
|
|
@@ -16,16 +20,61 @@ const lookup = {};
|
|
|
16
20
|
* @param {Function} [led]
|
|
17
21
|
* @returns {Token}
|
|
18
22
|
*/
|
|
19
|
-
function createToken(
|
|
23
|
+
function createToken(
|
|
24
|
+
str,
|
|
25
|
+
precedence = 0,
|
|
26
|
+
type,
|
|
27
|
+
led = () => {},
|
|
28
|
+
nud = () => {}
|
|
29
|
+
) {
|
|
20
30
|
const token = { str, precedence, type };
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
|
|
32
|
+
switch (type) {
|
|
33
|
+
case "infix":
|
|
34
|
+
token.led = (parser, left) =>
|
|
35
|
+
led(left, parser.expression(token.precedence));
|
|
36
|
+
break;
|
|
37
|
+
case "infixr":
|
|
38
|
+
token.led = (parser, left) =>
|
|
39
|
+
led(left, parser.expression(token.precedence - 1));
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
token.led = led;
|
|
23
43
|
}
|
|
44
|
+
|
|
45
|
+
token.nud = nud;
|
|
24
46
|
lookup[str] = [token];
|
|
25
47
|
return token;
|
|
26
48
|
}
|
|
27
49
|
|
|
28
|
-
|
|
50
|
+
function createBinopToken(str, precedence, type, binop) {
|
|
51
|
+
const token = createToken(str, precedence, type, (left, right) => {
|
|
52
|
+
if (!left.eval && !right.eval) {
|
|
53
|
+
return binop(left, right);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
eval: (node, current, context) =>
|
|
58
|
+
binop(
|
|
59
|
+
node.left.eval
|
|
60
|
+
? node.left.eval(node.left, current, context)
|
|
61
|
+
: node.left,
|
|
62
|
+
node.right.eval
|
|
63
|
+
? node.right.eval(node.right, current, context)
|
|
64
|
+
: node.right
|
|
65
|
+
),
|
|
66
|
+
token,
|
|
67
|
+
left,
|
|
68
|
+
right
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
token.binop = binop;
|
|
73
|
+
|
|
74
|
+
return token;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export /** @type {Token} */ const PLUS = createBinopToken(
|
|
29
78
|
"+",
|
|
30
79
|
50,
|
|
31
80
|
"infix",
|
|
@@ -38,64 +87,132 @@ export /** @type {Token} */ const PLUS = createToken(
|
|
|
38
87
|
return left + right;
|
|
39
88
|
}
|
|
40
89
|
);
|
|
41
|
-
|
|
90
|
+
|
|
91
|
+
export /** @type {Token} */ const MINUS = createBinopToken(
|
|
42
92
|
"-",
|
|
43
93
|
50,
|
|
44
94
|
"infix",
|
|
45
95
|
(left, right) => left - right
|
|
46
96
|
);
|
|
47
|
-
export /** @type {Token} */ const STAR =
|
|
97
|
+
export /** @type {Token} */ const STAR = createBinopToken(
|
|
48
98
|
"*",
|
|
49
99
|
60,
|
|
50
100
|
"infix",
|
|
51
101
|
(left, right) => left * right
|
|
52
102
|
);
|
|
53
|
-
export /** @type {Token} */ const DIVIDE =
|
|
103
|
+
export /** @type {Token} */ const DIVIDE = createBinopToken(
|
|
54
104
|
"/",
|
|
55
105
|
60,
|
|
56
106
|
"infix",
|
|
57
107
|
(left, right) => left / right
|
|
58
108
|
);
|
|
59
109
|
export /** @type {Token} */ const NOT = createToken("!");
|
|
60
|
-
export /** @type {Token} */ const NOT_EQUAL =
|
|
110
|
+
export /** @type {Token} */ const NOT_EQUAL = createBinopToken(
|
|
61
111
|
"!=",
|
|
62
112
|
40,
|
|
63
113
|
"infixr",
|
|
64
114
|
(left, right) => left != right
|
|
65
115
|
);
|
|
66
|
-
export /** @type {Token} */ const EQUAL =
|
|
116
|
+
export /** @type {Token} */ const EQUAL = createBinopToken(
|
|
67
117
|
"=",
|
|
68
118
|
40,
|
|
69
119
|
"infixr",
|
|
70
120
|
(left, right) => left == right
|
|
71
121
|
);
|
|
72
|
-
export /** @type {Token} */ const GREATER =
|
|
122
|
+
export /** @type {Token} */ const GREATER = createBinopToken(
|
|
73
123
|
">",
|
|
74
124
|
40,
|
|
75
125
|
"infixr",
|
|
76
126
|
(left, right) => left > right
|
|
77
127
|
);
|
|
78
|
-
export /** @type {Token} */ const GREATER_EQUAL =
|
|
128
|
+
export /** @type {Token} */ const GREATER_EQUAL = createBinopToken(
|
|
79
129
|
">=",
|
|
80
130
|
40,
|
|
81
131
|
"infixr",
|
|
82
132
|
(left, right) => left >= right
|
|
83
133
|
);
|
|
84
|
-
export /** @type {Token} */ const LESS =
|
|
134
|
+
export /** @type {Token} */ const LESS = createBinopToken(
|
|
85
135
|
"<",
|
|
86
136
|
40,
|
|
87
137
|
"infixr",
|
|
88
138
|
(left, right) => left < right
|
|
89
139
|
);
|
|
90
|
-
export /** @type {Token} */ const LESS_EQUAL =
|
|
140
|
+
export /** @type {Token} */ const LESS_EQUAL = createBinopToken(
|
|
91
141
|
"<=",
|
|
92
142
|
40,
|
|
93
143
|
"infixr",
|
|
94
144
|
(left, right) => left <= right
|
|
95
145
|
);
|
|
96
|
-
export /** @type {Token} */ const OPEN_ROUND = createToken(
|
|
146
|
+
export /** @type {Token} */ const OPEN_ROUND = createToken(
|
|
147
|
+
"(",
|
|
148
|
+
40,
|
|
149
|
+
"prefix",
|
|
150
|
+
(parser, left) => {
|
|
151
|
+
const args = [];
|
|
152
|
+
while (parser.token !== CLOSE_ROUND) {
|
|
153
|
+
args.push(parser.expression(0));
|
|
154
|
+
if (parser.token === COMMA) {
|
|
155
|
+
parser.advance();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
left.args = args;
|
|
159
|
+
left.eval = functionEval;
|
|
160
|
+
|
|
161
|
+
parser.advance();
|
|
162
|
+
|
|
163
|
+
return left;
|
|
164
|
+
},
|
|
165
|
+
parser => {
|
|
166
|
+
const sequence = [];
|
|
167
|
+
|
|
168
|
+
while (parser.token !== CLOSE_ROUND) {
|
|
169
|
+
sequence.push(parser.expression(0));
|
|
170
|
+
if (parser.token === COMMA) {
|
|
171
|
+
parser.advance();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
parser.expect(CLOSE_ROUND);
|
|
175
|
+
|
|
176
|
+
// TODO always a sequence ?
|
|
177
|
+
return sequence.length > 1 ? sequence : sequence[0];
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
|
|
97
181
|
export /** @type {Token} */ const CLOSE_ROUND = createToken(")", 0, "infix");
|
|
98
|
-
export /** @type {Token} */ const OPEN_BRACKET = createToken(
|
|
182
|
+
export /** @type {Token} */ const OPEN_BRACKET = createToken(
|
|
183
|
+
"[",
|
|
184
|
+
10,
|
|
185
|
+
"prefix",
|
|
186
|
+
(parser, left) => {
|
|
187
|
+
if (parser.token === CLOSE_BRACKET) {
|
|
188
|
+
parser.advance();
|
|
189
|
+
left.path.push(ASTTrue);
|
|
190
|
+
} else {
|
|
191
|
+
const predicate = parser.expression(0);
|
|
192
|
+
parser.expect(CLOSE_BRACKET);
|
|
193
|
+
left.path.push(predicate);
|
|
194
|
+
}
|
|
195
|
+
return left;
|
|
196
|
+
},
|
|
197
|
+
parser => {
|
|
198
|
+
if (parser.token === CLOSE_BRACKET) {
|
|
199
|
+
parser.advance();
|
|
200
|
+
return ASTTrue;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const node = parser.expression(0);
|
|
204
|
+
parser.expect(CLOSE_BRACKET);
|
|
205
|
+
|
|
206
|
+
switch (typeof node) {
|
|
207
|
+
case "string":
|
|
208
|
+
case "number":
|
|
209
|
+
return { eval: pathEval, path: [node] };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return node;
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
|
|
99
216
|
export /** @type {Token} */ const CLOSE_BRACKET = createToken("]", 0, "infix");
|
|
100
217
|
export /** @type {Token} */ const OPEN_CURLY = createToken("{");
|
|
101
218
|
export /** @type {Token} */ const CLOSE_CURLY = createToken("}");
|
|
@@ -117,25 +234,65 @@ export /** @type {Token} */ const DOT = createToken(
|
|
|
117
234
|
}
|
|
118
235
|
);
|
|
119
236
|
export /** @type {Token} */ const AMPERSAND = createToken("&");
|
|
120
|
-
export /** @type {Token} */ const DOUBLE_AMPERSAND =
|
|
237
|
+
export /** @type {Token} */ const DOUBLE_AMPERSAND = createBinopToken(
|
|
121
238
|
"&&",
|
|
122
239
|
30,
|
|
123
240
|
"infixr",
|
|
124
241
|
(left, right) => left && right
|
|
125
242
|
);
|
|
126
243
|
export /** @type {Token} */ const BAR = createToken("|");
|
|
127
|
-
export /** @type {Token} */ const DOUBLE_BAR =
|
|
244
|
+
export /** @type {Token} */ const DOUBLE_BAR = createBinopToken(
|
|
128
245
|
"||",
|
|
129
246
|
30,
|
|
130
247
|
"infixr",
|
|
131
248
|
(left, right) => left || right
|
|
132
249
|
);
|
|
133
|
-
export /** @type {Token} */ const IDENTIFIER = createToken(
|
|
134
|
-
|
|
250
|
+
export /** @type {Token} */ const IDENTIFIER = createToken(
|
|
251
|
+
"IDENTIFIER",
|
|
252
|
+
0,
|
|
253
|
+
undefined,
|
|
254
|
+
undefined,
|
|
255
|
+
parser => {
|
|
256
|
+
return { eval: pathEval, path: [parser.value] };
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
export /** @type {Token} */ const STRING = createToken(
|
|
261
|
+
"STRING",
|
|
262
|
+
0,
|
|
263
|
+
undefined,
|
|
264
|
+
undefined,
|
|
265
|
+
parser => parser.value
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
export /** @type {Token} */ const NUMBER = createToken(
|
|
269
|
+
"NUMBER",
|
|
270
|
+
0,
|
|
271
|
+
undefined,
|
|
272
|
+
undefined,
|
|
273
|
+
parser => parser.value
|
|
274
|
+
);
|
|
275
|
+
export /** @type {Token} */ const BOOLEAN = createToken(
|
|
276
|
+
"BOOLEAN",
|
|
277
|
+
0,
|
|
278
|
+
undefined,
|
|
279
|
+
undefined,
|
|
280
|
+
parser => parser.value
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
export /** @type {Token} */ const EOF = createToken(
|
|
284
|
+
"EOF",
|
|
285
|
+
-1,
|
|
286
|
+
"eof",
|
|
287
|
+
undefined,
|
|
288
|
+
parser => {
|
|
289
|
+
throw new Error("unexpected EOF");
|
|
290
|
+
}
|
|
291
|
+
);
|
|
135
292
|
|
|
136
293
|
export const keywords = {
|
|
137
|
-
true: [true],
|
|
138
|
-
false: [false]
|
|
294
|
+
true: [BOOLEAN, true],
|
|
295
|
+
false: [BOOLEAN, false]
|
|
139
296
|
};
|
|
140
297
|
|
|
141
298
|
const esc = {
|
|
@@ -197,7 +354,7 @@ export function* tokens(string, options = {}) {
|
|
|
197
354
|
case " ":
|
|
198
355
|
switch (state) {
|
|
199
356
|
case "number":
|
|
200
|
-
yield [options.parseFloat(value)];
|
|
357
|
+
yield [NUMBER, options.parseFloat(value)];
|
|
201
358
|
state = undefined;
|
|
202
359
|
case undefined:
|
|
203
360
|
break;
|
|
@@ -226,13 +383,13 @@ export function* tokens(string, options = {}) {
|
|
|
226
383
|
case "'":
|
|
227
384
|
switch (state) {
|
|
228
385
|
case "number":
|
|
229
|
-
yield [options.parseFloat(value)];
|
|
386
|
+
yield [NUMBER,options.parseFloat(value)];
|
|
230
387
|
case undefined:
|
|
231
388
|
startString(c);
|
|
232
389
|
break;
|
|
233
390
|
case "string":
|
|
234
391
|
if (c === quote) {
|
|
235
|
-
yield [value];
|
|
392
|
+
yield [STRING, value];
|
|
236
393
|
state = undefined;
|
|
237
394
|
} else {
|
|
238
395
|
value += c;
|
|
@@ -254,7 +411,7 @@ export function* tokens(string, options = {}) {
|
|
|
254
411
|
case "|":
|
|
255
412
|
switch (state) {
|
|
256
413
|
case "number":
|
|
257
|
-
yield [options.parseFloat(value)];
|
|
414
|
+
yield [NUMBER, options.parseFloat(value)];
|
|
258
415
|
case undefined:
|
|
259
416
|
state = c;
|
|
260
417
|
break;
|
|
@@ -285,7 +442,7 @@ export function* tokens(string, options = {}) {
|
|
|
285
442
|
case "=":
|
|
286
443
|
switch (state) {
|
|
287
444
|
case "number":
|
|
288
|
-
yield [options.parseFloat(value)];
|
|
445
|
+
yield [NUMBER, options.parseFloat(value)];
|
|
289
446
|
case undefined:
|
|
290
447
|
state = c;
|
|
291
448
|
break;
|
|
@@ -326,7 +483,7 @@ export function* tokens(string, options = {}) {
|
|
|
326
483
|
case "}":
|
|
327
484
|
switch (state) {
|
|
328
485
|
case "number":
|
|
329
|
-
yield [options.parseFloat(value)];
|
|
486
|
+
yield [NUMBER, options.parseFloat(value)];
|
|
330
487
|
case undefined:
|
|
331
488
|
state = c;
|
|
332
489
|
break;
|
|
@@ -377,7 +534,7 @@ export function* tokens(string, options = {}) {
|
|
|
377
534
|
default:
|
|
378
535
|
switch (state) {
|
|
379
536
|
case "number":
|
|
380
|
-
yield [options.parseFloat(value)];
|
|
537
|
+
yield [NUMBER, options.parseFloat(value)];
|
|
381
538
|
case undefined:
|
|
382
539
|
state = "identifier";
|
|
383
540
|
value = c;
|
|
@@ -400,7 +557,7 @@ export function* tokens(string, options = {}) {
|
|
|
400
557
|
case "string":
|
|
401
558
|
throw new Error("unterminated string", { cause: string });
|
|
402
559
|
case "number":
|
|
403
|
-
yield [options.parseFloat(value)];
|
|
560
|
+
yield [NUMBER, options.parseFloat(value)];
|
|
404
561
|
break;
|
|
405
562
|
case "identifier":
|
|
406
563
|
yield keywordOrIdentifier();
|
package/types/ast.d.mts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} AST
|
|
3
|
+
* @property {Function} [eval]
|
|
4
|
+
*/
|
|
3
5
|
export function pathEval(node: any, current: any, context: any): any;
|
|
4
6
|
export function functionEval(node: any, current: any, context: any): any;
|
|
5
7
|
export namespace ASTTrue {
|
package/types/tokens.d.mts
CHANGED
|
@@ -34,11 +34,14 @@ export namespace DOUBLE_AMPERSAND { }
|
|
|
34
34
|
export namespace BAR { }
|
|
35
35
|
export namespace DOUBLE_BAR { }
|
|
36
36
|
export namespace IDENTIFIER { }
|
|
37
|
+
export namespace STRING { }
|
|
38
|
+
export namespace NUMBER { }
|
|
39
|
+
export namespace BOOLEAN { }
|
|
37
40
|
export namespace EOF { }
|
|
38
41
|
export namespace keywords {
|
|
39
|
-
let _true: boolean[];
|
|
42
|
+
let _true: (boolean | Token)[];
|
|
40
43
|
export { _true as true };
|
|
41
|
-
let _false: boolean[];
|
|
44
|
+
let _false: (boolean | Token)[];
|
|
42
45
|
export { _false as false };
|
|
43
46
|
}
|
|
44
47
|
export type Token = {
|