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