@shapeshift-labs/frontier-lang-parser 0.3.42 → 0.3.44
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/action-body.js +20 -0
- package/dist/action-syntax-children.js +27 -3
- package/package.json +2 -2
package/dist/action-body.js
CHANGED
|
@@ -82,6 +82,11 @@ function parseActionBodyLine(line, index) {
|
|
|
82
82
|
if (rowKind === 'callEffect') {
|
|
83
83
|
return compactRecord({ kind: 'callEffect', id: idFrom(rest, `action_body_callEffect_${name}`), name, capability: readInlineWord('capability', rest) ?? readInlineWord('effect', rest) ?? name, input: readInlineActionValue('input', rest) });
|
|
84
84
|
}
|
|
85
|
+
if (rowKind === 'let') {
|
|
86
|
+
const value = readInlineActionBindingValue('value', rest);
|
|
87
|
+
if (!rawName || rawName.startsWith('@') || !isActionBindingName(name) || !value) return undefined;
|
|
88
|
+
return compactRecord({ kind: 'let', id: idFrom(rest, `action_body_let_${name}`), name, value });
|
|
89
|
+
}
|
|
85
90
|
if (rowKind === 'return') {
|
|
86
91
|
const valueText = rawName?.startsWith('@') ? rest.trim() : `${rawName ?? ''}${rest ?? ''}`.trim();
|
|
87
92
|
return compactRecord({ kind: 'return', id: idFrom(rest, `action_body_return_${index}`), value: valueText ? readActionValue(valueText) : undefined });
|
|
@@ -158,6 +163,11 @@ function readInlineActionValue(label, text) {
|
|
|
158
163
|
return value ? readActionValue(value) : undefined;
|
|
159
164
|
}
|
|
160
165
|
|
|
166
|
+
function readInlineActionBindingValue(label, text) {
|
|
167
|
+
const value = readInlineActionValue(label, text);
|
|
168
|
+
return isSupportedBindingValue(value) ? value : undefined;
|
|
169
|
+
}
|
|
170
|
+
|
|
161
171
|
function readActionValue(value) {
|
|
162
172
|
const text = value.trim();
|
|
163
173
|
const quoted = /^["']([^"']*)["']$/.exec(text);
|
|
@@ -169,6 +179,16 @@ function readActionValue(value) {
|
|
|
169
179
|
return { expression: text };
|
|
170
180
|
}
|
|
171
181
|
|
|
182
|
+
function isSupportedBindingValue(value) {
|
|
183
|
+
if (!value) return false;
|
|
184
|
+
if (Object.prototype.hasOwnProperty.call(value, 'value')) return true;
|
|
185
|
+
return /^[A-Za-z_$][\w$-]*(?:\.[A-Za-z_$][\w$-]*)*$/.test(String(value.expression ?? '').trim());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function isActionBindingName(value) {
|
|
189
|
+
return /^[A-Za-z_$][\w$-]*$/.test(String(value ?? ''));
|
|
190
|
+
}
|
|
191
|
+
|
|
172
192
|
function idFrom(header, fallback) { return /@id\(\s*["']([^"']+)["']\s*\)/.exec(header)?.[1] ?? fallback; }
|
|
173
193
|
function readInlineWord(label, text) { return new RegExp('(?:^|\\s)' + label + '\\s+([^\\s,]+)').exec(text)?.[1]?.trim(); }
|
|
174
194
|
function firstIdentifier(text) { return /^([A-Za-z_$][\w$-]*)\b/.exec(text)?.[1]; }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const ACTION_BODY_ROWS = new Set(['set', 'insert', 'remove', 'merge', 'callEffect', 'return', 'if']);
|
|
1
|
+
const ACTION_BODY_ROWS = new Set(['set', 'insert', 'remove', 'merge', 'callEffect', 'return', 'if', 'let']);
|
|
2
2
|
|
|
3
3
|
export function readActionSyntaxChildren(source, block, options) {
|
|
4
4
|
const body = source.slice(block.bodyStartOffset, block.bodyEndOffset);
|
|
@@ -56,7 +56,8 @@ function actionSyntaxChild(source, block, options, line, state, parentActionBody
|
|
|
56
56
|
const rowKind = row?.[1] ?? 'unknown';
|
|
57
57
|
const name = actionRowName(rowKind, row?.[2], rowIndex);
|
|
58
58
|
const rest = row?.[2]?.startsWith('@') ? ` ${row[2]}${row[3] ?? ''}` : (row?.[3] ?? '');
|
|
59
|
-
const
|
|
59
|
+
const validation = validateActionRow(rowKind, row?.[2], rest);
|
|
60
|
+
const recognized = ACTION_BODY_ROWS.has(rowKind) && validation.ok;
|
|
60
61
|
return cleanRecord({
|
|
61
62
|
kind: recognized ? 'actionBodyRow' : 'actionUnknownRow',
|
|
62
63
|
rowKind,
|
|
@@ -75,7 +76,7 @@ function actionSyntaxChild(source, block, options, line, state, parentActionBody
|
|
|
75
76
|
parentActionBodyId,
|
|
76
77
|
sourceSpan: sourceSpan(source, block, line.startOffset, line.endOffset, options),
|
|
77
78
|
recognized,
|
|
78
|
-
reason: recognized ? undefined :
|
|
79
|
+
reason: recognized ? undefined : validation.reason
|
|
79
80
|
});
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -86,6 +87,29 @@ function actionRowName(rowKind, rawName, rowIndex) {
|
|
|
86
87
|
return rawName && !rawName.startsWith('@') ? rawName : `${rowKind}_${rowIndex}`;
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
function validateActionRow(rowKind, rawName, rest) {
|
|
91
|
+
if (!ACTION_BODY_ROWS.has(rowKind)) return { ok: false, reason: 'unsupported-action-body-row' };
|
|
92
|
+
if (rowKind !== 'let') return { ok: true };
|
|
93
|
+
if (!rawName || rawName.startsWith('@') || !/^[A-Za-z_$][\w$-]*$/.test(rawName)) {
|
|
94
|
+
return { ok: false, reason: 'unsupported-action-binding-name' };
|
|
95
|
+
}
|
|
96
|
+
const value = readInlineValue('value', rest);
|
|
97
|
+
if (!value || !isSupportedBindingValue(value)) {
|
|
98
|
+
return { ok: false, reason: 'unsupported-action-binding-value' };
|
|
99
|
+
}
|
|
100
|
+
return { ok: true };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function readInlineValue(label, text) {
|
|
104
|
+
return new RegExp('(?:^|\\s)' + label + '\\s+(.+?)(?=\\s+[A-Za-z_$][\\w$-]*\\s+|$)').exec(text)?.[1]?.trim();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isSupportedBindingValue(value) {
|
|
108
|
+
if (/^["'][^"']*["']$/.test(value)) return true;
|
|
109
|
+
if (/^(true|false|null|-?\d+(?:\.\d+)?)$/.test(value)) return true;
|
|
110
|
+
return /^[A-Za-z_$][\w$-]*(?:\.[A-Za-z_$][\w$-]*)*$/.test(value);
|
|
111
|
+
}
|
|
112
|
+
|
|
89
113
|
function readNestedBodyBlocks(kind, source) {
|
|
90
114
|
const blocks = [];
|
|
91
115
|
const header = new RegExp('\\b' + kind.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '(?:\\s+([^{}\\n]+?))?\\s*\\{', 'g');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shapeshift-labs/frontier-lang-parser",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.44",
|
|
4
4
|
"description": "Parser for the first Frontier Lang .frontier syntax slice.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "node scripts/build.mjs",
|
|
25
|
-
"test": "npm run build && node test/smoke.mjs && node test/target-projection-aggregate-smoke.mjs && node test/conversion-constraint-fields-smoke.mjs && node test/conversion-evidence-smoke.mjs && node test/package-canvas-surface-smoke.mjs && node test/view-render-graph-smoke.mjs && node test/resource-graph-smoke.mjs && node test/interlingua-smoke.mjs && node test/dialect-registry-smoke.mjs",
|
|
25
|
+
"test": "npm run build && node test/smoke.mjs && node test/action-body-smoke.mjs && node test/target-projection-aggregate-smoke.mjs && node test/conversion-constraint-fields-smoke.mjs && node test/conversion-evidence-smoke.mjs && node test/package-canvas-surface-smoke.mjs && node test/view-render-graph-smoke.mjs && node test/resource-graph-smoke.mjs && node test/interlingua-smoke.mjs && node test/dialect-registry-smoke.mjs",
|
|
26
26
|
"typecheck": "node ./node_modules/typescript/bin/tsc --noEmit -p test/tsconfig.json",
|
|
27
27
|
"fuzz": "npm run build && node fuzz/smoke.mjs",
|
|
28
28
|
"bench": "npm run build && node bench/smoke.mjs",
|