@bablr/language-en-json 0.12.0 → 0.13.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/grammar.js +157 -148
- package/package.json +11 -14
- package/lib/grammar.macro.js +0 -285
package/lib/grammar.js
CHANGED
|
@@ -1,222 +1,231 @@
|
|
|
1
|
-
/* @macrome
|
|
2
|
-
* @generatedby @bablr/macrome-generator-bablr
|
|
3
|
-
* @generatedfrom ./grammar.macro.js#eb47e9a464d603cac4f3c0b96efeefd4b1e2ab7d
|
|
4
|
-
* This file is autogenerated. Please do not edit it directly.
|
|
5
|
-
* When editing run `npx macrome watch` then change the file this is generated from.
|
|
6
|
-
*/
|
|
7
|
-
import _applyDecs from "@babel/runtime/helpers/applyDecs2305";
|
|
8
|
-
let _initProto, _ExpressionDecs, _ArrayDecs, _ObjectDecs, _StringDecs, _NumberDecs, _InfinityDecs, _BooleanDecs, _NullDecs, _KeywordDecs, _PunctuatorDecs, _ListDecs, _AnyDecs, _AllDecs;
|
|
9
1
|
import { re, spam as m } from '@bablr/boot';
|
|
10
|
-
import { basicTriviaEnhancer } from '@bablr/helpers/trivia';
|
|
11
2
|
import * as productions from '@bablr/helpers/productions';
|
|
12
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
o,
|
|
5
|
+
eat,
|
|
6
|
+
eatMatch,
|
|
7
|
+
match,
|
|
8
|
+
fail,
|
|
9
|
+
defineAttribute,
|
|
10
|
+
startSpan,
|
|
11
|
+
endSpan,
|
|
12
|
+
} from '@bablr/helpers/grammar';
|
|
13
13
|
import { buildString } from '@bablr/helpers/builders';
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
import Space from '@bablr/language-en-blank-space';
|
|
15
|
+
import { get, printSource } from '@bablr/agast-helpers/tree';
|
|
16
|
+
|
|
17
|
+
export const dependencies = { Space };
|
|
18
|
+
|
|
19
19
|
export const canonicalURL = 'https://bablr.org/languages/core/en/json';
|
|
20
|
+
|
|
20
21
|
export const defaultMatcher = m`<_Expression />`;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
|
|
23
|
+
const escapables = new Map(
|
|
24
|
+
Object.entries({
|
|
25
|
+
b: '\b', // these two escapes are antiquated
|
|
26
|
+
f: '\f', // but giving their meaning away could be confusing
|
|
27
|
+
n: '\n',
|
|
28
|
+
r: '\r',
|
|
29
|
+
t: '\t',
|
|
30
|
+
0: '\0',
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export function* eatMatchTrivia() {
|
|
35
|
+
let trivia = null;
|
|
36
|
+
while (yield match(re`/[ \t\r\n]/`)) {
|
|
37
|
+
trivia = yield eat(m`#: :Space: <_Blank />`);
|
|
38
|
+
}
|
|
39
|
+
return trivia;
|
|
33
40
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
static {
|
|
39
|
-
[_initProto] = _applyDecs(this, [[_ExpressionDecs, 2, "Expression"], [_ArrayDecs, 2, "Array"], [_ObjectDecs, 2, "Object"], [Node, 2, "Property"], [_StringDecs, 2, "String"], [[AllowEmpty, Node], 2, "StringContent"], [Node, 2, "EscapeSequence"], [Node, 2, "EscapeCode"], [_NumberDecs, 2, "Number"], [Node, 2, "Integer"], [Node, 2, "UnsignedInteger"], [Node, 2, "UnsignedHexInteger"], [_InfinityDecs, 2, "Infinity"], [_BooleanDecs, 2, "Boolean"], [_NullDecs, 2, "Null"], [_KeywordDecs, 2, "Keyword"], [_PunctuatorDecs, 2, "Punctuator"], [_ListDecs, 2, "List"], [_AnyDecs, 2, "Any"], [_AllDecs, 2, "All"]], []).e;
|
|
40
|
-
}
|
|
41
|
+
|
|
42
|
+
export const fragmentProduction = 'Fragment';
|
|
43
|
+
|
|
44
|
+
export const grammar = class JSONGrammar {
|
|
41
45
|
constructor() {
|
|
42
|
-
|
|
46
|
+
this.emptyables = new Set(['StringContent', 'List']);
|
|
47
|
+
this.literals = new Set(['Keyword']);
|
|
43
48
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
}) {
|
|
49
|
-
// needed for the trivia plugin
|
|
49
|
+
|
|
50
|
+
*Fragment({ props: { rootMatcher } }) {
|
|
51
|
+
yield* eatMatchTrivia();
|
|
50
52
|
yield eat(rootMatcher);
|
|
53
|
+
yield* eatMatchTrivia();
|
|
51
54
|
}
|
|
55
|
+
|
|
52
56
|
*Expression() {
|
|
53
|
-
yield
|
|
57
|
+
if (yield eatMatch(m`<Array '[' />`)) {
|
|
58
|
+
} else if (yield eatMatch(m`<Object '{' />`)) {
|
|
59
|
+
} else if (yield eatMatch(m`<String /['"]/ />`)) {
|
|
60
|
+
} else if (yield eatMatch(m`<Number /\d|-[\d\g]/ />`)) {
|
|
61
|
+
} else if (yield eatMatch(m`<Null 'null' />`)) {
|
|
62
|
+
} else {
|
|
63
|
+
yield eatMatch(m`<Boolean /true|false/ />`);
|
|
64
|
+
}
|
|
54
65
|
}
|
|
66
|
+
|
|
55
67
|
*Array() {
|
|
56
|
-
yield eat(m`openToken
|
|
57
|
-
yield
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
yield eat(m`openToken*: <* '[' />`);
|
|
69
|
+
yield* eatMatchTrivia();
|
|
70
|
+
let sep = true;
|
|
71
|
+
|
|
72
|
+
while (sep && (yield match(re`/[^\]]/s`))) {
|
|
73
|
+
yield eat(m`elements[]$: <_Expression />`);
|
|
74
|
+
yield* eatMatchTrivia();
|
|
75
|
+
sep = yield eatMatch(m`#separatorTokens: <* ',' />`);
|
|
76
|
+
if (sep) {
|
|
77
|
+
yield* eatMatchTrivia();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
yield eat(m`closeToken*: <* ']' />`);
|
|
63
81
|
}
|
|
82
|
+
|
|
64
83
|
*Object() {
|
|
65
|
-
yield eat(m`openToken
|
|
84
|
+
yield eat(m`openToken*: <* '{' />`);
|
|
85
|
+
yield* eatMatchTrivia();
|
|
66
86
|
let sep = true;
|
|
67
|
-
|
|
68
|
-
yield
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
yield
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
87
|
+
|
|
88
|
+
while (sep && (yield match(re`/[^}]/s`))) {
|
|
89
|
+
yield match(m`<__All />`, [m`key$: <//>`, m`sigilToken*: <* ':' />`]);
|
|
90
|
+
yield eat(m`properties[]$: <Property />`);
|
|
91
|
+
yield* eatMatchTrivia();
|
|
92
|
+
sep = yield eatMatch(m`#separatorTokens: <* ',' />`);
|
|
93
|
+
if (sep) {
|
|
94
|
+
yield* eatMatchTrivia();
|
|
95
|
+
}
|
|
75
96
|
}
|
|
76
|
-
yield eat(m`closeToken
|
|
97
|
+
yield eat(m`closeToken*: <* '}' />`);
|
|
77
98
|
}
|
|
99
|
+
|
|
78
100
|
*Property() {
|
|
79
101
|
yield eat(m`key$: <String />`);
|
|
80
|
-
yield
|
|
81
|
-
yield eat(m`
|
|
102
|
+
yield* eatMatchTrivia();
|
|
103
|
+
yield eat(m`sigilToken*: <* ':' />`);
|
|
104
|
+
yield* eatMatchTrivia();
|
|
105
|
+
yield eat(m`value$: <_Expression />`);
|
|
82
106
|
}
|
|
107
|
+
|
|
83
108
|
*String() {
|
|
84
|
-
yield eat(m`openToken
|
|
109
|
+
yield eat(m`openToken*: <* '"' />`);
|
|
110
|
+
yield startSpan('String:Double', '"');
|
|
85
111
|
yield eat(m`content$: <*StringContent />`);
|
|
86
|
-
yield
|
|
112
|
+
yield endSpan();
|
|
113
|
+
yield eat(m`closeToken*: <* '"' />`);
|
|
87
114
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
span
|
|
91
|
-
}
|
|
92
|
-
}) {
|
|
115
|
+
|
|
116
|
+
*StringContent() {
|
|
93
117
|
let esc, lit;
|
|
94
118
|
do {
|
|
95
|
-
|
|
96
|
-
|
|
119
|
+
lit = yield eatMatch(re`/[^\r\n\\\g]+/`);
|
|
120
|
+
esc = yield eatMatch(m`@: <EscapeSequence '\\' />`);
|
|
97
121
|
} while (esc || lit);
|
|
98
122
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
yield fail();
|
|
107
|
-
}
|
|
108
|
-
yield eat(m`sigilToken: <*Punctuator '\\' { openSpan: 'Escape' } />`);
|
|
123
|
+
|
|
124
|
+
*EscapeSequence({ ctx }) {
|
|
125
|
+
let { getGapNode } = ctx;
|
|
126
|
+
|
|
127
|
+
yield startSpan('Escape');
|
|
128
|
+
yield eat(m`sigilToken*: <* '\\' />`);
|
|
129
|
+
|
|
109
130
|
let match_;
|
|
110
131
|
let cooked;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
132
|
+
|
|
133
|
+
if ((match_ = yield match(re`/[\\/bfnrt0"]/`))) {
|
|
134
|
+
const matchText = printSource(match_);
|
|
135
|
+
yield eat(m`code*: <*Keyword ${buildString(matchText)} />`);
|
|
136
|
+
|
|
114
137
|
cooked = escapables.get(matchText) || matchText;
|
|
115
138
|
} else if (yield match('u')) {
|
|
116
|
-
let codeNode = yield eat(m`code
|
|
117
|
-
|
|
139
|
+
let codeNode = yield eat(m`code*: <EscapeCode />`);
|
|
140
|
+
|
|
141
|
+
const type = printSource(get('typeToken', codeNode.node));
|
|
142
|
+
|
|
118
143
|
if (type) {
|
|
119
|
-
const value =
|
|
120
|
-
|
|
121
|
-
throw new Error('not implemented');
|
|
122
|
-
}
|
|
144
|
+
const value = printSource(getGapNode(get('value', codeNode.node)));
|
|
145
|
+
|
|
123
146
|
if (type === 'u') {
|
|
124
147
|
cooked = String.fromCharCode(parseInt(value, 16));
|
|
125
148
|
} else {
|
|
126
149
|
throw new Error();
|
|
127
150
|
}
|
|
128
151
|
} else {
|
|
129
|
-
let value =
|
|
152
|
+
let value = printSource(codeNode.node, { getGapNode });
|
|
130
153
|
cooked = escapables.get(value) || value;
|
|
131
154
|
}
|
|
132
155
|
} else {
|
|
133
156
|
yield fail();
|
|
134
157
|
}
|
|
158
|
+
|
|
159
|
+
// TODO error if we don't see the span ended
|
|
160
|
+
yield endSpan();
|
|
161
|
+
|
|
135
162
|
yield defineAttribute('cooked', cooked);
|
|
136
163
|
}
|
|
164
|
+
|
|
137
165
|
*EscapeCode() {
|
|
138
|
-
if (yield eatMatch(m`typeToken
|
|
139
|
-
if (yield eatMatch(m`openToken
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
yield
|
|
143
|
-
yield eat(m`closeToken
|
|
166
|
+
if (yield eatMatch(m`typeToken*: <*Keyword 'u' />`)) {
|
|
167
|
+
if (yield eatMatch(m`openToken*: <* '{' />`)) {
|
|
168
|
+
yield* eatMatchTrivia();
|
|
169
|
+
yield eat(m`value: <*UnsignedHexInteger />`);
|
|
170
|
+
yield* eatMatchTrivia();
|
|
171
|
+
yield eat(m`closeToken*: <* '}' />`);
|
|
144
172
|
} else {
|
|
145
|
-
yield eat(m`value
|
|
146
|
-
yield eat(m`closeToken: null`);
|
|
173
|
+
yield eat(m`value: <*UnsignedHexInteger /[\da-fA-F]{4}/ />`);
|
|
147
174
|
}
|
|
148
175
|
}
|
|
149
176
|
}
|
|
177
|
+
|
|
150
178
|
*Number() {
|
|
151
|
-
yield eat(m`wholePart$: <Integer />`, o({
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
let fs = yield eatMatch(m`fractionalSeparatorToken: <*Punctuator '.' />`, null, o({
|
|
156
|
-
bind: true
|
|
157
|
-
}));
|
|
179
|
+
yield eat(m`wholePart$: <Integer />`, o({ noDoubleZero: true, matchSign: '-' }));
|
|
180
|
+
|
|
181
|
+
let fs = yield eatMatch(m`fractionalSeparatorToken*: <* '.' />`);
|
|
182
|
+
|
|
158
183
|
if (fs) {
|
|
159
184
|
yield eat(m`fractionalPart$: <*UnsignedInteger />`);
|
|
160
185
|
} else {
|
|
161
186
|
yield eat(m`fractionalPart$: null`);
|
|
162
187
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
188
|
+
|
|
189
|
+
let es = yield eatMatch(m`exponentSeparatorToken*: <* /[eE]/ />`);
|
|
190
|
+
|
|
166
191
|
if (es) {
|
|
167
|
-
yield eat(m`exponentPart$: <Integer />`, {
|
|
168
|
-
matchSign: /[+-]/
|
|
169
|
-
});
|
|
192
|
+
yield eat(m`exponentPart$: <Integer />`, { matchSign: /[+-]/ });
|
|
170
193
|
} else {
|
|
171
194
|
yield eat(m`exponentPart$: null`);
|
|
172
195
|
}
|
|
173
196
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
matchSign = null,
|
|
177
|
-
noDoubleZero = false
|
|
178
|
-
}
|
|
179
|
-
}) {
|
|
197
|
+
|
|
198
|
+
*Integer({ props: { matchSign = null, noDoubleZero = false } }) {
|
|
180
199
|
if (matchSign) {
|
|
181
|
-
yield eatMatch(m`signToken
|
|
182
|
-
bind: true
|
|
183
|
-
}));
|
|
184
|
-
} else {
|
|
185
|
-
yield eat(m`signToken: null`);
|
|
200
|
+
yield eatMatch(m`signToken*: <* ${buildString(matchSign)} />`);
|
|
186
201
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
*UnsignedInteger({
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
},
|
|
195
|
-
ctx
|
|
196
|
-
}) {
|
|
197
|
-
let firstDigit = ctx.sourceTextFor(yield eat(re`/\d/`));
|
|
202
|
+
|
|
203
|
+
yield eat(m`value$: <*UnsignedInteger />`, o({ noDoubleZero }));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
*UnsignedInteger({ props: { noDoubleZero = false } }) {
|
|
207
|
+
let firstDigit = printSource(yield eat(re`/\d/`));
|
|
208
|
+
|
|
198
209
|
if (!noDoubleZero || firstDigit.value !== '0') {
|
|
199
210
|
yield eatMatch(re`/\d+/`);
|
|
200
211
|
}
|
|
201
212
|
}
|
|
213
|
+
|
|
202
214
|
*UnsignedHexInteger() {
|
|
203
215
|
yield eatMatch(re`/[\da-fA-F]+/`);
|
|
204
216
|
}
|
|
205
|
-
|
|
206
|
-
yield eatMatch(m`signToken: <*Punctuator '-' />`, null, o({
|
|
207
|
-
bind: true
|
|
208
|
-
}));
|
|
209
|
-
yield eat(m`sigilToken: <*Keyword 'Infinity' />`);
|
|
210
|
-
}
|
|
217
|
+
|
|
211
218
|
*Boolean() {
|
|
212
|
-
yield eat(m`sigilToken
|
|
219
|
+
yield eat(m`sigilToken*: <*Keyword /true|false/ />`);
|
|
213
220
|
}
|
|
221
|
+
|
|
214
222
|
*Null() {
|
|
215
|
-
yield eat(m`sigilToken
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
yield eat(m`sigilToken*: <*Keyword 'null' />`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
All(args) {
|
|
227
|
+
return productions.All(args);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
export default { canonicalURL, dependencies, grammar, defaultMatcher, fragmentProduction };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bablr/language-en-json",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.1",
|
|
4
4
|
"description": "A BABLR language for JSON",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=12.0.0"
|
|
@@ -14,26 +14,20 @@
|
|
|
14
14
|
"lib/**/*.js"
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "macrome build",
|
|
18
|
-
"watch": "macrome watch",
|
|
19
|
-
"clean": "macrome clean",
|
|
20
17
|
"test": "mocha"
|
|
21
18
|
},
|
|
22
19
|
"sideEffects": false,
|
|
23
20
|
"dependencies": {
|
|
24
|
-
"@bablr/agast-helpers": "0.
|
|
25
|
-
"@bablr/agast-vm-helpers": "0.
|
|
26
|
-
"@bablr/boot": "0.
|
|
27
|
-
"@bablr/helpers": "0.
|
|
28
|
-
"@bablr/language-en-blank-space": "0.
|
|
29
|
-
"@babel/runtime": "7.28.2"
|
|
21
|
+
"@bablr/agast-helpers": "0.10.2",
|
|
22
|
+
"@bablr/agast-vm-helpers": "0.10.2",
|
|
23
|
+
"@bablr/boot": "0.11.1",
|
|
24
|
+
"@bablr/helpers": "0.25.1",
|
|
25
|
+
"@bablr/language-en-blank-space": "0.10.1"
|
|
30
26
|
},
|
|
31
27
|
"devDependencies": {
|
|
32
28
|
"@bablr/eslint-config-base": "github:bablr-lang/eslint-config-base#c97bfa4b3663f8378e9b3e42bb5a41e685406cf9",
|
|
33
|
-
"@bablr/macrome": "^0.1.3",
|
|
34
|
-
"@bablr/macrome-generator-bablr": "^0.3.2",
|
|
35
29
|
"@qnighy/dedent": "0.1.1",
|
|
36
|
-
"bablr": "^0.
|
|
30
|
+
"bablr": "^0.11.2",
|
|
37
31
|
"enhanced-resolve": "^5.12.0",
|
|
38
32
|
"eslint": "^7.32.0",
|
|
39
33
|
"eslint-import-resolver-enhanced-resolve": "^1.0.5",
|
|
@@ -48,7 +42,10 @@
|
|
|
48
42
|
"grammar",
|
|
49
43
|
"english"
|
|
50
44
|
],
|
|
51
|
-
"repository":
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+ssh://git@github.com/bablr-lang/language-en-json.git"
|
|
48
|
+
},
|
|
52
49
|
"homepage": "https://github.com/bablr-lang/language-en-json",
|
|
53
50
|
"author": "Conrad Buck <conartist6@gmail.com>",
|
|
54
51
|
"license": "MIT"
|
package/lib/grammar.macro.js
DELETED
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
import { re, spam as m } from '@bablr/boot';
|
|
2
|
-
import { basicTriviaEnhancer } from '@bablr/helpers/trivia';
|
|
3
|
-
import * as productions from '@bablr/helpers/productions';
|
|
4
|
-
import { o, eat, eatMatch, match, fail, defineAttribute } from '@bablr/helpers/grammar';
|
|
5
|
-
import { buildString } from '@bablr/helpers/builders';
|
|
6
|
-
import { Node, CoveredBy, AllowEmpty, InjectFrom, Literal } from '@bablr/helpers/decorators';
|
|
7
|
-
import * as Space from '@bablr/language-en-blank-space';
|
|
8
|
-
|
|
9
|
-
export const dependencies = { Space };
|
|
10
|
-
|
|
11
|
-
export const canonicalURL = 'https://bablr.org/languages/core/en/json';
|
|
12
|
-
|
|
13
|
-
export const defaultMatcher = m`<_Expression />`;
|
|
14
|
-
|
|
15
|
-
const escapables = new Map(
|
|
16
|
-
Object.entries({
|
|
17
|
-
b: '\b', // these two escapes are antiquated
|
|
18
|
-
f: '\f', // but giving their meaning away could be confusing
|
|
19
|
-
n: '\n',
|
|
20
|
-
r: '\r',
|
|
21
|
-
t: '\t',
|
|
22
|
-
0: '\0',
|
|
23
|
-
}),
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
function first(iter) {
|
|
27
|
-
for (let value of iter) return value;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const grammar = basicTriviaEnhancer(
|
|
31
|
-
{
|
|
32
|
-
triviaIsAllowed: (s) => s.span === 'Bare',
|
|
33
|
-
triviaMatcher: m`#: :Space: <*Space /[ \n\r\t]/ />`,
|
|
34
|
-
},
|
|
35
|
-
class JSONGrammar {
|
|
36
|
-
*[Symbol.for('@bablr/fragment')]({ props: { rootMatcher } }) {
|
|
37
|
-
// needed for the trivia plugin
|
|
38
|
-
yield eat(rootMatcher);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
@CoveredBy('Element')
|
|
42
|
-
*Expression() {
|
|
43
|
-
yield eat(m`<__Any />`, [
|
|
44
|
-
m`<Array '[' />`,
|
|
45
|
-
m`<Object '{' />`,
|
|
46
|
-
m`<String /['"]/ />`,
|
|
47
|
-
m`<Number /\d|-[\d\g]/ {span: 'Number'} />`,
|
|
48
|
-
m`<Infinity /-?Infinity/ />`,
|
|
49
|
-
m`<Null 'null' />`,
|
|
50
|
-
m`<Boolean /true|false/ />`,
|
|
51
|
-
]);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
@CoveredBy('Expression')
|
|
55
|
-
@Node
|
|
56
|
-
*Array() {
|
|
57
|
-
yield eat(m`openToken: <*Punctuator '[' { balanced: ']' } />`);
|
|
58
|
-
yield eat(
|
|
59
|
-
m`<__List />`,
|
|
60
|
-
o({
|
|
61
|
-
element: m`elements[]+$: <_Expression />`,
|
|
62
|
-
separator: m`#separatorTokens[]: <*Punctuator ',' />`,
|
|
63
|
-
allowTrailingSeparator: false,
|
|
64
|
-
}),
|
|
65
|
-
);
|
|
66
|
-
yield eat(m`closeToken: <*Punctuator ']' { balancer: true } />`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
@CoveredBy('Expression')
|
|
70
|
-
@Node
|
|
71
|
-
*Object() {
|
|
72
|
-
yield eat(m`openToken: <*Punctuator '{' { balanced: '}' } />`);
|
|
73
|
-
let sep = true;
|
|
74
|
-
|
|
75
|
-
yield eatMatch(m`#separatorTokens[]: []`);
|
|
76
|
-
yield eatMatch(m`properties[]$: []`);
|
|
77
|
-
|
|
78
|
-
while (sep && (yield match(re`/.|\g/s`))) {
|
|
79
|
-
let suppressGap = !!(yield match(m`<__All />`, [
|
|
80
|
-
m`key: <//>`,
|
|
81
|
-
m`sigilToken: <*Punctuator ':' />`,
|
|
82
|
-
]));
|
|
83
|
-
yield eat(m`properties[]$: <Property />`, null, o({ suppressGap }));
|
|
84
|
-
sep = yield eatMatch(m`#separatorTokens[]: <*Punctuator ',' />`);
|
|
85
|
-
}
|
|
86
|
-
yield eat(m`closeToken: <*Punctuator '}' { balancer: true } />`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
@Node
|
|
90
|
-
*Property() {
|
|
91
|
-
yield eat(m`key$: <String />`);
|
|
92
|
-
yield eat(m`sigilToken: <*Punctuator ':' />`);
|
|
93
|
-
yield eat(m`value+$: <_Expression />`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
@CoveredBy('Expression')
|
|
97
|
-
@Node
|
|
98
|
-
*String() {
|
|
99
|
-
yield eat(m`openToken: <*Punctuator '"' { balanced: '"', balancedSpan: 'String:Double' } />`);
|
|
100
|
-
|
|
101
|
-
yield eat(m`content$: <*StringContent />`);
|
|
102
|
-
|
|
103
|
-
yield eat(m`closeToken: <*Punctuator '"' { balancer: true } />`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
@AllowEmpty
|
|
107
|
-
@Node
|
|
108
|
-
*StringContent({ state: { span } }) {
|
|
109
|
-
let esc, lit;
|
|
110
|
-
do {
|
|
111
|
-
esc = (yield match('\\')) && (yield eat(m`@: <EscapeSequence />`));
|
|
112
|
-
lit =
|
|
113
|
-
span === 'String:Single'
|
|
114
|
-
? yield eatMatch(re`/[^\r\n\\'\g]+/`)
|
|
115
|
-
: yield eatMatch(re`/[^\r\n\\"\g]+/`);
|
|
116
|
-
} while (esc || lit);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
@Node
|
|
120
|
-
*EscapeSequence({ state: { span }, ctx }) {
|
|
121
|
-
if (!span.startsWith('String')) {
|
|
122
|
-
yield fail();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
yield eat(m`sigilToken: <*Punctuator '\\' { openSpan: 'Escape' } />`);
|
|
126
|
-
|
|
127
|
-
let match_;
|
|
128
|
-
let cooked;
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
(match_ =
|
|
132
|
-
span === 'String:Single'
|
|
133
|
-
? yield match(re`/[\\/bfnrt0']/`)
|
|
134
|
-
: yield match(re`/[\\/bfnrt0"]/`))
|
|
135
|
-
) {
|
|
136
|
-
const matchText = ctx.sourceTextFor(match_);
|
|
137
|
-
yield eat(m`code: <*Keyword ${buildString(matchText)} { closeSpan: 'Escape' } />`);
|
|
138
|
-
|
|
139
|
-
cooked = escapables.get(matchText) || matchText;
|
|
140
|
-
} else if (yield match('u')) {
|
|
141
|
-
let codeNode = yield eat(m`code: <EscapeCode { closeSpan: 'Escape' } />`);
|
|
142
|
-
|
|
143
|
-
const type = ctx.sourceTextFor(codeNode.get('typeToken'));
|
|
144
|
-
|
|
145
|
-
if (type) {
|
|
146
|
-
const value = ctx.sourceTextFor(codeNode.get('value'));
|
|
147
|
-
|
|
148
|
-
if (!span.startsWith('String')) {
|
|
149
|
-
throw new Error('not implemented');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (type === 'u') {
|
|
153
|
-
cooked = String.fromCharCode(parseInt(value, 16));
|
|
154
|
-
} else {
|
|
155
|
-
throw new Error();
|
|
156
|
-
}
|
|
157
|
-
} else {
|
|
158
|
-
let value = ctx.sourceTextFor(codeNode);
|
|
159
|
-
cooked = escapables.get(value) || value;
|
|
160
|
-
}
|
|
161
|
-
} else {
|
|
162
|
-
yield fail();
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
yield defineAttribute('cooked', cooked);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
@Node
|
|
169
|
-
*EscapeCode() {
|
|
170
|
-
if (yield eatMatch(m`typeToken: <*Keyword 'u' />`)) {
|
|
171
|
-
if (
|
|
172
|
-
yield eatMatch(
|
|
173
|
-
m`openToken: <*Punctuator '{' { balanced: '}' } />`,
|
|
174
|
-
null,
|
|
175
|
-
o({ bind: true }),
|
|
176
|
-
)
|
|
177
|
-
) {
|
|
178
|
-
yield eat(m`value$: <*UnsignedHexInteger />`);
|
|
179
|
-
yield eat(m`closeToken: <*Punctuator '}' { balancer: true } />`);
|
|
180
|
-
} else {
|
|
181
|
-
yield eat(m`value$: <*UnsignedHexInteger /[\da-fA-F]{4}/ />`);
|
|
182
|
-
yield eat(m`closeToken: null`);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
@CoveredBy('Expression')
|
|
188
|
-
@Node
|
|
189
|
-
*Number() {
|
|
190
|
-
yield eat(m`wholePart$: <Integer />`, o({ noDoubleZero: true, matchSign: '-' }));
|
|
191
|
-
|
|
192
|
-
let fs = yield eatMatch(
|
|
193
|
-
m`fractionalSeparatorToken: <*Punctuator '.' />`,
|
|
194
|
-
null,
|
|
195
|
-
o({ bind: true }),
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
if (fs) {
|
|
199
|
-
yield eat(m`fractionalPart$: <*UnsignedInteger />`);
|
|
200
|
-
} else {
|
|
201
|
-
yield eat(m`fractionalPart$: null`);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
let es = yield eatMatch(
|
|
205
|
-
m`exponentSeparatorToken: <*Punctuator /[eE]/ />`,
|
|
206
|
-
null,
|
|
207
|
-
o({ bind: true }),
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
if (es) {
|
|
211
|
-
yield eat(m`exponentPart$: <Integer />`, { matchSign: /[+-]/ });
|
|
212
|
-
} else {
|
|
213
|
-
yield eat(m`exponentPart$: null`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
@Node
|
|
218
|
-
*Integer({ props: { matchSign = null, noDoubleZero = false } }) {
|
|
219
|
-
if (matchSign) {
|
|
220
|
-
yield eatMatch(
|
|
221
|
-
m`signToken: <*Punctuator ${buildString(matchSign)} />`,
|
|
222
|
-
null,
|
|
223
|
-
o({ bind: true }),
|
|
224
|
-
);
|
|
225
|
-
} else {
|
|
226
|
-
yield eat(m`signToken: null`);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
yield eat(m`value$: <*UnsignedInteger />`, o({ noDoubleZero }));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
@Node
|
|
233
|
-
*UnsignedInteger({ props: { noDoubleZero = false }, ctx }) {
|
|
234
|
-
let firstDigit = ctx.sourceTextFor(yield eat(re`/\d/`));
|
|
235
|
-
|
|
236
|
-
if (!noDoubleZero || firstDigit.value !== '0') {
|
|
237
|
-
yield eatMatch(re`/\d+/`);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
@Node
|
|
242
|
-
*UnsignedHexInteger() {
|
|
243
|
-
yield eatMatch(re`/[\da-fA-F]+/`);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
@CoveredBy('Expression')
|
|
247
|
-
@Node
|
|
248
|
-
*Infinity() {
|
|
249
|
-
yield eatMatch(m`signToken: <*Punctuator '-' />`, null, o({ bind: true }));
|
|
250
|
-
yield eat(m`sigilToken: <*Keyword 'Infinity' />`);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
@CoveredBy('Expression')
|
|
254
|
-
@Node
|
|
255
|
-
*Boolean() {
|
|
256
|
-
yield eat(m`sigilToken: <*Keyword /true|false/ />`);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
@CoveredBy('Expression')
|
|
260
|
-
@Node
|
|
261
|
-
*Null() {
|
|
262
|
-
yield eat(m`sigilToken: <*Keyword 'null' />`);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
@Literal
|
|
266
|
-
@Node
|
|
267
|
-
@InjectFrom(productions)
|
|
268
|
-
*Keyword() {}
|
|
269
|
-
|
|
270
|
-
@Literal
|
|
271
|
-
@Node
|
|
272
|
-
@InjectFrom(productions)
|
|
273
|
-
*Punctuator() {}
|
|
274
|
-
|
|
275
|
-
@AllowEmpty
|
|
276
|
-
@InjectFrom(productions)
|
|
277
|
-
*List() {}
|
|
278
|
-
|
|
279
|
-
@InjectFrom(productions)
|
|
280
|
-
*Any() {}
|
|
281
|
-
|
|
282
|
-
@InjectFrom(productions)
|
|
283
|
-
*All() {}
|
|
284
|
-
},
|
|
285
|
-
);
|