@weborigami/language 0.0.52 → 0.0.53
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/language",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.53",
|
|
4
4
|
"description": "Web Origami expression language compiler and runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./main.js",
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"typescript": "5.4.5"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@weborigami/async-tree": "0.0.
|
|
15
|
-
"@weborigami/types": "0.0.
|
|
14
|
+
"@weborigami/async-tree": "0.0.53",
|
|
15
|
+
"@weborigami/types": "0.0.53",
|
|
16
16
|
"watcher": "2.3.1"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
import * as ops from "../runtime/ops.js";
|
|
10
|
-
import { makeFunctionCall, makeObject, makePipeline, makeTemplate } from "./parserHelpers.js";
|
|
10
|
+
import { makeArray, makeFunctionCall, makeObject, makePipeline, makeTemplate } from "./parserHelpers.js";
|
|
11
11
|
|
|
12
12
|
// If a parse result is an object that will be evaluated at runtime, attach the
|
|
13
13
|
// location of the source code that produced it for debugging and error messages.
|
|
@@ -39,10 +39,18 @@ args "function arguments"
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
array "array"
|
|
42
|
-
= "[" __
|
|
43
|
-
return annotate(
|
|
42
|
+
= "[" __ entries:arrayEntries? __ closingBracket {
|
|
43
|
+
return annotate(makeArray(entries ?? []), location());
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// A separated list of array entries
|
|
47
|
+
arrayEntries
|
|
48
|
+
= @arrayEntry|1.., separator| separator?
|
|
49
|
+
|
|
50
|
+
arrayEntry
|
|
51
|
+
= spread
|
|
52
|
+
/ expr
|
|
53
|
+
|
|
46
54
|
// Something that can be called. This is more restrictive than the `expr`
|
|
47
55
|
// parser; it doesn't accept regular function calls.
|
|
48
56
|
callTarget "function call"
|
package/src/compiler/parse.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
//
|
|
13
13
|
|
|
14
14
|
import * as ops from "../runtime/ops.js";
|
|
15
|
-
import { makeFunctionCall, makeObject, makePipeline, makeTemplate } from "./parserHelpers.js";
|
|
15
|
+
import { makeArray, makeFunctionCall, makeObject, makePipeline, makeTemplate } from "./parserHelpers.js";
|
|
16
16
|
|
|
17
17
|
// If a parse result is an object that will be evaluated at runtime, attach the
|
|
18
18
|
// location of the source code that produced it for debugging and error messages.
|
|
@@ -193,7 +193,7 @@ function peg$parse(input, options) {
|
|
|
193
193
|
var peg$FAILED = {};
|
|
194
194
|
var peg$source = options.grammarSource;
|
|
195
195
|
|
|
196
|
-
var peg$startRuleFunctions = { __: peg$parse__, absoluteFilePath: peg$parseabsoluteFilePath, args: peg$parseargs, array: peg$parsearray, callTarget: peg$parsecallTarget, closingBrace: peg$parseclosingBrace, closingBracket: peg$parseclosingBracket, closingParen: peg$parseclosingParen, comment: peg$parsecomment, digits: peg$parsedigits, doubleArrow: peg$parsedoubleArrow, doubleQuoteString: peg$parsedoubleQuoteString, doubleQuoteStringChar: peg$parsedoubleQuoteStringChar, ellipsis: peg$parseellipsis, escapedChar: peg$parseescapedChar, expr: peg$parseexpr, expression: peg$parseexpression, float: peg$parsefloat, functionComposition: peg$parsefunctionComposition, group: peg$parsegroup, host: peg$parsehost, identifier: peg$parseidentifier, identifierChar: peg$parseidentifierChar, identifierList: peg$parseidentifierList, implicitParensArgs: peg$parseimplicitParensArgs, inlineSpace: peg$parseinlineSpace, integer: peg$parseinteger, lambda: peg$parselambda, leadingSlashPath: peg$parseleadingSlashPath, list: peg$parselist, multiLineComment: peg$parsemultiLineComment, newLine: peg$parsenewLine, number: peg$parsenumber, object: peg$parseobject, objectEntries: peg$parseobjectEntries, objectEntry: peg$parseobjectEntry, objectProperty: peg$parseobjectProperty, parameterizedLambda: peg$parseparameterizedLambda, parensArgs: peg$parseparensArgs, pipeline: peg$parsepipeline, path: peg$parsepath, pathKey: peg$parsepathKey, protocolCall: peg$parseprotocolCall, protocol: peg$parseprotocol, reservedProtocol: peg$parsereservedProtocol, scopeReference: peg$parsescopeReference, separator: peg$parseseparator, shebang: peg$parseshebang, sign: peg$parsesign, singleArrow: peg$parsesingleArrow, singleLineComment: peg$parsesingleLineComment, singleQuoteString: peg$parsesingleQuoteString, singleQuoteStringChar: peg$parsesingleQuoteStringChar, spread: peg$parsespread, step: peg$parsestep, start: peg$parsestart, string: peg$parsestring, templateDocument: peg$parsetemplateDocument, templateDocumentChar: peg$parsetemplateDocumentChar, templateDocumentContents: peg$parsetemplateDocumentContents, templateDocumentText: peg$parsetemplateDocumentText, templateLiteral: peg$parsetemplateLiteral, templateLiteralChar: peg$parsetemplateLiteralChar, templateLiteralContents: peg$parsetemplateLiteralContents, templateLiteralText: peg$parsetemplateLiteralText, templateSubstitution: peg$parsetemplateSubstitution, textChar: peg$parsetextChar, tree: peg$parsetree, treeAssignment: peg$parsetreeAssignment, treeEntries: peg$parsetreeEntries, treeEntry: peg$parsetreeEntry, whitespaceWithNewLine: peg$parsewhitespaceWithNewLine };
|
|
196
|
+
var peg$startRuleFunctions = { __: peg$parse__, absoluteFilePath: peg$parseabsoluteFilePath, args: peg$parseargs, array: peg$parsearray, arrayEntries: peg$parsearrayEntries, arrayEntry: peg$parsearrayEntry, callTarget: peg$parsecallTarget, closingBrace: peg$parseclosingBrace, closingBracket: peg$parseclosingBracket, closingParen: peg$parseclosingParen, comment: peg$parsecomment, digits: peg$parsedigits, doubleArrow: peg$parsedoubleArrow, doubleQuoteString: peg$parsedoubleQuoteString, doubleQuoteStringChar: peg$parsedoubleQuoteStringChar, ellipsis: peg$parseellipsis, escapedChar: peg$parseescapedChar, expr: peg$parseexpr, expression: peg$parseexpression, float: peg$parsefloat, functionComposition: peg$parsefunctionComposition, group: peg$parsegroup, host: peg$parsehost, identifier: peg$parseidentifier, identifierChar: peg$parseidentifierChar, identifierList: peg$parseidentifierList, implicitParensArgs: peg$parseimplicitParensArgs, inlineSpace: peg$parseinlineSpace, integer: peg$parseinteger, lambda: peg$parselambda, leadingSlashPath: peg$parseleadingSlashPath, list: peg$parselist, multiLineComment: peg$parsemultiLineComment, newLine: peg$parsenewLine, number: peg$parsenumber, object: peg$parseobject, objectEntries: peg$parseobjectEntries, objectEntry: peg$parseobjectEntry, objectProperty: peg$parseobjectProperty, parameterizedLambda: peg$parseparameterizedLambda, parensArgs: peg$parseparensArgs, pipeline: peg$parsepipeline, path: peg$parsepath, pathKey: peg$parsepathKey, protocolCall: peg$parseprotocolCall, protocol: peg$parseprotocol, reservedProtocol: peg$parsereservedProtocol, scopeReference: peg$parsescopeReference, separator: peg$parseseparator, shebang: peg$parseshebang, sign: peg$parsesign, singleArrow: peg$parsesingleArrow, singleLineComment: peg$parsesingleLineComment, singleQuoteString: peg$parsesingleQuoteString, singleQuoteStringChar: peg$parsesingleQuoteStringChar, spread: peg$parsespread, step: peg$parsestep, start: peg$parsestart, string: peg$parsestring, templateDocument: peg$parsetemplateDocument, templateDocumentChar: peg$parsetemplateDocumentChar, templateDocumentContents: peg$parsetemplateDocumentContents, templateDocumentText: peg$parsetemplateDocumentText, templateLiteral: peg$parsetemplateLiteral, templateLiteralChar: peg$parsetemplateLiteralChar, templateLiteralContents: peg$parsetemplateLiteralContents, templateLiteralText: peg$parsetemplateLiteralText, templateSubstitution: peg$parsetemplateSubstitution, textChar: peg$parsetextChar, tree: peg$parsetree, treeAssignment: peg$parsetreeAssignment, treeEntries: peg$parsetreeEntries, treeEntry: peg$parsetreeEntry, whitespaceWithNewLine: peg$parsewhitespaceWithNewLine };
|
|
197
197
|
var peg$startRuleFunction = peg$parse__;
|
|
198
198
|
|
|
199
199
|
var peg$c0 = "//";
|
|
@@ -329,8 +329,8 @@ function peg$parse(input, options) {
|
|
|
329
329
|
var peg$f2 = function(path) {
|
|
330
330
|
return annotate([ops.traverse, ...path], location());
|
|
331
331
|
};
|
|
332
|
-
var peg$f3 = function(
|
|
333
|
-
return annotate(
|
|
332
|
+
var peg$f3 = function(entries) {
|
|
333
|
+
return annotate(makeArray(entries ?? []), location());
|
|
334
334
|
};
|
|
335
335
|
var peg$f4 = function() {
|
|
336
336
|
error("Expected right curly brace");
|
|
@@ -682,7 +682,7 @@ function peg$parse(input, options) {
|
|
|
682
682
|
}
|
|
683
683
|
if (s1 !== peg$FAILED) {
|
|
684
684
|
s2 = peg$parse__();
|
|
685
|
-
s3 = peg$
|
|
685
|
+
s3 = peg$parsearrayEntries();
|
|
686
686
|
if (s3 === peg$FAILED) {
|
|
687
687
|
s3 = null;
|
|
688
688
|
}
|
|
@@ -708,6 +708,60 @@ function peg$parse(input, options) {
|
|
|
708
708
|
return s0;
|
|
709
709
|
}
|
|
710
710
|
|
|
711
|
+
function peg$parsearrayEntries() {
|
|
712
|
+
var s0, s1, s2, s3, s4;
|
|
713
|
+
|
|
714
|
+
s0 = peg$currPos;
|
|
715
|
+
s1 = peg$currPos;
|
|
716
|
+
s2 = [];
|
|
717
|
+
s3 = peg$parsearrayEntry();
|
|
718
|
+
while (s3 !== peg$FAILED) {
|
|
719
|
+
s2.push(s3);
|
|
720
|
+
s3 = peg$currPos;
|
|
721
|
+
s4 = peg$parseseparator();
|
|
722
|
+
if (s4 !== peg$FAILED) {
|
|
723
|
+
s4 = peg$parsearrayEntry();
|
|
724
|
+
if (s4 === peg$FAILED) {
|
|
725
|
+
peg$currPos = s3;
|
|
726
|
+
s3 = peg$FAILED;
|
|
727
|
+
} else {
|
|
728
|
+
s3 = s4;
|
|
729
|
+
}
|
|
730
|
+
} else {
|
|
731
|
+
s3 = s4;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
if (s2.length < 1) {
|
|
735
|
+
peg$currPos = s1;
|
|
736
|
+
s1 = peg$FAILED;
|
|
737
|
+
} else {
|
|
738
|
+
s1 = s2;
|
|
739
|
+
}
|
|
740
|
+
if (s1 !== peg$FAILED) {
|
|
741
|
+
s2 = peg$parseseparator();
|
|
742
|
+
if (s2 === peg$FAILED) {
|
|
743
|
+
s2 = null;
|
|
744
|
+
}
|
|
745
|
+
s0 = s1;
|
|
746
|
+
} else {
|
|
747
|
+
peg$currPos = s0;
|
|
748
|
+
s0 = peg$FAILED;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
return s0;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
function peg$parsearrayEntry() {
|
|
755
|
+
var s0;
|
|
756
|
+
|
|
757
|
+
s0 = peg$parsespread();
|
|
758
|
+
if (s0 === peg$FAILED) {
|
|
759
|
+
s0 = peg$parsepipeline();
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
return s0;
|
|
763
|
+
}
|
|
764
|
+
|
|
711
765
|
function peg$parsecallTarget() {
|
|
712
766
|
var s0, s1;
|
|
713
767
|
|
|
@@ -3146,6 +3200,8 @@ const peg$allowedStartRules = [
|
|
|
3146
3200
|
"absoluteFilePath",
|
|
3147
3201
|
"args",
|
|
3148
3202
|
"array",
|
|
3203
|
+
"arrayEntries",
|
|
3204
|
+
"arrayEntry",
|
|
3149
3205
|
"callTarget",
|
|
3150
3206
|
"closingBrace",
|
|
3151
3207
|
"closingBracket",
|
|
@@ -2,6 +2,38 @@ import * as ops from "../runtime/ops.js";
|
|
|
2
2
|
|
|
3
3
|
// Parser helpers
|
|
4
4
|
|
|
5
|
+
export function makeArray(entries) {
|
|
6
|
+
let currentEntries = [];
|
|
7
|
+
const spreads = [];
|
|
8
|
+
|
|
9
|
+
for (const value of entries) {
|
|
10
|
+
if (Array.isArray(value) && value[0] === ops.spread) {
|
|
11
|
+
if (currentEntries.length > 0) {
|
|
12
|
+
spreads.push([ops.array, ...currentEntries]);
|
|
13
|
+
currentEntries = [];
|
|
14
|
+
}
|
|
15
|
+
spreads.push(...value.slice(1));
|
|
16
|
+
} else {
|
|
17
|
+
currentEntries.push(value);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Finish any current entries.
|
|
22
|
+
if (currentEntries.length > 0) {
|
|
23
|
+
spreads.push([ops.array, ...currentEntries]);
|
|
24
|
+
currentEntries = [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (spreads.length > 1) {
|
|
28
|
+
return [ops.merge, ...spreads];
|
|
29
|
+
}
|
|
30
|
+
if (spreads.length === 1) {
|
|
31
|
+
return spreads[0];
|
|
32
|
+
} else {
|
|
33
|
+
return [ops.array];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
5
37
|
export function makeFunctionCall(target, chain) {
|
|
6
38
|
let value = target;
|
|
7
39
|
// The chain is an array of arguments (which are themselves arrays). We
|
|
@@ -33,6 +33,11 @@ export default async function mergeTrees(...trees) {
|
|
|
33
33
|
return mergeObjects(...unpacked);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
// If all trees are arrays, return an array.
|
|
37
|
+
if (unpacked.every((tree) => Array.isArray(tree))) {
|
|
38
|
+
return unpacked.flat();
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
// If a tree can take a scope, give it one that includes the other trees and
|
|
37
42
|
// the current scope.
|
|
38
43
|
const scopedTrees = unpacked.map((tree) => {
|
|
@@ -17,6 +17,11 @@ describe("Origami parser", () => {
|
|
|
17
17
|
assertParse("array", "[]", [ops.array]);
|
|
18
18
|
assertParse("array", "[1, 2, 3]", [ops.array, 1, 2, 3]);
|
|
19
19
|
assertParse("array", "[ 1 , 2 , 3 ]", [ops.array, 1, 2, 3]);
|
|
20
|
+
assertParse("array", "[ 1, ...[2, 3]]", [
|
|
21
|
+
ops.merge,
|
|
22
|
+
[ops.array, 1],
|
|
23
|
+
[ops.array, 2, 3],
|
|
24
|
+
]);
|
|
20
25
|
});
|
|
21
26
|
|
|
22
27
|
test("treeAssignment", () => {
|