clarity-pattern-parser 11.0.1 → 11.0.3
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/index.browser.js +108 -12
- package/dist/index.browser.js.map +1 -1
- package/dist/index.esm.js +108 -12
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +108 -12
- package/dist/index.js.map +1 -1
- package/dist/patterns/Context.d.ts +0 -1
- package/dist/patterns/RightAssociatedPattern.d.ts +31 -0
- package/package.json +1 -1
- package/src/grammar/Grammar.test.ts +11 -0
- package/src/grammar/Grammar.ts +24 -9
- package/src/grammar/patterns/optionsLiteral.ts +7 -1
- package/src/patterns/Context.ts +0 -3
- package/src/patterns/ExpressionPattern.ts +1 -1
- package/src/patterns/PrecedenceTree.ts +1 -1
- package/src/patterns/RightAssociatedPattern.ts +0 -2
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Node } from "../ast/Node";
|
|
2
|
+
import { Cursor } from "./Cursor";
|
|
3
|
+
import { ParseResult } from "./ParseResult";
|
|
4
|
+
import { Pattern } from "./Pattern";
|
|
5
|
+
export declare class RightAssociatedPattern implements Pattern {
|
|
6
|
+
private _id;
|
|
7
|
+
private _type;
|
|
8
|
+
private _name;
|
|
9
|
+
private _parent;
|
|
10
|
+
private _children;
|
|
11
|
+
get id(): string;
|
|
12
|
+
get type(): string;
|
|
13
|
+
get name(): string;
|
|
14
|
+
get parent(): Pattern | null;
|
|
15
|
+
set parent(pattern: Pattern | null);
|
|
16
|
+
get children(): Pattern[];
|
|
17
|
+
get startedOnIndex(): number;
|
|
18
|
+
constructor(pattern: Pattern);
|
|
19
|
+
parse(cursor: Cursor): Node | null;
|
|
20
|
+
exec(text: string, record?: boolean | undefined): ParseResult;
|
|
21
|
+
test(text: string, record?: boolean | undefined): boolean;
|
|
22
|
+
clone(_name?: string | undefined): Pattern;
|
|
23
|
+
getTokens(): string[];
|
|
24
|
+
getTokensAfter(_childReference: Pattern): string[];
|
|
25
|
+
getNextTokens(): string[];
|
|
26
|
+
getPatterns(): Pattern[];
|
|
27
|
+
getPatternsAfter(_childReference: Pattern): Pattern[];
|
|
28
|
+
getNextPatterns(): Pattern[];
|
|
29
|
+
find(predicate: (pattern: Pattern) => boolean): Pattern | null;
|
|
30
|
+
isEqual(pattern: Pattern): boolean;
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -584,4 +584,15 @@ describe("Grammar", () => {
|
|
|
584
584
|
expect(result).toBe(result);
|
|
585
585
|
});
|
|
586
586
|
|
|
587
|
+
test("Expression Pattern With Right Association", () => {
|
|
588
|
+
const { expression } = patterns`
|
|
589
|
+
variables = "a" | "b" | "c" | "d" | "e"
|
|
590
|
+
ternary = expression + " ? " + expression + " : " + expression
|
|
591
|
+
expression = ternary right | variables
|
|
592
|
+
`;
|
|
593
|
+
let result = expression.exec("a ? b : c ? d : e");
|
|
594
|
+
debugger;
|
|
595
|
+
expect(result).toBe(result);
|
|
596
|
+
});
|
|
597
|
+
|
|
587
598
|
});
|
package/src/grammar/Grammar.ts
CHANGED
|
@@ -11,7 +11,8 @@ import { Repeat, RepeatOptions } from "../patterns/Repeat";
|
|
|
11
11
|
import { AutoComplete } from "../intellisense/AutoComplete";
|
|
12
12
|
import { Optional } from "../patterns/Optional";
|
|
13
13
|
import { Context } from "../patterns/Context";
|
|
14
|
-
import {ExpressionPattern} from "../patterns/ExpressionPattern";
|
|
14
|
+
import { ExpressionPattern } from "../patterns/ExpressionPattern";
|
|
15
|
+
import { RightAssociatedPattern } from "../patterns/RightAssociatedPattern";
|
|
15
16
|
|
|
16
17
|
let anonymousIndexId = 0;
|
|
17
18
|
|
|
@@ -248,14 +249,22 @@ export class Grammar {
|
|
|
248
249
|
private _buildOptions(name: string, node: Node) {
|
|
249
250
|
const patternNodes = node.children.filter(n => n.name !== "default-divider" && n.name !== "greedy-divider");
|
|
250
251
|
const isGreedy = node.find(n => n.name === "greedy-divider") != null;
|
|
251
|
-
const patterns = patternNodes.map(n =>
|
|
252
|
-
|
|
252
|
+
const patterns = patternNodes.map(n => {
|
|
253
|
+
const rightAssociated = n.find(n => n.name === "right-associated");
|
|
254
|
+
if (rightAssociated != null) {
|
|
255
|
+
return new RightAssociatedPattern(this._buildPattern(n.children[0]));
|
|
256
|
+
} else {
|
|
257
|
+
return this._buildPattern(n.children[0]);
|
|
258
|
+
}
|
|
253
259
|
|
|
254
|
-
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
const hasRecursivePattern = patterns.some(p => this._isRecursive(name, p));
|
|
263
|
+
if (hasRecursivePattern && !isGreedy) {
|
|
255
264
|
try {
|
|
256
265
|
const expression = new ExpressionPattern(name, patterns);
|
|
257
266
|
return expression;
|
|
258
|
-
} catch{}
|
|
267
|
+
} catch { }
|
|
259
268
|
}
|
|
260
269
|
|
|
261
270
|
const or = new Options(name, patterns, isGreedy);
|
|
@@ -271,10 +280,16 @@ export class Grammar {
|
|
|
271
280
|
}
|
|
272
281
|
|
|
273
282
|
private _isRecursivePattern(name: string, pattern: Pattern) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
283
|
+
if (pattern.children.length === 0){
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const firstChild = pattern.children[0];
|
|
288
|
+
const lastChild = pattern.children[pattern.children.length - 1];
|
|
289
|
+
const isLongEnough = pattern.children.length >= 2;
|
|
290
|
+
return pattern.type === "sequence" && isLongEnough &&
|
|
291
|
+
(firstChild.type === "reference" && firstChild.name === name) ||
|
|
292
|
+
(lastChild.type === "reference" && lastChild.name === name);
|
|
278
293
|
}
|
|
279
294
|
|
|
280
295
|
private _buildPattern(node: Node): Pattern {
|
|
@@ -3,11 +3,17 @@ import { Regex } from "../../patterns/Regex";
|
|
|
3
3
|
import { name } from "./name";
|
|
4
4
|
import { anonymousPattern } from "./anonymousPattern";
|
|
5
5
|
import { Options } from "../../patterns/Options";
|
|
6
|
+
import { Sequence } from "../../patterns/Sequence";
|
|
7
|
+
import { Optional } from "../../patterns/Optional";
|
|
8
|
+
import { Literal } from "../../patterns/Literal";
|
|
6
9
|
|
|
7
10
|
const patternName = name.clone("pattern-name");
|
|
8
11
|
patternName.setTokens(["[PATTERN_NAME]"]);
|
|
9
12
|
|
|
10
|
-
const patterns = new
|
|
13
|
+
const patterns = new Sequence("patterns", [
|
|
14
|
+
new Options("options-patterns", [patternName, anonymousPattern]),
|
|
15
|
+
new Optional("optional-right-associated", new Literal("right-associated", " right"))
|
|
16
|
+
]);
|
|
11
17
|
const defaultDivider = new Regex("default-divider", "\\s*[|]\\s*");
|
|
12
18
|
defaultDivider.setTokens(["|"]);
|
|
13
19
|
|
package/src/patterns/Context.ts
CHANGED
|
@@ -14,8 +14,6 @@ export class Context implements Pattern {
|
|
|
14
14
|
private _pattern: Pattern;
|
|
15
15
|
private _patterns: Record<string, Pattern>;
|
|
16
16
|
|
|
17
|
-
shouldCompactAst = false;
|
|
18
|
-
|
|
19
17
|
get id(): string {
|
|
20
18
|
return this._id;
|
|
21
19
|
}
|
|
@@ -82,7 +80,6 @@ export class Context implements Pattern {
|
|
|
82
80
|
clone(name = this._name): Pattern {
|
|
83
81
|
const clone = new Context(name, this._pattern, Object.values(this._patterns));
|
|
84
82
|
clone._id = this._id;
|
|
85
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
86
83
|
return clone;
|
|
87
84
|
}
|
|
88
85
|
|
|
@@ -147,7 +147,7 @@ export class PrecedenceTree {
|
|
|
147
147
|
let node = this._atomNode;
|
|
148
148
|
|
|
149
149
|
if (this._prefixNode != null && this._atomNode != null) {
|
|
150
|
-
node = this._prefixNode;
|
|
150
|
+
node = this._prefixNode.findRoot();
|
|
151
151
|
this._prefixPlaceholder.replaceWith(this._atomNode);
|
|
152
152
|
}
|
|
153
153
|
|