@graffiticode/parser 1.4.2 → 1.4.4
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/.claude/settings.local.json +2 -1
- package/package.json +2 -2
- package/src/ast.js +12 -6
- package/src/folder.js +2 -1
- package/src/parse.js +5 -5
- package/src/unparse.spec.js +6 -0
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"Bash(grep:*)",
|
|
9
9
|
"Bash(npm install:*)",
|
|
10
10
|
"Bash(NODE_OPTIONS=--experimental-vm-modules node -e \"\nimport { parser } from './src/parser.js';\nimport { unparse } from './src/unparse.js';\nimport { lexicon as basisLexicon } from '@graffiticode/basis';\n\nconst src = 'case x of 1: \\\\\"one\\\\\" 2: \\\\\"two\\\\\" end..';\nconsole.log\\('Input:', src\\);\nconst ast = await parser.parse\\(0, src, basisLexicon\\);\nconsole.log\\('AST:', JSON.stringify\\(ast, null, 2\\)\\);\nconst result = unparse\\(ast, basisLexicon\\);\nconsole.log\\('Unparsed:', result\\);\n\")",
|
|
11
|
-
"Bash(NODE_OPTIONS=--experimental-vm-modules node -e \"\nimport { parser } from './src/parser.js';\nimport { unparse } from './src/unparse.js';\nimport { lexicon as basisLexicon } from '@graffiticode/basis';\n\n// Test nested case-of\nconst src1 = 'case x of 1: case y of 3: \\\\\"a\\\\\" 4: \\\\\"b\\\\\" end 2: \\\\\"two\\\\\" end..';\nconsole.log\\('Input:', src1\\);\ntry {\n const ast1 = await parser.parse\\(0, src1, basisLexicon\\);\n console.log\\('Unparsed:', unparse\\(ast1, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\nconsole.log\\('---'\\);\n\n// Test with expression as case target\nconst src2 = 'case add 1 2 of 3: \\\\\"yes\\\\\" 4: \\\\\"no\\\\\" end..';\nconsole.log\\('Input:', src2\\);\ntry {\n const ast2 = await parser.parse\\(0, src2, basisLexicon\\);\n console.log\\('AST:', JSON.stringify\\(ast2, null, 2\\)\\);\n console.log\\('Unparsed:', unparse\\(ast2, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\nconsole.log\\('---'\\);\n\n// Test with identifier patterns\nconst src3 = 'case x of y: y end..';\nconsole.log\\('Input:', src3\\);\ntry {\n const ast3 = await parser.parse\\(0, src3, basisLexicon\\);\n console.log\\('AST:', JSON.stringify\\(ast3, null, 2\\)\\);\n console.log\\('Unparsed:', unparse\\(ast3, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\nconsole.log\\('---'\\);\n\n// Test case-of inside a let or other expression\nconst src4 = 'let x = 5 in case x of 5: \\\\\"five\\\\\" end..';\nconsole.log\\('Input:', src4\\);\ntry {\n const ast4 = await parser.parse\\(0, src4, basisLexicon\\);\n console.log\\('Unparsed:', unparse\\(ast4, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\nconsole.log\\('---'\\);\n\n// Test case-of as argument to a function\nconst src5 = 'add \\(case x of 1: 10 2: 20 end\\) 5..';\nconsole.log\\('Input:', src5\\);\ntry {\n const ast5 = await parser.parse\\(0, src5, basisLexicon\\);\n console.log\\('Unparsed:', unparse\\(ast5, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\")"
|
|
11
|
+
"Bash(NODE_OPTIONS=--experimental-vm-modules node -e \"\nimport { parser } from './src/parser.js';\nimport { unparse } from './src/unparse.js';\nimport { lexicon as basisLexicon } from '@graffiticode/basis';\n\n// Test nested case-of\nconst src1 = 'case x of 1: case y of 3: \\\\\"a\\\\\" 4: \\\\\"b\\\\\" end 2: \\\\\"two\\\\\" end..';\nconsole.log\\('Input:', src1\\);\ntry {\n const ast1 = await parser.parse\\(0, src1, basisLexicon\\);\n console.log\\('Unparsed:', unparse\\(ast1, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\nconsole.log\\('---'\\);\n\n// Test with expression as case target\nconst src2 = 'case add 1 2 of 3: \\\\\"yes\\\\\" 4: \\\\\"no\\\\\" end..';\nconsole.log\\('Input:', src2\\);\ntry {\n const ast2 = await parser.parse\\(0, src2, basisLexicon\\);\n console.log\\('AST:', JSON.stringify\\(ast2, null, 2\\)\\);\n console.log\\('Unparsed:', unparse\\(ast2, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\nconsole.log\\('---'\\);\n\n// Test with identifier patterns\nconst src3 = 'case x of y: y end..';\nconsole.log\\('Input:', src3\\);\ntry {\n const ast3 = await parser.parse\\(0, src3, basisLexicon\\);\n console.log\\('AST:', JSON.stringify\\(ast3, null, 2\\)\\);\n console.log\\('Unparsed:', unparse\\(ast3, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\nconsole.log\\('---'\\);\n\n// Test case-of inside a let or other expression\nconst src4 = 'let x = 5 in case x of 5: \\\\\"five\\\\\" end..';\nconsole.log\\('Input:', src4\\);\ntry {\n const ast4 = await parser.parse\\(0, src4, basisLexicon\\);\n console.log\\('Unparsed:', unparse\\(ast4, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\nconsole.log\\('---'\\);\n\n// Test case-of as argument to a function\nconst src5 = 'add \\(case x of 1: 10 2: 20 end\\) 5..';\nconsole.log\\('Input:', src5\\);\ntry {\n const ast5 = await parser.parse\\(0, src5, basisLexicon\\);\n console.log\\('Unparsed:', unparse\\(ast5, basisLexicon\\)\\);\n} catch\\(e\\) { console.log\\('Error:', e.message\\); }\n\")",
|
|
12
|
+
"Bash(git:*)"
|
|
12
13
|
]
|
|
13
14
|
}
|
|
14
15
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graffiticode/parser",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -22,6 +22,6 @@
|
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"description": "",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@graffiticode/basis": "^1.
|
|
25
|
+
"@graffiticode/basis": "^1.7.3"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/ast.js
CHANGED
|
@@ -532,12 +532,18 @@ export class Ast {
|
|
|
532
532
|
Ast.push(ctx, { tag: "POW", elts: [n1, n2] });
|
|
533
533
|
}
|
|
534
534
|
|
|
535
|
-
static concat(ctx) {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
535
|
+
static concat(ctx, count) {
|
|
536
|
+
// Chain binary CONCATs from the parts on the stack.
|
|
537
|
+
// E.g. 3 parts [a, b, c] becomes CONCAT(CONCAT(a, b), c)
|
|
538
|
+
const parts = [];
|
|
539
|
+
for (let i = 0; i < count; i++) {
|
|
540
|
+
parts.unshift(Ast.pop(ctx));
|
|
541
|
+
}
|
|
542
|
+
let result = parts[0];
|
|
543
|
+
for (let i = 1; i < parts.length; i++) {
|
|
544
|
+
result = { tag: "CONCAT", elts: [result, parts[i]] };
|
|
545
|
+
}
|
|
546
|
+
Ast.push(ctx, result);
|
|
541
547
|
}
|
|
542
548
|
|
|
543
549
|
static eq(ctx) {
|
package/src/folder.js
CHANGED
package/src/parse.js
CHANGED
|
@@ -108,8 +108,8 @@ export const parse = (function () {
|
|
|
108
108
|
null: { tk: 0x15, cls: "val", length: 0 },
|
|
109
109
|
val: { tk: 1, name: "VAL", cls: "function", length: 2, arity: 2 },
|
|
110
110
|
key: { tk: 1, name: "KEY", cls: "function", length: 2, arity: 2 },
|
|
111
|
-
|
|
112
|
-
concat: { tk: 1, name: "CONCAT", cls: "function", length:
|
|
111
|
+
length: { tk: 1, name: "LEN", cls: "function", length: 1, arity: 1 },
|
|
112
|
+
concat: { tk: 1, name: "CONCAT", cls: "function", length: 2, arity: 2 },
|
|
113
113
|
add: { tk: 1, name: "ADD", cls: "function", length: 2, arity: 2 },
|
|
114
114
|
mul: { tk: 1, name: "MUL", cls: "function", length: 2, arity: 2 },
|
|
115
115
|
pow: { tk: 1, name: "POW", cls: "function", length: 2, arity: 2 },
|
|
@@ -362,9 +362,9 @@ export const parse = (function () {
|
|
|
362
362
|
const processedSuffix = processEscapeSequences(lexeme);
|
|
363
363
|
Ast.string(ctx, processedSuffix, getCoord(ctx)); // strip quotes;
|
|
364
364
|
countCounter(ctx);
|
|
365
|
-
|
|
365
|
+
const count = ctx.state.exprc;
|
|
366
366
|
stopCounter(ctx);
|
|
367
|
-
Ast.concat(ctx);
|
|
367
|
+
Ast.concat(ctx, count);
|
|
368
368
|
cc.cls = "string";
|
|
369
369
|
return cc;
|
|
370
370
|
});
|
|
@@ -1240,7 +1240,7 @@ export const parse = (function () {
|
|
|
1240
1240
|
}
|
|
1241
1241
|
|
|
1242
1242
|
// `abc` --> "abc"
|
|
1243
|
-
// `a${x}c` --> concat
|
|
1243
|
+
// `a${x}c` --> concat (concat "a" x) "c"
|
|
1244
1244
|
function string(ctx, c) {
|
|
1245
1245
|
const quoteChar = c;
|
|
1246
1246
|
ctx.state.quoteCharStack.push(c);
|
package/src/unparse.spec.js
CHANGED
|
@@ -162,6 +162,12 @@ describe("unparse", () => {
|
|
|
162
162
|
expect(unparsed).toBe("concat 'hello' ' world'..");
|
|
163
163
|
});
|
|
164
164
|
|
|
165
|
+
it("should unparse template literal", async () => {
|
|
166
|
+
const source = 'let x = "world"..`hello ${x}`..';
|
|
167
|
+
const unparsed = await testRoundTrip(source);
|
|
168
|
+
expect(unparsed).toBe('concat concat "hello " "world" ""..');
|
|
169
|
+
});
|
|
170
|
+
|
|
165
171
|
it.skip("should unparse complex arithmetic expression", async () => {
|
|
166
172
|
const source = "mul (add 1 2) 3..";
|
|
167
173
|
const unparsed = await testRoundTrip(source);
|