parser-lr 0.4.0 → 0.5.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 +35 -1
- package/bin/parser-lr.js +369 -9068
- package/bin/parser-lr.js.map +1 -1
- package/dist/lib/grammar/grammar-json-path.d.ts +2 -0
- package/dist/lib/grammar/grammar-json-path.d.ts.map +1 -0
- package/dist/lib/grammar/grammar-json-path.esm.d.ts +5 -0
- package/dist/lib/grammar/grammar-json-path.esm.d.ts.map +1 -0
- package/dist/lib/grammar/grammar-json-path.esm.js +9 -0
- package/dist/lib/grammar/grammar-json-path.esm.js.map +1 -0
- package/dist/lib/grammar/grammar-json-path.js +2 -0
- package/dist/lib/grammar/grammar-json-path.js.map +1 -0
- package/dist/lib/grammar/grammar.json +1218 -4476
- package/dist/lib/grammar/index.d.ts +2 -0
- package/dist/lib/grammar/index.d.ts.map +1 -1
- package/dist/lib/grammar/index.js +1 -0
- package/dist/lib/grammar/index.js.map +1 -1
- package/dist/lib/grammar/meta-grammar-table.d.ts.map +1 -1
- package/dist/lib/grammar/meta-grammar-table.js +4 -2
- package/dist/lib/grammar/meta-grammar-table.js.map +1 -1
- package/dist/lib/grammar/table-validator.d.ts +26 -0
- package/dist/lib/grammar/table-validator.d.ts.map +1 -0
- package/dist/lib/grammar/table-validator.js +211 -0
- package/dist/lib/grammar/table-validator.js.map +1 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/transform/cst-transformer.d.ts +14 -0
- package/dist/lib/transform/cst-transformer.d.ts.map +1 -1
- package/dist/lib/transform/cst-transformer.js +82 -11
- package/dist/lib/transform/cst-transformer.js.map +1 -1
- package/dist/lib/transform/grammar-fixture.d.ts +56 -0
- package/dist/lib/transform/grammar-fixture.d.ts.map +1 -0
- package/dist/lib/transform/grammar-fixture.js +101 -0
- package/dist/lib/transform/grammar-fixture.js.map +1 -0
- package/dist/lib-cjs/ast/ast-node.js +70 -0
- package/dist/lib-cjs/ast/ast-node.js.map +1 -0
- package/dist/lib-cjs/errors/index.js +9 -0
- package/dist/lib-cjs/errors/index.js.map +1 -0
- package/dist/lib-cjs/errors/parser-lr-error.js +52 -0
- package/dist/lib-cjs/errors/parser-lr-error.js.map +1 -0
- package/dist/lib-cjs/grammar/ast-schema.js +43 -0
- package/dist/lib-cjs/grammar/ast-schema.js.map +1 -0
- package/dist/lib-cjs/grammar/ast-type.js +3 -0
- package/dist/lib-cjs/grammar/ast-type.js.map +1 -0
- package/dist/lib-cjs/grammar/expression.js +3 -0
- package/dist/lib-cjs/grammar/expression.js.map +1 -0
- package/dist/lib-cjs/grammar/grammar-from-cst.js +641 -0
- package/dist/lib-cjs/grammar/grammar-from-cst.js.map +1 -0
- package/dist/lib-cjs/grammar/grammar-json-path.js +13 -0
- package/dist/lib-cjs/grammar/grammar-json-path.js.map +1 -0
- package/dist/lib-cjs/grammar/grammar-literals.js +71 -0
- package/dist/lib-cjs/grammar/grammar-literals.js.map +1 -0
- package/dist/lib-cjs/grammar/grammar.js +64 -0
- package/dist/lib-cjs/grammar/grammar.js.map +1 -0
- package/dist/lib-cjs/grammar/grammar.json +5760 -0
- package/dist/lib-cjs/grammar/index.js +19 -0
- package/dist/lib-cjs/grammar/index.js.map +1 -0
- package/dist/lib-cjs/grammar/meta-grammar-table.js +39 -0
- package/dist/lib-cjs/grammar/meta-grammar-table.js.map +1 -0
- package/dist/lib-cjs/grammar/production.js +3 -0
- package/dist/lib-cjs/grammar/production.js.map +1 -0
- package/dist/lib-cjs/grammar/read-grammar-error.js +22 -0
- package/dist/lib-cjs/grammar/read-grammar-error.js.map +1 -0
- package/dist/lib-cjs/grammar/read-grammar.js +24 -0
- package/dist/lib-cjs/grammar/read-grammar.js.map +1 -0
- package/dist/lib-cjs/grammar/table-validator.js +215 -0
- package/dist/lib-cjs/grammar/table-validator.js.map +1 -0
- package/dist/lib-cjs/grammar/token-rule.js +3 -0
- package/dist/lib-cjs/grammar/token-rule.js.map +1 -0
- package/dist/lib-cjs/grammar/transform-expression.js +3 -0
- package/dist/lib-cjs/grammar/transform-expression.js.map +1 -0
- package/dist/lib-cjs/grammar/transform-rule.js +3 -0
- package/dist/lib-cjs/grammar/transform-rule.js.map +1 -0
- package/dist/lib-cjs/grammar/transform-schema.js +43 -0
- package/dist/lib-cjs/grammar/transform-schema.js.map +1 -0
- package/dist/lib-cjs/index.js +66 -0
- package/dist/lib-cjs/index.js.map +1 -0
- package/dist/lib-cjs/lexer/index.js +32 -0
- package/dist/lib-cjs/lexer/index.js.map +1 -0
- package/dist/lib-cjs/lexer/lexer-compile-error.js +22 -0
- package/dist/lib-cjs/lexer/lexer-compile-error.js.map +1 -0
- package/dist/lib-cjs/lexer/lexer-compile.js +201 -0
- package/dist/lib-cjs/lexer/lexer-compile.js.map +1 -0
- package/dist/lib-cjs/lexer/lexer-error.js +22 -0
- package/dist/lib-cjs/lexer/lexer-error.js.map +1 -0
- package/dist/lib-cjs/lexer/lexer-input-error.js +17 -0
- package/dist/lib-cjs/lexer/lexer-input-error.js.map +1 -0
- package/dist/lib-cjs/lexer/lexer-state-error.js +19 -0
- package/dist/lib-cjs/lexer/lexer-state-error.js.map +1 -0
- package/dist/lib-cjs/lexer/lexer.js +278 -0
- package/dist/lib-cjs/lexer/lexer.js.map +1 -0
- package/dist/lib-cjs/lexer/token.js +44 -0
- package/dist/lib-cjs/lexer/token.js.map +1 -0
- package/dist/lib-cjs/package.json +3 -0
- package/dist/lib-cjs/parse-context-error.js +19 -0
- package/dist/lib-cjs/parse-context-error.js.map +1 -0
- package/dist/lib-cjs/parse-context.js +137 -0
- package/dist/lib-cjs/parse-context.js.map +1 -0
- package/dist/lib-cjs/parse-output-error.js +19 -0
- package/dist/lib-cjs/parse-output-error.js.map +1 -0
- package/dist/lib-cjs/parse-output.js +18 -0
- package/dist/lib-cjs/parse-output.js.map +1 -0
- package/dist/lib-cjs/parse-table/analysis/first-follow.js +294 -0
- package/dist/lib-cjs/parse-table/analysis/first-follow.js.map +1 -0
- package/dist/lib-cjs/parse-table/analysis/index.js +9 -0
- package/dist/lib-cjs/parse-table/analysis/index.js.map +1 -0
- package/dist/lib-cjs/parse-table/bnf/bnf-grammar.js +140 -0
- package/dist/lib-cjs/parse-table/bnf/bnf-grammar.js.map +1 -0
- package/dist/lib-cjs/parse-table/bnf/bnf-production.js +3 -0
- package/dist/lib-cjs/parse-table/bnf/bnf-production.js.map +1 -0
- package/dist/lib-cjs/parse-table/bnf/bnf-symbol.js +39 -0
- package/dist/lib-cjs/parse-table/bnf/bnf-symbol.js.map +1 -0
- package/dist/lib-cjs/parse-table/bnf/desugar-ebnf.js +224 -0
- package/dist/lib-cjs/parse-table/bnf/desugar-ebnf.js.map +1 -0
- package/dist/lib-cjs/parse-table/bnf/index.js +13 -0
- package/dist/lib-cjs/parse-table/bnf/index.js.map +1 -0
- package/dist/lib-cjs/parse-table/build-lr-table.js +171 -0
- package/dist/lib-cjs/parse-table/build-lr-table.js.map +1 -0
- package/dist/lib-cjs/parse-table/index.js +49 -0
- package/dist/lib-cjs/parse-table/index.js.map +1 -0
- package/dist/lib-cjs/parse-table/lr-algorithm-error.js +19 -0
- package/dist/lib-cjs/parse-table/lr-algorithm-error.js.map +1 -0
- package/dist/lib-cjs/parse-table/lr-algorithm.js +31 -0
- package/dist/lib-cjs/parse-table/lr-algorithm.js.map +1 -0
- package/dist/lib-cjs/parse-table/lr0/index.js +14 -0
- package/dist/lib-cjs/parse-table/lr0/index.js.map +1 -0
- package/dist/lib-cjs/parse-table/lr0/lr0-item-set.js +286 -0
- package/dist/lib-cjs/parse-table/lr0/lr0-item-set.js.map +1 -0
- package/dist/lib-cjs/parse-table/lr1/index.js +18 -0
- package/dist/lib-cjs/parse-table/lr1/index.js.map +1 -0
- package/dist/lib-cjs/parse-table/lr1/lr1-item-set.js +432 -0
- package/dist/lib-cjs/parse-table/lr1/lr1-item-set.js.map +1 -0
- package/dist/lib-cjs/parse-table/parse-table-build-error.js +24 -0
- package/dist/lib-cjs/parse-table/parse-table-build-error.js.map +1 -0
- package/dist/lib-cjs/parse-table/parse-table-error.js +19 -0
- package/dist/lib-cjs/parse-table/parse-table-error.js.map +1 -0
- package/dist/lib-cjs/parse-table/parse-table-json.js +12 -0
- package/dist/lib-cjs/parse-table/parse-table-json.js.map +1 -0
- package/dist/lib-cjs/parse-table/parse-table.js +345 -0
- package/dist/lib-cjs/parse-table/parse-table.js.map +1 -0
- package/dist/lib-cjs/parse-table/slr/index.js +13 -0
- package/dist/lib-cjs/parse-table/slr/index.js.map +1 -0
- package/dist/lib-cjs/parse-table/slr/parse-action.js +8 -0
- package/dist/lib-cjs/parse-table/slr/parse-action.js.map +1 -0
- package/dist/lib-cjs/parse-table/slr/slr-table.js +18 -0
- package/dist/lib-cjs/parse-table/slr/slr-table.js.map +1 -0
- package/dist/lib-cjs/parse-table/table/index.js +21 -0
- package/dist/lib-cjs/parse-table/table/index.js.map +1 -0
- package/dist/lib-cjs/parse-table/table/lr-parse-table.js +192 -0
- package/dist/lib-cjs/parse-table/table/lr-parse-table.js.map +1 -0
- package/dist/lib-cjs/parse-table/table/parse-action.js +54 -0
- package/dist/lib-cjs/parse-table/table/parse-action.js.map +1 -0
- package/dist/lib-cjs/parse-table/table/table-builder-base.js +153 -0
- package/dist/lib-cjs/parse-table/table/table-builder-base.js.map +1 -0
- package/dist/lib-cjs/parse-table/token-inventory.js +18 -0
- package/dist/lib-cjs/parse-table/token-inventory.js.map +1 -0
- package/dist/lib-cjs/parser-lr.js +143 -0
- package/dist/lib-cjs/parser-lr.js.map +1 -0
- package/dist/lib-cjs/shift-reduce/index.js +11 -0
- package/dist/lib-cjs/shift-reduce/index.js.map +1 -0
- package/dist/lib-cjs/shift-reduce/shift-reduce-engine.js +224 -0
- package/dist/lib-cjs/shift-reduce/shift-reduce-engine.js.map +1 -0
- package/dist/lib-cjs/transform/binding-map.js +82 -0
- package/dist/lib-cjs/transform/binding-map.js.map +1 -0
- package/dist/lib-cjs/transform/cst-transformer.js +480 -0
- package/dist/lib-cjs/transform/cst-transformer.js.map +1 -0
- package/dist/lib-cjs/transform/grammar-fixture.js +109 -0
- package/dist/lib-cjs/transform/grammar-fixture.js.map +1 -0
- package/dist/lib-cjs/transform/index.js +12 -0
- package/dist/lib-cjs/transform/index.js.map +1 -0
- package/docs/grammar.md +80 -0
- package/docs/parser-lr-enhancement-proposals.md +548 -0
- package/grammars/6502.grammar +233 -0
- package/grammars/calc.grammar +30 -0
- package/grammars/ferrite.grammar +991 -0
- package/grammars/fixtures/build-optional/build-optional.grammar +32 -0
- package/grammars/fixtures/build-optional/input.txt +1 -0
- package/grammars/fixtures/comparison-op/comparison-op.grammar +28 -0
- package/grammars/fixtures/comparison-op/input.txt +1 -0
- package/grammars/fixtures/flatten-repeat/flatten-repeat.grammar +28 -0
- package/grammars/fixtures/flatten-repeat/input.txt +1 -0
- package/grammars/fixtures/help-topic/help-topic.grammar +28 -0
- package/grammars/fixtures/help-topic/input.txt +1 -0
- package/grammars/fixtures/let-target/input.txt +1 -0
- package/grammars/fixtures/let-target/let-target.grammar +33 -0
- package/grammars/fixtures/pass-preserves-production/bare-terminal/bare-terminal.grammar +24 -0
- package/grammars/fixtures/pass-preserves-production/bare-terminal/input.txt +1 -0
- package/grammars/fixtures/pass-preserves-production/labeled-variant/input-end-if.txt +1 -0
- package/grammars/fixtures/pass-preserves-production/labeled-variant/input-end.txt +1 -0
- package/grammars/fixtures/pass-preserves-production/labeled-variant/labeled-variant.grammar +24 -0
- package/grammars/fixtures/pass-preserves-production/optional-absent/input.txt +1 -0
- package/grammars/fixtures/pass-preserves-production/optional-absent/optional-absent.grammar +24 -0
- package/grammars/fixtures/pass-preserves-production/optional-present/input.txt +1 -0
- package/grammars/fixtures/pass-preserves-production/optional-present/optional-present.grammar +24 -0
- package/grammars/grammar.grammar +428 -0
- package/grammars/lisp.grammar +95 -0
- package/package.json +10 -5
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fixtureGrammarPath = fixtureGrammarPath;
|
|
4
|
+
exports.findChildrenBySymbol = findChildrenBySymbol;
|
|
5
|
+
exports.findChildBySymbol = findChildBySymbol;
|
|
6
|
+
exports.parseFixture = parseFixture;
|
|
7
|
+
exports.discoverFixtures = discoverFixtures;
|
|
8
|
+
exports.runFixtureCase = runFixtureCase;
|
|
9
|
+
const node_fs_1 = require("node:fs");
|
|
10
|
+
const node_path_1 = require("node:path");
|
|
11
|
+
const parse_context_js_1 = require("../parse-context.js");
|
|
12
|
+
/**
|
|
13
|
+
* Returns the `.grammar` file for one fixture directory.
|
|
14
|
+
*
|
|
15
|
+
* Fixture grammars are named after their directory (for example
|
|
16
|
+
* `bare-terminal/bare-terminal.grammar`). The meta-grammar keeps the reserved
|
|
17
|
+
* name `grammar.grammar` at the repo root only.
|
|
18
|
+
*
|
|
19
|
+
* @param fixtureDir - Directory containing a fixture grammar and input files.
|
|
20
|
+
*/
|
|
21
|
+
function fixtureGrammarPath(fixtureDir) {
|
|
22
|
+
const grammarPath = (0, node_path_1.join)(fixtureDir, `${(0, node_path_1.basename)(fixtureDir)}.grammar`);
|
|
23
|
+
return (0, node_fs_1.existsSync)(grammarPath) ? grammarPath : null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns child AST nodes matching a symbol name.
|
|
27
|
+
*
|
|
28
|
+
* @param node - Parent AST node.
|
|
29
|
+
* @param symbol - Child symbol to find.
|
|
30
|
+
*/
|
|
31
|
+
function findChildrenBySymbol(node, symbol) {
|
|
32
|
+
return node.children.filter((child) => child.symbol === symbol);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns the first child AST node matching a symbol name.
|
|
36
|
+
*
|
|
37
|
+
* @param node - Parent AST node.
|
|
38
|
+
* @param symbol - Child symbol to find.
|
|
39
|
+
*/
|
|
40
|
+
function findChildBySymbol(node, symbol) {
|
|
41
|
+
return node.children.find((child) => child.symbol === symbol) ?? null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parses one fixture grammar and input file into an AST.
|
|
45
|
+
*
|
|
46
|
+
* @param fixtureDir - Directory containing a named fixture grammar and an input file.
|
|
47
|
+
* @param inputFileName - Input file name within the fixture directory.
|
|
48
|
+
*/
|
|
49
|
+
function parseFixture(fixtureDir, inputFileName = 'input.txt') {
|
|
50
|
+
const grammarPath = fixtureGrammarPath(fixtureDir);
|
|
51
|
+
if (grammarPath === null) {
|
|
52
|
+
throw new Error(`fixture grammar not found in ${fixtureDir}`);
|
|
53
|
+
}
|
|
54
|
+
const grammarSource = (0, node_fs_1.readFileSync)(grammarPath, 'utf8');
|
|
55
|
+
const input = (0, node_fs_1.readFileSync)((0, node_path_1.join)(fixtureDir, inputFileName), 'utf8').trimEnd();
|
|
56
|
+
const context = parse_context_js_1.ParseContext.fromGrammar(grammarSource, 'lr1');
|
|
57
|
+
return context.parseSource(input);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Discovers fixture directories containing a named `.grammar` file under a root path.
|
|
61
|
+
*
|
|
62
|
+
* @param rootDir - Root directory to scan recursively.
|
|
63
|
+
*/
|
|
64
|
+
function discoverFixtures(rootDir) {
|
|
65
|
+
const fixtures = [];
|
|
66
|
+
const visit = (directory) => {
|
|
67
|
+
const grammarPath = fixtureGrammarPath(directory);
|
|
68
|
+
if (grammarPath !== null) {
|
|
69
|
+
const inputFiles = (0, node_fs_1.readdirSync)(directory)
|
|
70
|
+
.filter((name) => name.startsWith('input') && name.endsWith('.txt'))
|
|
71
|
+
.sort();
|
|
72
|
+
for (const inputFile of inputFiles) {
|
|
73
|
+
const baseName = inputFile.replace(/^input/, '').replace(/\.txt$/, '');
|
|
74
|
+
const expectedName = baseName === '' ? 'expected.json' : `expected${baseName}.json`;
|
|
75
|
+
const expectedPath = (0, node_path_1.join)(directory, expectedName);
|
|
76
|
+
fixtures.push({
|
|
77
|
+
name: `${directory.split('/').slice(-2).join('/')}/${inputFile}`,
|
|
78
|
+
grammarPath,
|
|
79
|
+
inputPath: (0, node_path_1.join)(directory, inputFile),
|
|
80
|
+
expectedPath: (0, node_fs_1.existsSync)(expectedPath) ? expectedPath : null,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
for (const entry of (0, node_fs_1.readdirSync)(directory, { withFileTypes: true })) {
|
|
85
|
+
if (entry.isDirectory()) {
|
|
86
|
+
visit((0, node_path_1.join)(directory, entry.name));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
visit(rootDir);
|
|
91
|
+
return fixtures;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Parses a fixture case and compares to expected JSON when present.
|
|
95
|
+
*
|
|
96
|
+
* @param fixture - Fixture metadata.
|
|
97
|
+
*/
|
|
98
|
+
function runFixtureCase(fixture, expectFn) {
|
|
99
|
+
const grammarSource = (0, node_fs_1.readFileSync)(fixture.grammarPath, 'utf8');
|
|
100
|
+
const input = (0, node_fs_1.readFileSync)(fixture.inputPath, 'utf8').trimEnd();
|
|
101
|
+
const context = parse_context_js_1.ParseContext.fromGrammar(grammarSource, 'lr1');
|
|
102
|
+
const ast = context.parseSource(input);
|
|
103
|
+
if (fixture.expectedPath !== null) {
|
|
104
|
+
const expected = JSON.parse((0, node_fs_1.readFileSync)(fixture.expectedPath, 'utf8'));
|
|
105
|
+
expectFn(ast).toEqual(expected);
|
|
106
|
+
}
|
|
107
|
+
return ast;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=grammar-fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grammar-fixture.js","sourceRoot":"","sources":["../../../src/lib/transform/grammar-fixture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformCst = exports.describeProductionSlots = exports.CstTransformer = exports.referenceSlotIndex = exports.productionSlots = exports.parseRhsSymbolKey = void 0;
|
|
4
|
+
var binding_map_js_1 = require("./binding-map.js");
|
|
5
|
+
Object.defineProperty(exports, "parseRhsSymbolKey", { enumerable: true, get: function () { return binding_map_js_1.parseRhsSymbolKey; } });
|
|
6
|
+
Object.defineProperty(exports, "productionSlots", { enumerable: true, get: function () { return binding_map_js_1.productionSlots; } });
|
|
7
|
+
Object.defineProperty(exports, "referenceSlotIndex", { enumerable: true, get: function () { return binding_map_js_1.referenceSlotIndex; } });
|
|
8
|
+
var cst_transformer_js_1 = require("./cst-transformer.js");
|
|
9
|
+
Object.defineProperty(exports, "CstTransformer", { enumerable: true, get: function () { return cst_transformer_js_1.CstTransformer; } });
|
|
10
|
+
Object.defineProperty(exports, "describeProductionSlots", { enumerable: true, get: function () { return cst_transformer_js_1.describeProductionSlots; } });
|
|
11
|
+
Object.defineProperty(exports, "transformCst", { enumerable: true, get: function () { return cst_transformer_js_1.transformCst; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/transform/index.ts"],"names":[],"mappings":";;;AAAA,mDAA0F;AAAjF,mHAAA,iBAAiB,OAAA;AAAE,iHAAA,eAAe,OAAA;AAAE,oHAAA,kBAAkB,OAAA;AAE/D,2DAA6F;AAApF,oHAAA,cAAc,OAAA;AAAE,6HAAA,uBAAuB,OAAA;AAAE,kHAAA,YAAY,OAAA"}
|
package/docs/grammar.md
CHANGED
|
@@ -155,6 +155,85 @@ transform
|
|
|
155
155
|
;
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
+
### Choosing `pass`, `build`, and `flatten`
|
|
159
|
+
|
|
160
|
+
| Transform | Use when |
|
|
161
|
+
|-----------|----------|
|
|
162
|
+
| `pass(slot)` | Lift one bound child unchanged. `pass(boundSlot)` preserves the bound production symbol and its `#` variant. `pass(terminalName)` at the same rule may collapse to that terminal. |
|
|
163
|
+
| `build(type.#variant, …)` | Construct an AST node with a fixed shape. Omit absent optional bindings from the argument list. |
|
|
164
|
+
| `flatten(type.#variant, head, tail)` | Turn a `{ repeat }` list into one AST node with ordered children. Use the repeat non-terminal (for example `list$repeat_0`) as `tail` on the head production. |
|
|
165
|
+
|
|
166
|
+
**Production symbols are preserved.** When a CST node has parse-table metadata, transforms keep its production name even if it has only one terminal child. Bare `CLS` through `pass(stmt)` where `[stmt]:cls_stmt` yields an `cls_stmt` node, not `kw_cls`.
|
|
167
|
+
|
|
168
|
+
Run `parser-lr table validate -g mylang.grammar` to check `ast` / `transform` consistency. The validator warns when `pass(boundSlot)` targets a production that can match a single terminal and has no transform rule.
|
|
169
|
+
|
|
170
|
+
## Statement authoring
|
|
171
|
+
|
|
172
|
+
Statements follow the same `grammar` / `ast` / `transform` pattern as expressions. Dispatch on stable `*_stmt` production names instead of keyword tokens.
|
|
173
|
+
|
|
174
|
+
```ebnf
|
|
175
|
+
grammar
|
|
176
|
+
statement =
|
|
177
|
+
#cls pass(stmt)
|
|
178
|
+
| #print pass(stmt)
|
|
179
|
+
| #end pass(stmt)
|
|
180
|
+
;
|
|
181
|
+
|
|
182
|
+
cls_stmt =
|
|
183
|
+
#bare kw_cls
|
|
184
|
+
| #with kw_cls kw_with [bg]:expr
|
|
185
|
+
;
|
|
186
|
+
|
|
187
|
+
print_stmt =
|
|
188
|
+
#bare kw_print
|
|
189
|
+
| #items kw_print [list]:print_list
|
|
190
|
+
;
|
|
191
|
+
|
|
192
|
+
end_stmt =
|
|
193
|
+
#program kw_end
|
|
194
|
+
| #if kw_end kw_if
|
|
195
|
+
;
|
|
196
|
+
|
|
197
|
+
ast
|
|
198
|
+
cls_stmt =
|
|
199
|
+
#bare kw_cls
|
|
200
|
+
| #with kw_cls kw_with [bg]:expr
|
|
201
|
+
;
|
|
202
|
+
|
|
203
|
+
print_stmt =
|
|
204
|
+
#bare kw_print
|
|
205
|
+
| #items kw_print [list]:print_list
|
|
206
|
+
;
|
|
207
|
+
|
|
208
|
+
end_stmt =
|
|
209
|
+
#program kw_end
|
|
210
|
+
| #if kw_end kw_if
|
|
211
|
+
;
|
|
212
|
+
|
|
213
|
+
transform
|
|
214
|
+
statement ->
|
|
215
|
+
#cls pass(stmt)
|
|
216
|
+
| #print pass(stmt)
|
|
217
|
+
| #end pass(stmt)
|
|
218
|
+
;
|
|
219
|
+
|
|
220
|
+
cls_stmt ->
|
|
221
|
+
#bare cls_stmt.#bare(kw_cls)
|
|
222
|
+
| #with cls_stmt.#with(kw_cls, kw_with, bg) ;
|
|
223
|
+
|
|
224
|
+
print_stmt ->
|
|
225
|
+
#bare print_stmt.#bare(kw_print)
|
|
226
|
+
| #items print_stmt.#items(kw_print, list) ;
|
|
227
|
+
|
|
228
|
+
end_stmt ->
|
|
229
|
+
#program end_stmt.#program(kw_end)
|
|
230
|
+
| #if end_stmt.#if(kw_end, kw_if) ;
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
After `pass(stmt)`, consumers see `cls_stmt`, `print_stmt`, or `end_stmt` at the statement root. Add `ast` + `transform` rules per statement production rather than scanning for keyword terminals in bridge code.
|
|
234
|
+
|
|
235
|
+
See [`docs/parser-lr-enhancement-proposals.md`](parser-lr-enhancement-proposals.md) for the EduBASIC migration that motivated these conventions.
|
|
236
|
+
|
|
158
237
|
## Complete example
|
|
159
238
|
|
|
160
239
|
See [`grammars/calc.grammar`](../grammars/calc.grammar) for a small working grammar with `grammar`, `ast`, and `transform` sections. [`grammars/lisp.grammar`](../grammars/lisp.grammar) and [`grammars/6502.grammar`](../grammars/6502.grammar) show larger languages.
|
|
@@ -163,6 +242,7 @@ See [`grammars/calc.grammar`](../grammars/calc.grammar) for a small working gram
|
|
|
163
242
|
|
|
164
243
|
```bash
|
|
165
244
|
parser-lr table generate -g mylang.grammar -o mylang.json
|
|
245
|
+
parser-lr table validate -g mylang.grammar
|
|
166
246
|
parser-lr parse -i source.txt -g mylang.grammar
|
|
167
247
|
parser-lr parse -i source.txt -t mylang.json
|
|
168
248
|
```
|