clarity-pattern-parser 10.0.1 → 10.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/ast/Node.d.ts +1 -0
- package/dist/index.browser.js +12 -11
- package/dist/index.browser.js.map +1 -1
- package/dist/index.esm.js +12 -11
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/dist/patterns/Not.d.ts +0 -1
- package/dist/patterns/Repeat.d.ts +2 -2
- package/package.json +1 -1
- package/src/ast/Node.ts +4 -0
- package/src/grammar/Grammar.test.ts +34 -0
- package/src/grammar/Grammar.ts +1 -1
- package/src/intellisense/AutoComplete.test.ts +1 -1
- package/src/patterns/FiniteRepeat.test.ts +6 -0
- package/src/patterns/FiniteRepeat.ts +1 -1
- package/src/patterns/InfiniteRepeat.test.ts +6 -0
- package/src/patterns/InfiniteRepeat.ts +2 -2
- package/src/patterns/Not.test.ts +0 -1
- package/src/patterns/Not.ts +0 -4
- package/src/patterns/Repeat.ts +2 -2
- package/src/patterns/Sequence.test.ts +3 -2
- package/src/patterns/Sequence.ts +2 -2
package/dist/patterns/Not.d.ts
CHANGED
|
@@ -14,7 +14,6 @@ export declare class Not implements Pattern {
|
|
|
14
14
|
get parent(): Pattern | null;
|
|
15
15
|
set parent(pattern: Pattern | null);
|
|
16
16
|
get children(): Pattern[];
|
|
17
|
-
get isOptional(): boolean;
|
|
18
17
|
constructor(name: string, pattern: Pattern);
|
|
19
18
|
test(text: string): boolean;
|
|
20
19
|
exec(text: string, record?: boolean): ParseResult;
|
|
@@ -21,8 +21,8 @@ export declare class Repeat implements Pattern {
|
|
|
21
21
|
get parent(): Pattern | null;
|
|
22
22
|
set parent(value: Pattern | null);
|
|
23
23
|
get children(): Pattern[];
|
|
24
|
-
get min():
|
|
25
|
-
get max():
|
|
24
|
+
get min(): number;
|
|
25
|
+
get max(): number;
|
|
26
26
|
constructor(name: string, pattern: Pattern, options?: RepeatOptions);
|
|
27
27
|
parse(cursor: Cursor): Node | null;
|
|
28
28
|
exec(text: string): ParseResult;
|
package/package.json
CHANGED
package/src/ast/Node.ts
CHANGED
|
@@ -315,6 +315,10 @@ export class Node {
|
|
|
315
315
|
return JSON.stringify(this.toCycleFreeObject(), null, space);
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
+
isEqual(node: Node) {
|
|
319
|
+
return node.toJson(0) === this.toJson(0);
|
|
320
|
+
}
|
|
321
|
+
|
|
318
322
|
static createValueNode(name: string, value: string) {
|
|
319
323
|
return new Node("custom-value-node", name, 0, 0, [], value);
|
|
320
324
|
}
|
|
@@ -511,4 +511,38 @@ describe("Grammar", () => {
|
|
|
511
511
|
expect(patterns.john).not.toBeNull();
|
|
512
512
|
expect(patterns.jane).not.toBeNull();
|
|
513
513
|
});
|
|
514
|
+
|
|
515
|
+
test("Grammar Import", async () => {
|
|
516
|
+
const importExpression = `first-name = "John"`;
|
|
517
|
+
const spaceExpression = `
|
|
518
|
+
use params { custom-space }
|
|
519
|
+
space = custom-space
|
|
520
|
+
`;
|
|
521
|
+
const expression = `
|
|
522
|
+
use params {
|
|
523
|
+
custom-space
|
|
524
|
+
}
|
|
525
|
+
import { first-name } from "first-name.cpat"
|
|
526
|
+
import { space } from "space.cpat" with params {
|
|
527
|
+
custom-space = custom-space
|
|
528
|
+
}
|
|
529
|
+
last-name = "Doe"
|
|
530
|
+
full-name = first-name + space + last-name
|
|
531
|
+
`;
|
|
532
|
+
|
|
533
|
+
const pathMap: Record<string, string> = {
|
|
534
|
+
"space.cpat": spaceExpression,
|
|
535
|
+
"first-name.cpat": importExpression,
|
|
536
|
+
"root.cpat": expression
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
function resolveImport(resource: string) {
|
|
540
|
+
return Promise.resolve({ expression: pathMap[resource], resource });
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
const patterns = await Grammar.import("root.cpat", { resolveImport, params: [new Literal("custom-space", " ")] });
|
|
544
|
+
const fullname = patterns["full-name"] as Pattern;
|
|
545
|
+
const result = fullname.exec("John Doe");
|
|
546
|
+
expect(result?.ast?.value).toBe("John Doe");
|
|
547
|
+
});
|
|
514
548
|
});
|
package/src/grammar/Grammar.ts
CHANGED
|
@@ -462,7 +462,7 @@ export class Grammar {
|
|
|
462
462
|
);
|
|
463
463
|
|
|
464
464
|
const grammar = new Grammar({
|
|
465
|
-
params: importedValues,
|
|
465
|
+
params: [...importedValues, ...this._parseContext.paramsByName.values()],
|
|
466
466
|
originResource: this._originResource,
|
|
467
467
|
resolveImport: this._resolveImport
|
|
468
468
|
});
|
|
@@ -118,7 +118,7 @@ describe("AutoComplete", () => {
|
|
|
118
118
|
|
|
119
119
|
expect(result.ast).toBeNull();
|
|
120
120
|
expect(result.options).toEqual(expectedOptions);
|
|
121
|
-
expect(result.errorAtIndex).toBe(text.length)
|
|
121
|
+
expect(result.errorAtIndex).toBe(text.length);
|
|
122
122
|
expect(result.isComplete).toBeFalsy();
|
|
123
123
|
expect(result.cursor).not.toBeNull();
|
|
124
124
|
});
|
|
@@ -478,4 +478,10 @@ describe("BoundedRepeat", () => {
|
|
|
478
478
|
expect(comma).toBe(numbers.children[1]);
|
|
479
479
|
});
|
|
480
480
|
|
|
481
|
+
test("Trim Trailing Complex Delimiter Pattern", () => {
|
|
482
|
+
const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), { divider: new Sequence("comma", [new Literal(",", ","), new Literal("space", " ")]), trimDivider: true, max: 3 });
|
|
483
|
+
const result = numbers.parse(new Cursor("1, 2,"));
|
|
484
|
+
expect(result?.value).toBe("1, 2");
|
|
485
|
+
});
|
|
486
|
+
|
|
481
487
|
});
|
|
@@ -117,7 +117,7 @@ export class FiniteRepeat implements Pattern {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
if (this._trimDivider && this._hasDivider) {
|
|
120
|
-
const isDividerLastMatch =
|
|
120
|
+
const isDividerLastMatch = this.children.length > 1 && nodes[nodes.length - 1].name === this.children[1].name;
|
|
121
121
|
if (isDividerLastMatch) {
|
|
122
122
|
const node = nodes.pop() as Node;
|
|
123
123
|
cursor.moveTo(node.firstIndex);
|
|
@@ -264,5 +264,11 @@ describe("InfiniteRepeat", () => {
|
|
|
264
264
|
expect(result.cursor.hasError).toBeTruthy();
|
|
265
265
|
});
|
|
266
266
|
|
|
267
|
+
test("Trim Trailing Complex Delimiter Pattern", () => {
|
|
268
|
+
const numbers = new InfiniteRepeat("numbers", new Regex("number", "\\d"), { divider: new Sequence("comma", [new Literal(",", ","), new Literal("space", " ")]), trimDivider: true });
|
|
269
|
+
const result = numbers.parse(new Cursor("1, 2,"));
|
|
270
|
+
expect(result?.value).toBe("1, 2");
|
|
271
|
+
});
|
|
272
|
+
|
|
267
273
|
|
|
268
274
|
});
|
|
@@ -196,7 +196,7 @@ export class InfiniteRepeat implements Pattern {
|
|
|
196
196
|
if (dividerNode == null) {
|
|
197
197
|
cursor.moveTo(dividerStartIndex);
|
|
198
198
|
|
|
199
|
-
if (
|
|
199
|
+
if (repeatNode == null) {
|
|
200
200
|
// If neither the repeat pattern or divider pattern matched get out.
|
|
201
201
|
passed = true;
|
|
202
202
|
break;
|
|
@@ -235,7 +235,7 @@ export class InfiniteRepeat implements Pattern {
|
|
|
235
235
|
if (
|
|
236
236
|
hasDivider &&
|
|
237
237
|
this._trimDivider &&
|
|
238
|
-
|
|
238
|
+
this._nodes[this._nodes.length - 1].name === this._divider?.name
|
|
239
239
|
) {
|
|
240
240
|
const dividerNode = this._nodes.pop() as Node;
|
|
241
241
|
cursor.moveTo(dividerNode.firstIndex);
|
package/src/patterns/Not.test.ts
CHANGED
package/src/patterns/Not.ts
CHANGED
package/src/patterns/Repeat.ts
CHANGED
|
@@ -53,11 +53,11 @@ export class Repeat implements Pattern {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
get min() {
|
|
56
|
-
return
|
|
56
|
+
return this._options.min;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
get max() {
|
|
60
|
-
return
|
|
60
|
+
return this._options.max;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
constructor(name: string, pattern: Pattern, options: RepeatOptions = {}) {
|
|
@@ -3,6 +3,7 @@ import { Sequence } from "./Sequence";
|
|
|
3
3
|
import { Literal } from "./Literal";
|
|
4
4
|
import { Node } from "../ast/Node";
|
|
5
5
|
import { Optional } from "./Optional";
|
|
6
|
+
import { Pattern } from "./Pattern";
|
|
6
7
|
|
|
7
8
|
describe("Sequence", () => {
|
|
8
9
|
test("No Patterns", () => {
|
|
@@ -310,9 +311,9 @@ describe("Sequence", () => {
|
|
|
310
311
|
|
|
311
312
|
const sequenceClone = parent.find(p => p.name === "sequence");
|
|
312
313
|
const nextPatterns = sequenceClone?.getNextPatterns() || [];
|
|
313
|
-
const b = parent.find(p => p.name === "b")
|
|
314
|
+
const b = parent.find(p => p.name === "b") as Pattern;
|
|
314
315
|
|
|
315
|
-
expect(nextPatterns[0]
|
|
316
|
+
expect(nextPatterns[0].isEqual(b)).toBeTruthy();
|
|
316
317
|
});
|
|
317
318
|
|
|
318
319
|
test("Get Next Patterns With Null Parent", () => {
|
package/src/patterns/Sequence.ts
CHANGED
|
@@ -212,7 +212,7 @@ export class Sequence implements Pattern {
|
|
|
212
212
|
for (const child of this._children) {
|
|
213
213
|
tokens.push(...child.getTokens());
|
|
214
214
|
|
|
215
|
-
if (child.type !== "optional") {
|
|
215
|
+
if (child.type !== "optional" && child.type !== "not") {
|
|
216
216
|
break;
|
|
217
217
|
}
|
|
218
218
|
}
|
|
@@ -243,7 +243,7 @@ export class Sequence implements Pattern {
|
|
|
243
243
|
for (const child of this._children) {
|
|
244
244
|
patterns.push(...child.getPatterns());
|
|
245
245
|
|
|
246
|
-
if (child.type !== "optional") {
|
|
246
|
+
if (child.type !== "optional" && child.type !== "not") {
|
|
247
247
|
break;
|
|
248
248
|
}
|
|
249
249
|
}
|