@bablr/boot 0.10.0 → 0.11.1
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/lib/index.js +43 -14
- package/lib/languages/cstml.js +174 -111
- package/lib/languages/instruction.js +32 -22
- package/lib/languages/json.js +11 -29
- package/lib/languages/regex.js +6 -32
- package/lib/languages/spamex.js +83 -88
- package/lib/match.js +19 -16
- package/lib/miniparser.js +141 -112
- package/lib/path.js +5 -1
- package/package.json +7 -4
package/lib/index.js
CHANGED
|
@@ -1,26 +1,39 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import cstmll from './languages/cstml.js';
|
|
2
|
+
import spamex from './languages/spamex.js';
|
|
3
|
+
import regex from './languages/regex.js';
|
|
4
|
+
import instruction from './languages/instruction.js';
|
|
5
5
|
|
|
6
6
|
import { TemplateParser } from './miniparser.js';
|
|
7
7
|
import { buildEmbeddedMatcher, buildEmbeddedRegex } from '@bablr/agast-vm-helpers/builders';
|
|
8
|
+
import { reifyExpression } from '@bablr/agast-vm-helpers';
|
|
9
|
+
import { interpolate } from '@bablr/agast-helpers/template';
|
|
10
|
+
import { buildGapTag } from '@bablr/agast-helpers/builders';
|
|
11
|
+
import { buildNode } from '@bablr/agast-helpers/path';
|
|
8
12
|
|
|
9
13
|
const trees = new WeakMap();
|
|
10
14
|
|
|
11
15
|
export const buildTag = (language, defaultType) => {
|
|
12
16
|
const defaultTag = (quasis, ...exprs) => {
|
|
13
17
|
let tree;
|
|
14
|
-
if (trees.has(quasis)
|
|
18
|
+
if (trees.has(quasis)) {
|
|
15
19
|
tree = trees.get(quasis);
|
|
16
20
|
} else {
|
|
17
|
-
tree = new TemplateParser(
|
|
21
|
+
tree = new TemplateParser(
|
|
22
|
+
language,
|
|
23
|
+
quasis.raw,
|
|
24
|
+
exprs.map((e) => buildNode(buildGapTag())),
|
|
25
|
+
).eatProduction({
|
|
18
26
|
language: language.name,
|
|
19
|
-
|
|
27
|
+
name: defaultType,
|
|
20
28
|
});
|
|
21
29
|
|
|
22
30
|
trees.set(quasis, tree);
|
|
23
31
|
}
|
|
32
|
+
|
|
33
|
+
if (exprs.length) {
|
|
34
|
+
tree = interpolate(tree, exprs);
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
return tree;
|
|
25
38
|
};
|
|
26
39
|
|
|
@@ -29,21 +42,30 @@ export const buildTag = (language, defaultType) => {
|
|
|
29
42
|
return defaultTag.apply(receiver, argsList);
|
|
30
43
|
},
|
|
31
44
|
|
|
32
|
-
get(_,
|
|
45
|
+
get(_, name) {
|
|
33
46
|
const trees = new WeakMap();
|
|
34
47
|
|
|
35
48
|
return (quasis, ...exprs) => {
|
|
36
49
|
let tree;
|
|
37
|
-
if (trees.has(quasis)
|
|
50
|
+
if (trees.has(quasis)) {
|
|
38
51
|
tree = trees.get(quasis);
|
|
39
52
|
} else {
|
|
40
|
-
tree = new TemplateParser(
|
|
53
|
+
tree = new TemplateParser(
|
|
54
|
+
language,
|
|
55
|
+
quasis.raw,
|
|
56
|
+
exprs.map((e) => buildNode(buildGapTag())),
|
|
57
|
+
).eatProduction({
|
|
41
58
|
language: language.name,
|
|
42
|
-
|
|
59
|
+
name,
|
|
43
60
|
});
|
|
44
61
|
|
|
45
62
|
trees.set(quasis, tree);
|
|
46
63
|
}
|
|
64
|
+
|
|
65
|
+
if (exprs.length) {
|
|
66
|
+
tree = interpolate(tree, exprs);
|
|
67
|
+
}
|
|
68
|
+
|
|
47
69
|
return tree;
|
|
48
70
|
};
|
|
49
71
|
},
|
|
@@ -52,7 +74,7 @@ export const buildTag = (language, defaultType) => {
|
|
|
52
74
|
|
|
53
75
|
export const parse = (language, type, sourceText, expressions = []) => {
|
|
54
76
|
let source = Array.isArray(sourceText) ? sourceText : [sourceText];
|
|
55
|
-
return new TemplateParser(language, source, expressions).
|
|
77
|
+
return new TemplateParser(language, source, expressions).eatProduction({
|
|
56
78
|
language: language.name,
|
|
57
79
|
type,
|
|
58
80
|
});
|
|
@@ -60,12 +82,19 @@ export const parse = (language, type, sourceText, expressions = []) => {
|
|
|
60
82
|
|
|
61
83
|
export const str = buildTag(cstmll, 'String');
|
|
62
84
|
export const num = buildTag(cstmll, 'Integer');
|
|
63
|
-
export const cst = buildTag(cstmll, '
|
|
85
|
+
export const cst = buildTag(cstmll, 'Document');
|
|
86
|
+
export const t_ = buildTag(cstmll, 'Tag');
|
|
64
87
|
export const cstml = cst;
|
|
65
|
-
export const spam_ = buildTag(spamex, '
|
|
88
|
+
export const spam_ = buildTag(spamex, 'PropertyMatcher');
|
|
66
89
|
export const re_ = buildTag(regex, 'Pattern');
|
|
67
90
|
export const i = buildTag(instruction, 'Call');
|
|
68
91
|
|
|
92
|
+
export const t = new Proxy(t_, {
|
|
93
|
+
apply(tag, _, args) {
|
|
94
|
+
return reifyExpression(tag(...args));
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
|
|
69
98
|
export const spam = new Proxy(spam_, {
|
|
70
99
|
apply(tag, _, args) {
|
|
71
100
|
return buildEmbeddedMatcher(tag(...args));
|
package/lib/languages/cstml.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { get, sourceTextFor } from '@bablr/agast-helpers/tree';
|
|
1
|
+
import JSON from './json.js';
|
|
2
|
+
import { get } from '@bablr/agast-helpers/tree';
|
|
4
3
|
|
|
5
4
|
const _ = /\s+/y;
|
|
6
|
-
const PN =
|
|
5
|
+
const PN = null;
|
|
7
6
|
const KW = 'Keyword';
|
|
8
7
|
|
|
9
8
|
export const name = 'CSTML';
|
|
@@ -16,11 +15,11 @@ export const dependencies = {
|
|
|
16
15
|
|
|
17
16
|
export const covers = new Map([
|
|
18
17
|
[
|
|
19
|
-
|
|
18
|
+
Symbol.for('@bablr/node'),
|
|
20
19
|
new Set([
|
|
21
20
|
'Document',
|
|
22
|
-
'DocumentVersion',
|
|
23
21
|
'DoctypeTag',
|
|
22
|
+
'BoundNode',
|
|
24
23
|
'Property',
|
|
25
24
|
'ReferenceTag',
|
|
26
25
|
'ReferenceFlags',
|
|
@@ -29,31 +28,50 @@ export const covers = new Map([
|
|
|
29
28
|
'GlobalIdentifier',
|
|
30
29
|
'NullTag',
|
|
31
30
|
'GapTag',
|
|
32
|
-
'
|
|
31
|
+
'ShiftTag',
|
|
32
|
+
'TreeNode',
|
|
33
|
+
'NullNode',
|
|
34
|
+
'GapNode',
|
|
33
35
|
'IdentifierPath',
|
|
36
|
+
'BindingSegment',
|
|
34
37
|
'OpenNodeTag',
|
|
35
38
|
'CloseNodeTag',
|
|
36
39
|
'LiteralTag',
|
|
37
40
|
'BindingTag',
|
|
38
|
-
'InitializerTag',
|
|
39
41
|
'AttributeDefinition',
|
|
40
42
|
'Number',
|
|
41
43
|
'Digit',
|
|
42
|
-
'Content',
|
|
43
44
|
'NodeFlags',
|
|
44
45
|
]),
|
|
45
46
|
],
|
|
47
|
+
[
|
|
48
|
+
'Tag',
|
|
49
|
+
new Set([
|
|
50
|
+
'DoctypeTag',
|
|
51
|
+
'ReferenceTag',
|
|
52
|
+
'NullTag',
|
|
53
|
+
'GapTag',
|
|
54
|
+
'ShiftTag',
|
|
55
|
+
'OpenNodeTag',
|
|
56
|
+
'CloseNodeTag',
|
|
57
|
+
'LiteralTag',
|
|
58
|
+
'BindingTag',
|
|
59
|
+
'AttributeDefinition',
|
|
60
|
+
]),
|
|
61
|
+
],
|
|
62
|
+
[
|
|
63
|
+
'Expression',
|
|
64
|
+
new Set(['ShiftExpression', 'BindingExpression', 'TreeNode', 'NullNode', 'GapNode']),
|
|
65
|
+
],
|
|
46
66
|
]);
|
|
47
67
|
|
|
48
68
|
export const grammar = class CSTMLMiniparserGrammar {
|
|
49
|
-
// @Node
|
|
50
69
|
Document(p) {
|
|
51
70
|
p.eatProduction('DoctypeTag', { path: 'doctype' });
|
|
52
71
|
p.eatMatchTrivia(_);
|
|
53
|
-
p.eatProduction('
|
|
72
|
+
p.eatProduction('Expression', { path: 'tree' });
|
|
54
73
|
}
|
|
55
74
|
|
|
56
|
-
// @Node
|
|
57
75
|
DoctypeTag(p) {
|
|
58
76
|
p.eat('<!', PN, { path: 'openToken' });
|
|
59
77
|
p.eatProduction('JSON:UnsignedInteger', { path: 'version' });
|
|
@@ -70,39 +88,32 @@ export const grammar = class CSTMLMiniparserGrammar {
|
|
|
70
88
|
p.eat('>', PN, { path: 'closeToken' });
|
|
71
89
|
}
|
|
72
90
|
|
|
73
|
-
// @Node
|
|
74
91
|
NullTag(p) {
|
|
75
92
|
p.eat('null', KW, { path: 'sigilToken' });
|
|
76
93
|
}
|
|
77
94
|
|
|
78
|
-
// @Node
|
|
79
95
|
GapTag(p) {
|
|
80
96
|
p.eat('<//>', PN, { path: 'sigilToken' });
|
|
81
97
|
}
|
|
82
98
|
|
|
83
|
-
// @Node
|
|
84
99
|
LiteralTag(p) {
|
|
85
100
|
p.eatProduction('JSON:String', { path: 'value' });
|
|
86
101
|
}
|
|
87
102
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
103
|
+
TreeNode(p, props) {
|
|
104
|
+
if (p.match(/['"]/y)) {
|
|
105
|
+
do {
|
|
106
|
+
p.eatProduction('LiteralTag', { path: 'children[]' });
|
|
107
|
+
p.eatMatchTrivia(_);
|
|
108
|
+
} while (p.match(/['"]/y));
|
|
109
|
+
return;
|
|
95
110
|
}
|
|
96
|
-
return { attrs: { isArray } };
|
|
97
|
-
}
|
|
98
111
|
|
|
99
|
-
|
|
100
|
-
Node(p, props) {
|
|
101
|
-
let open = p.eatProduction('OpenNodeTag', { path: 'open', noInterpolate: true }, props);
|
|
112
|
+
let open = p.eatProduction('OpenNodeTag', { path: 'openTag', noInterpolate: true }, props);
|
|
102
113
|
|
|
103
114
|
p.eatMatchTrivia(_);
|
|
104
115
|
|
|
105
|
-
if (open.attributes.
|
|
116
|
+
if (open.value.attributes.selfClosing) {
|
|
106
117
|
let token = !!get(['flags', 'token'], open);
|
|
107
118
|
|
|
108
119
|
while (p.atExpression || !(p.match(/<\/[^/]/y) || p.done)) {
|
|
@@ -110,7 +121,7 @@ export const grammar = class CSTMLMiniparserGrammar {
|
|
|
110
121
|
p.eatMatchTrivia(_);
|
|
111
122
|
}
|
|
112
123
|
|
|
113
|
-
p.eatProduction('CloseNodeTag', { path: '
|
|
124
|
+
p.eatProduction('CloseNodeTag', { path: 'closeTag', noInterpolate: true });
|
|
114
125
|
}
|
|
115
126
|
}
|
|
116
127
|
|
|
@@ -138,9 +149,8 @@ export const grammar = class CSTMLMiniparserGrammar {
|
|
|
138
149
|
}
|
|
139
150
|
}
|
|
140
151
|
|
|
141
|
-
// @Node
|
|
142
152
|
AttributeDefinition(p) {
|
|
143
|
-
p.eat('{', PN, { path: 'openToken'
|
|
153
|
+
p.eat('{', PN, { path: 'openToken' });
|
|
144
154
|
p.eatMatchTrivia(_);
|
|
145
155
|
p.eatProduction('IdentifierPath', { path: 'key' });
|
|
146
156
|
p.eatMatchTrivia(_);
|
|
@@ -148,88 +158,73 @@ export const grammar = class CSTMLMiniparserGrammar {
|
|
|
148
158
|
p.eatMatchTrivia(_);
|
|
149
159
|
p.eatProduction('JSON:Expression', { path: 'value' });
|
|
150
160
|
p.eatMatchTrivia(_);
|
|
151
|
-
p.eat('}', PN, { path: 'closeToken'
|
|
161
|
+
p.eat('}', PN, { path: 'closeToken' });
|
|
152
162
|
}
|
|
153
163
|
|
|
154
|
-
// @Node
|
|
155
164
|
Property(p) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
ref = p.eatProduction('ReferenceTag', { path: 'reference' });
|
|
165
|
+
if (p.match(/[a-zA-Z`\\\u{80}-\u{10ffff}.#@_]/uy)) {
|
|
166
|
+
p.eatProduction('ReferenceTag', { path: 'referenceTag' });
|
|
159
167
|
}
|
|
160
168
|
p.eatMatchTrivia(_);
|
|
161
|
-
|
|
162
|
-
p.eatProduction('BindingTag', { path: 'binding' });
|
|
163
|
-
p.eatMatchTrivia(_);
|
|
164
|
-
}
|
|
165
|
-
let refType = ref && get('type', ref);
|
|
166
|
-
p.eatProduction('PropertyValue', {
|
|
169
|
+
p.eatProduction('Expression', {
|
|
167
170
|
path: 'value',
|
|
168
|
-
allowFragment: refType && sourceTextFor(refType) === '_',
|
|
169
171
|
});
|
|
170
172
|
}
|
|
171
173
|
|
|
172
|
-
|
|
174
|
+
NullNode(p) {
|
|
175
|
+
p.eatProduction('NullTag', { path: 'sigilTag' });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
GapNode(p) {
|
|
179
|
+
p.eatProduction('GapTag', { path: 'sigilTag' });
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
Node(p) {
|
|
173
183
|
if (p.match('null')) {
|
|
174
|
-
p.eatProduction('
|
|
175
|
-
} else if (p.match(/\[\]|undefined/y)) {
|
|
176
|
-
p.eatProduction('InitializerTag');
|
|
184
|
+
p.eatProduction('NullNode');
|
|
177
185
|
} else if (p.match('<//>')) {
|
|
178
|
-
p.eatProduction('
|
|
186
|
+
p.eatProduction('GapNode');
|
|
187
|
+
} else if (p.match('</>') || p.match('<!')) {
|
|
188
|
+
p.fail();
|
|
179
189
|
} else {
|
|
180
|
-
p.eatProduction('
|
|
190
|
+
p.eatProduction('TreeNode', { propertyValue: true });
|
|
181
191
|
}
|
|
182
192
|
}
|
|
183
193
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
p.eatMatch('
|
|
187
|
-
p.eatMatch('$', PN, { path: 'hasGapToken' });
|
|
188
|
-
p.eatMatch('_', PN, { path: 'fragmentToken' });
|
|
189
|
-
p.eatMatch('_', PN, { path: 'multiFragmentToken' });
|
|
190
|
-
}
|
|
194
|
+
NodeFlags(p, props) {
|
|
195
|
+
let token = !!(p.eatMatch('*', PN, { path: 'tokenToken' }) || props.token);
|
|
196
|
+
let hasGap = !!p.eatMatch('$', PN, { path: 'hasGapToken' });
|
|
191
197
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (p.match(/['"]/y)) {
|
|
195
|
-
p.eatProduction('JSON:String', { path: 'literalValue' });
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
+
return { attrs: { token, hasGap } };
|
|
199
|
+
}
|
|
198
200
|
|
|
199
|
-
|
|
201
|
+
OpenNodeTag(p) {
|
|
202
|
+
p.eat('<', PN, { path: 'openToken' });
|
|
200
203
|
|
|
201
|
-
let flags = null;
|
|
202
204
|
if (!p.atExpression) {
|
|
203
|
-
|
|
205
|
+
p.eatProduction('NodeFlags', { path: 'flags' });
|
|
204
206
|
}
|
|
205
207
|
|
|
206
208
|
let sp = null;
|
|
207
209
|
|
|
208
|
-
let
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (propertyValue && fragmentFlag && !multiFragmentFlag) throw new Error();
|
|
213
|
-
|
|
214
|
-
if (forceFragment && !fragmentFlag) throw new Error();
|
|
215
|
-
|
|
216
|
-
if (!fragmentFlag && !p.match(/./sy)) {
|
|
217
|
-
throw new Error();
|
|
210
|
+
let type;
|
|
211
|
+
if ((type = p.match(/__|_/y))) {
|
|
212
|
+
p.eat(type, null, { path: 'type' });
|
|
218
213
|
}
|
|
219
214
|
|
|
220
|
-
if (
|
|
215
|
+
if (!type && !p.match(/./sy)) {
|
|
221
216
|
throw new Error();
|
|
222
217
|
}
|
|
223
218
|
|
|
224
|
-
if (
|
|
225
|
-
p.eatProduction('Identifier', { path: '
|
|
226
|
-
|
|
227
|
-
sp = p.eatMatchTrivia(_);
|
|
219
|
+
if (type !== '__' && p.match(/[a-zA-Z`u{80}-\u{10ffff}]/uy)) {
|
|
220
|
+
p.eatProduction('Identifier', { path: 'name' });
|
|
221
|
+
}
|
|
228
222
|
|
|
229
|
-
|
|
223
|
+
sp = p.eatMatchTrivia(_);
|
|
230
224
|
|
|
225
|
+
if (!type) {
|
|
231
226
|
if (sp && (p.match(/['"]/y) || p.atExpression)) {
|
|
232
|
-
|
|
227
|
+
p.eatProduction('JSON:String', { path: 'literalValue' });
|
|
233
228
|
|
|
234
229
|
sp = p.eatMatchTrivia(_);
|
|
235
230
|
}
|
|
@@ -242,48 +237,92 @@ export const grammar = class CSTMLMiniparserGrammar {
|
|
|
242
237
|
p.eatMatchTrivia(_);
|
|
243
238
|
}
|
|
244
239
|
let sc = p.eatMatch('/', PN, { path: 'selfClosingToken' });
|
|
245
|
-
p.eat('>', PN, { path: 'closeToken'
|
|
240
|
+
p.eat('>', PN, { path: 'closeToken' });
|
|
246
241
|
|
|
247
|
-
const
|
|
242
|
+
const selfClosing = !sc && (p.path.depth > 0 || p.span.type !== 'Bare');
|
|
248
243
|
|
|
249
|
-
return { attrs: {
|
|
244
|
+
return { attrs: { selfClosing } };
|
|
250
245
|
}
|
|
251
246
|
|
|
252
|
-
// @Node
|
|
253
247
|
CloseNodeTag(p) {
|
|
254
|
-
p.eat('</', PN, { path: 'openToken'
|
|
255
|
-
p.eat('>', PN, { path: 'closeToken'
|
|
248
|
+
p.eat('</', PN, { path: 'openToken' });
|
|
249
|
+
p.eat('>', PN, { path: 'closeToken' });
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
Expression(p) {
|
|
253
|
+
p.eatProduction('BoundNode');
|
|
254
|
+
|
|
255
|
+
p.eatMatchTrivia('_');
|
|
256
|
+
|
|
257
|
+
if (p.match('^^^')) {
|
|
258
|
+
return { shift: 'ShiftExpression' };
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
BoundNode(p) {
|
|
263
|
+
while (p.match(':')) {
|
|
264
|
+
p.eatProduction('BindingTag', { path: 'bindingTags' });
|
|
265
|
+
p.eatMatchTrivia(_);
|
|
266
|
+
}
|
|
267
|
+
p.eatProduction('Node', { path: 'node' });
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
ShiftExpression(p) {
|
|
271
|
+
p.eatProduction('BoundNode', { path: 'original' });
|
|
272
|
+
p.eatMatchTrivia(_);
|
|
273
|
+
p.eatProduction('ShiftTag', { path: 'sigilTag' });
|
|
274
|
+
p.eatMatchTrivia(_);
|
|
275
|
+
p.eatProduction('TreeNode', { path: 'value' });
|
|
256
276
|
}
|
|
257
277
|
|
|
258
|
-
// @Node
|
|
259
278
|
BindingTag(p) {
|
|
260
|
-
p.eat(':', PN, { path: 'openToken'
|
|
261
|
-
|
|
262
|
-
|
|
279
|
+
p.eat(':', PN, { path: 'openToken' });
|
|
280
|
+
|
|
281
|
+
p.eatMatchTrivia(_);
|
|
282
|
+
let first = true;
|
|
283
|
+
while (!p.match(':') && (first || p.match('/'))) {
|
|
284
|
+
if (!first) {
|
|
285
|
+
p.eat('/', PN, { path: '#separatorTokens' });
|
|
286
|
+
}
|
|
287
|
+
p.eatProduction('BindingSegment', { path: 'segments[]' });
|
|
288
|
+
p.eatMatchTrivia(_);
|
|
289
|
+
first = false;
|
|
263
290
|
}
|
|
264
|
-
p.eat(':', PN, { path: 'closeToken'
|
|
291
|
+
p.eat(':', PN, { path: 'closeToken' });
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
BindingSegment(p) {
|
|
295
|
+
p.eatMatchTrivia(_);
|
|
296
|
+
if (p.match('..')) {
|
|
297
|
+
p.eat('..', PN, { path: 'path' });
|
|
298
|
+
} else {
|
|
299
|
+
p.eatProduction('Identifier', { path: 'path' });
|
|
300
|
+
}
|
|
301
|
+
p.eatMatchTrivia(_);
|
|
265
302
|
}
|
|
266
303
|
|
|
267
304
|
IdentifierPath(p) {
|
|
268
|
-
|
|
269
|
-
while (p.match('.')) {
|
|
270
|
-
|
|
305
|
+
let first = true;
|
|
306
|
+
while (first || p.match('.')) {
|
|
307
|
+
if (!first) {
|
|
308
|
+
p.eat('.', PN, { path: '#separatorTokens' });
|
|
309
|
+
}
|
|
310
|
+
|
|
271
311
|
p.eatProduction('Identifier', { path: 'segments[]' });
|
|
312
|
+
first = false;
|
|
272
313
|
}
|
|
273
314
|
}
|
|
274
315
|
|
|
275
|
-
// @Node
|
|
276
316
|
Identifier(p) {
|
|
277
317
|
let res, q;
|
|
278
318
|
q = p.match('`');
|
|
279
|
-
if (q) p.eat('`', PN, { path: 'openToken'
|
|
319
|
+
if (q) p.eat('`', PN, { path: 'openToken' });
|
|
280
320
|
|
|
281
|
-
p.eatProduction('IdentifierContent', { path: 'content'
|
|
321
|
+
p.eatProduction('IdentifierContent', { path: 'content' }, { quoted: !!q });
|
|
282
322
|
|
|
283
|
-
if (q) p.eat('`', PN, { path: 'closeToken'
|
|
323
|
+
if (q) p.eat('`', PN, { path: 'closeToken' });
|
|
284
324
|
}
|
|
285
325
|
|
|
286
|
-
// @Node
|
|
287
326
|
IdentifierContent(p, props) {
|
|
288
327
|
let { quoted = false } = props || {};
|
|
289
328
|
|
|
@@ -301,19 +340,37 @@ export const grammar = class CSTMLMiniparserGrammar {
|
|
|
301
340
|
} while (lit || esc);
|
|
302
341
|
}
|
|
303
342
|
|
|
304
|
-
// @Cover
|
|
305
343
|
Tag(p) {
|
|
306
|
-
|
|
344
|
+
p.eatMatchTrivia(_);
|
|
345
|
+
if (p.match('{')) {
|
|
346
|
+
p.eatProduction('AttributeDefinition');
|
|
347
|
+
} else if (p.match('null')) {
|
|
348
|
+
p.eatProduction('NullTag');
|
|
349
|
+
} else if (p.match(/[.#@_a-zA-Z\u0060\u{80}-\u{10ffff}]/uy)) {
|
|
350
|
+
p.eatProduction('ReferenceTag');
|
|
351
|
+
} else if (p.match(':')) {
|
|
352
|
+
p.eatProduction('BindingTag');
|
|
353
|
+
} else if (p.match('<!')) {
|
|
354
|
+
p.eatProduction('DoctypeTag');
|
|
355
|
+
} else if (p.match('<//>')) {
|
|
356
|
+
p.eatProduction('GapTag');
|
|
357
|
+
} else if (p.match('^^^')) {
|
|
358
|
+
p.eatProduction('ShiftTag');
|
|
359
|
+
} else if (p.match('</')) {
|
|
360
|
+
p.eatProduction('CloseNodeTag');
|
|
361
|
+
} else if (p.match('<')) {
|
|
362
|
+
p.eatProduction('OpenNodeTag');
|
|
363
|
+
} else if (p.match(/['"]/y)) {
|
|
307
364
|
p.eatProduction('LiteralTag');
|
|
308
365
|
} else {
|
|
309
366
|
throw new Error();
|
|
310
367
|
}
|
|
368
|
+
p.eatMatchTrivia(_);
|
|
311
369
|
}
|
|
312
370
|
|
|
313
|
-
// @Node
|
|
314
371
|
ReferenceTag(p) {
|
|
315
372
|
let type;
|
|
316
|
-
if ((type = p.match(
|
|
373
|
+
if ((type = p.match(/\.\.|[.#@_]/y))) {
|
|
317
374
|
p.eat(type, PN, { path: 'type' });
|
|
318
375
|
}
|
|
319
376
|
|
|
@@ -322,16 +379,22 @@ export const grammar = class CSTMLMiniparserGrammar {
|
|
|
322
379
|
}
|
|
323
380
|
p.eatMatchTrivia(_);
|
|
324
381
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
p.eatMatchTrivia(_);
|
|
328
|
-
}
|
|
382
|
+
p.eatProduction('ReferenceFlags', { path: 'flags' });
|
|
383
|
+
p.eatMatchTrivia(_);
|
|
329
384
|
p.eat(':', PN, { path: 'mapToken' });
|
|
330
385
|
}
|
|
331
386
|
|
|
332
|
-
// @Node
|
|
333
387
|
ReferenceFlags(p) {
|
|
388
|
+
p.eatMatch('[]', PN, { path: 'arrayToken' });
|
|
334
389
|
p.eatMatch('+', PN, { path: 'expressionToken' });
|
|
335
|
-
p.eatMatch('
|
|
390
|
+
let i = p.eatMatch('*', PN, { path: 'intrinsicToken' });
|
|
391
|
+
let g = p.eatMatch('$', PN, { path: 'hasGapToken' });
|
|
392
|
+
if (i && g) p.fail();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
ShiftTag(p) {
|
|
396
|
+
p.eat('^^^', PN, { path: 'sigilToken' });
|
|
336
397
|
}
|
|
337
398
|
};
|
|
399
|
+
|
|
400
|
+
export default { name, canonicalURL, dependencies, covers, grammar };
|