@ohm-js/wasm 0.6.17 → 0.7.1

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.
@@ -1,140 +0,0 @@
1
- import { assert, checkNotNull } from "./assert.js";
2
- function childAt(children, idx, ruleName, propName = '') {
3
- if (idx > children.length) {
4
- const path = propName ? `${ruleName}.${propName}` : ruleName;
5
- throw new Error(`${path}: Child index ${idx} out of range`);
6
- }
7
- return checkNotNull(children[idx]);
8
- }
9
- export function createToAst(mapping, opts = {}) {
10
- const builder = new AstBuilder(mapping, opts);
11
- return (nodeOrResult) => builder.toAst(nodeOrResult);
12
- }
13
- export class AstBuilder {
14
- currNode;
15
- _mapping;
16
- _depth = -1;
17
- _debug = false;
18
- constructor(mapping, opts = {}) {
19
- const handleListOf = (child) => this.toAst(child);
20
- const handleEmptyListOf = () => [];
21
- const handleNonemptyListOf = (first, sepAndElemList) => {
22
- assert(!!sepAndElemList?.isList(), 'Expected a ListNode');
23
- return [this.toAst(first), ...sepAndElemList.collect((_, elem) => this.toAst(elem))];
24
- };
25
- this._mapping = {
26
- listOf: handleListOf,
27
- ListOf: handleListOf,
28
- emptyListOf: handleEmptyListOf,
29
- EmptyListOf: handleEmptyListOf,
30
- nonemptyListOf: handleNonemptyListOf,
31
- NonemptyListOf: handleNonemptyListOf,
32
- ...mapping,
33
- };
34
- this._debug = opts.debug ?? false;
35
- }
36
- _debugLog(...data) {
37
- if (this._debug)
38
- console.log(' '.repeat(this._depth), ...data);
39
- }
40
- _visitTerminal(node) {
41
- return node.sourceString;
42
- }
43
- _visitNonterminal(node) {
44
- const { children, ctorName } = node;
45
- const mapping = this._mapping;
46
- this._debugLog(`> ${ctorName}`);
47
- const dbgReturn = (val) => {
48
- this._debugLog(`| ${ctorName} DONE`);
49
- return val;
50
- };
51
- // without customization
52
- if (!Object.hasOwn(mapping, ctorName)) {
53
- // lexical rule
54
- if (node.isLexical()) {
55
- return node.sourceString;
56
- }
57
- // singular node (e.g. only surrounded by literals or lookaheads)
58
- const realChildren = children.filter(c => !c.isTerminal());
59
- if (realChildren.length === 1) {
60
- return dbgReturn(this.toAst(realChildren[0]));
61
- }
62
- // rest: terms with multiple children
63
- }
64
- // direct forward
65
- if (typeof mapping[ctorName] === 'number') {
66
- const idx = mapping[ctorName];
67
- return dbgReturn(this.toAst(childAt(children, idx, ctorName)));
68
- }
69
- assert(typeof mapping[ctorName] !== 'function', "shouldn't be possible");
70
- // named/mapped children or unnamed children ('0', '1', '2', ...)
71
- const propMap = mapping[ctorName] || children;
72
- const ans = {
73
- type: ctorName,
74
- };
75
- // eslint-disable-next-line guard-for-in
76
- for (const prop in propMap) {
77
- const mappedProp = mapping[ctorName] && mapping[ctorName][prop];
78
- if (typeof mappedProp === 'number') {
79
- // direct forward
80
- ans[prop] = this.toAst(childAt(children, mappedProp, ctorName, prop));
81
- }
82
- else if (typeof mappedProp === 'string' ||
83
- typeof mappedProp === 'boolean' ||
84
- mappedProp === null) {
85
- // primitive value
86
- ans[prop] = mappedProp;
87
- }
88
- else if (typeof mappedProp === 'object' && mappedProp instanceof Number) {
89
- // primitive number (must be unboxed)
90
- ans[prop] = Number(mappedProp);
91
- }
92
- else if (typeof mappedProp === 'function') {
93
- // computed value
94
- ans[prop] = mappedProp.call(this, children);
95
- }
96
- else if (mappedProp === undefined) {
97
- const child = children[Number(prop)];
98
- if (child && !child.isTerminal()) {
99
- ans[prop] = this.toAst(child);
100
- }
101
- else {
102
- // delete predefined 'type' properties, like 'type', if explicitly removed
103
- delete ans[prop];
104
- }
105
- }
106
- }
107
- return dbgReturn(ans);
108
- }
109
- toAst(nodeOrResult) {
110
- let node = nodeOrResult;
111
- if (typeof nodeOrResult.succeeded === 'function') {
112
- const matchResult = nodeOrResult;
113
- assert(matchResult.succeeded(), 'Cannot convert failed match result to AST');
114
- node = matchResult.grammar.getCstRoot();
115
- }
116
- let ans;
117
- this._depth++;
118
- if (node.isTerminal()) {
119
- ans = this._visitTerminal(node);
120
- }
121
- else if (node.isOptional()) {
122
- ans = node.ifPresent((child) => this.toAst(child), () => null);
123
- }
124
- else if (node.isList() || node.isSeq()) {
125
- ans = node.children.map(c => this.toAst(c));
126
- }
127
- else {
128
- assert(node.isNonterminal(), `Unknown node type: ${node.type}`);
129
- this.currNode = node;
130
- ans =
131
- typeof this._mapping[node.ctorName] === 'function'
132
- ? this._mapping[node.ctorName].apply(this, node.children)
133
- : this._visitNonterminal(node);
134
- this.currNode = undefined;
135
- }
136
- this._depth--;
137
- return ans;
138
- }
139
- }
140
- //# sourceMappingURL=AstBuilder.js.map