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.
@@ -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(): any;
25
- get max(): any;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clarity-pattern-parser",
3
- "version": "10.0.1",
3
+ "version": "10.0.3",
4
4
  "description": "Parsing Library for Typescript and Javascript.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",
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
  });
@@ -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 = cursor.leafMatch.pattern === this.children[1];
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 (dividerNode == null && repeatNode == null) {
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
- cursor.leafMatch.pattern === this._divider
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);
@@ -53,7 +53,6 @@ describe("Not", () => {
53
53
  expect(notA.name).toBe("not-a");
54
54
  expect(notA.parent).toBeNull();
55
55
  expect(notA.children[0].name).toBe("a");
56
- expect(notA.isOptional).toBeFalsy();
57
56
  });
58
57
 
59
58
  test("Not A Not", () => {
@@ -36,10 +36,6 @@ export class Not implements Pattern {
36
36
  return this._children;
37
37
  }
38
38
 
39
- get isOptional(): boolean {
40
- return false;
41
- }
42
-
43
39
  constructor(name: string, pattern: Pattern) {
44
40
  this._id = `not-${idIndex++}`;
45
41
  this._type = "not";
@@ -53,11 +53,11 @@ export class Repeat implements Pattern {
53
53
  }
54
54
 
55
55
  get min() {
56
- return (this.children[0] as any).min;
56
+ return this._options.min;
57
57
  }
58
58
 
59
59
  get max() {
60
- return (this.children[0] as any).max || Infinity;
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]).toBe(b);
316
+ expect(nextPatterns[0].isEqual(b)).toBeTruthy();
316
317
  });
317
318
 
318
319
  test("Get Next Patterns With Null Parent", () => {
@@ -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
  }