@ohm-js/wasm 0.6.16 → 0.7.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/dist/src/ir.js CHANGED
@@ -6,9 +6,10 @@ export const alt = (children) => ({
6
6
  outArity: outArity(children[0]),
7
7
  });
8
8
  export const any = () => ({ type: 'Any' });
9
- export const apply = (ruleName, children = []) => ({
9
+ export const apply = (ruleName, descriptionId, children = []) => ({
10
10
  type: 'Apply',
11
11
  ruleName,
12
+ descriptionId,
12
13
  children,
13
14
  });
14
15
  export const applyGeneralized = (ruleName, caseIdx) => ({
@@ -47,7 +48,7 @@ export const seq = (children) => ({
47
48
  outArity: children.reduce((acc, child) => acc + outArity(child), 0),
48
49
  });
49
50
  export const star = (child) => ({ type: 'Star', child });
50
- export const terminal = (value, caseInsensitive = false) => ({
51
+ export const terminal = (value) => ({
51
52
  type: 'Terminal',
52
53
  value,
53
54
  });
@@ -55,9 +56,10 @@ export const unicodeChar = (categoryOrProp) => ({
55
56
  type: 'UnicodeChar',
56
57
  categoryOrProp,
57
58
  });
58
- export const liftedTerminal = (terminalId) => ({
59
+ export const liftedTerminal = (terminalId, failureId) => ({
59
60
  type: 'LiftedTerminal',
60
61
  terminalId,
62
+ failureId,
61
63
  });
62
64
  // Helpers
63
65
  // -------
@@ -119,7 +121,7 @@ export function substituteParams(exp, actuals) {
119
121
  case 'Apply':
120
122
  if (exp.children.length === 0)
121
123
  return exp;
122
- return apply(exp.ruleName, exp.children.map((c) => {
124
+ return apply(exp.ruleName, exp.descriptionId, exp.children.map((c) => {
123
125
  const ans = substituteParams(c, actuals);
124
126
  return checkApplyLike(ans);
125
127
  }));
@@ -6,6 +6,21 @@ export declare const CstNodeType: {
6
6
  readonly SEQ: 4;
7
7
  };
8
8
  export type CstNodeType = (typeof CstNodeType)[keyof typeof CstNodeType];
9
+ export declare class Interval {
10
+ startIdx: number;
11
+ endIdx: number;
12
+ private _sourceString;
13
+ constructor(sourceString: string, startIdx: number, endIdx: number);
14
+ get sourceString(): string;
15
+ get contents(): string;
16
+ }
17
+ export declare class Failure {
18
+ private _description;
19
+ private _fluffy;
20
+ constructor(description: string, fluffy: boolean);
21
+ isFluffy(): boolean;
22
+ toString(): string;
23
+ }
9
24
  export declare class WasmGrammar {
10
25
  name: string;
11
26
  private _instance?;
@@ -13,6 +28,7 @@ export declare class WasmGrammar {
13
28
  private _ruleIds;
14
29
  private _ruleNames;
15
30
  private _input;
31
+ _failureDescriptions: string[];
16
32
  private _resultStack;
17
33
  private _managedResultCount;
18
34
  /**
@@ -30,9 +46,11 @@ export declare class WasmGrammar {
30
46
  _instantiate(source: BufferSource, debugImports?: any): Promise<this>;
31
47
  _instantiateStreaming(source: Response | Promise<Response>, debugImports?: any): Promise<WasmGrammar>;
32
48
  private _getGrammarName;
33
- private _extractRuleIds;
49
+ private _extractStrings;
34
50
  private _detachMatchResult;
35
51
  match<T>(input: string, ruleName?: string): MatchResult;
52
+ recordFailures(): number[];
53
+ getFailureDescription(id: number): string;
36
54
  getMemorySizeBytes(): number;
37
55
  getCstRoot(): CstNode;
38
56
  private _fillInputBuffer;
@@ -196,27 +214,30 @@ export declare class MatchResult {
196
214
  _ctx: MatchContext;
197
215
  _succeeded: boolean;
198
216
  constructor(grammar: WasmGrammar, startExpr: string, ctx: MatchContext, succeeded: boolean);
217
+ get input(): string;
199
218
  [Symbol.dispose](): void;
200
219
  detach(): void;
201
220
  succeeded(): this is SucceededMatchResult;
202
221
  failed(): this is FailedMatchResult;
203
222
  toString(): string;
204
- use<T>(cb: (r: MatchResult) => T): T;
223
+ use<T>(cb: (r: this) => T): T;
205
224
  }
206
225
  export declare class SucceededMatchResult extends MatchResult {
207
226
  _cst: CstNode;
208
227
  constructor(grammar: WasmGrammar, startExpr: string, ctx: MatchContext, succeeded: boolean);
209
228
  }
210
229
  export declare class FailedMatchResult extends MatchResult {
211
- constructor(grammar: WasmGrammar, startExpr: string, ctx: MatchContext, succeeded: boolean, rightmostFailurePosition: number, optRecordedFailures?: any);
230
+ constructor(grammar: WasmGrammar, startExpr: string, ctx: MatchContext, succeeded: boolean, rightmostFailurePosition: number);
212
231
  _rightmostFailurePosition: number;
213
- _rightmostFailures: any;
214
- shortMessage: string;
215
- message: string;
232
+ private _rightmostFailures;
233
+ private _failureDescriptions;
216
234
  getRightmostFailurePosition(): number;
217
- getRightmostFailures(): any;
235
+ getRightmostFailures(): Failure[];
236
+ private _getFailureDescriptions;
218
237
  getExpectedText(): string;
219
- getInterval(): void;
238
+ getInterval(): Interval;
239
+ get message(): string;
240
+ get shortMessage(): string;
220
241
  }
221
242
  export {};
222
243
  //# sourceMappingURL=miniohm.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import { assert, checkNotNull } from "./assert.js";
2
+ import { getLineAndColumn, getLineAndColumnMessage } from 'ohm-js/extras';
2
3
  const MATCH_RECORD_TYPE_MASK = 0b11;
3
4
  // A MatchRecord is the representation of a CstNode in Wasm linear memory.
4
5
  const MatchRecordType = {
@@ -30,6 +31,37 @@ const UnicodeCategoryNames = [
30
31
  'Lo', // Other_Letter
31
32
  ];
32
33
  const utf8 = new TextDecoder('utf-8');
34
+ // Minimal implementation of Interval (for FailedMatchResult)
35
+ export class Interval {
36
+ startIdx;
37
+ endIdx;
38
+ _sourceString;
39
+ constructor(sourceString, startIdx, endIdx) {
40
+ this._sourceString = sourceString;
41
+ this.startIdx = startIdx;
42
+ this.endIdx = endIdx;
43
+ }
44
+ get sourceString() {
45
+ return this._sourceString;
46
+ }
47
+ get contents() {
48
+ return this._sourceString.slice(this.startIdx, this.endIdx);
49
+ }
50
+ }
51
+ export class Failure {
52
+ _description;
53
+ _fluffy;
54
+ constructor(description, fluffy) {
55
+ this._description = description;
56
+ this._fluffy = fluffy;
57
+ }
58
+ isFluffy() {
59
+ return this._fluffy;
60
+ }
61
+ toString() {
62
+ return this._description;
63
+ }
64
+ }
33
65
  function regexFromCategoryBitmap(bitmap) {
34
66
  const cats = [];
35
67
  for (let i = 0; i < 32; i++) {
@@ -40,6 +72,35 @@ function regexFromCategoryBitmap(bitmap) {
40
72
  return new RegExp(cats.map(cat => `\\p{${cat}}`).join('|'), 'uy' // u: unicode, y: sticky
41
73
  );
42
74
  }
75
+ function parseStringTable(module, sectionName) {
76
+ const sections = WebAssembly.Module.customSections(module, sectionName);
77
+ assert(sections.length === 1, `Expected one ${sectionName} section, found ${sections.length}`);
78
+ const data = new Uint8Array(sections[0]);
79
+ const dataView = new DataView(data.buffer);
80
+ let offset = 0;
81
+ const parseU32 = () => {
82
+ // Quick 'n dirty ULeb128 parsing, assuming no more than 2 bytes.
83
+ const b1 = dataView.getUint8(offset++);
84
+ let value = b1 & 0x7f;
85
+ if (b1 & 0x80) {
86
+ const b2 = dataView.getUint8(offset++);
87
+ assert((b2 & 0x80) === 0, 'Expected max two bytes');
88
+ value |= (b2 & 0x7f) << 7;
89
+ }
90
+ return value;
91
+ };
92
+ const decoder = new TextDecoder('utf-8');
93
+ const numEntries = parseU32();
94
+ const ans = [];
95
+ for (let i = 0; i < numEntries; i++) {
96
+ const stringLen = parseU32();
97
+ const bytes = data.slice(offset, offset + stringLen);
98
+ offset += stringLen;
99
+ const name = decoder.decode(bytes);
100
+ ans.push(name);
101
+ }
102
+ return ans;
103
+ }
43
104
  export class WasmGrammar {
44
105
  name = '';
45
106
  _instance = undefined;
@@ -92,6 +153,7 @@ export class WasmGrammar {
92
153
  _ruleIds = new Map();
93
154
  _ruleNames = [];
94
155
  _input = '';
156
+ _failureDescriptions = []; // Should be treated as package private
95
157
  _resultStack = [];
96
158
  _managedResultCount = 0;
97
159
  /**
@@ -109,7 +171,7 @@ export class WasmGrammar {
109
171
  }
110
172
  _init(module, instance) {
111
173
  this._instance = instance;
112
- this._extractRuleIds(module);
174
+ this._extractStrings(module);
113
175
  this.name = this._getGrammarName(module);
114
176
  return this;
115
177
  }
@@ -159,32 +221,15 @@ export class WasmGrammar {
159
221
  const decoder = new TextDecoder('utf-8');
160
222
  return decoder.decode(data);
161
223
  }
162
- _extractRuleIds(module) {
163
- const sections = WebAssembly.Module.customSections(module, 'ruleNames');
164
- assert(sections.length === 1, `Expected one ruleNames section, found ${sections.length}`);
165
- const data = new Uint8Array(sections[0]);
166
- const dataView = new DataView(data.buffer);
167
- let offset = 0;
168
- const parseU32 = () => {
169
- // Quick 'n dirty ULeb128 parsing, assuming no more than 2 bytes.
170
- const b1 = dataView.getUint8(offset++);
171
- let value = b1 & 0x7f;
172
- if (b1 & 0x80) {
173
- const b2 = dataView.getUint8(offset++);
174
- assert((b2 & 0x80) === 0, 'Expected max two bytes');
175
- value |= (b2 & 0x7f) << 7;
176
- }
177
- return value;
178
- };
179
- const decoder = new TextDecoder('utf-8');
180
- const numEntries = parseU32();
181
- for (let i = 0; i < numEntries; i++) {
182
- const stringLen = parseU32();
183
- const bytes = data.slice(offset, offset + stringLen);
184
- offset += stringLen;
185
- const name = decoder.decode(bytes);
186
- this._ruleIds.set(name, i);
187
- this._ruleNames.push(name);
224
+ _extractStrings(module) {
225
+ assert(this._ruleNames.length === 0);
226
+ assert(this._ruleIds.size === 0);
227
+ for (const ruleName of parseStringTable(module, 'ruleNames')) {
228
+ this._ruleIds.set(ruleName, this._ruleIds.size);
229
+ this._ruleNames.push(ruleName);
230
+ }
231
+ for (const str of parseStringTable(module, 'failureDescriptions')) {
232
+ this._failureDescriptions.push(str);
188
233
  }
189
234
  }
190
235
  _detachMatchResult(result) {
@@ -209,6 +254,25 @@ export class WasmGrammar {
209
254
  this._resultStack.push(result);
210
255
  return result;
211
256
  }
257
+ recordFailures() {
258
+ const { exports } = this._instance;
259
+ exports.recordFailures(this._ruleIds.get(this._ruleNames[0]));
260
+ const ans = [];
261
+ for (let i = 0; i < exports.getRecordedFailuresLength(); i++) {
262
+ if (!exports.isFluffy(i)) {
263
+ // Filter out fluffy failures
264
+ ans.push(exports.recordedFailuresAt(i));
265
+ }
266
+ }
267
+ // Deduplicate
268
+ return [...new Set(ans)];
269
+ }
270
+ getFailureDescription(id) {
271
+ const isNot = (id & 0x80000000) !== 0;
272
+ const realId = id & 0x7fffffff;
273
+ const desc = this._failureDescriptions[realId];
274
+ return isNot ? 'not ' + desc : desc;
275
+ }
212
276
  getMemorySizeBytes() {
213
277
  return this._instance.exports.memory.buffer.byteLength;
214
278
  }
@@ -541,6 +605,9 @@ export class MatchResult {
541
605
  this._ctx = ctx;
542
606
  this._succeeded = succeeded;
543
607
  }
608
+ get input() {
609
+ return this.grammar._input;
610
+ }
544
611
  [Symbol.dispose]() {
545
612
  this.detach();
546
613
  }
@@ -581,31 +648,81 @@ export class SucceededMatchResult extends MatchResult {
581
648
  }
582
649
  }
583
650
  export class FailedMatchResult extends MatchResult {
584
- constructor(grammar, startExpr, ctx, succeeded, rightmostFailurePosition, optRecordedFailures) {
651
+ constructor(grammar, startExpr, ctx, succeeded, rightmostFailurePosition) {
585
652
  super(grammar, startExpr, ctx, succeeded);
586
653
  this._rightmostFailurePosition = rightmostFailurePosition;
587
- this._rightmostFailures = optRecordedFailures;
588
- // TODO: Define these as lazy properties, like in the JS implementation.
589
- this.shortMessage = this.message = `Match failed at pos ${rightmostFailurePosition}`;
590
654
  }
591
655
  _rightmostFailurePosition;
592
- _rightmostFailures;
593
- shortMessage;
594
- message;
656
+ _rightmostFailures = null;
657
+ _failureDescriptions = null;
595
658
  getRightmostFailurePosition() {
596
659
  return this._rightmostFailurePosition;
597
660
  }
598
661
  getRightmostFailures() {
599
- throw new Error('Not implemented yet: getRightmostFailures');
662
+ if (this._rightmostFailures === null) {
663
+ const { exports } = this.grammar._instance;
664
+ const ruleIds = this.grammar._ruleIds;
665
+ const ruleNames = this.grammar._ruleNames;
666
+ exports.recordFailures(ruleIds.get(ruleNames[0]));
667
+ // Use a Map to deduplicate by description while preserving fluffy status.
668
+ // A failure is only fluffy if ALL occurrences are fluffy.
669
+ const failureMap = new Map();
670
+ for (let i = 0; i < exports.getRecordedFailuresLength(); i++) {
671
+ const id = exports.recordedFailuresAt(i);
672
+ const desc = this.grammar.getFailureDescription(id);
673
+ const fluffy = exports.isFluffy(i);
674
+ if (failureMap.has(desc)) {
675
+ // Only keep fluffy=true if both are fluffy
676
+ failureMap.set(desc, failureMap.get(desc) && fluffy);
677
+ }
678
+ else {
679
+ failureMap.set(desc, fluffy);
680
+ }
681
+ }
682
+ this._rightmostFailures = Array.from(failureMap.entries()).map(([desc, fluffy]) => new Failure(desc, fluffy));
683
+ }
684
+ return this._rightmostFailures;
685
+ }
686
+ // Get the non-fluffy failure descriptions.
687
+ _getFailureDescriptions() {
688
+ if (this._failureDescriptions === null) {
689
+ this._failureDescriptions = this.getRightmostFailures()
690
+ .filter(f => !f.isFluffy())
691
+ .map(f => f.toString());
692
+ }
693
+ return this._failureDescriptions;
600
694
  }
601
695
  // Return a string summarizing the expected contents of the input stream when
602
696
  // the match failure occurred.
603
697
  getExpectedText() {
604
698
  assert(!this._succeeded, 'cannot get expected text of a successful MatchResult');
605
- throw new Error('Not implemented yet: getExpectedText');
699
+ const descriptions = this._getFailureDescriptions();
700
+ switch (descriptions.length) {
701
+ case 0:
702
+ return '';
703
+ case 1:
704
+ return descriptions[0];
705
+ case 2:
706
+ return descriptions[0] + ' or ' + descriptions[1];
707
+ default:
708
+ // For 3+ items: "a, b, or c"
709
+ return (descriptions.slice(0, -1).join(', ') +
710
+ ', or ' +
711
+ descriptions[descriptions.length - 1]);
712
+ }
606
713
  }
607
714
  getInterval() {
608
- throw new Error('Not implemented yet: getInterval');
715
+ const pos = this.getRightmostFailurePosition();
716
+ return new Interval(this.input, pos, pos);
717
+ }
718
+ get message() {
719
+ const detail = 'Expected ' + this.getExpectedText();
720
+ return getLineAndColumnMessage(this.input, this.getRightmostFailurePosition()) + detail;
721
+ }
722
+ get shortMessage() {
723
+ const detail = 'expected ' + this.getExpectedText();
724
+ const errorInfo = getLineAndColumn(this.input, this.getRightmostFailurePosition());
725
+ return 'Line ' + errorInfo.lineNum + ', col ' + errorInfo.colNum + ': ' + detail;
609
726
  }
610
727
  }
611
728
  //# sourceMappingURL=miniohm.js.map
@@ -0,0 +1,16 @@
1
+ export function awaitBuiltInRules(cb: any): void;
2
+ export function announceBuiltInRules(grammar: any): void;
3
+ export function getLineAndColumn(str: any, offset: any): {
4
+ offset: any;
5
+ lineNum: number;
6
+ colNum: number;
7
+ line: any;
8
+ prevLine: any;
9
+ nextLine: any;
10
+ toString: typeof lineAndColumnToMessage;
11
+ };
12
+ export function getLineAndColumnMessage(str: any, offset: any, ...ranges: any[]): any;
13
+ export function uniqueId(prefix: any): string;
14
+ declare function lineAndColumnToMessage(...ranges: any[]): any;
15
+ export {};
16
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1,150 @@
1
+ import * as common from './common.js';
2
+ // --------------------------------------------------------------------
3
+ // Private stuff
4
+ // --------------------------------------------------------------------
5
+ // Given an array of numbers `arr`, return an array of the numbers as strings,
6
+ // right-justified and padded to the same length.
7
+ function padNumbersToEqualLength(arr) {
8
+ let maxLen = 0;
9
+ const strings = arr.map(n => {
10
+ const str = n.toString();
11
+ maxLen = Math.max(maxLen, str.length);
12
+ return str;
13
+ });
14
+ return strings.map(s => common.padLeft(s, maxLen));
15
+ }
16
+ // Produce a new string that would be the result of copying the contents
17
+ // of the string `src` onto `dest` at offset `offest`.
18
+ function strcpy(dest, src, offset) {
19
+ const origDestLen = dest.length;
20
+ const start = dest.slice(0, offset);
21
+ const end = dest.slice(offset + src.length);
22
+ return (start + src + end).substr(0, origDestLen);
23
+ }
24
+ // Casts the underlying lineAndCol object to a formatted message string,
25
+ // highlighting `ranges`.
26
+ function lineAndColumnToMessage(...ranges) {
27
+ const lineAndCol = this;
28
+ const { offset } = lineAndCol;
29
+ const { repeatStr } = common;
30
+ const sb = new common.StringBuffer();
31
+ sb.append('Line ' + lineAndCol.lineNum + ', col ' + lineAndCol.colNum + ':\n');
32
+ // An array of the previous, current, and next line numbers as strings of equal length.
33
+ const lineNumbers = padNumbersToEqualLength([
34
+ lineAndCol.prevLine == null ? 0 : lineAndCol.lineNum - 1,
35
+ lineAndCol.lineNum,
36
+ lineAndCol.nextLine == null ? 0 : lineAndCol.lineNum + 1,
37
+ ]);
38
+ // Helper for appending formatting input lines to the buffer.
39
+ const appendLine = (num, content, prefix) => {
40
+ sb.append(prefix + lineNumbers[num] + ' | ' + content + '\n');
41
+ };
42
+ // Include the previous line for context if possible.
43
+ if (lineAndCol.prevLine != null) {
44
+ appendLine(0, lineAndCol.prevLine, ' ');
45
+ }
46
+ // Line that the error occurred on.
47
+ appendLine(1, lineAndCol.line, '> ');
48
+ // Build up the line that points to the offset and possible indicates one or more ranges.
49
+ // Start with a blank line, and indicate each range by overlaying a string of `~` chars.
50
+ const lineLen = lineAndCol.line.length;
51
+ let indicationLine = repeatStr(' ', lineLen + 1);
52
+ for (let i = 0; i < ranges.length; ++i) {
53
+ let startIdx = ranges[i][0];
54
+ let endIdx = ranges[i][1];
55
+ common.assert(startIdx >= 0 && startIdx <= endIdx, 'range start must be >= 0 and <= end');
56
+ const lineStartOffset = offset - lineAndCol.colNum + 1;
57
+ startIdx = Math.max(0, startIdx - lineStartOffset);
58
+ endIdx = Math.min(endIdx - lineStartOffset, lineLen);
59
+ indicationLine = strcpy(indicationLine, repeatStr('~', endIdx - startIdx), startIdx);
60
+ }
61
+ const gutterWidth = 2 + lineNumbers[1].length + 3;
62
+ sb.append(repeatStr(' ', gutterWidth));
63
+ indicationLine = strcpy(indicationLine, '^', lineAndCol.colNum - 1);
64
+ sb.append(indicationLine.replace(/ +$/, '') + '\n');
65
+ // Include the next line for context if possible.
66
+ if (lineAndCol.nextLine != null) {
67
+ appendLine(2, lineAndCol.nextLine, ' ');
68
+ }
69
+ return sb.contents();
70
+ }
71
+ // --------------------------------------------------------------------
72
+ // Exports
73
+ // --------------------------------------------------------------------
74
+ let builtInRulesCallbacks = [];
75
+ // Since Grammar.BuiltInRules is bootstrapped, most of Ohm can't directly depend it.
76
+ // This function allows modules that do depend on the built-in rules to register a callback
77
+ // that will be called later in the initialization process.
78
+ export function awaitBuiltInRules(cb) {
79
+ builtInRulesCallbacks.push(cb);
80
+ }
81
+ export function announceBuiltInRules(grammar) {
82
+ builtInRulesCallbacks.forEach(cb => {
83
+ cb(grammar);
84
+ });
85
+ builtInRulesCallbacks = null;
86
+ }
87
+ // Return an object with the line and column information for the given
88
+ // offset in `str`.
89
+ export function getLineAndColumn(str, offset) {
90
+ let lineNum = 1;
91
+ let colNum = 1;
92
+ let currOffset = 0;
93
+ let lineStartOffset = 0;
94
+ let nextLine = null;
95
+ let prevLine = null;
96
+ let prevLineStartOffset = -1;
97
+ while (currOffset < offset) {
98
+ const c = str.charAt(currOffset++);
99
+ if (c === '\n') {
100
+ lineNum++;
101
+ colNum = 1;
102
+ prevLineStartOffset = lineStartOffset;
103
+ lineStartOffset = currOffset;
104
+ }
105
+ else if (c !== '\r') {
106
+ colNum++;
107
+ }
108
+ }
109
+ // Find the end of the target line.
110
+ let lineEndOffset = str.indexOf('\n', lineStartOffset);
111
+ if (lineEndOffset === -1) {
112
+ lineEndOffset = str.length;
113
+ }
114
+ else {
115
+ // Get the next line.
116
+ const nextLineEndOffset = str.indexOf('\n', lineEndOffset + 1);
117
+ nextLine =
118
+ nextLineEndOffset === -1
119
+ ? str.slice(lineEndOffset)
120
+ : str.slice(lineEndOffset, nextLineEndOffset);
121
+ // Strip leading and trailing EOL char(s).
122
+ nextLine = nextLine.replace(/^\r?\n/, '').replace(/\r$/, '');
123
+ }
124
+ // Get the previous line.
125
+ if (prevLineStartOffset >= 0) {
126
+ // Strip trailing EOL char(s).
127
+ prevLine = str.slice(prevLineStartOffset, lineStartOffset).replace(/\r?\n$/, '');
128
+ }
129
+ // Get the target line, stripping a trailing carriage return if necessary.
130
+ const line = str.slice(lineStartOffset, lineEndOffset).replace(/\r$/, '');
131
+ return {
132
+ offset,
133
+ lineNum,
134
+ colNum,
135
+ line,
136
+ prevLine,
137
+ nextLine,
138
+ toString: lineAndColumnToMessage,
139
+ };
140
+ }
141
+ // Return a nicely-formatted string describing the line and column for the
142
+ // given offset in `str` highlighting `ranges`.
143
+ export function getLineAndColumnMessage(str, offset, ...ranges) {
144
+ return getLineAndColumn(str, offset).toString(...ranges);
145
+ }
146
+ export const uniqueId = (() => {
147
+ let idCounter = 0;
148
+ return prefix => '' + prefix + idCounter++;
149
+ })();
150
+ //# sourceMappingURL=util.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ohm-js/wasm",
3
- "version": "0.6.16",
3
+ "version": "0.7.0",
4
4
  "description": "Compile Ohm.js grammars to WebAsssembly",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -1,22 +0,0 @@
1
- import type { CstNode, CstNodeChildren, MatchResult, NonterminalNode, TerminalNode } from './miniohm.ts';
2
- export type AstNodeTemplate<R> = {
3
- [property: string]: number | string | boolean | object | null | ((this: AstBuilder, children: CstNodeChildren) => R);
4
- };
5
- export type AstMapping<R> = Record<string, AstNodeTemplate<R> | number | ((this: AstBuilder, ...children: CstNodeChildren) => R)>;
6
- export declare function createToAst<TNode = any>(mapping: AstMapping<TNode>, opts?: {
7
- debug?: boolean;
8
- }): (nodeOrResult: MatchResult | CstNode) => TNode;
9
- export declare class AstBuilder<TNode = any> {
10
- currNode?: CstNode;
11
- private _mapping;
12
- private _depth;
13
- private _debug;
14
- constructor(mapping: AstMapping<TNode>, opts?: {
15
- debug?: boolean;
16
- });
17
- private _debugLog;
18
- _visitTerminal(node: TerminalNode): string;
19
- _visitNonterminal(node: NonterminalNode): unknown;
20
- toAst(nodeOrResult: MatchResult | CstNode): TNode;
21
- }
22
- //# sourceMappingURL=AstBuilder.d.ts.map