grammar-composer 0.4.0 → 0.6.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.
Files changed (60) hide show
  1. package/README.md +144 -89
  2. package/dist/exports/Exports.d.ts +2 -0
  3. package/dist/exports/Exports.d.ts.map +1 -1
  4. package/dist/exports/Exports.js +2 -0
  5. package/dist/exports/Exports.js.map +1 -1
  6. package/dist/parser-generator/Grammar.d.ts +8 -1
  7. package/dist/parser-generator/Grammar.d.ts.map +1 -1
  8. package/dist/parser-generator/Grammar.js +30 -225
  9. package/dist/parser-generator/Grammar.js.map +1 -1
  10. package/dist/parser-generator/ParseError.d.ts +37 -0
  11. package/dist/parser-generator/ParseError.d.ts.map +1 -0
  12. package/dist/parser-generator/ParseError.js +226 -0
  13. package/dist/parser-generator/ParseError.js.map +1 -0
  14. package/dist/parser-generator/StaticAnalysis.d.ts +6 -0
  15. package/dist/parser-generator/StaticAnalysis.d.ts.map +1 -0
  16. package/dist/parser-generator/StaticAnalysis.js +283 -0
  17. package/dist/parser-generator/StaticAnalysis.js.map +1 -0
  18. package/dist/parser-generator/TerminalToText.d.ts +15 -0
  19. package/dist/parser-generator/TerminalToText.d.ts.map +1 -0
  20. package/dist/parser-generator/TerminalToText.js +158 -0
  21. package/dist/parser-generator/TerminalToText.js.map +1 -0
  22. package/dist/parser-generator/TopDownParser.d.ts +4 -2
  23. package/dist/parser-generator/TopDownParser.d.ts.map +1 -1
  24. package/dist/parser-generator/TopDownParser.js +44 -42
  25. package/dist/parser-generator/TopDownParser.js.map +1 -1
  26. package/dist/tests/Test.js +23 -23
  27. package/dist/tests/Test.js.map +1 -1
  28. package/dist/tests/test-grammars/JsonGrammar.d.ts +12 -11
  29. package/dist/tests/test-grammars/JsonGrammar.d.ts.map +1 -1
  30. package/dist/tests/test-grammars/JsonGrammar.js +25 -10
  31. package/dist/tests/test-grammars/JsonGrammar.js.map +1 -1
  32. package/dist/tests/test-grammars/RegExpGrammar.d.ts +25 -25
  33. package/dist/tests/test-grammars/RegExpGrammar.d.ts.map +1 -1
  34. package/dist/tests/test-grammars/RegExpGrammar.js +48 -31
  35. package/dist/tests/test-grammars/RegExpGrammar.js.map +1 -1
  36. package/dist/tests/test-grammars/XmlGrammar.d.ts +11 -10
  37. package/dist/tests/test-grammars/XmlGrammar.d.ts.map +1 -1
  38. package/dist/tests/test-grammars/XmlGrammar.js +19 -8
  39. package/dist/tests/test-grammars/XmlGrammar.js.map +1 -1
  40. package/dist/utilities/LineAndColumn.d.ts +7 -0
  41. package/dist/utilities/LineAndColumn.d.ts.map +1 -0
  42. package/dist/utilities/LineAndColumn.js +52 -0
  43. package/dist/utilities/LineAndColumn.js.map +1 -0
  44. package/dist/utilities/Timer.d.ts +7 -3
  45. package/dist/utilities/Timer.d.ts.map +1 -1
  46. package/dist/utilities/Timer.js +41 -39
  47. package/dist/utilities/Timer.js.map +1 -1
  48. package/package.json +3 -3
  49. package/src/exports/Exports.ts +2 -0
  50. package/src/parser-generator/Grammar.ts +59 -265
  51. package/src/parser-generator/ParseError.ts +337 -0
  52. package/src/parser-generator/StaticAnalysis.ts +340 -0
  53. package/src/parser-generator/TerminalToText.ts +196 -0
  54. package/src/parser-generator/TopDownParser.ts +67 -49
  55. package/src/tests/Test.ts +26 -24
  56. package/src/tests/test-grammars/JsonGrammar.ts +28 -10
  57. package/src/tests/test-grammars/RegExpGrammar.ts +65 -46
  58. package/src/tests/test-grammars/XmlGrammar.ts +20 -8
  59. package/src/utilities/LineAndColumn.ts +61 -0
  60. package/src/utilities/Timer.ts +50 -48
@@ -0,0 +1,226 @@
1
+ import { buildCaretSpacing, expandTabs, getLineAndColumn } from '../utilities/LineAndColumn.js';
2
+ import { escapeChar, TerminalToText } from './TerminalToText.js';
3
+ /////////////////////////////////////////////////////////////////////////////////////////////////
4
+ // Parse error class
5
+ /////////////////////////////////////////////////////////////////////////////////////////////////
6
+ export class ParseError extends Error {
7
+ input;
8
+ offset;
9
+ line;
10
+ column;
11
+ found;
12
+ expected;
13
+ contextProduction;
14
+ constructor(details, maxDisplayedLineLength = 100) {
15
+ const { line, column } = getLineAndColumn(details.input, details.offset);
16
+ const errorMessage = buildErrorMessage(details, line, column, maxDisplayedLineLength);
17
+ super(errorMessage);
18
+ this.name = 'ParseError';
19
+ this.input = details.input;
20
+ this.offset = details.offset;
21
+ this.line = line;
22
+ this.column = column;
23
+ if (details.offset < details.input.length) {
24
+ this.found = details.input[details.offset];
25
+ }
26
+ this.expected = details.expected;
27
+ this.contextProduction = details.contextProductionName;
28
+ }
29
+ // Dedicated factory for the case where parsing failed because no expected
30
+ // terminal matched at some position.
31
+ static createFailedParseError(input, offset, bestFailedMatches) {
32
+ const { expected, contextProduction } = analyzeFailedMatches(bestFailedMatches);
33
+ return new ParseError({
34
+ input,
35
+ offset,
36
+ expected,
37
+ contextProductionName: contextProduction.name
38
+ });
39
+ }
40
+ // Dedicated factory for the case where parsing consumed only part of the input
41
+ // without any specific terminal failing.
42
+ static createIncompleteParseError(input, offset, parsedLength) {
43
+ return new ParseError({ input, offset, parsedLength });
44
+ }
45
+ }
46
+ /////////////////////////////////////////////////////////////////////////////////////////////////
47
+ // Failed match analysis
48
+ /////////////////////////////////////////////////////////////////////////////////////////////////
49
+ // Computes the data needed to describe a parse failure: the deduplicated list of expected
50
+ // terminals (each retaining the production it belongs to) and the shared context production.
51
+ // The actual message formatting is owned by ParseError.
52
+ export function analyzeFailedMatches(failedMatches) {
53
+ const productionStacks = failedMatches.map(failedMatch => failedMatch.productionStack);
54
+ const commonProductionPrefix = findCommonProductionPrefix(productionStacks);
55
+ const contextProduction = commonProductionPrefix[commonProductionPrefix.length - 1];
56
+ // Collect every production each distinct terminal could be part of, together with
57
+ // the production stack that led to it. The production is the one directly below
58
+ // the shared context production.
59
+ const candidatesByTerminal = new Map();
60
+ for (const failedMatch of failedMatches) {
61
+ const subProduction = failedMatch.productionStack[commonProductionPrefix.length] ?? contextProduction;
62
+ if (subProduction === undefined) {
63
+ continue;
64
+ }
65
+ const stringifiedFailedTerminal = stringifyFailedTerminal(failedMatch);
66
+ const candidates = candidatesByTerminal.get(stringifiedFailedTerminal) ?? [];
67
+ candidates.push({ production: subProduction, productionStack: failedMatch.productionStack });
68
+ candidatesByTerminal.set(stringifiedFailedTerminal, candidates);
69
+ }
70
+ // When the same terminal can be reached through several productions and one of
71
+ // them is an ancestor of another (e.g. the same pattern is referenced both
72
+ // directly and through a parent production), keep only the innermost production.
73
+ const expected = [];
74
+ for (const [stringifiedFailedTerminal, candidates] of candidatesByTerminal) {
75
+ for (const candidate of candidates) {
76
+ if (isRedundantCandidate(candidate, candidates)) {
77
+ continue;
78
+ }
79
+ if (!expected.some(entry => entry.productionName === candidate.production.name && entry.terminalString === stringifiedFailedTerminal)) {
80
+ expected.push({ productionName: candidate.production.name, terminalString: stringifiedFailedTerminal });
81
+ }
82
+ }
83
+ }
84
+ return {
85
+ expected,
86
+ contextProduction,
87
+ };
88
+ }
89
+ // A candidate is redundant when the same terminal is also expected by a deeper
90
+ // production within the same context, i.e. when another candidate's production
91
+ // appears below this candidate's production in its own stack.
92
+ function isRedundantCandidate(candidate, candidates) {
93
+ const candidateIndex = stackIndexOf(candidate.productionStack, candidate.production);
94
+ for (const other of candidates) {
95
+ if (other === candidate) {
96
+ continue;
97
+ }
98
+ const otherIndex = stackIndexOf(candidate.productionStack, other.production);
99
+ if (otherIndex > candidateIndex) {
100
+ return true;
101
+ }
102
+ }
103
+ return false;
104
+ }
105
+ // Compares nonterminals by their canonical grammar reference, because the same
106
+ // production can be represented by multiple cloned instances during a parse.
107
+ function stackIndexOf(productionStack, production) {
108
+ const canonical = production.grammarNonterminal ?? production;
109
+ return productionStack.findIndex(nonterminal => (nonterminal.grammarNonterminal ?? nonterminal) === canonical);
110
+ }
111
+ function stringifyFailedTerminal(failedMatch) {
112
+ const { terminal, productionStack } = failedMatch;
113
+ if (terminal.name !== undefined) {
114
+ return terminal.name;
115
+ }
116
+ const innermostProduction = productionStack[productionStack.length - 1];
117
+ if (innermostProduction !== undefined && innermostProduction.content === terminal) {
118
+ return innermostProduction.name;
119
+ }
120
+ const stringifiedLengthLimit = 100;
121
+ const terminalToText = new TerminalToText(stringifiedLengthLimit);
122
+ return terminalToText.stringifyTerminal(terminal);
123
+ }
124
+ /////////////////////////////////////////////////////////////////////////////////////////////////
125
+ // Production grouping
126
+ /////////////////////////////////////////////////////////////////////////////////////////////////
127
+ // The stacks are compared by canonical nonterminal identity rather than object identity,
128
+ // because the same production can be represented by multiple distinct object instances
129
+ // during a single parse: the grammar builder creates spread copies of the canonical
130
+ // nonterminal for optional references and for references wrapped in cached(). Each clone
131
+ // keeps a reference to the original in 'grammarNonterminal'.
132
+ export function findCommonProductionPrefix(productionStacks) {
133
+ if (productionStacks.length === 0) {
134
+ return [];
135
+ }
136
+ let commonPrefix = productionStacks[0];
137
+ for (let i = 1; i < productionStacks.length; i++) {
138
+ const stack = productionStacks[i];
139
+ let commonLength = 0;
140
+ while (commonLength < commonPrefix.length &&
141
+ commonLength < stack.length &&
142
+ areSameNonterminal(commonPrefix[commonLength], stack[commonLength])) {
143
+ commonLength += 1;
144
+ }
145
+ commonPrefix = commonPrefix.slice(0, commonLength);
146
+ if (commonPrefix.length === 0) {
147
+ break;
148
+ }
149
+ }
150
+ return commonPrefix;
151
+ }
152
+ function areSameNonterminal(a, b) {
153
+ return (a.grammarNonterminal ?? a) === (b.grammarNonterminal ?? b);
154
+ }
155
+ /////////////////////////////////////////////////////////////////////////////////////////////////
156
+ // Parse error helpers
157
+ /////////////////////////////////////////////////////////////////////////////////////////////////
158
+ function buildErrorMessage(details, line, column, maxDisplayedLineLength) {
159
+ const context = formatErrorContext(details.input, details.offset, maxDisplayedLineLength);
160
+ if (details.parsedLength !== undefined) {
161
+ return `Failed parsing the input text ${context}\n\n` +
162
+ `Stopped parsing at line ${line}, column ${column} (${details.parsedLength} of ${details.input.length} characters consumed).`;
163
+ }
164
+ const expected = details.expected ?? [];
165
+ const expectedMessage = expected.length > 0
166
+ ? buildExpectedGroupsMessage(expected)
167
+ : '';
168
+ const contextMessage = details.contextProductionName !== undefined
169
+ ? `While parsing '${details.contextProductionName}', expected one of the following:\n\n${expectedMessage}`
170
+ : `Expected one of the following:\n\n${expectedMessage}`;
171
+ return `Failed parsing the input text ${context}\n\n${contextMessage}`;
172
+ }
173
+ // Formats the expected terminals grouped by production, with a blank line between
174
+ // the groups so the message stays readable.
175
+ function buildExpectedGroupsMessage(expected) {
176
+ const expectedByProduction = new Map();
177
+ for (const { productionName, terminalString } of expected) {
178
+ const stringifiedTerminals = expectedByProduction.get(productionName) ?? [];
179
+ if (!stringifiedTerminals.includes(terminalString)) {
180
+ stringifiedTerminals.push(terminalString);
181
+ }
182
+ expectedByProduction.set(productionName, stringifiedTerminals);
183
+ }
184
+ return [...expectedByProduction.entries()]
185
+ .map(([productionName, stringifiedTerminals]) => `In '${productionName}': ${stringifiedTerminals.join(', ')}`)
186
+ .join('\n\n');
187
+ }
188
+ export function formatErrorContext(input, offset, maxDisplayedLineLength) {
189
+ const { line, column } = getLineAndColumn(input, offset);
190
+ let lineStartOffset = offset;
191
+ while (lineStartOffset > 0 && input[lineStartOffset - 1] !== '\n') {
192
+ lineStartOffset -= 1;
193
+ }
194
+ let lineEndOffset = offset;
195
+ while (lineEndOffset < input.length && input[lineEndOffset] !== '\n') {
196
+ lineEndOffset += 1;
197
+ }
198
+ const lineText = input.substring(lineStartOffset, lineEndOffset).replace(/\r$/, '');
199
+ let displayedText = lineText;
200
+ let displayedCaretColumn = column;
201
+ // If the failing line is very long (e.g. minified input), show a window around the
202
+ // error position instead of the entire line.
203
+ if (lineText.length > maxDisplayedLineLength) {
204
+ const rawCaretOffset = Math.min(column - 1, lineText.length);
205
+ const radius = Math.floor(maxDisplayedLineLength / 2);
206
+ const contextStart = Math.max(0, rawCaretOffset - radius);
207
+ const contextEnd = Math.min(lineText.length, rawCaretOffset + radius);
208
+ const hasTruncatedStart = contextStart > 0;
209
+ const hasTruncatedEnd = contextEnd < lineText.length;
210
+ const truncatedLine = lineText.substring(contextStart, contextEnd);
211
+ displayedText = `${hasTruncatedStart ? '…' : ''}${truncatedLine}${hasTruncatedEnd ? '…' : ''}`;
212
+ displayedCaretColumn = (rawCaretOffset - contextStart) + (hasTruncatedStart ? 1 : 0) + 1;
213
+ }
214
+ let unexpectedTargetText;
215
+ if (offset < input.length) {
216
+ const targetChar = input[offset];
217
+ const escapedTargetChar = escapeChar(targetChar);
218
+ unexpectedTargetText = ` (unexpected character '${escapedTargetChar}')`;
219
+ }
220
+ else {
221
+ unexpectedTargetText = ' (unexpected end of input)';
222
+ }
223
+ const text = `at line ${line}, column ${column}${unexpectedTargetText}:\n\n\t${expandTabs(displayedText)}\n\t${buildCaretSpacing(displayedText, displayedCaretColumn)}^`;
224
+ return text;
225
+ }
226
+ //# sourceMappingURL=ParseError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParseError.js","sourceRoot":"","sources":["../../src/parser-generator/ParseError.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Pattern } from 'regexp-composer';
2
+ import { GrammarElement } from './Grammar.js';
3
+ export declare function detectAndAnnotateOptionalNodes(rootNode: GrammarElement): void;
4
+ export declare function detectAndErrorOnLeftRecursion(rootNode: GrammarElement): void;
5
+ export declare function validatePatternCaptureGroups(pattern: Pattern): void;
6
+ //# sourceMappingURL=StaticAnalysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StaticAnalysis.d.ts","sourceRoot":"","sources":["../../src/parser-generator/StaticAnalysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAK7C,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,cAAc,QAmMtE;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,cAAc,QA+CrE;AAWD,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6EnE"}
@@ -0,0 +1,283 @@
1
+ import { isArray, isBoolean, isString } from '../utilities/Utilities.js';
2
+ /////////////////////////////////////////////////////////////////////////////////////////////////
3
+ // Internal static analysis methods
4
+ /////////////////////////////////////////////////////////////////////////////////////////////////
5
+ export function detectAndAnnotateOptionalNodes(rootNode) {
6
+ const visitedNodes = new Set();
7
+ const resolvedNodes = new Map();
8
+ const unresolvedNodes = new Map();
9
+ function processDepthFirst(node) {
10
+ if (visitedNodes.has(node)) {
11
+ return resolvedNodes.get(node);
12
+ }
13
+ visitedNodes.add(node);
14
+ switch (node.type) {
15
+ case 'StringTerminal':
16
+ case 'PatternTerminal': {
17
+ resolvedNodes.set(node, node.optional);
18
+ return node.optional;
19
+ }
20
+ case 'Nonterminal':
21
+ case 'Repetition': {
22
+ const result = processDepthFirst(node.content);
23
+ if (node.optional) {
24
+ resolvedNodes.set(node, true);
25
+ return true;
26
+ }
27
+ else if (isBoolean(result)) {
28
+ resolvedNodes.set(node, result);
29
+ return result;
30
+ }
31
+ else {
32
+ unresolvedNodes.set(node, { dependencies: new Set([node.content]), isChoice: false });
33
+ return undefined;
34
+ }
35
+ }
36
+ case 'Sequence': {
37
+ const dependencies = new Set();
38
+ let hasNonOptionalResolvedMember = false;
39
+ for (const element of node.members) {
40
+ const result = processDepthFirst(element);
41
+ if (isBoolean(result)) {
42
+ if (result === false) {
43
+ hasNonOptionalResolvedMember = true;
44
+ }
45
+ }
46
+ else {
47
+ dependencies.add(element);
48
+ }
49
+ }
50
+ if (node.optional === true) {
51
+ resolvedNodes.set(node, true);
52
+ return true;
53
+ }
54
+ else if (hasNonOptionalResolvedMember) {
55
+ resolvedNodes.set(node, false);
56
+ return false;
57
+ }
58
+ else if (dependencies.size === 0) {
59
+ resolvedNodes.set(node, true);
60
+ return true;
61
+ }
62
+ else {
63
+ unresolvedNodes.set(node, { dependencies, isChoice: false });
64
+ return undefined;
65
+ }
66
+ }
67
+ case 'Choice': {
68
+ const dependencies = new Set();
69
+ let hasOptionalResolvedMember = false;
70
+ for (const element of node.members) {
71
+ const result = processDepthFirst(element);
72
+ if (isBoolean(result)) {
73
+ if (result === true) {
74
+ hasOptionalResolvedMember = true;
75
+ }
76
+ }
77
+ else {
78
+ dependencies.add(element);
79
+ }
80
+ }
81
+ if (node.optional === true) {
82
+ resolvedNodes.set(node, true);
83
+ return true;
84
+ }
85
+ else if (hasOptionalResolvedMember) {
86
+ resolvedNodes.set(node, true);
87
+ return true;
88
+ }
89
+ else if (dependencies.size === 0) {
90
+ resolvedNodes.set(node, false);
91
+ return false;
92
+ }
93
+ else {
94
+ unresolvedNodes.set(node, { dependencies, isChoice: true });
95
+ return undefined;
96
+ }
97
+ }
98
+ }
99
+ return undefined;
100
+ }
101
+ // Process depth first to resolve the easy cases, for productions that contain
102
+ // no cyclic references:
103
+ processDepthFirst(rootNode);
104
+ // Now the remainder consists of nodes containing cyclic references that have not yet been resolved.
105
+ // Use a form of iterative elimination and substitution to resolve them:
106
+ while (unresolvedNodes.size > 0) {
107
+ // This variable tracks whether at least one dependency was resolved, in any node.
108
+ // If it stays false, it means that no improvement was made during the iteration,
109
+ // and we should exit the loop.
110
+ let atLastOneDependencyResolvedInAnyNode = false;
111
+ const nodesToDelete = [];
112
+ // Scan the unresolved nodes to locate any new resolved dependencies
113
+ for (const [node, { dependencies, isChoice }] of unresolvedNodes) {
114
+ let nodeResolved = false;
115
+ // Iterate over all unresolved dependencies for the node
116
+ for (const dependency of Array.from(dependencies)) {
117
+ // Check if the dependency has been resolved
118
+ const value = resolvedNodes.get(dependency);
119
+ if (value !== undefined) {
120
+ // If it did, record that some dependencies were resolved
121
+ atLastOneDependencyResolvedInAnyNode = true;
122
+ if (isChoice) {
123
+ if (value === true) {
124
+ resolvedNodes.set(node, true);
125
+ nodeResolved = true;
126
+ break;
127
+ }
128
+ }
129
+ else {
130
+ if (value === false) {
131
+ resolvedNodes.set(node, false);
132
+ nodeResolved = true;
133
+ break;
134
+ }
135
+ }
136
+ dependencies.delete(dependency);
137
+ }
138
+ }
139
+ if (nodeResolved) {
140
+ nodesToDelete.push(node);
141
+ }
142
+ else if (dependencies.size === 0) {
143
+ if (isChoice) {
144
+ resolvedNodes.set(node, false);
145
+ }
146
+ else {
147
+ resolvedNodes.set(node, true);
148
+ }
149
+ nodesToDelete.push(node);
150
+ }
151
+ }
152
+ for (const node of nodesToDelete) {
153
+ unresolvedNodes.delete(node);
154
+ }
155
+ // If not even one dependency was eliminated for any node,
156
+ // it means that only mutually cyclic nodes are left unresolved, so exit the loop.
157
+ if (!atLastOneDependencyResolvedInAnyNode) {
158
+ break;
159
+ }
160
+ }
161
+ // All remaining unresolved nodes must now be optional,
162
+ // since they are all mutually cyclic and all their non-cyclic grammar elements are known to be optional.
163
+ for (const node of unresolvedNodes.keys()) {
164
+ resolvedNodes.set(node, true);
165
+ unresolvedNodes.delete(node);
166
+ }
167
+ // Finally set the 'optional' property of all nodes based on the detected values.
168
+ for (const [node, isOptional] of resolvedNodes) {
169
+ node.optional = isOptional;
170
+ }
171
+ }
172
+ export function detectAndErrorOnLeftRecursion(rootNode) {
173
+ const currentlyIteratedNodes = new Set();
174
+ function detect(node) {
175
+ if (currentlyIteratedNodes.has(node)) {
176
+ if (node.type === 'Nonterminal') {
177
+ throw new Error(`Detected left recursion for nonterminal '${node.name}'.`);
178
+ }
179
+ else {
180
+ throw new Error(`Detected left recursion for node: ${JSON.stringify(node, undefined, 4)}`);
181
+ }
182
+ }
183
+ currentlyIteratedNodes.add(node);
184
+ switch (node.type) {
185
+ case 'Nonterminal':
186
+ case 'Repetition': {
187
+ detect(node.content);
188
+ break;
189
+ }
190
+ case 'Sequence': {
191
+ for (const member of node.members) {
192
+ detect(member);
193
+ if (!member.optional) {
194
+ break;
195
+ }
196
+ }
197
+ break;
198
+ }
199
+ case 'Choice': {
200
+ for (const member of node.members) {
201
+ detect(member);
202
+ }
203
+ break;
204
+ }
205
+ }
206
+ currentlyIteratedNodes.delete(node);
207
+ }
208
+ detect(rootNode);
209
+ }
210
+ // Walks the regexp-composer Pattern AST to validate its capture groups.
211
+ //
212
+ // The JavaScript RegExp engine collapses multiple named groups that share a name
213
+ // into a single entry, and cannot reliably report the ordering of a mix of named
214
+ // and unnamed groups. Both cases are problematic for the parser, so we detect them
215
+ // here, once, at grammar build time (before the RegExp is even compiled), instead of
216
+ // during parsing.
217
+ //
218
+ // Mirrors the AST traversal performed by regexp-composer's own 'isPatternOptional'.
219
+ export function validatePatternCaptureGroups(pattern) {
220
+ const seenNamedCaptureGroupNames = new Set();
221
+ let hasNamedCaptureGroup = false;
222
+ let hasUnnamedCaptureGroup = false;
223
+ function walk(node) {
224
+ if (isString(node)) {
225
+ return;
226
+ }
227
+ if (isArray(node)) {
228
+ for (const element of node) {
229
+ walk(element);
230
+ }
231
+ return;
232
+ }
233
+ switch (node.type) {
234
+ case 'capture': {
235
+ if (node.name !== undefined) {
236
+ if (seenNamedCaptureGroupNames.has(node.name)) {
237
+ throw new Error(`The regular expression pattern contains multiple named capture groups with the same name '${node.name}'. Named capture groups must have unique names.`);
238
+ }
239
+ seenNamedCaptureGroupNames.add(node.name);
240
+ hasNamedCaptureGroup = true;
241
+ }
242
+ else {
243
+ hasUnnamedCaptureGroup = true;
244
+ }
245
+ walk(node.content);
246
+ return;
247
+ }
248
+ // Composite nodes that wrap content without creating a capturing group:
249
+ case 'possibly':
250
+ case 'zeroOrMore':
251
+ case 'oneOrMore':
252
+ case 'repeated':
253
+ case 'followedBy':
254
+ case 'notFollowedBy':
255
+ case 'precededBy':
256
+ case 'notPrecededBy': {
257
+ walk(node.content);
258
+ return;
259
+ }
260
+ case 'anyOf': {
261
+ for (const member of node.members) {
262
+ walk(member);
263
+ }
264
+ return;
265
+ }
266
+ // These nodes never introduce capturing groups and contain only
267
+ // character-level tokens or backreferences:
268
+ case 'notAnyOfChars':
269
+ case 'specialToken':
270
+ case 'sameAs': {
271
+ return;
272
+ }
273
+ default: {
274
+ throw new Error(`Unrecognized pattern type: ${node.type}`);
275
+ }
276
+ }
277
+ }
278
+ walk(pattern);
279
+ if (hasNamedCaptureGroup && hasUnnamedCaptureGroup) {
280
+ throw new Error(`The regular expression pattern contains a combination of named and unnamed capture groups. Due to limitations of the JavaScript RegExp engine, it is impossible to reliably identify the ordering of this combination, please use either all unnamed or all named capture groups, but not both.`);
281
+ }
282
+ }
283
+ //# sourceMappingURL=StaticAnalysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StaticAnalysis.js","sourceRoot":"","sources":["../../src/parser-generator/StaticAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAGxE,iGAAiG;AACjG,mCAAmC;AACnC,iGAAiG;AACjG,MAAM,UAAU,8BAA8B,CAAC,QAAwB;IACtE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAA;IAE9C,MAAM,aAAa,GAAG,IAAI,GAAG,EAA2B,CAAA;IACxD,MAAM,eAAe,GAAG,IAAI,GAAG,EAA4E,CAAA;IAE3G,SAAS,iBAAiB,CAAC,IAAoB;QAC9C,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC/B,CAAC;QAED,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEtB,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,gBAAgB,CAAC;YACtB,KAAK,iBAAiB,EAAE,CAAC;gBACxB,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;gBAEtC,OAAO,IAAI,CAAC,QAAQ,CAAA;YACrB,CAAC;YAED,KAAK,aAAa,CAAC;YACnB,KAAK,YAAY,EAAE,CAAC;gBACnB,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAE9C,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACnB,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;oBAE7B,OAAO,IAAI,CAAA;gBACZ,CAAC;qBAAM,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC9B,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;oBAE/B,OAAO,MAAM,CAAA;gBACd,CAAC;qBAAM,CAAC;oBACP,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,YAAY,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;oBAErF,OAAO,SAAS,CAAA;gBACjB,CAAC;YACF,CAAC;YAED,KAAK,UAAU,EAAE,CAAC;gBACjB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAA;gBAE9C,IAAI,4BAA4B,GAAG,KAAK,CAAA;gBAExC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACpC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;oBAEzC,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;wBACvB,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;4BACtB,4BAA4B,GAAG,IAAI,CAAA;wBACpC,CAAC;oBACF,CAAC;yBAAM,CAAC;wBACP,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;oBAC1B,CAAC;gBACF,CAAC;gBAED,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;oBAC5B,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;oBAE7B,OAAO,IAAI,CAAA;gBACZ,CAAC;qBAAM,IAAI,4BAA4B,EAAE,CAAC;oBACzC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;oBAE9B,OAAO,KAAK,CAAA;gBACb,CAAC;qBAAM,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBACpC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;oBAE7B,OAAO,IAAI,CAAA;gBACZ,CAAC;qBAAM,CAAC;oBACP,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;oBAE5D,OAAO,SAAS,CAAA;gBACjB,CAAC;YACF,CAAC;YAED,KAAK,QAAQ,EAAE,CAAC;gBACf,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAA;gBAC9C,IAAI,yBAAyB,GAAG,KAAK,CAAA;gBAErC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACpC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;oBAEzC,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;wBACvB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;4BACrB,yBAAyB,GAAG,IAAI,CAAA;wBACjC,CAAC;oBACF,CAAC;yBAAM,CAAC;wBACP,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;oBAC1B,CAAC;gBACF,CAAC;gBAED,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;oBAC5B,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;oBAE7B,OAAO,IAAI,CAAA;gBACZ,CAAC;qBAAM,IAAI,yBAAyB,EAAE,CAAC;oBACtC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;oBAE7B,OAAO,IAAI,CAAA;gBACZ,CAAC;qBAAM,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBACpC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;oBAE9B,OAAO,KAAK,CAAA;gBACb,CAAC;qBAAM,CAAC;oBACP,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;oBAE3D,OAAO,SAAS,CAAA;gBACjB,CAAC;YACF,CAAC;QACF,CAAC;QAED,OAAO,SAAS,CAAA;IACjB,CAAC;IAED,8EAA8E;IAC9E,wBAAwB;IACxB,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IAE3B,oGAAoG;IACpG,wEAAwE;IACxE,OAAO,eAAe,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACjC,kFAAkF;QAClF,iFAAiF;QACjF,+BAA+B;QAC/B,IAAI,oCAAoC,GAAG,KAAK,CAAA;QAEhD,MAAM,aAAa,GAAqB,EAAE,CAAA;QAE1C,oEAAoE;QACpE,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC;YAClE,IAAI,YAAY,GAAG,KAAK,CAAA;YAExB,wDAAwD;YACxD,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBACnD,4CAA4C;gBAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;gBAE3C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBACzB,yDAAyD;oBACzD,oCAAoC,GAAG,IAAI,CAAA;oBAE3C,IAAI,QAAQ,EAAE,CAAC;wBACd,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;4BACpB,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;4BAC7B,YAAY,GAAG,IAAI,CAAA;4BACnB,MAAK;wBACN,CAAC;oBACF,CAAC;yBAAM,CAAC;wBACP,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;4BACrB,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;4BAC9B,YAAY,GAAG,IAAI,CAAA;4BACnB,MAAK;wBACN,CAAC;oBACF,CAAC;oBAED,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;gBAChC,CAAC;YACF,CAAC;YAED,IAAI,YAAY,EAAE,CAAC;gBAClB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACzB,CAAC;iBAAM,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACpC,IAAI,QAAQ,EAAE,CAAC;oBACd,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBAC/B,CAAC;qBAAM,CAAC;oBACP,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;gBAC9B,CAAC;gBAED,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACzB,CAAC;QACF,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YAClC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;QAED,0DAA0D;QAC1D,kFAAkF;QAClF,IAAI,CAAC,oCAAoC,EAAE,CAAC;YAC3C,MAAK;QACN,CAAC;IACF,CAAC;IAED,uDAAuD;IACvD,yGAAyG;IACzG,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC7B,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC7B,CAAC;IAED,iFAAiF;IACjF,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,aAAa,EAAE,CAAC;QAChD,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAA;IAC3B,CAAC;AACF,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,QAAwB;IACrE,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAkB,CAAA;IAExD,SAAS,MAAM,CAAC,IAAoB;QACnC,IAAI,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,4CAA4C,IAAI,CAAC,IAAI,IAAI,CAAC,CAAA;YAC3E,CAAC;iBAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;YAC3F,CAAC;QACF,CAAC;QAED,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEhC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,aAAa,CAAC;YACnB,KAAK,YAAY,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAEpB,MAAK;YACN,CAAC;YAED,KAAK,UAAU,EAAE,CAAC;gBACjB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACnC,MAAM,CAAC,MAAM,CAAC,CAAA;oBAEd,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;wBACtB,MAAK;oBACN,CAAC;gBACF,CAAC;gBAED,MAAK;YACN,CAAC;YAED,KAAK,QAAQ,EAAE,CAAC;gBACf,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACnC,MAAM,CAAC,MAAM,CAAC,CAAA;gBACf,CAAC;gBAED,MAAK;YACN,CAAC;QACF,CAAC;QAED,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,CAAA;AACjB,CAAC;AAED,wEAAwE;AACxE,EAAE;AACF,iFAAiF;AACjF,iFAAiF;AACjF,mFAAmF;AACnF,qFAAqF;AACrF,kBAAkB;AAClB,EAAE;AACF,oFAAoF;AACpF,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC5D,MAAM,0BAA0B,GAAG,IAAI,GAAG,EAAU,CAAA;IACpD,IAAI,oBAAoB,GAAG,KAAK,CAAA;IAChC,IAAI,sBAAsB,GAAG,KAAK,CAAA;IAElC,SAAS,IAAI,CAAC,IAAa;QAC1B,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,OAAM;QACP,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,OAAO,CAAC,CAAA;YACd,CAAC;YAED,OAAM;QACP,CAAC;QAED,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,SAAS,EAAE,CAAC;gBAChB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC7B,IAAI,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC/C,MAAM,IAAI,KAAK,CAAC,6FAA6F,IAAI,CAAC,IAAI,iDAAiD,CAAC,CAAA;oBACzK,CAAC;oBAED,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;oBACzC,oBAAoB,GAAG,IAAI,CAAA;gBAC5B,CAAC;qBAAM,CAAC;oBACP,sBAAsB,GAAG,IAAI,CAAA;gBAC9B,CAAC;gBAED,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAElB,OAAM;YACP,CAAC;YAED,wEAAwE;YACxE,KAAK,UAAU,CAAC;YAChB,KAAK,YAAY,CAAC;YAClB,KAAK,WAAW,CAAC;YACjB,KAAK,UAAU,CAAC;YAChB,KAAK,YAAY,CAAC;YAClB,KAAK,eAAe,CAAC;YACrB,KAAK,YAAY,CAAC;YAClB,KAAK,eAAe,EAAE,CAAC;gBACtB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAElB,OAAM;YACP,CAAC;YAED,KAAK,OAAO,EAAE,CAAC;gBACd,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACnC,IAAI,CAAC,MAAM,CAAC,CAAA;gBACb,CAAC;gBAED,OAAM;YACP,CAAC;YAED,gEAAgE;YAChE,4CAA4C;YAC5C,KAAK,eAAe,CAAC;YACrB,KAAK,cAAc,CAAC;YACpB,KAAK,QAAQ,EAAE,CAAC;gBACf,OAAM;YACP,CAAC;YAED,SAAS,CAAC;gBACT,MAAM,IAAI,KAAK,CAAC,8BAA+B,IAAY,CAAC,IAAI,EAAE,CAAC,CAAA;YACpE,CAAC;QACF,CAAC;IACF,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,CAAA;IAEb,IAAI,oBAAoB,IAAI,sBAAsB,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,iSAAiS,CAAC,CAAA;IACnT,CAAC;AACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Pattern, SpecialToken } from 'regexp-composer';
2
+ import type { PatternTerminal, StringTerminal, Terminal } from './Grammar.js';
3
+ export declare class TerminalToText {
4
+ private stringifiedLengthLimit;
5
+ constructor(stringifiedLengthLimit: number);
6
+ stringifyTerminal(terminal: Terminal): string;
7
+ stringifyStringTerminal(terminal: StringTerminal): string;
8
+ stringifyPatternTerminal(terminal: PatternTerminal): string;
9
+ stringifyPattern(pattern: Pattern): string;
10
+ stringifyPatternStringLiteral(text: string): string;
11
+ stringifySpecialToken(token: SpecialToken): string;
12
+ truncateString(str: string, lengthLimit: number): string;
13
+ }
14
+ export declare function escapeChar(char: string): string;
15
+ //# sourceMappingURL=TerminalToText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerminalToText.d.ts","sourceRoot":"","sources":["../../src/parser-generator/TerminalToText.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAK7E,qBAAa,cAAc;IACd,OAAO,CAAC,sBAAsB;IAA1C,YAAoB,sBAAsB,EAAE,MAAM,EACjD;IAED,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAM5C;IAED,uBAAuB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAExD;IAED,wBAAwB,CAAC,QAAQ,EAAE,eAAe,UAmBjD;IAED,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CA+FzC;IAED,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUlD;IAED,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAgBjD;IAED,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAMvD;CACD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgB/C"}