clarity-pattern-parser 11.3.9 → 11.3.11

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.
@@ -13,6 +13,12 @@ export interface AutoCompleteOptions {
13
13
  * and the string array are the tokens suggested for that pattern.
14
14
  */
15
15
  customTokens?: Record<string, string[]>;
16
+ /**
17
+ * Suggestions may share the same text but differ in their suggestionSequence.
18
+ * By default, duplicates are removed and only the first instance is kept.
19
+ * Disabling deduplication allows all distinct instances to be returned together.
20
+ */
21
+ disableDedupe?: boolean;
16
22
  }
17
23
  export declare class AutoComplete {
18
24
  private _pattern;
@@ -20,17 +26,29 @@ export declare class AutoComplete {
20
26
  private _cursor;
21
27
  private _text;
22
28
  constructor(pattern: Pattern, options?: AutoCompleteOptions);
29
+ suggestFor(text: string): Suggestion;
23
30
  suggestForWithCursor(cursor: Cursor): Suggestion;
24
31
  private getFurthestPosition;
25
- suggestFor(text: string): Suggestion;
26
- private _getAllOptions;
27
- private _getOptionsFromErrors;
28
- private _createSuggestionsFromRoot;
29
- private _createSuggestionsFromMatch;
30
- private _getTokensForPattern;
31
- private _getAugmentedTokens;
32
+ private _getAllSuggestionsOptions;
33
+ private _createSuggestionOptionsFromErrors;
34
+ private _createSuggestionOptionsFromMatch;
35
+ /**
36
+ * Compares suggestions with provided text and removes completed sub-sequences and preceding text
37
+ * - IE. **currentText:** *abc*, **sequence:** *[{ab}{cd}{ef}*
38
+ * - refines to {d}{ef}
39
+ */
40
+ private _trimSuggestionsByExistingText;
41
+ /** Removed segments already accounted for in the existing text.
42
+ * ie. sequence pattern segments ≈ [{look}, {an example}, {phrase}]
43
+ * fullText = "look an"
44
+ * remove {look} segment as its already been completed by the existing text.
45
+ */
46
+ private _filterCompletedSubSegments;
47
+ private _getCompositeSuggestionsForPattern;
48
+ private _getCustomTokens;
49
+ private _deDupeCompositeSuggestions;
32
50
  private _createSuggestions;
33
- private _createSuggestion;
51
+ private _createSuggestionOption;
34
52
  static suggestFor(text: string, pattern: Pattern, options?: AutoCompleteOptions): Suggestion;
35
53
  static suggestForWithCursor(cursor: Cursor, pattern: Pattern, options?: AutoCompleteOptions): Suggestion;
36
54
  }
@@ -1,4 +1,20 @@
1
- export interface SuggestionOption {
2
- text: string;
1
+ import { Pattern } from "../patterns/Pattern";
2
+ /**
3
+ * A CompositeSuggestion associated with a index to start at when inserting into existing text.
4
+ */
5
+ export interface SuggestionOption extends CompositeSuggestion {
3
6
  startIndex: number;
4
7
  }
8
+ /**
9
+ * Represents a composed suggestion, derived from potential next tokens defined by the pattern, and configured auto complete options
10
+ * text: represents the full composed text of the suggestion; a concatenated string of relevant suggestion segments.
11
+ */
12
+ export interface CompositeSuggestion {
13
+ text: string;
14
+ suggestionSequence: SuggestionSegment[];
15
+ }
16
+ /** A segment of a parent composite suggestion and a reference to the pattern that this segment token was derived from. */
17
+ export interface SuggestionSegment {
18
+ text: string;
19
+ pattern: Pattern;
20
+ }
@@ -19,6 +19,7 @@ export declare class InfiniteRepeat implements Pattern {
19
19
  private _firstIndex;
20
20
  private _min;
21
21
  private _trimDivider;
22
+ private _patterns;
22
23
  get id(): string;
23
24
  get type(): string;
24
25
  get name(): string;
package/jest.config.js CHANGED
@@ -1,4 +1,6 @@
1
1
  module.exports = {
2
+ "preset": 'ts-jest',
3
+ "testEnvironment": 'node',
2
4
  "roots": [
3
5
  "<rootDir>/src"
4
6
  ],
@@ -1,4 +1,6 @@
1
1
  module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
2
4
  "roots": [
3
5
  "<rootDir>/src"
4
6
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clarity-pattern-parser",
3
- "version": "11.3.9",
3
+ "version": "11.3.11",
4
4
  "description": "Parsing Library for Typescript and Javascript.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",
@@ -33,12 +33,13 @@
33
33
  "parser-generator"
34
34
  ],
35
35
  "devDependencies": {
36
+ "@rollup/plugin-typescript": "^11.1.6",
36
37
  "@types/jest": "^26.0.23",
37
- "jest": "^26.6.3",
38
+ "jest": "^30.1.3",
38
39
  "rollup": "^2.41.2",
39
- "@rollup/plugin-typescript": "^11.1.6",
40
- "ts-jest": "^26.5.3",
40
+ "ts-jest": "^29.4.4",
41
41
  "tslib": "^2.1.0",
42
42
  "typescript": "^4.2.3"
43
- }
44
- }
43
+ },
44
+ "packageManager": "yarn@4.9.0+sha512.5f5f00843eae735dfab6f0442524603e987ceca55e98b36eb0120f4e58908e5b1406545321e46627dca97d15d562f23dc13fb96cabd4e6bc92d379f619001e4e"
45
+ }
@@ -0,0 +1,88 @@
1
+ import { Context } from "../patterns/Context";
2
+ import { Expression } from "../patterns/Expression";
3
+ import { Literal } from "../patterns/Literal";
4
+ import { Reference } from "../patterns/Reference";
5
+ import { Repeat } from "../patterns/Repeat";
6
+ import { Sequence } from "../patterns/Sequence";
7
+ import { Options } from "../patterns/Options";
8
+ import { Optional } from "../patterns/Optional";
9
+ import { TakeUntil } from "../patterns/TakeUntil";
10
+
11
+ new Context("expression",
12
+ new Expression("expression", [
13
+ new Sequence("prefix-expression", [
14
+ new Literal("pre", "pre"),
15
+ new Reference("expression")
16
+ ]),
17
+ new Sequence("postfix-expression", [
18
+ new Reference("expression"),
19
+ new Literal("post", "post")
20
+ ]),
21
+ new Sequence("infix-expression", [
22
+ new Reference("expression"),
23
+ new Literal(" and ", " and "),
24
+ new Reference("expression")
25
+ ]),
26
+ new Expression("item", [
27
+ new Options("names", [
28
+ new Literal("john", "John"),
29
+ new Literal("Jane", "Jane")
30
+ ]),
31
+ new Reference("array")
32
+ ])
33
+ ]), [
34
+ new Literal("john", "John"),
35
+ new Options("names", [
36
+ new Literal("john", "John"),
37
+ new Literal("Jane", "Jane")
38
+ ]),
39
+ new Literal("space", "\\s+"),
40
+ new Literal("comma", "\\s*,\\s*"),
41
+ new Expression("item", [
42
+ new Options("names", [
43
+ new Literal("john", "John"),
44
+ new Literal("Jane", "Jane")
45
+ ]),
46
+ new Reference("array")
47
+ ]),
48
+ new Repeat("items",
49
+ new Expression("item", [
50
+ new Options("names", [
51
+ new Literal("john", "John"),
52
+ new Literal("Jane", "Jane")
53
+ ]),
54
+ new Reference("array")
55
+ ]), { min: 1, divider: new Literal("comma", "\\s*,\\s*") }),
56
+ new Sequence("array", [
57
+ new Literal("[", "["),
58
+ new Optional("optional-space",
59
+ new Literal("space", "\\s+")),
60
+ new Optional("optional-items",
61
+ new Repeat("items",
62
+ new Expression("item", [
63
+ new Options("names", [
64
+ new Literal("john", "John"),
65
+ new Literal("Jane", "Jane")
66
+ ]),
67
+ new Reference("array")
68
+ ]), { min: 1, divider: new Literal("comma", "\\s*,\\s*") })),
69
+ new Optional("optional-space",
70
+ new Literal("space", "\\s+")),
71
+ new Literal("]", "]")
72
+ ]),
73
+ new Sequence("prefix-expression", [
74
+ new Literal("pre", "pre"),
75
+ new Reference("expression")
76
+ ]),
77
+ new Sequence("postfix-expression", [
78
+ new Reference("expression"),
79
+ new Literal("post", "post")
80
+ ]),
81
+ new Sequence("infix-expression", [
82
+ new Reference("expression"),
83
+ new Literal(" and ", " and "),
84
+ new Reference("expression")
85
+ ]),
86
+ new TakeUntil("take-until",
87
+ new Literal("</script", "</script"))
88
+ ])
@@ -16,6 +16,7 @@ describe("generator", () => {
16
16
  postfix-expression = expression + "post"
17
17
  infix-expression = expression + " and " + expression
18
18
  expression = prefix-expression | postfix-expression | infix-expression | item
19
+ take-until = ? -> | "</script"
19
20
  `;
20
21
 
21
22
  const visitor = new TypescriptVisitor();
@@ -70,6 +70,9 @@ export class Generator {
70
70
  case "sequence": {
71
71
  return this._visitor.sequence(pattern, args, this._depth);
72
72
  }
73
+ case "take-until": {
74
+ return this._visitor.takeUntil(pattern, args, this._depth);
75
+ }
73
76
  }
74
77
  throw Error("Cannot find pattern.");
75
78
  });
@@ -20,4 +20,5 @@ export interface IVisitor {
20
20
  finiteRepeat(pattern: Pattern, depth: number): string
21
21
  rightAssociated(pattern: Pattern, args: string[], depth: number): string;
22
22
  sequence(pattern: Pattern, args: string[], depth: number): string;
23
+ takeUntil(pattern: Pattern, args: string[], depth: number): string;
23
24
  }
@@ -7,6 +7,20 @@ import { Repeat } from "../patterns/Repeat";
7
7
  import { IGenerator } from "./igenerator";
8
8
  import { IVisitor } from "./ivisitor";
9
9
 
10
+ const importMap: any = {
11
+ "literal": "Literal",
12
+ "optional": "Optional",
13
+ "options": "Options",
14
+ "reference": "Reference",
15
+ "regex": "Regex",
16
+ "repeat": "Repeat",
17
+ "right-associated": "RightAssociation",
18
+ "sequence": "Sequence",
19
+ "take-until": "TakeUntil",
20
+ "context": "Context",
21
+ "expression": "Expression"
22
+ };
23
+
10
24
  export class TypescriptVisitor implements IVisitor {
11
25
  private _generator: IGenerator | null = null;
12
26
 
@@ -24,9 +38,11 @@ export class TypescriptVisitor implements IVisitor {
24
38
 
25
39
  end() { }
26
40
 
27
- header(): string {
28
- return "";
41
+ header( patterns: string[]): string {
42
+ console.log(patterns);
43
+ return `import { ${patterns.map(p => importMap[p]).join(", ")} } from "../index.ts";`;
29
44
  }
45
+
30
46
  footer(): string {
31
47
  return "";
32
48
  }
@@ -97,7 +113,6 @@ export class TypescriptVisitor implements IVisitor {
97
113
  const name = pattern.name;
98
114
  const regex = pattern as Regex;
99
115
  return `new Literal("${name}", "${this._escapeString(regex.regex)}")`;
100
-
101
116
  }
102
117
 
103
118
  infiniteRepeat(pattern: Pattern, depth: number): string {
@@ -143,6 +158,12 @@ export class TypescriptVisitor implements IVisitor {
143
158
  return `new Sequence("${name}", [${args.join(", ")}${this._generateTabs(depth)}])`;
144
159
  }
145
160
 
161
+ takeUntil(pattern: Pattern, args: string[], depth: number): string {
162
+ args = this._indent(args, depth + 1);
163
+ const name = pattern.name;
164
+ return `new TakeUntil("${name}", ${args.join("")})`;
165
+ }
166
+
146
167
  private _escapeString(value: string) {
147
168
  return value.replaceAll('"', '\\"');
148
169
  }
@@ -363,6 +363,7 @@ describe("Grammar", () => {
363
363
  space = " "
364
364
  full-name = first-name + space + last-name
365
365
  `;
366
+
366
367
  function resolveImport(resource: string) {
367
368
  expect(resource).toBe("some/path/to/file.cpat");
368
369
  return Promise.resolve({ expression: importExpression, resource });
@@ -289,6 +289,8 @@ export class Grammar {
289
289
  }
290
290
 
291
291
  private _isRecursivePattern(name: string, pattern: Pattern) {
292
+ // Because we don't know if the pattern is a sequence with a reference we have to just assume it is.
293
+ // The better solution here would be to not have options at all and just use expresssion pattern instead.
292
294
  if (pattern.type === "reference") {
293
295
  return true;
294
296
  }
@@ -35,4 +35,40 @@ describe("Patterns String Template Literal", () => {
35
35
  result && result.ast && result.ast.findAll(n => n.name.includes("space")).forEach(n => n.remove());
36
36
  expect(result?.ast?.value).toBe("<div><div></div><div></div></div>");
37
37
  });
38
+
39
+ test("Expression Pattern", () => {
40
+ const { expr } = patterns`
41
+ integer = /\\d+/
42
+ operator = "+" | "-" | "*" | "/"
43
+ unary-operator = "+" | "-"
44
+ postfix-operator = "++" | "--"
45
+ binary-expr = expr + operator + expr
46
+ unary-expr = unary-operator + expr
47
+ postfix-expr = expr + postfix-operator
48
+ expr = postfix-expr | unary-expr | binary-expr | integer
49
+ `;
50
+
51
+ const result = expr.exec("-10++");
52
+ const ast = result?.ast;
53
+
54
+ expect(ast?.name).toBe("unary-expr");
55
+
56
+ expect(ast?.children[0].type).toBe("literal");
57
+ expect(ast?.children[0].name).toBe("-");
58
+ expect(ast?.children[0].value).toBe("-");
59
+
60
+ expect(ast?.children[1].type).toBe("expression");
61
+ expect(ast?.children[1].name).toBe("postfix-expr");
62
+ expect(ast?.children[1].value).toBe("10++");
63
+
64
+ expect(ast?.children[1].children[0].type).toBe("regex");
65
+ expect(ast?.children[1].children[0].name).toBe("integer");
66
+ expect(ast?.children[1].children[0].value).toBe("10");
67
+
68
+ expect(ast?.children[1].children[1].type).toBe("literal");
69
+ expect(ast?.children[1].children[1].name).toBe("++");
70
+ expect(ast?.children[1].children[1].value).toBe("++");
71
+
72
+ expect(result?.ast?.value).toBe("-10++");
73
+ });
38
74
  });