grammar-composer 0.3.1 → 0.5.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.
- package/README.md +144 -89
- package/dist/exports/Exports.d.ts +2 -0
- package/dist/exports/Exports.d.ts.map +1 -1
- package/dist/exports/Exports.js +2 -0
- package/dist/exports/Exports.js.map +1 -1
- package/dist/parser-generator/Grammar.d.ts +12 -5
- package/dist/parser-generator/Grammar.d.ts.map +1 -1
- package/dist/parser-generator/Grammar.js +81 -263
- package/dist/parser-generator/Grammar.js.map +1 -1
- package/dist/parser-generator/ParseError.d.ts +37 -0
- package/dist/parser-generator/ParseError.d.ts.map +1 -0
- package/dist/parser-generator/ParseError.js +226 -0
- package/dist/parser-generator/ParseError.js.map +1 -0
- package/dist/parser-generator/StaticAnalysis.d.ts +6 -0
- package/dist/parser-generator/StaticAnalysis.d.ts.map +1 -0
- package/dist/parser-generator/StaticAnalysis.js +283 -0
- package/dist/parser-generator/StaticAnalysis.js.map +1 -0
- package/dist/parser-generator/TerminalToText.d.ts +15 -0
- package/dist/parser-generator/TerminalToText.d.ts.map +1 -0
- package/dist/parser-generator/TerminalToText.js +158 -0
- package/dist/parser-generator/TerminalToText.js.map +1 -0
- package/dist/parser-generator/TopDownParser.d.ts +4 -2
- package/dist/parser-generator/TopDownParser.d.ts.map +1 -1
- package/dist/parser-generator/TopDownParser.js +52 -52
- package/dist/parser-generator/TopDownParser.js.map +1 -1
- package/dist/tests/Test.js +36 -26
- package/dist/tests/Test.js.map +1 -1
- package/dist/tests/test-grammars/JsonGrammar.d.ts +12 -11
- package/dist/tests/test-grammars/JsonGrammar.d.ts.map +1 -1
- package/dist/tests/test-grammars/JsonGrammar.js +25 -10
- package/dist/tests/test-grammars/JsonGrammar.js.map +1 -1
- package/dist/tests/test-grammars/RegExpGrammar.d.ts +34 -28
- package/dist/tests/test-grammars/RegExpGrammar.d.ts.map +1 -1
- package/dist/tests/test-grammars/RegExpGrammar.js +104 -60
- package/dist/tests/test-grammars/RegExpGrammar.js.map +1 -1
- package/dist/tests/test-grammars/SimpleTestGrammar1.d.ts +5 -0
- package/dist/tests/test-grammars/SimpleTestGrammar1.d.ts.map +1 -0
- package/dist/tests/test-grammars/SimpleTestGrammar1.js +7 -0
- package/dist/tests/test-grammars/SimpleTestGrammar1.js.map +1 -0
- package/dist/tests/test-grammars/XmlGrammar.d.ts +11 -10
- package/dist/tests/test-grammars/XmlGrammar.d.ts.map +1 -1
- package/dist/tests/test-grammars/XmlGrammar.js +19 -8
- package/dist/tests/test-grammars/XmlGrammar.js.map +1 -1
- package/dist/utilities/LineAndColumn.d.ts +7 -0
- package/dist/utilities/LineAndColumn.d.ts.map +1 -0
- package/dist/utilities/LineAndColumn.js +52 -0
- package/dist/utilities/LineAndColumn.js.map +1 -0
- package/dist/utilities/Utilities.d.ts +7 -7
- package/dist/utilities/Utilities.d.ts.map +1 -1
- package/dist/utilities/Utilities.js.map +1 -1
- package/package.json +2 -2
- package/src/exports/Exports.ts +2 -0
- package/src/parser-generator/Grammar.ts +120 -308
- package/src/parser-generator/ParseError.ts +337 -0
- package/src/parser-generator/StaticAnalysis.ts +340 -0
- package/src/parser-generator/TerminalToText.ts +196 -0
- package/src/parser-generator/TopDownParser.ts +76 -64
- package/src/tests/Test.ts +44 -28
- package/src/tests/test-grammars/JsonGrammar.ts +28 -10
- package/src/tests/test-grammars/RegExpGrammar.ts +193 -96
- package/src/tests/test-grammars/SimpleTestGrammar1.ts +10 -0
- package/src/tests/test-grammars/XmlGrammar.ts +20 -8
- package/src/utilities/LineAndColumn.ts +61 -0
- package/src/utilities/Utilities.ts +7 -7
|
@@ -5,103 +5,157 @@ export class RegExpGrammar {
|
|
|
5
5
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
6
6
|
// High-level productions
|
|
7
7
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
8
|
+
root = () => this.disjunctionOrSequence
|
|
9
|
+
|
|
10
|
+
disjunctionOrSequence = () => [
|
|
11
|
+
G.anyOf(
|
|
12
|
+
this.disjunction,
|
|
13
|
+
this.sequence,
|
|
14
|
+
)
|
|
15
|
+
]
|
|
16
|
+
|
|
8
17
|
disjunction = () => [
|
|
9
18
|
this.sequence,
|
|
10
19
|
|
|
11
|
-
G.
|
|
12
|
-
|
|
13
|
-
this.
|
|
20
|
+
G.oneOrMore([
|
|
21
|
+
'|',
|
|
22
|
+
this.sequence,
|
|
14
23
|
])
|
|
15
24
|
]
|
|
16
25
|
|
|
17
|
-
sequence = () => G.
|
|
26
|
+
sequence = () => G.cached(
|
|
27
|
+
G.zeroOrMore(this.sequenceElement)
|
|
28
|
+
)
|
|
18
29
|
|
|
19
|
-
|
|
30
|
+
sequenceElement = () => G.anyOf(
|
|
20
31
|
this.anchor,
|
|
21
32
|
this.lookaround,
|
|
22
|
-
this.
|
|
33
|
+
this.quantifiedExpression,
|
|
34
|
+
this.quantifiableExpression,
|
|
23
35
|
)
|
|
24
36
|
|
|
25
37
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
26
|
-
//
|
|
38
|
+
// Quantifiable expression
|
|
27
39
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
28
|
-
|
|
40
|
+
quantifiableExpression = () => G.cached(
|
|
29
41
|
G.anyOf(
|
|
30
42
|
this.group,
|
|
31
43
|
this.backReference,
|
|
32
44
|
this.singleCharExpression
|
|
33
|
-
)
|
|
45
|
+
)
|
|
46
|
+
)
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.countRangeQuantifier,
|
|
40
|
-
)),
|
|
48
|
+
quantifiedExpression = () => [
|
|
49
|
+
this.quantifiableExpression,
|
|
50
|
+
this.quantifier,
|
|
51
|
+
]
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
54
|
+
// Quantifier expressions
|
|
55
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
56
|
+
starQuantifier = () => [
|
|
57
|
+
'*',
|
|
58
|
+
G.possibly(this.nongreedyQuantifier)
|
|
43
59
|
]
|
|
44
60
|
|
|
45
|
-
|
|
46
|
-
'
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
])
|
|
61
|
+
plusQuantifier = () => [
|
|
62
|
+
'+',
|
|
63
|
+
G.possibly(this.nongreedyQuantifier)
|
|
64
|
+
]
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
'
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
optionalQuantifier = () => [
|
|
67
|
+
'?',
|
|
68
|
+
G.possibly(this.nongreedyQuantifier)
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
exactCountQuantifier = () => [
|
|
72
|
+
G.pattern([
|
|
73
|
+
'{',
|
|
74
|
+
R.captureAs('count',
|
|
75
|
+
R.oneOrMore(digit)
|
|
76
|
+
),
|
|
77
|
+
'}',
|
|
78
|
+
]),
|
|
79
|
+
G.possibly(this.nongreedyQuantifier)
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
countRangeQuantifier = () => [
|
|
83
|
+
G.pattern([
|
|
84
|
+
'{',
|
|
85
|
+
R.captureAs('start',
|
|
86
|
+
R.oneOrMore(digit)
|
|
87
|
+
),
|
|
88
|
+
',',
|
|
89
|
+
R.possibly(R.captureAs('end',
|
|
90
|
+
R.oneOrMore(digit))
|
|
91
|
+
),
|
|
92
|
+
'}',
|
|
93
|
+
]),
|
|
94
|
+
G.possibly(this.nongreedyQuantifier)
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
nongreedyQuantifier = () => '?'
|
|
98
|
+
|
|
99
|
+
quantifier = () => G.anyOf(
|
|
100
|
+
this.starQuantifier,
|
|
101
|
+
this.plusQuantifier,
|
|
102
|
+
this.optionalQuantifier,
|
|
103
|
+
this.exactCountQuantifier,
|
|
104
|
+
this.countRangeQuantifier,
|
|
105
|
+
)
|
|
58
106
|
|
|
59
107
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
60
108
|
// Group expressions
|
|
61
109
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
62
|
-
group = () => G.anyOf(
|
|
63
|
-
this.uncapturedGroup,
|
|
64
|
-
this.namedCaptureGroup,
|
|
65
|
-
this.unnamedCaptureGroup,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
110
|
uncapturedGroup = () => [
|
|
69
111
|
'(?:',
|
|
70
|
-
this.
|
|
112
|
+
this.disjunctionOrSequence,
|
|
71
113
|
')',
|
|
72
114
|
]
|
|
73
115
|
|
|
74
116
|
namedCaptureGroup = () => [
|
|
75
117
|
'(?<',
|
|
76
|
-
G.pattern(R.captureAs('name',
|
|
118
|
+
G.pattern(R.captureAs('name',
|
|
119
|
+
R.oneOrMore(identifierChar))
|
|
120
|
+
),
|
|
77
121
|
'>',
|
|
78
|
-
this.
|
|
122
|
+
this.disjunctionOrSequence,
|
|
79
123
|
')',
|
|
80
124
|
]
|
|
81
125
|
|
|
82
126
|
unnamedCaptureGroup = () => [
|
|
83
127
|
'(',
|
|
84
|
-
this.
|
|
128
|
+
this.disjunctionOrSequence,
|
|
85
129
|
')',
|
|
86
130
|
]
|
|
87
131
|
|
|
132
|
+
group = () => G.anyOf(
|
|
133
|
+
this.uncapturedGroup,
|
|
134
|
+
this.namedCaptureGroup,
|
|
135
|
+
this.unnamedCaptureGroup,
|
|
136
|
+
)
|
|
137
|
+
|
|
88
138
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
89
139
|
// Backreferences
|
|
90
140
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
91
141
|
unnamedBackreference = () =>
|
|
92
142
|
G.pattern([
|
|
93
143
|
'\\',
|
|
94
|
-
R.captureAs('index',
|
|
144
|
+
R.captureAs('index',
|
|
145
|
+
digit
|
|
146
|
+
),
|
|
95
147
|
])
|
|
96
148
|
|
|
97
149
|
namedBackreference = () =>
|
|
98
150
|
G.pattern([
|
|
99
151
|
'\\k<',
|
|
100
|
-
R.captureAs('name',
|
|
152
|
+
R.captureAs('name',
|
|
153
|
+
R.oneOrMore(identifierChar)
|
|
154
|
+
),
|
|
101
155
|
'>',
|
|
102
156
|
])
|
|
103
157
|
|
|
104
|
-
backReference = G.anyOf(
|
|
158
|
+
backReference = () => G.anyOf(
|
|
105
159
|
this.unnamedBackreference,
|
|
106
160
|
this.namedBackreference,
|
|
107
161
|
)
|
|
@@ -111,29 +165,29 @@ export class RegExpGrammar {
|
|
|
111
165
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
112
166
|
positiveLookahead = () => [
|
|
113
167
|
'(?=',
|
|
114
|
-
this.
|
|
168
|
+
this.disjunctionOrSequence,
|
|
115
169
|
')',
|
|
116
170
|
]
|
|
117
171
|
|
|
118
172
|
negativeLookahead = () => [
|
|
119
173
|
'(?!',
|
|
120
|
-
this.
|
|
174
|
+
this.disjunctionOrSequence,
|
|
121
175
|
')',
|
|
122
176
|
]
|
|
123
177
|
|
|
124
178
|
positiveLookbehind = () => [
|
|
125
179
|
'(?<=',
|
|
126
|
-
this.
|
|
180
|
+
this.disjunctionOrSequence,
|
|
127
181
|
')',
|
|
128
182
|
]
|
|
129
183
|
|
|
130
184
|
negativeLookbehind = () => [
|
|
131
185
|
'(?<!',
|
|
132
|
-
this.
|
|
186
|
+
this.disjunctionOrSequence,
|
|
133
187
|
')',
|
|
134
188
|
]
|
|
135
189
|
|
|
136
|
-
lookaround = G.anyOf(
|
|
190
|
+
lookaround = () => G.anyOf(
|
|
137
191
|
this.positiveLookahead,
|
|
138
192
|
this.negativeLookahead,
|
|
139
193
|
this.positiveLookbehind,
|
|
@@ -154,24 +208,31 @@ export class RegExpGrammar {
|
|
|
154
208
|
)
|
|
155
209
|
|
|
156
210
|
unreservedCharLiteral = () => G.pattern(
|
|
157
|
-
R.
|
|
211
|
+
R.captureAs('char',
|
|
212
|
+
R.notAnyOfChars('[', '.', '*', '+', '?', '^', '$', '{', '}', '(', ')', '|', ']', '\\')
|
|
213
|
+
)
|
|
158
214
|
)
|
|
159
215
|
|
|
160
216
|
escapedCharLiteral = () => G.pattern([
|
|
161
217
|
'\\',
|
|
162
|
-
R.
|
|
218
|
+
R.captureAs('char',
|
|
219
|
+
R.anyChar
|
|
220
|
+
)
|
|
163
221
|
])
|
|
164
222
|
|
|
165
223
|
hexCharcode = () =>
|
|
166
224
|
G.pattern([
|
|
167
225
|
'\\x',
|
|
168
|
-
|
|
169
|
-
|
|
226
|
+
R.captureAs('value',
|
|
227
|
+
R.repeated(2, hexDigit)
|
|
228
|
+
)
|
|
170
229
|
])
|
|
171
230
|
|
|
172
231
|
controlCharcode = () => G.pattern([
|
|
173
232
|
'\\c',
|
|
174
|
-
R.
|
|
233
|
+
R.captureAs('value',
|
|
234
|
+
R.anyOf(R.charRange('A', 'Z'), R.charRange('a', 'z'))
|
|
235
|
+
)
|
|
175
236
|
])
|
|
176
237
|
|
|
177
238
|
nullCharcode = () => G.pattern('\\0')
|
|
@@ -180,48 +241,55 @@ export class RegExpGrammar {
|
|
|
180
241
|
G.pattern([
|
|
181
242
|
'\\u',
|
|
182
243
|
'{',
|
|
183
|
-
R.captureAs('value',
|
|
244
|
+
R.captureAs('value',
|
|
245
|
+
R.repeated([1, 6], hexDigit)
|
|
246
|
+
),
|
|
184
247
|
'}',
|
|
185
248
|
]),
|
|
186
249
|
G.pattern([
|
|
187
250
|
'\\u',
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
hexDigit
|
|
251
|
+
R.captureAs('value',
|
|
252
|
+
R.repeated(4, hexDigit)
|
|
253
|
+
)
|
|
192
254
|
])
|
|
193
255
|
)
|
|
194
256
|
|
|
195
257
|
codepointRange = () => G.pattern([
|
|
196
258
|
'\\u',
|
|
197
259
|
'{',
|
|
198
|
-
R.captureAs('start',
|
|
260
|
+
R.captureAs('start',
|
|
261
|
+
R.oneOrMore(hexDigit)
|
|
262
|
+
),
|
|
199
263
|
'-',
|
|
200
|
-
R.captureAs('end',
|
|
264
|
+
R.captureAs('end',
|
|
265
|
+
R.oneOrMore(hexDigit)
|
|
266
|
+
),
|
|
201
267
|
'}',
|
|
202
268
|
])
|
|
203
269
|
|
|
204
|
-
unicodeProperty = () =>
|
|
270
|
+
unicodeProperty = () => [
|
|
205
271
|
'\\p',
|
|
206
272
|
this.unicodePropertyBodyPattern,
|
|
207
|
-
]
|
|
273
|
+
]
|
|
208
274
|
|
|
209
|
-
notUnicodeProperty = () =>
|
|
275
|
+
notUnicodeProperty = () => [
|
|
210
276
|
'\\P',
|
|
211
277
|
this.unicodePropertyBodyPattern,
|
|
212
|
-
]
|
|
278
|
+
]
|
|
213
279
|
|
|
214
|
-
unicodePropertyBodyPattern
|
|
280
|
+
unicodePropertyBodyPattern = () => G.pattern([
|
|
215
281
|
'{',
|
|
216
|
-
R.captureAs('property',
|
|
282
|
+
R.captureAs('property',
|
|
283
|
+
R.oneOrMore(R.anyOf(letter, digit, '_', '-'))
|
|
284
|
+
),
|
|
217
285
|
R.possibly([
|
|
218
286
|
'=',
|
|
219
|
-
R.captureAs('value',
|
|
287
|
+
R.captureAs('value',
|
|
288
|
+
R.oneOrMore(R.anyOf(letter, digit, '_', '-'))
|
|
289
|
+
),
|
|
220
290
|
]),
|
|
221
291
|
'}',
|
|
222
|
-
]
|
|
223
|
-
|
|
224
|
-
charClassChar = () => G.pattern(R.notAnyOfChars(']'))
|
|
292
|
+
])
|
|
225
293
|
|
|
226
294
|
charClass = () => [
|
|
227
295
|
'[',
|
|
@@ -233,36 +301,42 @@ export class RegExpGrammar {
|
|
|
233
301
|
this.notUnicodeProperty,
|
|
234
302
|
this.escapedCharacterClass,
|
|
235
303
|
this.charcodeOrEscapedChar,
|
|
236
|
-
this.
|
|
304
|
+
this.charClassLiteral
|
|
237
305
|
)),
|
|
238
306
|
']',
|
|
239
307
|
]
|
|
240
308
|
|
|
241
|
-
charcodeOrEscapedChar = G.anyOf(
|
|
309
|
+
charcodeOrEscapedChar = () => G.anyOf(
|
|
242
310
|
this.codepoint,
|
|
243
311
|
this.hexCharcode,
|
|
244
312
|
this.controlCharcode,
|
|
313
|
+
this.nullCharcode,
|
|
245
314
|
this.escapedCharLiteral,
|
|
246
315
|
)
|
|
247
316
|
|
|
248
|
-
|
|
317
|
+
charClassLiteral = () => G.pattern(
|
|
318
|
+
R.captureAs('char',
|
|
319
|
+
R.notAnyOfChars(']')
|
|
320
|
+
)
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
charRangeElement = () => G.anyOf(
|
|
249
324
|
this.charcodeOrEscapedChar,
|
|
250
|
-
|
|
325
|
+
this.charClassLiteral,
|
|
251
326
|
)
|
|
252
327
|
|
|
328
|
+
charRangeStart = () => this.charRangeElement
|
|
329
|
+
charRangeEnd = () => this.charRangeElement
|
|
330
|
+
|
|
253
331
|
charRange = () => [
|
|
254
|
-
this.
|
|
332
|
+
this.charRangeStart,
|
|
255
333
|
'-',
|
|
256
|
-
this.
|
|
334
|
+
this.charRangeEnd,
|
|
257
335
|
]
|
|
258
336
|
|
|
259
337
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
260
338
|
// Special symbols
|
|
261
339
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
262
|
-
starQuantifier = () => '*'
|
|
263
|
-
plusQuantifier = () => '+'
|
|
264
|
-
nongreedyQuantifier = () => '?'
|
|
265
|
-
|
|
266
340
|
charClassNegator = () => '^'
|
|
267
341
|
|
|
268
342
|
inputStartAnchor = () => '^'
|
|
@@ -270,34 +344,39 @@ export class RegExpGrammar {
|
|
|
270
344
|
|
|
271
345
|
anyCharWildcard = () => '.'
|
|
272
346
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
anchor = G.anyOf(this.inputStartAnchor, this.inputEndAnchor)
|
|
347
|
+
anchor = () =>
|
|
348
|
+
G.anyOf(this.inputStartAnchor, this.inputEndAnchor)
|
|
276
349
|
|
|
277
350
|
escapedCharacterClass = () => G.pattern(R.anyOf(
|
|
278
|
-
R.captureAs('whitespace',
|
|
279
|
-
R.captureAs('nonWhitespace',
|
|
280
|
-
R.captureAs('digit',
|
|
281
|
-
R.captureAs('nonDigit',
|
|
282
|
-
R.captureAs('word',
|
|
283
|
-
R.captureAs('nonWord',
|
|
284
|
-
R.captureAs('wordBoundary',
|
|
285
|
-
R.captureAs('nonWordBoundary',
|
|
286
|
-
R.captureAs('formFeed',
|
|
287
|
-
R.captureAs('carriageReturn',
|
|
288
|
-
R.captureAs('lineFeed',
|
|
289
|
-
R.captureAs('tab',
|
|
290
|
-
R.captureAs('verticalTab',
|
|
291
|
-
R.captureAs('backwardSlash',
|
|
351
|
+
R.captureAs('whitespace', escapedChars.whitespace),
|
|
352
|
+
R.captureAs('nonWhitespace', escapedChars.nonWhitespace),
|
|
353
|
+
R.captureAs('digit', escapedChars.digit),
|
|
354
|
+
R.captureAs('nonDigit', escapedChars.nonDigit),
|
|
355
|
+
R.captureAs('word', escapedChars.word),
|
|
356
|
+
R.captureAs('nonWord', escapedChars.nonWord),
|
|
357
|
+
R.captureAs('wordBoundary', escapedChars.wordBoundary),
|
|
358
|
+
R.captureAs('nonWordBoundary', escapedChars.nonWordBoundary),
|
|
359
|
+
R.captureAs('formFeed', escapedChars.formFeed),
|
|
360
|
+
R.captureAs('carriageReturn', escapedChars.carriageReturn),
|
|
361
|
+
R.captureAs('lineFeed', escapedChars.lineFeed),
|
|
362
|
+
R.captureAs('tab', escapedChars.tab),
|
|
363
|
+
R.captureAs('verticalTab', escapedChars.verticalTab),
|
|
364
|
+
R.captureAs('backwardSlash', escapedChars.backwardSlash),
|
|
292
365
|
))
|
|
293
366
|
}
|
|
294
367
|
|
|
368
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
369
|
+
// Shared regular expressions
|
|
370
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
295
371
|
const digit = R.charRange('0', '9')
|
|
296
372
|
const letter = R.anyOf(R.charRange('a', 'z'), R.charRange('A', 'Z'))
|
|
297
373
|
const hexDigit = R.anyOf(digit, R.charRange('a', 'f'), R.charRange('A', 'F'))
|
|
298
374
|
const identifierChar = R.anyOf(letter, digit, '_', '$')
|
|
299
375
|
|
|
300
|
-
|
|
376
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
377
|
+
// Escaped characters lookup
|
|
378
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
379
|
+
const escapedChars = {
|
|
301
380
|
whitespace: '\\s',
|
|
302
381
|
nonWhitespace: '\\S',
|
|
303
382
|
digit: '\\d',
|
|
@@ -313,3 +392,21 @@ const escapedCharString = {
|
|
|
313
392
|
verticalTab: '\\v',
|
|
314
393
|
backwardSlash: '\\\\'
|
|
315
394
|
}
|
|
395
|
+
|
|
396
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
397
|
+
// Wrapped nonterminal names
|
|
398
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
399
|
+
export const regExpGrammarUnwrappedNonterminalNames: G.GrammarNonterminalNames<RegExpGrammar> = [
|
|
400
|
+
'disjunctionOrSequence',
|
|
401
|
+
'group',
|
|
402
|
+
'backReference',
|
|
403
|
+
'lookaround',
|
|
404
|
+
'unicodeProperty',
|
|
405
|
+
'notUnicodeProperty',
|
|
406
|
+
'unicodePropertyBodyPattern',
|
|
407
|
+
'charcodeOrEscapedChar',
|
|
408
|
+
'charRangeElement',
|
|
409
|
+
'anchor',
|
|
410
|
+
'quantifiableExpression',
|
|
411
|
+
'sequenceElement',
|
|
412
|
+
]
|
|
@@ -14,7 +14,7 @@ export class XmlGrammar {
|
|
|
14
14
|
)
|
|
15
15
|
]
|
|
16
16
|
|
|
17
|
-
textFragment = G.pattern([
|
|
17
|
+
textFragment = () => G.pattern([
|
|
18
18
|
R.oneOrMore(R.notAnyOfChars('<'))
|
|
19
19
|
])
|
|
20
20
|
|
|
@@ -26,7 +26,7 @@ export class XmlGrammar {
|
|
|
26
26
|
this.tagEnd
|
|
27
27
|
]
|
|
28
28
|
|
|
29
|
-
openingTagStart = G.pattern([
|
|
29
|
+
openingTagStart = () => G.pattern([
|
|
30
30
|
'<',
|
|
31
31
|
|
|
32
32
|
R.possibly('?'),
|
|
@@ -38,7 +38,7 @@ export class XmlGrammar {
|
|
|
38
38
|
R.zeroOrMore(R.whitespace),
|
|
39
39
|
])
|
|
40
40
|
|
|
41
|
-
tagEnd = G.pattern([
|
|
41
|
+
tagEnd = () => G.pattern([
|
|
42
42
|
R.zeroOrMore(R.whitespace),
|
|
43
43
|
|
|
44
44
|
R.possibly(R.anyOf('/', '?')),
|
|
@@ -46,7 +46,7 @@ export class XmlGrammar {
|
|
|
46
46
|
'>'
|
|
47
47
|
])
|
|
48
48
|
|
|
49
|
-
attribute = G.pattern([
|
|
49
|
+
attribute = () => G.pattern([
|
|
50
50
|
R.zeroOrMore(R.whitespace),
|
|
51
51
|
|
|
52
52
|
R.captureAs('attributeName',
|
|
@@ -66,7 +66,7 @@ export class XmlGrammar {
|
|
|
66
66
|
])
|
|
67
67
|
])
|
|
68
68
|
|
|
69
|
-
closingTag = G.pattern([
|
|
69
|
+
closingTag = () => G.pattern([
|
|
70
70
|
'</',
|
|
71
71
|
|
|
72
72
|
R.zeroOrMore(R.whitespace),
|
|
@@ -88,7 +88,7 @@ export class XmlGrammar {
|
|
|
88
88
|
this.tagEnd
|
|
89
89
|
]
|
|
90
90
|
|
|
91
|
-
declarationTagOpening = G.pattern([
|
|
91
|
+
declarationTagOpening = () => G.pattern([
|
|
92
92
|
'<!',
|
|
93
93
|
|
|
94
94
|
R.captureAs('tagName',
|
|
@@ -98,7 +98,7 @@ export class XmlGrammar {
|
|
|
98
98
|
R.zeroOrMore(R.whitespace)
|
|
99
99
|
])
|
|
100
100
|
|
|
101
|
-
declarationTagAttribute = G.pattern([
|
|
101
|
+
declarationTagAttribute = () => G.pattern([
|
|
102
102
|
R.zeroOrMore(R.whitespace),
|
|
103
103
|
|
|
104
104
|
R.anyOf(
|
|
@@ -112,7 +112,7 @@ export class XmlGrammar {
|
|
|
112
112
|
R.zeroOrMore(R.whitespace),
|
|
113
113
|
])
|
|
114
114
|
|
|
115
|
-
comment = G.pattern([
|
|
115
|
+
comment = () => G.pattern([
|
|
116
116
|
'<!--',
|
|
117
117
|
|
|
118
118
|
R.captureAs('commentBody',
|
|
@@ -123,6 +123,9 @@ export class XmlGrammar {
|
|
|
123
123
|
])
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
127
|
+
// Helper regular expressions
|
|
128
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
126
129
|
const quotedString = R.anyOf(
|
|
127
130
|
[
|
|
128
131
|
'"',
|
|
@@ -139,3 +142,12 @@ const quotedString = R.anyOf(
|
|
|
139
142
|
"'"
|
|
140
143
|
],
|
|
141
144
|
)
|
|
145
|
+
|
|
146
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
147
|
+
// Wrapped nonterminal names
|
|
148
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
149
|
+
export const xmlGrammarUnwrappedNonterminalNames: G.GrammarNonterminalNames<XmlGrammar> = [
|
|
150
|
+
'openingTagStart',
|
|
151
|
+
'tagEnd',
|
|
152
|
+
'declarationTagOpening',
|
|
153
|
+
]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Position helpers
|
|
3
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
4
|
+
export function getLineAndColumn(input: string, offset: number): { line: number, column: number } {
|
|
5
|
+
let line = 1
|
|
6
|
+
let lineStartOffset = 0
|
|
7
|
+
|
|
8
|
+
for (let i = 0; i < offset && i < input.length; i++) {
|
|
9
|
+
if (input[i] === '\n') {
|
|
10
|
+
line += 1
|
|
11
|
+
lineStartOffset = i + 1
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
line,
|
|
17
|
+
column: offset - lineStartOffset + 1
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const tabSize = 4
|
|
22
|
+
|
|
23
|
+
export function expandTabs(text: string): string {
|
|
24
|
+
let result = ''
|
|
25
|
+
let column = 0
|
|
26
|
+
|
|
27
|
+
for (const char of text) {
|
|
28
|
+
if (char === '\t') {
|
|
29
|
+
const spacesToNextTabStop = tabSize - (column % tabSize)
|
|
30
|
+
|
|
31
|
+
result += ' '.repeat(spacesToNextTabStop)
|
|
32
|
+
column += spacesToNextTabStop
|
|
33
|
+
} else {
|
|
34
|
+
result += char
|
|
35
|
+
column += 1
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return result
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function buildCaretSpacing(text: string, caretColumn: number): string {
|
|
43
|
+
let spacing = ''
|
|
44
|
+
let column = 0
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < caretColumn - 1 && i < text.length; i++) {
|
|
47
|
+
const char = text[i]
|
|
48
|
+
|
|
49
|
+
if (char === '\t') {
|
|
50
|
+
const spacesToNextTabStop = tabSize - (column % tabSize)
|
|
51
|
+
|
|
52
|
+
spacing += ' '.repeat(spacesToNextTabStop)
|
|
53
|
+
column += spacesToNextTabStop
|
|
54
|
+
} else {
|
|
55
|
+
spacing += ' '
|
|
56
|
+
column += 1
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return spacing
|
|
61
|
+
}
|