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.
- package/.yarn/install-state.gz +0 -0
- package/dist/index.browser.js +205 -120
- package/dist/index.browser.js.map +1 -1
- package/dist/index.esm.js +205 -120
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +205 -120
- package/dist/index.js.map +1 -1
- package/dist/intellisense/AutoComplete.d.ts +26 -8
- package/dist/intellisense/SuggestionOption.d.ts +18 -2
- package/dist/patterns/InfiniteRepeat.d.ts +1 -0
- package/jest.config.js +2 -0
- package/jest.coverage.config.js +2 -0
- package/package.json +7 -6
- package/src/generator/delete.ts +88 -0
- package/src/generator/generator.test.ts +1 -0
- package/src/generator/generator.ts +3 -0
- package/src/generator/ivisitor.ts +1 -0
- package/src/generator/typescriptVisitor.ts +24 -3
- package/src/grammar/Grammar.test.ts +1 -0
- package/src/grammar/Grammar.ts +2 -0
- package/src/grammar/patterns.test.ts +36 -0
- package/src/grammar/spec.md +233 -84
- package/src/intellisense/AutoComplete.test.ts +629 -156
- package/src/intellisense/AutoComplete.ts +232 -109
- package/src/intellisense/SuggestionOption.ts +25 -2
- package/src/patterns/Expression.ts +4 -2
- package/src/patterns/FiniteRepeat.ts +4 -6
- package/src/patterns/InfiniteRepeat.ts +7 -1
- package/src/patterns/Literal.test.ts +1 -1
- package/src/patterns/Options.test.ts +1 -1
- package/src/patterns/PrecedenceTree.ts +31 -7
- package/src/patterns/Reference.test.ts +1 -1
- package/src/patterns/Regex.test.ts +3 -3
- package/src/patterns/Sequence.test.ts +1 -1
package/src/grammar/spec.md
CHANGED
|
@@ -1,182 +1,331 @@
|
|
|
1
|
-
# Grammar
|
|
1
|
+
# Grammar Documentation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This guide describes the syntax rules and composition patterns supported by cpat. Each section shows how to define reusable parsing rules.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Literals
|
|
8
|
+
|
|
9
|
+
A **literal** matches an exact string.
|
|
10
|
+
|
|
11
|
+
```grammar
|
|
6
12
|
name = "Literal"
|
|
7
13
|
```
|
|
8
14
|
|
|
15
|
+
---
|
|
16
|
+
|
|
9
17
|
## Regex
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
A **regex** pattern matches text using a regular expression.
|
|
20
|
+
|
|
21
|
+
```grammar
|
|
12
22
|
digits = /\d+/
|
|
13
23
|
```
|
|
14
24
|
|
|
15
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.
|
|
16
27
|
|
|
17
|
-
|
|
18
|
-
you are creating a regular expression that is concerned about the beginning and
|
|
19
|
-
end of the text you should probably just use a regular expression.
|
|
28
|
+
---
|
|
20
29
|
|
|
21
|
-
##
|
|
22
|
-
This succeeds if it matches any of the options.
|
|
23
|
-
```
|
|
24
|
-
multiply = "*"
|
|
25
|
-
divide = "/"
|
|
26
|
-
operators = mulitply | divide
|
|
27
|
-
```
|
|
30
|
+
## Sequence
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
+
A **sequence** succeeds only if all patterns match in the given order.
|
|
33
|
+
|
|
34
|
+
```grammar
|
|
32
35
|
space = " "
|
|
33
36
|
first-name = "John"
|
|
34
37
|
last-name = "Doe"
|
|
35
|
-
full-name = first-name
|
|
38
|
+
full-name = first-name + space + last-name
|
|
36
39
|
```
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Optional Pattern
|
|
44
|
+
|
|
45
|
+
Patterns in a sequence may be marked **optional**.
|
|
46
|
+
|
|
47
|
+
```grammar
|
|
41
48
|
space = " "
|
|
42
49
|
first-name = /\w+/
|
|
43
50
|
last-name = /\w+/
|
|
44
51
|
middle-name = /\w+/
|
|
45
|
-
middle-name-with-space = middle-name
|
|
52
|
+
middle-name-with-space = middle-name + space
|
|
46
53
|
|
|
47
|
-
full-name = first-name
|
|
54
|
+
full-name = first-name + space + middle-name-with-space? + last-name
|
|
48
55
|
```
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
This will ensure that the first name isn't `Jack` before continuing to match for
|
|
52
|
-
a name.
|
|
57
|
+
---
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
## Negative Lookahead
|
|
60
|
+
|
|
61
|
+
Use `!` to prevent a specific pattern from matching.
|
|
62
|
+
|
|
63
|
+
```grammar
|
|
55
64
|
space = " "
|
|
56
65
|
first-name = /\w+/
|
|
57
66
|
last-name = /\w+/
|
|
58
|
-
middle-name = /\w+/
|
|
59
|
-
middle-name-with-space = m-middle-name & space
|
|
60
67
|
jack = "Jack"
|
|
61
68
|
|
|
62
|
-
full-name = !jack
|
|
69
|
+
full-name = !jack + first-name + space + last-name
|
|
63
70
|
```
|
|
64
71
|
|
|
65
|
-
|
|
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
|
|
66
84
|
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Repeat
|
|
89
|
+
|
|
90
|
+
### Zero or More
|
|
91
|
+
|
|
92
|
+
```grammar
|
|
67
93
|
digit = /\d/
|
|
68
94
|
digits = (digit)*
|
|
69
95
|
```
|
|
70
96
|
|
|
71
|
-
### Zero
|
|
72
|
-
|
|
97
|
+
### Zero or More with Delimiters
|
|
98
|
+
|
|
99
|
+
```grammar
|
|
73
100
|
digit = /\d/
|
|
74
101
|
comma = ","
|
|
75
102
|
digits = (digit, comma)*
|
|
76
103
|
```
|
|
77
104
|
|
|
78
|
-
###
|
|
79
|
-
|
|
105
|
+
### One or More with Trimmed Trailing Delimiter
|
|
106
|
+
|
|
107
|
+
```grammar
|
|
80
108
|
digit = /\d/
|
|
81
109
|
comma = ","
|
|
82
|
-
digits = (digit, comma)
|
|
110
|
+
digits = (digit, comma trim)+
|
|
83
111
|
```
|
|
84
112
|
|
|
85
|
-
This
|
|
113
|
+
This prevents trailing commas from being accepted.
|
|
86
114
|
|
|
87
|
-
|
|
88
|
-
const expression = `
|
|
89
|
-
digit = /\d/
|
|
90
|
-
comma = ","
|
|
91
|
-
digits = (digit, comma){t}
|
|
92
|
-
`;
|
|
93
|
-
|
|
94
|
-
const { digits } = Gammar.parse(expression);
|
|
115
|
+
---
|
|
95
116
|
|
|
96
|
-
|
|
97
|
-
expect(result.ast?.value).toBe("1,2,3");
|
|
117
|
+
### One or More
|
|
98
118
|
|
|
99
|
-
|
|
100
|
-
|
|
119
|
+
```grammar
|
|
120
|
+
digit = /\d/
|
|
121
|
+
digits = (digit)+
|
|
101
122
|
```
|
|
102
123
|
|
|
103
|
-
###
|
|
124
|
+
### Exact Count
|
|
104
125
|
|
|
105
|
-
```
|
|
126
|
+
```grammar
|
|
106
127
|
digit = /\d/
|
|
107
|
-
|
|
108
|
-
digits = (digit, comma)*
|
|
128
|
+
digits = (digit){2}
|
|
109
129
|
```
|
|
110
130
|
|
|
111
|
-
###
|
|
131
|
+
### Bounded Repeats
|
|
112
132
|
|
|
113
|
-
```
|
|
133
|
+
```grammar
|
|
114
134
|
digit = /\d/
|
|
115
|
-
|
|
116
|
-
digits = (digit
|
|
135
|
+
digits = (digit){1,3} # between 1 and 3
|
|
136
|
+
digits = (digit){,3} # up to 3
|
|
117
137
|
```
|
|
118
138
|
|
|
119
|
-
|
|
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
|
|
120
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
|
|
121
159
|
```
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
|
125
179
|
```
|
|
126
180
|
|
|
127
|
-
|
|
181
|
+
Examples:
|
|
182
|
+
- `4 * 2`
|
|
183
|
+
- `7 + 3`
|
|
184
|
+
|
|
185
|
+
---
|
|
128
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
|
|
129
196
|
```
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
|
133
227
|
```
|
|
134
228
|
|
|
135
|
-
|
|
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
|
|
136
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
|
|
137
274
|
import { spaces } from "https://some.cdn.com/some/spaces.cpat"
|
|
138
275
|
|
|
139
276
|
first-name = "John"
|
|
140
277
|
last-name = "Doe"
|
|
141
|
-
full-name = first-name
|
|
278
|
+
full-name = first-name + spaces + last-name
|
|
142
279
|
```
|
|
143
280
|
|
|
144
|
-
###
|
|
145
|
-
|
|
281
|
+
### Multiple Named Imports
|
|
282
|
+
|
|
283
|
+
```grammar
|
|
146
284
|
import { spaces, first-name } from "https://some.cdn.com/some/spaces.cpat"
|
|
147
285
|
|
|
148
286
|
last-name = "Doe"
|
|
149
|
-
full-name = first-name
|
|
287
|
+
full-name = first-name + spaces + last-name
|
|
150
288
|
```
|
|
151
289
|
|
|
152
|
-
###
|
|
153
|
-
|
|
290
|
+
### Multiple Imports
|
|
291
|
+
|
|
292
|
+
```grammar
|
|
154
293
|
import { spaces, first-name } from "https://some.cdn.com/some/patterns.cpat"
|
|
155
294
|
import { last-name } from "https://some.cdn.com/some/last-name.cpat"
|
|
156
295
|
|
|
157
|
-
full-name = first-name
|
|
296
|
+
full-name = first-name + spaces + last-name
|
|
158
297
|
```
|
|
159
298
|
|
|
160
|
-
|
|
161
|
-
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Import Parameters
|
|
302
|
+
|
|
303
|
+
You can inject parameters into imported patterns.
|
|
304
|
+
|
|
305
|
+
**File:** `main.ts`
|
|
162
306
|
```ts
|
|
163
|
-
const firstName = new Literal("first-name", "
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
file.cpat
|
|
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] });
|
|
167
310
|
```
|
|
168
|
-
import params { first-names, last-names }
|
|
169
311
|
|
|
170
|
-
|
|
312
|
+
**File:** `file.cpat`
|
|
313
|
+
```grammar
|
|
314
|
+
use params { first-name, last-name }
|
|
315
|
+
|
|
316
|
+
full-name = first-name + spaces + last-name
|
|
171
317
|
```
|
|
172
318
|
|
|
173
319
|
### Imports with Params
|
|
174
|
-
|
|
175
|
-
|
|
320
|
+
|
|
321
|
+
```grammar
|
|
322
|
+
use params { other-pattern }
|
|
176
323
|
import { first-names, last-names } from "some-file.cpat" with params {
|
|
177
324
|
some-pattern = "Some Pattern"
|
|
178
325
|
some-pattern2 = other-pattern
|
|
179
326
|
}
|
|
180
327
|
|
|
181
|
-
full-name = first-names
|
|
328
|
+
full-name = first-names + spaces + last-names
|
|
182
329
|
```
|
|
330
|
+
|
|
331
|
+
---
|