clarity-pattern-parser 11.5.3 → 11.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 (40) hide show
  1. package/architecture.md +300 -0
  2. package/dist/grammar/Grammar.d.ts +24 -25
  3. package/dist/grammar/patterns/grammar.d.ts +99 -0
  4. package/dist/grammar/patterns/grammar.test.d.ts +1 -0
  5. package/dist/index.browser.js +2270 -2536
  6. package/dist/index.browser.js.map +1 -1
  7. package/dist/index.esm.js +2270 -2536
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +2270 -2536
  10. package/dist/index.js.map +1 -1
  11. package/dist/patterns/Expression.d.ts +3 -2
  12. package/grammar-guide.md +836 -0
  13. package/package.json +1 -1
  14. package/src/grammar/Grammar.test.ts +418 -0
  15. package/src/grammar/Grammar.ts +483 -515
  16. package/src/grammar/patterns/grammar.test.ts +276 -0
  17. package/src/grammar/patterns/grammar.ts +113 -37
  18. package/src/grammar/patterns.ts +6 -6
  19. package/src/patterns/Expression.ts +28 -13
  20. package/src/grammar/patterns/anonymousPattern.ts +0 -23
  21. package/src/grammar/patterns/body.ts +0 -22
  22. package/src/grammar/patterns/comment.ts +0 -4
  23. package/src/grammar/patterns/decoratorStatement.ts +0 -85
  24. package/src/grammar/patterns/import.ts +0 -88
  25. package/src/grammar/patterns/literal.ts +0 -4
  26. package/src/grammar/patterns/literals.ts +0 -21
  27. package/src/grammar/patterns/name.ts +0 -3
  28. package/src/grammar/patterns/optionsLiteral.ts +0 -25
  29. package/src/grammar/patterns/pattern.ts +0 -29
  30. package/src/grammar/patterns/regexLiteral.ts +0 -5
  31. package/src/grammar/patterns/repeatLiteral.ts +0 -71
  32. package/src/grammar/patterns/sequenceLiteral.ts +0 -24
  33. package/src/grammar/patterns/spaces.ts +0 -16
  34. package/src/grammar/patterns/statement.ts +0 -22
  35. package/src/grammar/patterns/takeUtilLiteral.ts +0 -20
  36. package/src/grammar/spec.md +0 -331
  37. package/src/grammar_v2/patterns/Grammar.ts +0 -170
  38. package/src/grammar_v2/patterns/patterns/cpat.cpat +0 -91
  39. package/src/grammar_v2/patterns/patterns/grammar.test.ts +0 -218
  40. package/src/grammar_v2/patterns/patterns/grammar.ts +0 -103
@@ -1,331 +0,0 @@
1
- # Grammar Documentation
2
-
3
- This guide describes the syntax rules and composition patterns supported by cpat. Each section shows how to define reusable parsing rules.
4
-
5
- ---
6
-
7
- ## Literals
8
-
9
- A **literal** matches an exact string.
10
-
11
- ```grammar
12
- name = "Literal"
13
- ```
14
-
15
- ---
16
-
17
- ## Regex
18
-
19
- A **regex** pattern matches text using a regular expression.
20
-
21
- ```grammar
22
- digits = /\d+/
23
- ```
24
-
25
- ### Regex Caveats
26
- Do **not** use `^` at the start or `$` at the end of your regex. If you want to constrain the beginning or end of the input, use a dedicated pattern instead.
27
-
28
- ---
29
-
30
- ## Sequence
31
-
32
- A **sequence** succeeds only if all patterns match in the given order.
33
-
34
- ```grammar
35
- space = " "
36
- first-name = "John"
37
- last-name = "Doe"
38
- full-name = first-name + space + last-name
39
- ```
40
-
41
- ---
42
-
43
- ## Optional Pattern
44
-
45
- Patterns in a sequence may be marked **optional**.
46
-
47
- ```grammar
48
- space = " "
49
- first-name = /\w+/
50
- last-name = /\w+/
51
- middle-name = /\w+/
52
- middle-name-with-space = middle-name + space
53
-
54
- full-name = first-name + space + middle-name-with-space? + last-name
55
- ```
56
-
57
- ---
58
-
59
- ## Negative Lookahead
60
-
61
- Use `!` to prevent a specific pattern from matching.
62
-
63
- ```grammar
64
- space = " "
65
- first-name = /\w+/
66
- last-name = /\w+/
67
- jack = "Jack"
68
-
69
- full-name = !jack + first-name + space + last-name
70
- ```
71
-
72
- This ensures the first name is not `"Jack"`.
73
-
74
- ---
75
-
76
- ## Options
77
-
78
- An **options** pattern succeeds if *any one* of the choices matches.
79
-
80
- ```grammar
81
- multiply = "*"
82
- divide = "/"
83
- operators = multiply | divide
84
- ```
85
-
86
- ---
87
-
88
- ## Repeat
89
-
90
- ### Zero or More
91
-
92
- ```grammar
93
- digit = /\d/
94
- digits = (digit)*
95
- ```
96
-
97
- ### Zero or More with Delimiters
98
-
99
- ```grammar
100
- digit = /\d/
101
- comma = ","
102
- digits = (digit, comma)*
103
- ```
104
-
105
- ### One or More with Trimmed Trailing Delimiter
106
-
107
- ```grammar
108
- digit = /\d/
109
- comma = ","
110
- digits = (digit, comma trim)+
111
- ```
112
-
113
- This prevents trailing commas from being accepted.
114
-
115
- ---
116
-
117
- ### One or More
118
-
119
- ```grammar
120
- digit = /\d/
121
- digits = (digit)+
122
- ```
123
-
124
- ### Exact Count
125
-
126
- ```grammar
127
- digit = /\d/
128
- digits = (digit){2}
129
- ```
130
-
131
- ### Bounded Repeats
132
-
133
- ```grammar
134
- digit = /\d/
135
- digits = (digit){1,3} # between 1 and 3
136
- digits = (digit){,3} # up to 3
137
- ```
138
-
139
- ---
140
-
141
- ## Expressions
142
-
143
- Expressions support **prefix**, **infix**, **postfix**, and **right-associative** notation, with operator precedence and recursion.
144
-
145
- - **Prefix**: Operator(s) come before the expression. The sequence must end with the name of the expression being made.
146
- - **Infix**: Operator(s) come between expressions.
147
- - **Postfix**: Operator(s) come after the expression.
148
- - **Right-associative**: Operator(s) group toward the right.
149
-
150
- ### Prefix Expression
151
-
152
- ```grammar
153
- increment = "++"
154
- integer = /[1-9][0-9]*/
155
- space = /\s+/
156
-
157
- prefix-expr = increment + space? + expr
158
- expr = prefix-expr | integer
159
- ```
160
-
161
- Examples:
162
- - `++5`
163
- - `++ 10`
164
-
165
- ---
166
-
167
- ### Infix Expression
168
-
169
- ```grammar
170
- add-sub = "+" | "-"
171
- mul-div = "*" | "/"
172
- integer = /[1-9][0-9]*/
173
- space = /\s+/
174
-
175
- add-sub-expr = expr + space? + add-sub + space? + expr
176
- mul-div-expr = expr + space? + mul-div + space? + expr
177
-
178
- expr = mul-div-expr | add-sub-expr | integer
179
- ```
180
-
181
- Examples:
182
- - `4 * 2`
183
- - `7 + 3`
184
-
185
- ---
186
-
187
- ### Postfix Expression
188
-
189
- ```grammar
190
- factorial = "!"
191
- integer = /[1-9][0-9]?/
192
- space = /\s+/
193
-
194
- postfix-expr = expr + space? + factorial
195
- expr = postfix-expr | integer
196
- ```
197
-
198
- Examples:
199
- - `5!`
200
- - `10 !`
201
-
202
- ---
203
-
204
- ### Combined Expressions
205
-
206
- By layering them into a single `expr` rule, you can combine prefix, infix, and postfix with precedence:
207
-
208
- ```grammar
209
- increment = "++"
210
- factorial = "!"
211
- add-sub = "+" | "-"
212
- mul-div = "*" | "/"
213
-
214
- integer = /[1-9][0-9]*/
215
- space = /\s+/
216
-
217
- prefix-expr = increment + space? + expr
218
- postfix-expr = expr + space? + factorial
219
- mul-div-expr = expr + space? + mul-div + space? + expr
220
- add-sub-expr = expr + space? + add-sub + space? + expr
221
-
222
- expr = postfix-expr
223
- | prefix-expr
224
- | mul-div-expr
225
- | add-sub-expr
226
- | integer
227
- ```
228
-
229
- Examples:
230
- - `++5`
231
- - `5!`
232
- - `++5!`
233
- - `2 + 3 * 4`
234
-
235
- ---
236
-
237
- ### Recursive Expressions
238
-
239
- Since each rule references `expr`, the grammar is recursive and can handle deeply nested inputs.
240
-
241
- Examples:
242
- - `7++` → `postfix-expr`
243
- - `7++ * 9` → `mul-div-expr`
244
- - `7++ * 9 + 10` → `(7++) * 9 + 10` with correct precedence
245
-
246
- ---
247
-
248
- ### Right-Associative Expressions
249
-
250
- Some operators must associate to the **right**. Mark the operator with `right` to enforce this.
251
-
252
- ```grammar
253
- power = "^"
254
- integer = /[1-9][0-9]*/
255
- space = /\s+/
256
-
257
- power-expr = expr + space? + power + space? + expr
258
- expr = power-expr right | integer
259
- ```
260
-
261
- Examples:
262
- - `2 ^ 3 ^ 2`
263
- - Right-associative → `2 ^ (3 ^ 2)` = `512`
264
- - Left-associative → `(2 ^ 3) ^ 2` = `64`
265
-
266
- ---
267
-
268
-
269
- ## Imports
270
-
271
- ### Basic Import
272
-
273
- ```grammar
274
- import { spaces } from "https://some.cdn.com/some/spaces.cpat"
275
-
276
- first-name = "John"
277
- last-name = "Doe"
278
- full-name = first-name + spaces + last-name
279
- ```
280
-
281
- ### Multiple Named Imports
282
-
283
- ```grammar
284
- import { spaces, first-name } from "https://some.cdn.com/some/spaces.cpat"
285
-
286
- last-name = "Doe"
287
- full-name = first-name + spaces + last-name
288
- ```
289
-
290
- ### Multiple Imports
291
-
292
- ```grammar
293
- import { spaces, first-name } from "https://some.cdn.com/some/patterns.cpat"
294
- import { last-name } from "https://some.cdn.com/some/last-name.cpat"
295
-
296
- full-name = first-name + spaces + last-name
297
- ```
298
-
299
- ---
300
-
301
- ## Import Parameters
302
-
303
- You can inject parameters into imported patterns.
304
-
305
- **File:** `main.ts`
306
- ```ts
307
- const firstName = new Literal("first-name", "John");
308
- const lastName = new Literal("last-name", "Doe");
309
- const grammar = Grammar.import('file.cpat', { params: [firstName, LastName] });
310
- ```
311
-
312
- **File:** `file.cpat`
313
- ```grammar
314
- use params { first-name, last-name }
315
-
316
- full-name = first-name + spaces + last-name
317
- ```
318
-
319
- ### Imports with Params
320
-
321
- ```grammar
322
- use params { other-pattern }
323
- import { first-names, last-names } from "some-file.cpat" with params {
324
- some-pattern = "Some Pattern"
325
- some-pattern2 = other-pattern
326
- }
327
-
328
- full-name = first-names + spaces + last-names
329
- ```
330
-
331
- ---
@@ -1,170 +0,0 @@
1
- import { Node } from "../../ast/Node";
2
- import { tokens } from "../../grammar/decorators/tokens";
3
- import { GrammarFile } from "../../grammar/Grammar";
4
- import { generateErrorMessage } from "../../patterns/generate_error_message";
5
- import { Pattern } from "../../patterns/Pattern";
6
- import { grammar } from "./patterns/grammar"
7
-
8
- let anonymousIndexId = 0;
9
-
10
- function defaultImportResolver(_path: string, _basePath: string | null): Promise<GrammarFile> {
11
- throw new Error("No import resolver supplied.");
12
- }
13
-
14
- function defaultImportResolverSync(_path: string, _basePath: string | null): GrammarFile {
15
- throw new Error("No import resolver supplied.");
16
- }
17
-
18
- export type Decorator = (pattern: Pattern, arg?: string | boolean | number | null | Record<string, any> | any[]) => void;
19
-
20
- const defaultDecorators = {
21
- tokens: tokens
22
- };
23
-
24
- export interface GrammarOptions {
25
- resolveImport?: (resource: string, originResource: string | null) => Promise<GrammarFile>;
26
- resolveImportSync?: (resource: string, originResource: string | null) => GrammarFile;
27
- originResource?: string | null;
28
- params?: Pattern[];
29
- decorators?: Record<string, Decorator>;
30
- }
31
-
32
- class ParseContext {
33
- patternsByName = new Map<string, Pattern>();
34
- importedPatternsByName = new Map<string, Pattern>();
35
- paramsByName = new Map<string, Pattern>();
36
- decorators: Record<string, Decorator>;
37
-
38
- constructor(params: Pattern[], decorators: Record<string, Decorator> = {}) {
39
- params.forEach(p => this.paramsByName.set(p.name, p));
40
- this.decorators = { ...decorators, ...defaultDecorators };
41
- }
42
-
43
- getImportedPatterns() {
44
- return Array.from(this.importedPatternsByName.values());
45
- }
46
-
47
- getParams() {
48
- return Array.from(this.paramsByName.values());
49
- }
50
-
51
- }
52
-
53
- export class Grammar {
54
- private _options: GrammarOptions;
55
- private _parseContext: ParseContext;
56
- private _resolveImportSync: (resource: string, originResource: string | null) => GrammarFile;
57
-
58
- constructor(options: GrammarOptions) {
59
- this._options = options;
60
- this._parseContext = new ParseContext(options.params || [], options.decorators || {});
61
- this._resolveImportSync = options.resolveImportSync == null ? defaultImportResolverSync : options.resolveImportSync;
62
- }
63
-
64
- // parse(cpat: string): Promise<Pattern> { }
65
- // import(path: string): Promise<Pattern> { }
66
-
67
- // parseString(cpat: string): Pattern {
68
- // const ast = this._tryToParse(cpat);
69
-
70
- // this._flattenExpressions(ast);
71
-
72
- // }
73
-
74
- private _resolveImportsSync(ast: Node) {
75
- const importStatements = ast.findAll(n => {
76
- return n.name === "importStatement" || n.name === "useParamsStatement";
77
- });
78
-
79
- for (const importStatement of importStatements) {
80
- if (importStatement.name === "importStatement") {
81
- this._processImportSync(importStatement);
82
- } else {
83
- this._processUseParams(importStatement);
84
- }
85
- }
86
- }
87
-
88
- private _processImportSync(importStatement: Node) {
89
- const parseContext = this._parseContext;
90
- const resourceNode = importStatement.find(n => n.name === "resource") as Node;
91
- const params = this._getWithParams(importStatement);
92
- const resource = resourceNode.value.slice(1, -1);
93
- const grammarFile = this._resolveImportSync(resource, this._options.originResource || null);
94
-
95
-
96
- if (resourceNode == null) {
97
- throw new Error("Invalid import statement: resource is required");
98
- }
99
-
100
-
101
- }
102
-
103
- private _getWithParams(importStatement: Node) {
104
- const withParamsStatements = importStatement.find(n => n.name === "withParamsStatements");
105
-
106
- if (withParamsStatements == null) {
107
- return [];
108
- }
109
-
110
- const expression = withParamsStatements.toString();
111
- const importedValues = this._parseContext.getImportedPatterns();
112
-
113
- const grammar = new Grammar({
114
- params: [...importedValues, ...this._parseContext.paramsByName.values()],
115
- originResource: this._options.originResource,
116
- resolveImport: this._options.resolveImport,
117
- decorators: this._parseContext.decorators
118
- });
119
-
120
- // const patterns = grammar.parseString(expression);
121
- // return Array.from(Object.values(patterns));
122
- return[]
123
- }
124
-
125
-
126
- private _processUseParams(useParamsStatement: Node) {
127
- }
128
-
129
- private _tryToParse(cpat: string): Node {
130
- const { ast, cursor } = grammar.exec(cpat, true);
131
-
132
- if (ast == null) {
133
- const message = generateErrorMessage(grammar, cursor);
134
- throw new Error(`[Invalid Grammar] ${message}`);
135
- }
136
-
137
- return ast;
138
- }
139
-
140
-
141
- private _flattenExpressions(node: Node) {
142
- switch (node.name) {
143
- case "sequenceExpr":
144
- return this._unwrapNode("sequenceExpr", node);
145
- case "optionsExpr":
146
- return this._unwrapNode("optionsExpr", node);
147
- case "greedyOptionsExpr":
148
- return this._unwrapNode("greedyOptionsExpr", node);
149
- default:
150
- return node;
151
- }
152
- }
153
-
154
- private _unwrapNode(type: string, node: Node) {
155
- if (node.name !== type) {
156
- return node;
157
- }
158
-
159
- for (let x = 0; x < node.children.length; x++) {
160
- const child = node.children[x];
161
-
162
- if (child.name === type) {
163
- node.spliceChildren(x, 1, ...child.children);
164
- x--;
165
- }
166
- }
167
-
168
- return node;
169
- }
170
- }
@@ -1,91 +0,0 @@
1
- # syntax
2
- syntax = "syntax"
3
- import = "import"
4
- useParams = "use params"
5
- withParams = "with params"
6
- from = "from"
7
- right = "right"
8
- ws = /\s+/
9
- ls = /[ \t]+/
10
- assign = "="
11
- bar = "|"
12
- concat = "+"
13
- colon = ":"
14
- openParen = "("
15
- closeParen = ")"
16
- openSquareBracket = "["
17
- closeSquareBracket = "]"
18
- openBracket = "{"
19
- closeBracket = "}"
20
- comma = /\s*[,]\s*/
21
- trim = "trim"
22
- not = "!"
23
- optional = "?"
24
- newLine = /\s*(\r\n|\r|\n)\s*/
25
- syntaxVersion = /\S*/
26
- at = "@"
27
-
28
- literal = /"(?:\\.|[^"\\])*"/
29
- regexLiteral = /\/(\\/|[^\n\r])*\//
30
-
31
- integer = /[1-9][0-9]*|[0]/
32
- name = /[a-zA-Z_-]+[a-zA-Z0-9_-]*/
33
- patternName = name
34
- patternIdentifier = name
35
- resource = literal
36
-
37
- comment = /#[^\n\r]*/
38
-
39
- # JSON
40
- jsonString = literal
41
- jsonNumber = /-?\d+(\.\d+)?/
42
- jsonBoolean = "true" | "false"
43
- jsonNull = "null"
44
- jsonValue = jsonString | jsonNumber | jsonBoolean | jsonNull | jsonArray | jsonObject
45
- jsonArrayItems = (jsonValue, comma trim)+
46
- jsonArray = openSquareBracket +ws? + jsonArrayItems? + ws? + closeSquareBracket
47
- jsonObjectPropertyName = literal
48
- jsonObjectProperty = jsonObjectPropertyName + ws? + colon + ws? + jsonValue
49
- jsonObjectProperties = (jsonObjectProperty, comma trim)+
50
- jsonObject = openBracket + ws? + jsonObjectProperties? + ws? + closeBracket
51
-
52
- syntaxStatement = syntax + ws? + syntaxVersion
53
-
54
- decorationName = name
55
- decorationStatement = at + ws? + decorationName + ws? + openParen + ws? + jsonValue? + ws? + closeParen
56
-
57
- useParamPatterns = (patternName, comma trim)+
58
- useParamsStatement = useParams + ls? + openBracket + ws? + useParamPatterns + ws? + closeBracket
59
-
60
- withParamStatements = (patternAssignment, newLine trim)+
61
- withParamsExpr = withParams + ls? + openBracket + ws? + withParamStatements + ws? + closeBracket
62
-
63
- patternNames = (patternName, comma trim)+
64
- importedPatterns = openBracket + ws? + patternNames + ws? + closeBracket
65
- importStatement = import + ls? + importedPatterns + ls? + from + ls? + resource + ls? + withParamsExpr?
66
-
67
- notExpr = not + ls? + unaryPatternExpr
68
- optionalExpr = unaryPatternExpr + ls? + optional
69
- rightAssociationExpr = unaryPatternExpr + ls? + right
70
-
71
- unaryPatternExpr = notExpr | optionalExpr | rightAssociationExpr | patternIdentifier
72
-
73
- repeatBounds = openBracket + integer? + comma? + integer? + closeBracket
74
- oneOrMore = "+"
75
- zeroOrMore = "*"
76
- repeatOptions = oneOrMore | zeroOrMore | repeatBounds
77
- delimiter = comma + patternExpr + ws? + trim?
78
- repeatExpr = openParen + ws? + patternExpr + ws? + delimiter? + ws? + closeParen + repeatOptions
79
-
80
- sequenceExpr = patternExpr + ws? + "+" + ws? + patternExpr
81
- optionsExpr = patternExpr + ws? + "|" + ws? + patternExpr
82
- greedyOptionsExpr = patternExpr + ws? + "<|>" + ws? + patternExpr
83
- patternGroupExpr = openParen + ws? + patternExpr + ws? + closeParen
84
-
85
- exportPattern = patternName
86
- patternExpr = sequenceExpr | optionsExpr | greedyOptionsExpr | repeatExpr | patternGroupExpr | literal | regexLiteral | unaryPatternExpr
87
- patternAssignment = patternName + ws? + assign + ws? + patternExpr
88
- statement = useParamsStatement | importStatement | patternAssignment | decorationStatement | exportPattern | comment
89
- statements = (statement, newLine)+
90
- cpat = ws? + syntaxStatement? + ws? + statements?
91
-