@elaraai/east 1.0.84 → 1.0.85
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/src/analyze.d.ts.map +1 -1
- package/dist/src/analyze.js +48 -0
- package/dist/src/analyze.js.map +1 -1
- package/dist/src/ast_to_ir.coerce_to.spec.js +4 -4
- package/dist/src/ast_to_ir.coerce_to.spec.js.map +1 -1
- package/dist/src/ast_to_ir.d.ts +6 -1
- package/dist/src/ast_to_ir.d.ts.map +1 -1
- package/dist/src/ast_to_ir.js +20 -7
- package/dist/src/ast_to_ir.js.map +1 -1
- package/dist/src/builtins.d.ts +1 -1
- package/dist/src/builtins.d.ts.map +1 -1
- package/dist/src/builtins.js +52 -0
- package/dist/src/builtins.js.map +1 -1
- package/dist/src/codegen/canonical.d.ts +37 -0
- package/dist/src/codegen/canonical.d.ts.map +1 -0
- package/dist/src/codegen/canonical.js +208 -0
- package/dist/src/codegen/canonical.js.map +1 -0
- package/dist/src/codegen/codegen.spec.js +132 -201
- package/dist/src/codegen/codegen.spec.js.map +1 -1
- package/dist/src/codegen/printer.d.ts.map +1 -1
- package/dist/src/codegen/printer.js +142 -24
- package/dist/src/codegen/printer.js.map +1 -1
- package/dist/src/codegen/spellings.d.ts +4 -1
- package/dist/src/codegen/spellings.d.ts.map +1 -1
- package/dist/src/codegen/spellings.js +5 -1
- package/dist/src/codegen/spellings.js.map +1 -1
- package/dist/src/compile/builtins/index.d.ts.map +1 -1
- package/dist/src/compile/builtins/index.js +2 -0
- package/dist/src/compile/builtins/index.js.map +1 -1
- package/dist/src/compile/builtins/primitives.d.ts.map +1 -1
- package/dist/src/compile/builtins/primitives.js +2 -1
- package/dist/src/compile/builtins/primitives.js.map +1 -1
- package/dist/src/compile/builtins/query.d.ts +10 -0
- package/dist/src/compile/builtins/query.d.ts.map +1 -0
- package/dist/src/compile/builtins/query.js +5 -0
- package/dist/src/compile/builtins/query.js.map +1 -0
- package/dist/src/expr/block.d.ts.map +1 -1
- package/dist/src/expr/block.js +2 -1
- package/dist/src/expr/block.js.map +1 -1
- package/dist/src/expr/index.d.ts +75 -47
- package/dist/src/expr/index.d.ts.map +1 -1
- package/dist/src/expr/index.js +31 -0
- package/dist/src/expr/index.js.map +1 -1
- package/dist/src/expr/libs/datetime.d.ts +20 -20
- package/dist/src/expr/libs/datetime.d.ts.map +1 -1
- package/dist/src/expr/libs/datetime.js +208 -167
- package/dist/src/expr/libs/datetime.js.map +1 -1
- package/dist/src/expr/libs/float.d.ts +15 -15
- package/dist/src/expr/libs/float.d.ts.map +1 -1
- package/dist/src/expr/libs/float.js +298 -267
- package/dist/src/expr/libs/float.js.map +1 -1
- package/dist/src/expr/libs/integer.d.ts +12 -12
- package/dist/src/expr/libs/integer.d.ts.map +1 -1
- package/dist/src/expr/libs/integer.js +219 -194
- package/dist/src/expr/libs/integer.js.map +1 -1
- package/dist/src/expr/libs/lazy.d.ts +28 -0
- package/dist/src/expr/libs/lazy.d.ts.map +1 -0
- package/dist/src/expr/libs/lazy.js +55 -0
- package/dist/src/expr/libs/lazy.js.map +1 -0
- package/dist/src/expr/libs/lazy.spec.d.ts +6 -0
- package/dist/src/expr/libs/lazy.spec.d.ts.map +1 -0
- package/dist/src/expr/libs/lazy.spec.js +102 -0
- package/dist/src/expr/libs/lazy.spec.js.map +1 -0
- package/dist/src/expr/query.d.ts +60 -0
- package/dist/src/expr/query.d.ts.map +1 -0
- package/dist/src/expr/query.js +84 -0
- package/dist/src/expr/query.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/internal.d.ts +4 -0
- package/dist/src/internal.d.ts.map +1 -1
- package/dist/src/internal.js +9 -0
- package/dist/src/internal.js.map +1 -1
- package/dist/src/location.d.ts +22 -0
- package/dist/src/location.d.ts.map +1 -1
- package/dist/src/location.js +31 -0
- package/dist/src/location.js.map +1 -1
- package/dist/src/naming.d.ts +5 -3
- package/dist/src/naming.d.ts.map +1 -1
- package/dist/src/naming.js.map +1 -1
- package/dist/src/portable.spec.d.ts +6 -0
- package/dist/src/portable.spec.d.ts.map +1 -0
- package/dist/src/portable.spec.js +181 -0
- package/dist/src/portable.spec.js.map +1 -0
- package/dist/src/query/evaluate.d.ts +98 -0
- package/dist/src/query/evaluate.d.ts.map +1 -0
- package/dist/src/query/evaluate.js +193 -0
- package/dist/src/query/evaluate.js.map +1 -0
- package/dist/src/query/index.d.ts +17 -0
- package/dist/src/query/index.d.ts.map +1 -0
- package/dist/src/query/index.js +17 -0
- package/dist/src/query/index.js.map +1 -0
- package/dist/src/query/jq/catalog.d.ts +174 -0
- package/dist/src/query/jq/catalog.d.ts.map +1 -0
- package/dist/src/query/jq/catalog.js +1740 -0
- package/dist/src/query/jq/catalog.js.map +1 -0
- package/dist/src/query/jq/check.d.ts +210 -0
- package/dist/src/query/jq/check.d.ts.map +1 -0
- package/dist/src/query/jq/check.js +2261 -0
- package/dist/src/query/jq/check.js.map +1 -0
- package/dist/src/query/jq/complete.d.ts +89 -0
- package/dist/src/query/jq/complete.d.ts.map +1 -0
- package/dist/src/query/jq/complete.js +320 -0
- package/dist/src/query/jq/complete.js.map +1 -0
- package/dist/src/query/jq/describe.d.ts +53 -0
- package/dist/src/query/jq/describe.d.ts.map +1 -0
- package/dist/src/query/jq/describe.js +149 -0
- package/dist/src/query/jq/describe.js.map +1 -0
- package/dist/src/query/jq/lex.d.ts +118 -0
- package/dist/src/query/jq/lex.d.ts.map +1 -0
- package/dist/src/query/jq/lex.js +371 -0
- package/dist/src/query/jq/lex.js.map +1 -0
- package/dist/src/query/jq/literals.d.ts +49 -0
- package/dist/src/query/jq/literals.d.ts.map +1 -0
- package/dist/src/query/jq/literals.js +78 -0
- package/dist/src/query/jq/literals.js.map +1 -0
- package/dist/src/query/jq/messages.d.ts +126 -0
- package/dist/src/query/jq/messages.d.ts.map +1 -0
- package/dist/src/query/jq/messages.js +172 -0
- package/dist/src/query/jq/messages.js.map +1 -0
- package/dist/src/query/jq/parse.d.ts +70 -0
- package/dist/src/query/jq/parse.d.ts.map +1 -0
- package/dist/src/query/jq/parse.js +1013 -0
- package/dist/src/query/jq/parse.js.map +1 -0
- package/dist/src/query/jq/print.d.ts +59 -0
- package/dist/src/query/jq/print.d.ts.map +1 -0
- package/dist/src/query/jq/print.js +587 -0
- package/dist/src/query/jq/print.js.map +1 -0
- package/dist/src/query/jq/shapes.d.ts +345 -0
- package/dist/src/query/jq/shapes.d.ts.map +1 -0
- package/dist/src/query/jq/shapes.js +584 -0
- package/dist/src/query/jq/shapes.js.map +1 -0
- package/dist/src/query/jq/spans.d.ts +133 -0
- package/dist/src/query/jq/spans.d.ts.map +1 -0
- package/dist/src/query/jq/spans.js +195 -0
- package/dist/src/query/jq/spans.js.map +1 -0
- package/dist/src/query/jq/split.d.ts +334 -0
- package/dist/src/query/jq/split.d.ts.map +1 -0
- package/dist/src/query/jq/split.js +2108 -0
- package/dist/src/query/jq/split.js.map +1 -0
- package/dist/src/query/jq/strftime.d.ts +20 -0
- package/dist/src/query/jq/strftime.d.ts.map +1 -0
- package/dist/src/query/jq/strftime.js +65 -0
- package/dist/src/query/jq/strftime.js.map +1 -0
- package/dist/src/query/jq/summary.d.ts +139 -0
- package/dist/src/query/jq/summary.d.ts.map +1 -0
- package/dist/src/query/jq/summary.js +222 -0
- package/dist/src/query/jq/summary.js.map +1 -0
- package/dist/src/query/jq/translate-builtins.d.ts +21 -0
- package/dist/src/query/jq/translate-builtins.d.ts.map +1 -0
- package/dist/src/query/jq/translate-builtins.js +1873 -0
- package/dist/src/query/jq/translate-builtins.js.map +1 -0
- package/dist/src/query/jq/translate.d.ts +627 -0
- package/dist/src/query/jq/translate.d.ts.map +1 -0
- package/dist/src/query/jq/translate.js +3364 -0
- package/dist/src/query/jq/translate.js.map +1 -0
- package/dist/src/query/types.d.ts +505 -0
- package/dist/src/query/types.d.ts.map +1 -0
- package/dist/src/query/types.js +231 -0
- package/dist/src/query/types.js.map +1 -0
- package/dist/src/runner_exec.d.ts +134 -0
- package/dist/src/runner_exec.d.ts.map +1 -0
- package/dist/src/runner_exec.js +371 -0
- package/dist/src/runner_exec.js.map +1 -0
- package/dist/src/runner_exec.spec.d.ts +6 -0
- package/dist/src/runner_exec.spec.d.ts.map +1 -0
- package/dist/src/runner_exec.spec.js +198 -0
- package/dist/src/runner_exec.spec.js.map +1 -0
- package/dist/src/runner_io.d.ts +370 -0
- package/dist/src/runner_io.d.ts.map +1 -0
- package/dist/src/runner_io.js +563 -0
- package/dist/src/runner_io.js.map +1 -0
- package/dist/src/runner_io.spec.d.ts +6 -0
- package/dist/src/runner_io.spec.d.ts.map +1 -0
- package/dist/src/runner_io.spec.js +224 -0
- package/dist/src/runner_io.spec.js.map +1 -0
- package/dist/src/runner_merge.d.ts +95 -0
- package/dist/src/runner_merge.d.ts.map +1 -0
- package/dist/src/runner_merge.js +238 -0
- package/dist/src/runner_merge.js.map +1 -0
- package/dist/src/runner_protocol.d.ts +11 -4
- package/dist/src/runner_protocol.d.ts.map +1 -1
- package/dist/src/runner_protocol.js +11 -4
- package/dist/src/runner_protocol.js.map +1 -1
- package/dist/src/serialization/beast2/index.d.ts +1 -1
- package/dist/src/serialization/beast2/index.d.ts.map +1 -1
- package/dist/src/serialization/beast2/index.js.map +1 -1
- package/dist/src/serialization/beast2/v5/frames.d.ts +10 -6
- package/dist/src/serialization/beast2/v5/frames.d.ts.map +1 -1
- package/dist/src/serialization/beast2/v5/frames.js +10 -6
- package/dist/src/serialization/beast2/v5/frames.js.map +1 -1
- package/dist/src/serialization/beast2/v5/frames.spec.d.ts +6 -0
- package/dist/src/serialization/beast2/v5/frames.spec.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/frames.spec.js +42 -0
- package/dist/src/serialization/beast2/v5/frames.spec.js.map +1 -0
- package/dist/src/serialization/beast2/v5/index.spec.js +108 -0
- package/dist/src/serialization/beast2/v5/index.spec.js.map +1 -1
- package/dist/src/serialization/beast2/v5/lazy.d.ts +12 -7
- package/dist/src/serialization/beast2/v5/lazy.d.ts.map +1 -1
- package/dist/src/serialization/beast2/v5/lazy.js +16 -6
- package/dist/src/serialization/beast2/v5/lazy.js.map +1 -1
- package/dist/src/serialization/beast2/v5/lazy.spec.js +159 -18
- package/dist/src/serialization/beast2/v5/lazy.spec.js.map +1 -1
- package/dist/src/serialization/beast2/v5/stream.d.ts +110 -21
- package/dist/src/serialization/beast2/v5/stream.d.ts.map +1 -1
- package/dist/src/serialization/beast2/v5/stream.js +153 -42
- package/dist/src/serialization/beast2/v5/stream.js.map +1 -1
- package/dist/src/serialization/beast2/v5/weight.d.ts +36 -0
- package/dist/src/serialization/beast2/v5/weight.d.ts.map +1 -0
- package/dist/src/serialization/beast2/v5/weight.js +238 -0
- package/dist/src/serialization/beast2/v5/weight.js.map +1 -0
- package/dist/src/serialization/crc32.d.ts +38 -0
- package/dist/src/serialization/crc32.d.ts.map +1 -0
- package/dist/src/serialization/crc32.js +70 -0
- package/dist/src/serialization/crc32.js.map +1 -0
- package/dist/src/serialization/crc32.spec.d.ts +6 -0
- package/dist/src/serialization/crc32.spec.d.ts.map +1 -0
- package/dist/src/serialization/crc32.spec.js +92 -0
- package/dist/src/serialization/crc32.spec.js.map +1 -0
- package/dist/src/serialization/east-inferred.spec.js +4 -0
- package/dist/src/serialization/east-inferred.spec.js.map +1 -1
- package/dist/src/serialization/east.d.ts.map +1 -1
- package/dist/src/serialization/east.js +134 -110
- package/dist/src/serialization/east.js.map +1 -1
- package/dist/src/serialization/east.spec.js +185 -4
- package/dist/src/serialization/east.spec.js.map +1 -1
- package/dist/src/serialization/east_text.d.ts +25 -0
- package/dist/src/serialization/east_text.d.ts.map +1 -0
- package/dist/src/serialization/east_text.js +29 -0
- package/dist/src/serialization/east_text.js.map +1 -0
- package/dist/src/serialization/index.d.ts +1 -1
- package/dist/src/serialization/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +7 -6
- package/dist/src/types.js.map +1 -1
- package/package.json +6 -3
|
@@ -9,8 +9,9 @@ import { compareFor } from "../comparison.js";
|
|
|
9
9
|
import { SortedMap } from "../containers/sortedmap.js";
|
|
10
10
|
import { SortedSet } from "../containers/sortedset.js";
|
|
11
11
|
import { isVariant, variant } from "../containers/variant.js";
|
|
12
|
-
import { EastTypeValueType, toEastTypeValue } from "../type_of_type.js";
|
|
12
|
+
import { EastTypeValueType, isTypeValueEqual, toEastTypeValue } from "../type_of_type.js";
|
|
13
13
|
import { ref } from "../containers/ref.js";
|
|
14
|
+
import { printEastString } from "./east_text.js";
|
|
14
15
|
class ParseError extends Error {
|
|
15
16
|
position;
|
|
16
17
|
path;
|
|
@@ -55,65 +56,87 @@ function _encodeRelativeRef(currentPath, targetPath) {
|
|
|
55
56
|
return `${upLevels}#${remainingStr}`;
|
|
56
57
|
}
|
|
57
58
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
59
|
+
* Resolve a relative reference string against the current path, to the
|
|
60
|
+
* punctuated path of its target: "2#.foo[0]" is the current path up two
|
|
61
|
+
* levels, then `.foo[0]`. The reference's components are taken as the printer
|
|
62
|
+
* wrote them, whole, so a quoted name or a Dict key's text holding a `.` or a
|
|
63
|
+
* `]` names what it named.
|
|
61
64
|
*/
|
|
62
65
|
function _decodeRelativeRef(refStr, currentPath) {
|
|
63
66
|
const hashIdx = refStr.indexOf('#');
|
|
64
67
|
if (hashIdx === -1) {
|
|
65
68
|
throw new Error(`Invalid relative reference: ${refStr}`);
|
|
66
69
|
}
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
let upLevels;
|
|
70
|
-
try {
|
|
71
|
-
upLevels = parseInt(upLevelStr);
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
throw new Error(`Invalid relative reference: ${refStr}`);
|
|
75
|
-
}
|
|
76
|
-
if (upLevels < 0 || upLevels > currentPath.length) {
|
|
70
|
+
const upLevels = Number.parseInt(refStr.substring(0, hashIdx), 10);
|
|
71
|
+
if (Number.isNaN(upLevels) || upLevels > currentPath.length) {
|
|
77
72
|
throw new Error(`Invalid relative reference: going up ${upLevels} levels from depth ${currentPath.length}`);
|
|
78
73
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
pos = end;
|
|
96
|
-
}
|
|
97
|
-
else if (remainingStr[pos] === '[') {
|
|
98
|
-
// Bracket expression
|
|
99
|
-
let end = pos + 1;
|
|
100
|
-
let depth = 1;
|
|
101
|
-
while (end < remainingStr.length && depth > 0) {
|
|
102
|
-
if (remainingStr[end] === '[')
|
|
103
|
-
depth++;
|
|
104
|
-
else if (remainingStr[end] === ']')
|
|
105
|
-
depth--;
|
|
106
|
-
end++;
|
|
107
|
-
}
|
|
108
|
-
targetPath.push(remainingStr.substring(pos, end));
|
|
109
|
-
pos = end;
|
|
74
|
+
return _pathToPunctuated(currentPath.slice(0, currentPath.length - upLevels)) + refStr.substring(hashIdx + 1);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Find where a reference's path ends, from `pos`: the run of components a
|
|
78
|
+
* printer writes — `.` and a field or case name, bare or quoted in backticks,
|
|
79
|
+
* and a bracketed array index, Dict key or a Ref's `[]`. A quoted name, and a
|
|
80
|
+
* string or quoted name in a key, is taken whole, so a `.` or `]` in one does
|
|
81
|
+
* not end the path.
|
|
82
|
+
*/
|
|
83
|
+
function _scanReferencePath(input, pos) {
|
|
84
|
+
while (pos < input.length) {
|
|
85
|
+
const ch = input[pos];
|
|
86
|
+
if (ch === '.') {
|
|
87
|
+
pos += 1;
|
|
88
|
+
if (input[pos] === '`') {
|
|
89
|
+
pos = _skipQuoted(input, pos);
|
|
110
90
|
}
|
|
111
91
|
else {
|
|
112
|
-
pos
|
|
92
|
+
while (pos < input.length && /[a-zA-Z0-9_]/.test(input[pos])) {
|
|
93
|
+
pos += 1;
|
|
94
|
+
}
|
|
113
95
|
}
|
|
114
96
|
}
|
|
97
|
+
else if (ch === '[') {
|
|
98
|
+
pos += 1;
|
|
99
|
+
let depth = 1;
|
|
100
|
+
while (pos < input.length && depth > 0) {
|
|
101
|
+
const c = input[pos];
|
|
102
|
+
if (c === '"' || c === '`') {
|
|
103
|
+
pos = _skipQuoted(input, pos);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (c === '[')
|
|
107
|
+
depth++;
|
|
108
|
+
else if (c === ']')
|
|
109
|
+
depth--;
|
|
110
|
+
pos += 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return pos;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Find the position after the string or quoted name opening at `pos`: its
|
|
121
|
+
* closing quote is the first no `\` escapes, and with none it runs to the end
|
|
122
|
+
* of the input.
|
|
123
|
+
*/
|
|
124
|
+
function _skipQuoted(input, pos) {
|
|
125
|
+
const quote = input[pos];
|
|
126
|
+
pos += 1;
|
|
127
|
+
while (pos < input.length) {
|
|
128
|
+
const c = input[pos];
|
|
129
|
+
if (c === '\\') {
|
|
130
|
+
pos += 2;
|
|
131
|
+
}
|
|
132
|
+
else if (c === quote) {
|
|
133
|
+
return pos + 1;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
pos += 1;
|
|
137
|
+
}
|
|
115
138
|
}
|
|
116
|
-
return
|
|
139
|
+
return input.length;
|
|
117
140
|
}
|
|
118
141
|
export function encodeEastFor(type) {
|
|
119
142
|
// Convert EastType to EastTypeValue if necessary
|
|
@@ -176,7 +199,9 @@ export function printFor(type, typeCtx = new Map()) {
|
|
|
176
199
|
};
|
|
177
200
|
}
|
|
178
201
|
else if (type.type === "String") {
|
|
179
|
-
|
|
202
|
+
// Only the escapes the grammar reads, `\\` and `\"`: every other
|
|
203
|
+
// character, a newline or a tab among them, is written as itself.
|
|
204
|
+
return (x, _ctx) => printEastString(x);
|
|
180
205
|
}
|
|
181
206
|
else if (type.type === "DateTime") {
|
|
182
207
|
return (x, _ctx) => x.toISOString().substring(0, 23);
|
|
@@ -298,14 +323,18 @@ export function printFor(type, typeCtx = new Map()) {
|
|
|
298
323
|
}
|
|
299
324
|
else if (type.type === "Variant") {
|
|
300
325
|
const case_printers = {};
|
|
326
|
+
// The path component a back-reference through each case names it by: the
|
|
327
|
+
// case's name as the text spells it, quoted when it is no plain identifier
|
|
328
|
+
const case_paths = new Map();
|
|
301
329
|
const ret = (x, ctx = { refs: new Map(), currentPath: [] }) => {
|
|
302
330
|
// Add variant case to path
|
|
303
|
-
ctx.currentPath.push(
|
|
331
|
+
ctx.currentPath.push(case_paths.get(x.type));
|
|
304
332
|
const result = case_printers[x.type](x.value, ctx);
|
|
305
333
|
ctx.currentPath.pop();
|
|
306
334
|
return result;
|
|
307
335
|
};
|
|
308
336
|
for (const { name: k, type: t } of type.value) {
|
|
337
|
+
case_paths.set(k, `.${printIdentifier(k)}`);
|
|
309
338
|
if (t.type === "Null") {
|
|
310
339
|
const prefix = `.${printIdentifier(k)}`;
|
|
311
340
|
case_printers[k] = (_value, _ctx) => prefix;
|
|
@@ -449,13 +478,13 @@ const createParser = (type, frozen, typeCtx = new Map()) => {
|
|
|
449
478
|
case "Blob":
|
|
450
479
|
return parseBlob(frozen);
|
|
451
480
|
case "Ref":
|
|
452
|
-
return createRefParser(type.value, frozen, typeCtx);
|
|
481
|
+
return createRefParser(type.value, frozen, typeCtx, type);
|
|
453
482
|
case "Array":
|
|
454
|
-
return createArrayParser(type.value, frozen, typeCtx);
|
|
483
|
+
return createArrayParser(type.value, frozen, typeCtx, type);
|
|
455
484
|
case "Set":
|
|
456
|
-
return createSetParser(type.value, frozen, typeCtx);
|
|
485
|
+
return createSetParser(type.value, frozen, typeCtx, type);
|
|
457
486
|
case "Dict":
|
|
458
|
-
return createDictParser(type.value.key, type.value.value, frozen, typeCtx);
|
|
487
|
+
return createDictParser(type.value.key, type.value.value, frozen, typeCtx, type);
|
|
459
488
|
case "Struct":
|
|
460
489
|
return createStructParser(type.value, frozen, typeCtx);
|
|
461
490
|
case "Variant":
|
|
@@ -591,9 +620,11 @@ const isTokenTerminator = (input, pos) => {
|
|
|
591
620
|
/**
|
|
592
621
|
* Parses a $.path reference and returns the referenced value.
|
|
593
622
|
* Returns null if not at a reference (doesn't start with '$').
|
|
594
|
-
* Throws ParseError if the reference is invalid or undefined
|
|
623
|
+
* Throws ParseError if the reference is invalid or undefined, or names a
|
|
624
|
+
* container of another type than `type`, the one the text expects where the
|
|
625
|
+
* reference stands.
|
|
595
626
|
*/
|
|
596
|
-
const parseReference = (input, pos, ctx) => {
|
|
627
|
+
const parseReference = (input, pos, ctx, type) => {
|
|
597
628
|
// Check if this looks like a reference: either "#..." or "N#..." where N is a digit
|
|
598
629
|
let refStart = pos;
|
|
599
630
|
let isRelative = false;
|
|
@@ -628,41 +659,14 @@ const parseReference = (input, pos, ctx) => {
|
|
|
628
659
|
else {
|
|
629
660
|
refStart = pos + 1; // Start after '#'
|
|
630
661
|
}
|
|
631
|
-
|
|
632
|
-
while (pathEnd < input.length) {
|
|
633
|
-
const ch = input[pathEnd];
|
|
634
|
-
if (ch === '.') {
|
|
635
|
-
// Dot followed by identifier - keep going until we hit non-identifier char
|
|
636
|
-
pathEnd++;
|
|
637
|
-
while (pathEnd < input.length && /[a-zA-Z0-9_]/.test(input[pathEnd])) {
|
|
638
|
-
pathEnd++;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
else if (ch === '[') {
|
|
642
|
-
// Bracket - find the matching close bracket
|
|
643
|
-
pathEnd++;
|
|
644
|
-
let depth = 1;
|
|
645
|
-
while (pathEnd < input.length && depth > 0) {
|
|
646
|
-
if (input[pathEnd] === '[')
|
|
647
|
-
depth++;
|
|
648
|
-
else if (input[pathEnd] === ']')
|
|
649
|
-
depth--;
|
|
650
|
-
pathEnd++;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
else {
|
|
654
|
-
// Hit something that's not part of the path
|
|
655
|
-
break;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
662
|
+
const pathEnd = _scanReferencePath(input, refStart);
|
|
658
663
|
const refStr = input.substring(pos, pathEnd);
|
|
659
664
|
// Resolve the target path
|
|
660
665
|
let targetPathStr;
|
|
661
666
|
try {
|
|
662
667
|
if (isRelative) {
|
|
663
668
|
// refStr is like "1#.a" - pass it directly to _decodeRelativeRef
|
|
664
|
-
|
|
665
|
-
targetPathStr = _pathToPunctuated(targetPath);
|
|
669
|
+
targetPathStr = _decodeRelativeRef(refStr, ctx.currentPath);
|
|
666
670
|
}
|
|
667
671
|
else {
|
|
668
672
|
// Absolute reference: just use the path part directly (without the leading #)
|
|
@@ -673,10 +677,16 @@ const parseReference = (input, pos, ctx) => {
|
|
|
673
677
|
throw new ParseError(`invalid reference ${refStr}: ${e instanceof Error ? e.message : String(e)}`, pos);
|
|
674
678
|
}
|
|
675
679
|
// Look up in refs map
|
|
676
|
-
|
|
680
|
+
const target = ctx.refs.get(targetPathStr);
|
|
681
|
+
if (target === undefined) {
|
|
677
682
|
throw new ParseError(`undefined reference ${refStr}`, pos);
|
|
678
683
|
}
|
|
679
|
-
|
|
684
|
+
// A container of the type the text expects here, as East's type equality
|
|
685
|
+
// has it: one of another type would be read as a value of the wrong type
|
|
686
|
+
if (!isTypeValueEqual(target.type, type)) {
|
|
687
|
+
throw new ParseError(`invalid reference ${refStr}: it names a value of another type`, pos);
|
|
688
|
+
}
|
|
689
|
+
return { value: target.value, position: pathEnd };
|
|
680
690
|
};
|
|
681
691
|
const parseBoolean = (input, pos, _ctx) => {
|
|
682
692
|
pos = consumeWhitespace(input, pos);
|
|
@@ -720,7 +730,8 @@ const parseString = (input, pos, _ctx) => {
|
|
|
720
730
|
rangeStart = pos;
|
|
721
731
|
}
|
|
722
732
|
else {
|
|
723
|
-
//
|
|
733
|
+
// The grammar has these two escapes and no others: a printer writes
|
|
734
|
+
// every other character, a control character included, as itself.
|
|
724
735
|
throw new ParseError("unexpected escape sequence in string", pos);
|
|
725
736
|
}
|
|
726
737
|
}
|
|
@@ -785,7 +796,7 @@ const parseBlob = (frozen) => (input, pos, _ctx) => {
|
|
|
785
796
|
}
|
|
786
797
|
return { value: bytes, position: pos };
|
|
787
798
|
};
|
|
788
|
-
const createRefParser = (value_type, frozen, typeCtx) => {
|
|
799
|
+
const createRefParser = (value_type, frozen, typeCtx, self) => {
|
|
789
800
|
let valueParser;
|
|
790
801
|
const ret = (input, pos, ctx) => {
|
|
791
802
|
pos = consumeWhitespace(input, pos);
|
|
@@ -795,7 +806,7 @@ const createRefParser = (value_type, frozen, typeCtx) => {
|
|
|
795
806
|
ctx = { refs: new Map(), currentPath: [] };
|
|
796
807
|
}
|
|
797
808
|
// Check for reference first
|
|
798
|
-
const reference = parseReference(input, pos, ctx);
|
|
809
|
+
const reference = parseReference(input, pos, ctx, self);
|
|
799
810
|
if (reference) {
|
|
800
811
|
return reference;
|
|
801
812
|
}
|
|
@@ -807,7 +818,7 @@ const createRefParser = (value_type, frozen, typeCtx) => {
|
|
|
807
818
|
// Pre-register this ref if we have context
|
|
808
819
|
if (ctx) {
|
|
809
820
|
const pathStr = _pathToPunctuated(ctx.currentPath);
|
|
810
|
-
ctx.refs.set(pathStr, r);
|
|
821
|
+
ctx.refs.set(pathStr, { value: r, type: self });
|
|
811
822
|
}
|
|
812
823
|
if (ctx)
|
|
813
824
|
ctx.currentPath.push(`[]`);
|
|
@@ -835,7 +846,7 @@ const createRefParser = (value_type, frozen, typeCtx) => {
|
|
|
835
846
|
valueParser = createParser(value_type, frozen, typeCtx);
|
|
836
847
|
return ret;
|
|
837
848
|
};
|
|
838
|
-
const createArrayParser = (value_type, frozen, typeCtx) => {
|
|
849
|
+
const createArrayParser = (value_type, frozen, typeCtx, self) => {
|
|
839
850
|
let valueParser;
|
|
840
851
|
const ret = (input, pos, ctx) => {
|
|
841
852
|
pos = consumeWhitespace(input, pos);
|
|
@@ -845,7 +856,7 @@ const createArrayParser = (value_type, frozen, typeCtx) => {
|
|
|
845
856
|
ctx = { refs: new Map(), currentPath: [] };
|
|
846
857
|
}
|
|
847
858
|
// Check for reference first
|
|
848
|
-
const ref = parseReference(input, pos, ctx);
|
|
859
|
+
const ref = parseReference(input, pos, ctx, self);
|
|
849
860
|
if (ref) {
|
|
850
861
|
return ref;
|
|
851
862
|
}
|
|
@@ -857,7 +868,7 @@ const createArrayParser = (value_type, frozen, typeCtx) => {
|
|
|
857
868
|
// Pre-register this array if we have context
|
|
858
869
|
if (ctx) {
|
|
859
870
|
const pathStr = _pathToPunctuated(ctx.currentPath);
|
|
860
|
-
ctx.refs.set(pathStr, values);
|
|
871
|
+
ctx.refs.set(pathStr, { value: values, type: self });
|
|
861
872
|
}
|
|
862
873
|
// Handle empty array
|
|
863
874
|
if (input[pos] === ']') {
|
|
@@ -902,7 +913,7 @@ const createArrayParser = (value_type, frozen, typeCtx) => {
|
|
|
902
913
|
valueParser = createParser(value_type, frozen, typeCtx);
|
|
903
914
|
return ret;
|
|
904
915
|
};
|
|
905
|
-
const createSetParser = (key_type, frozen, typeCtx) => {
|
|
916
|
+
const createSetParser = (key_type, frozen, typeCtx, self) => {
|
|
906
917
|
const keyParser = createParser(key_type, frozen, typeCtx);
|
|
907
918
|
const keyCompare = compareFor(key_type);
|
|
908
919
|
return (input, pos, ctx) => {
|
|
@@ -913,7 +924,7 @@ const createSetParser = (key_type, frozen, typeCtx) => {
|
|
|
913
924
|
ctx = { refs: new Map(), currentPath: [] };
|
|
914
925
|
}
|
|
915
926
|
// Check for reference first
|
|
916
|
-
const ref = parseReference(input, pos, ctx);
|
|
927
|
+
const ref = parseReference(input, pos, ctx, self);
|
|
917
928
|
if (ref) {
|
|
918
929
|
return ref;
|
|
919
930
|
}
|
|
@@ -925,7 +936,7 @@ const createSetParser = (key_type, frozen, typeCtx) => {
|
|
|
925
936
|
// Pre-register this set if we have context
|
|
926
937
|
if (ctx) {
|
|
927
938
|
const pathStr = _pathToPunctuated(ctx.currentPath);
|
|
928
|
-
ctx.refs.set(pathStr, values);
|
|
939
|
+
ctx.refs.set(pathStr, { value: values, type: self });
|
|
929
940
|
}
|
|
930
941
|
// Handle empty set
|
|
931
942
|
if (input[pos] === '}') {
|
|
@@ -962,7 +973,7 @@ const createSetParser = (key_type, frozen, typeCtx) => {
|
|
|
962
973
|
}
|
|
963
974
|
};
|
|
964
975
|
};
|
|
965
|
-
const createDictParser = (key_type, value_type, frozen, typeCtx) => {
|
|
976
|
+
const createDictParser = (key_type, value_type, frozen, typeCtx, self) => {
|
|
966
977
|
const keyParser = createParser(key_type, frozen, typeCtx);
|
|
967
978
|
let valueParser;
|
|
968
979
|
const keyCompare = compareFor(key_type);
|
|
@@ -975,7 +986,7 @@ const createDictParser = (key_type, value_type, frozen, typeCtx) => {
|
|
|
975
986
|
ctx = { refs: new Map(), currentPath: [] };
|
|
976
987
|
}
|
|
977
988
|
// Check for reference first
|
|
978
|
-
const ref = parseReference(input, pos, ctx);
|
|
989
|
+
const ref = parseReference(input, pos, ctx, self);
|
|
979
990
|
if (ref) {
|
|
980
991
|
return ref;
|
|
981
992
|
}
|
|
@@ -987,7 +998,7 @@ const createDictParser = (key_type, value_type, frozen, typeCtx) => {
|
|
|
987
998
|
// Pre-register this dict if we have context
|
|
988
999
|
if (ctx) {
|
|
989
1000
|
const pathStr = _pathToPunctuated(ctx.currentPath);
|
|
990
|
-
ctx.refs.set(pathStr, values);
|
|
1001
|
+
ctx.refs.set(pathStr, { value: values, type: self });
|
|
991
1002
|
}
|
|
992
1003
|
// Handle empty dict
|
|
993
1004
|
if (input[pos] === ':') {
|
|
@@ -1073,7 +1084,9 @@ const parseQuotedIdentifier = (input, pos, _ctx) => {
|
|
|
1073
1084
|
pos += 1;
|
|
1074
1085
|
let rangeStart = pos;
|
|
1075
1086
|
let result = "";
|
|
1076
|
-
// search through for escape characters, copy string out in ranges
|
|
1087
|
+
// search through for escape characters, copy string out in ranges; an
|
|
1088
|
+
// escaped character is taken whole, so one right before the closing
|
|
1089
|
+
// backtick never hides it
|
|
1077
1090
|
while (pos < input.length) {
|
|
1078
1091
|
const char = input[pos];
|
|
1079
1092
|
if (char === '\\') {
|
|
@@ -1082,11 +1095,11 @@ const parseQuotedIdentifier = (input, pos, _ctx) => {
|
|
|
1082
1095
|
if (pos < input.length) {
|
|
1083
1096
|
const char2 = input[pos];
|
|
1084
1097
|
if (char2 === '\\' || char2 === '`') {
|
|
1085
|
-
|
|
1098
|
+
result = result + char2;
|
|
1086
1099
|
pos += 1;
|
|
1100
|
+
rangeStart = pos;
|
|
1087
1101
|
}
|
|
1088
1102
|
else {
|
|
1089
|
-
// TODO we need to (a) deal with escape sequences at least for unprintable characters and (b) safely handle LTR-RTL transition characters
|
|
1090
1103
|
throw new ParseError("unexpected escape sequence in identifier", pos);
|
|
1091
1104
|
}
|
|
1092
1105
|
}
|
|
@@ -1098,7 +1111,9 @@ const parseQuotedIdentifier = (input, pos, _ctx) => {
|
|
|
1098
1111
|
result = result + input.substring(rangeStart, pos);
|
|
1099
1112
|
return { value: result, position: pos + 1 };
|
|
1100
1113
|
}
|
|
1101
|
-
|
|
1114
|
+
else {
|
|
1115
|
+
pos += 1;
|
|
1116
|
+
}
|
|
1102
1117
|
}
|
|
1103
1118
|
throw new ParseError("unterminated identifier (missing closing `)", pos);
|
|
1104
1119
|
};
|
|
@@ -1120,6 +1135,10 @@ const parseIdentifier = (input, pos, _ctx) => {
|
|
|
1120
1135
|
};
|
|
1121
1136
|
const createStructParser = (fields, frozen, typeCtx) => {
|
|
1122
1137
|
const fieldNames = fields.map(f => f.name);
|
|
1138
|
+
// The path component a back-reference through each field names it by, as
|
|
1139
|
+
// the printer writes it: `.` and the field's name as the text spells it,
|
|
1140
|
+
// quoted when it is no plain identifier
|
|
1141
|
+
const fieldPaths = fieldNames.map(name => `.${printIdentifier(name)}`);
|
|
1123
1142
|
const fieldParsers = [];
|
|
1124
1143
|
const ret = (input, pos, ctx) => {
|
|
1125
1144
|
pos = consumeWhitespace(input, pos);
|
|
@@ -1168,7 +1187,7 @@ const createStructParser = (fields, frozen, typeCtx) => {
|
|
|
1168
1187
|
pos += 1;
|
|
1169
1188
|
const parser = fieldParsers[fieldIndex];
|
|
1170
1189
|
// Track path for struct fields
|
|
1171
|
-
const fieldPath =
|
|
1190
|
+
const fieldPath = fieldPaths[fieldIndex];
|
|
1172
1191
|
if (ctx)
|
|
1173
1192
|
ctx.currentPath.push(fieldPath);
|
|
1174
1193
|
try {
|
|
@@ -1240,6 +1259,9 @@ const createStructParser = (fields, frozen, typeCtx) => {
|
|
|
1240
1259
|
const createVariantParser = (cases, frozen, typeCtx) => {
|
|
1241
1260
|
const caseParsers = {};
|
|
1242
1261
|
const caseNames = cases.map(c => c.name);
|
|
1262
|
+
// The path component a back-reference through each case names it by, as the
|
|
1263
|
+
// printer writes it
|
|
1264
|
+
const casePaths = new Map(caseNames.map(name => [name, `.${printIdentifier(name)}`]));
|
|
1243
1265
|
const ret = (input, pos, ctx) => {
|
|
1244
1266
|
pos = consumeWhitespace(input, pos);
|
|
1245
1267
|
// Create context if we don't have one (for top-level parsing with aliases)
|
|
@@ -1257,15 +1279,17 @@ const createVariantParser = (cases, frozen, typeCtx) => {
|
|
|
1257
1279
|
throw new ParseError("whitespace not allowed between '.' and case identifier", pos);
|
|
1258
1280
|
}
|
|
1259
1281
|
const { value: caseName, position: casePos } = parseIdentifier(input, pos, ctx);
|
|
1260
|
-
|
|
1261
|
-
|
|
1282
|
+
// One of the type's own cases, never a name an object inherits (`toString`)
|
|
1283
|
+
const casePath = casePaths.get(caseName);
|
|
1284
|
+
const valueParser = casePath === undefined ? undefined : caseParsers[caseName];
|
|
1285
|
+
if (valueParser === undefined || casePath === undefined) {
|
|
1262
1286
|
throw new ParseError(`unknown variant case .${printIdentifier(caseName)}, expected one of: ${caseNames.map(c => `.${printIdentifier(c)}`).join(', ')}`, pos);
|
|
1263
1287
|
}
|
|
1264
1288
|
// Create variant with undefined placeholder
|
|
1265
1289
|
const v = variant(caseName, undefined);
|
|
1266
1290
|
// Parse the value with case name in path
|
|
1267
1291
|
if (ctx)
|
|
1268
|
-
ctx.currentPath.push(
|
|
1292
|
+
ctx.currentPath.push(casePath);
|
|
1269
1293
|
try {
|
|
1270
1294
|
const { value: caseValue, position: valuePos } = valueParser(input, casePos, ctx);
|
|
1271
1295
|
// Mutate the variant's value field
|
|
@@ -1277,7 +1301,7 @@ const createVariantParser = (cases, frozen, typeCtx) => {
|
|
|
1277
1301
|
}
|
|
1278
1302
|
catch (e) {
|
|
1279
1303
|
if (e instanceof ParseError) {
|
|
1280
|
-
const newPath =
|
|
1304
|
+
const newPath = casePath + (e.path ? e.path : '');
|
|
1281
1305
|
throw new ParseError(e.message, e.position, newPath);
|
|
1282
1306
|
}
|
|
1283
1307
|
throw e;
|
|
@@ -1886,7 +1910,7 @@ function parseInferredStruct(input, startPos, frozen) {
|
|
|
1886
1910
|
}
|
|
1887
1911
|
pos = consumeWhitespace(input, pos + 1);
|
|
1888
1912
|
// Parse field value and infer type
|
|
1889
|
-
const fieldPath =
|
|
1913
|
+
const fieldPath = `.${printIdentifier(fieldName)}`;
|
|
1890
1914
|
try {
|
|
1891
1915
|
const fieldValue = parseInferredValue(input, pos, frozen);
|
|
1892
1916
|
fields[fieldName] = fieldValue.type;
|
|
@@ -1953,7 +1977,7 @@ function parseInferredVariant(input, startPos, frozen) {
|
|
|
1953
1977
|
}
|
|
1954
1978
|
catch (e) {
|
|
1955
1979
|
if (e instanceof ParseError) {
|
|
1956
|
-
const newPath = `.${caseName}` + (e.path ? e.path : '');
|
|
1980
|
+
const newPath = `.${printIdentifier(caseName)}` + (e.path ? e.path : '');
|
|
1957
1981
|
throw new ParseError(e.message, e.position, newPath);
|
|
1958
1982
|
}
|
|
1959
1983
|
throw e;
|