@bablr/language-en-json 0.11.0 → 0.13.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/grammar.js +162 -158
- package/package.json +11 -14
- package/lib/grammar.macro.js +0 -285
package/lib/grammar.js
CHANGED
|
@@ -1,225 +1,229 @@
|
|
|
1
|
-
/* @macrome
|
|
2
|
-
* @generatedby @bablr/macrome-generator-bablr
|
|
3
|
-
* @generatedfrom ./grammar.macro.js#dd06bed2bba53b9dde1ae7cf33f8696edb684bd6
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
|
|
21
|
+
export const defaultMatcher = m`<_Expression />`;
|
|
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;
|
|
32
40
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
static {
|
|
38
|
-
[_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;
|
|
39
|
-
}
|
|
41
|
+
|
|
42
|
+
export const fragmentProduction = 'Fragment';
|
|
43
|
+
|
|
44
|
+
export const grammar = class JSONGrammar {
|
|
40
45
|
constructor() {
|
|
41
|
-
|
|
46
|
+
this.emptyables = new Set(['StringContent', 'List']);
|
|
47
|
+
this.literals = new Set(['Keyword']);
|
|
42
48
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
}) {
|
|
48
|
-
// needed for the trivia plugin
|
|
49
|
+
|
|
50
|
+
*Fragment({ props: { rootMatcher } }) {
|
|
51
|
+
yield* eatMatchTrivia();
|
|
49
52
|
yield eat(rootMatcher);
|
|
53
|
+
yield* eatMatchTrivia();
|
|
50
54
|
}
|
|
55
|
+
|
|
51
56
|
*Expression() {
|
|
52
|
-
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
|
+
}
|
|
53
65
|
}
|
|
66
|
+
|
|
54
67
|
*Array() {
|
|
55
|
-
yield eat(m`openToken
|
|
56
|
-
yield
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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*: <* ']' />`);
|
|
62
81
|
}
|
|
82
|
+
|
|
63
83
|
*Object() {
|
|
64
|
-
yield eat(m`openToken
|
|
84
|
+
yield eat(m`openToken*: <* '{' />`);
|
|
85
|
+
yield* eatMatchTrivia();
|
|
65
86
|
let sep = true;
|
|
66
|
-
|
|
67
|
-
yield
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
yield
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
+
}
|
|
74
96
|
}
|
|
75
|
-
yield eat(m`closeToken
|
|
97
|
+
yield eat(m`closeToken*: <* '}' />`);
|
|
76
98
|
}
|
|
99
|
+
|
|
77
100
|
*Property() {
|
|
78
101
|
yield eat(m`key$: <String />`);
|
|
79
|
-
yield
|
|
80
|
-
yield eat(m`
|
|
102
|
+
yield* eatMatchTrivia();
|
|
103
|
+
yield eat(m`sigilToken*: <* ':' />`);
|
|
104
|
+
yield* eatMatchTrivia();
|
|
105
|
+
yield eat(m`value+$: <_Expression />`);
|
|
81
106
|
}
|
|
107
|
+
|
|
82
108
|
*String() {
|
|
83
|
-
yield eat(m`openToken
|
|
109
|
+
yield eat(m`openToken*: <* '"' />`);
|
|
110
|
+
yield startSpan('String:Double', '"');
|
|
84
111
|
yield eat(m`content$: <*StringContent />`);
|
|
85
|
-
yield
|
|
112
|
+
yield endSpan();
|
|
113
|
+
yield eat(m`closeToken*: <* '"' />`);
|
|
86
114
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
span
|
|
90
|
-
}
|
|
91
|
-
}) {
|
|
115
|
+
|
|
116
|
+
*StringContent() {
|
|
92
117
|
let esc, lit;
|
|
93
118
|
do {
|
|
94
|
-
|
|
95
|
-
|
|
119
|
+
lit = yield eatMatch(re`/[^\r\n\\\g]+/`);
|
|
120
|
+
esc = yield eatMatch(m`@: <EscapeSequence '\\' />`);
|
|
96
121
|
} while (esc || lit);
|
|
97
122
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}) {
|
|
104
|
-
if (!span.startsWith('String')) {
|
|
105
|
-
yield fail();
|
|
106
|
-
}
|
|
107
|
-
yield eat(m`sigilToken: <*Punctuator '\\' { openSpan: 'Escape' } />`);
|
|
123
|
+
|
|
124
|
+
*EscapeSequence() {
|
|
125
|
+
yield startSpan('Escape');
|
|
126
|
+
yield eat(m`sigilToken*: <* '\\' />`);
|
|
127
|
+
|
|
108
128
|
let match_;
|
|
109
129
|
let cooked;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
130
|
+
|
|
131
|
+
if ((match_ = yield match(re`/[\\/bfnrt0"]/`))) {
|
|
132
|
+
const matchText = printSource(match_);
|
|
133
|
+
yield eat(m`code*: <*Keyword ${buildString(matchText)} />`);
|
|
134
|
+
|
|
113
135
|
cooked = escapables.get(matchText) || matchText;
|
|
114
136
|
} else if (yield match('u')) {
|
|
115
|
-
let codeNode = yield eat(m`code
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
if (type === 'u') {
|
|
126
|
-
cooked = String.fromCharCode(parseInt(value, 16));
|
|
127
|
-
} else {
|
|
128
|
-
throw new Error();
|
|
129
|
-
}
|
|
137
|
+
let codeNode = yield eat(m`code*: <EscapeCode />`);
|
|
138
|
+
|
|
139
|
+
const type = printSource(get('typeToken', codeNode.node));
|
|
140
|
+
|
|
141
|
+
if (type) {
|
|
142
|
+
const value = printSource(get('value', codeNode.node));
|
|
143
|
+
|
|
144
|
+
if (type === 'u') {
|
|
145
|
+
cooked = String.fromCharCode(parseInt(value, 16));
|
|
130
146
|
} else {
|
|
131
|
-
|
|
132
|
-
cooked = escapables.get(value) || value;
|
|
147
|
+
throw new Error();
|
|
133
148
|
}
|
|
149
|
+
} else {
|
|
150
|
+
let value = printSource(codeNode.node);
|
|
151
|
+
cooked = escapables.get(value) || value;
|
|
134
152
|
}
|
|
135
153
|
} else {
|
|
136
154
|
yield fail();
|
|
137
155
|
}
|
|
156
|
+
|
|
157
|
+
// TODO error if we don't see the span ended
|
|
158
|
+
yield endSpan();
|
|
159
|
+
|
|
138
160
|
yield defineAttribute('cooked', cooked);
|
|
139
161
|
}
|
|
162
|
+
|
|
140
163
|
*EscapeCode() {
|
|
141
|
-
if (yield eatMatch(m`typeToken
|
|
142
|
-
if (yield eatMatch(m`openToken
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
yield
|
|
146
|
-
yield eat(m`closeToken
|
|
164
|
+
if (yield eatMatch(m`typeToken*: <*Keyword 'u' />`)) {
|
|
165
|
+
if (yield eatMatch(m`openToken*: <* '{' />`)) {
|
|
166
|
+
yield* eatMatchTrivia();
|
|
167
|
+
yield eat(m`value: <*UnsignedHexInteger />`);
|
|
168
|
+
yield* eatMatchTrivia();
|
|
169
|
+
yield eat(m`closeToken*: <* '}' />`);
|
|
147
170
|
} else {
|
|
148
|
-
yield eat(m`value
|
|
149
|
-
yield eat(m`closeToken: null`);
|
|
171
|
+
yield eat(m`value: <*UnsignedHexInteger /[\da-fA-F]{4}/ />`);
|
|
150
172
|
}
|
|
151
173
|
}
|
|
152
174
|
}
|
|
175
|
+
|
|
153
176
|
*Number() {
|
|
154
|
-
yield eat(m`wholePart$: <Integer />`, o({
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
let fs = yield eatMatch(m`fractionalSeparatorToken: <*Punctuator '.' />`, null, o({
|
|
159
|
-
bind: true
|
|
160
|
-
}));
|
|
177
|
+
yield eat(m`wholePart$: <Integer />`, o({ noDoubleZero: true, matchSign: '-' }));
|
|
178
|
+
|
|
179
|
+
let fs = yield eatMatch(m`fractionalSeparatorToken*: <* '.' />`);
|
|
180
|
+
|
|
161
181
|
if (fs) {
|
|
162
182
|
yield eat(m`fractionalPart$: <*UnsignedInteger />`);
|
|
163
183
|
} else {
|
|
164
184
|
yield eat(m`fractionalPart$: null`);
|
|
165
185
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
186
|
+
|
|
187
|
+
let es = yield eatMatch(m`exponentSeparatorToken*: <* /[eE]/ />`);
|
|
188
|
+
|
|
169
189
|
if (es) {
|
|
170
|
-
yield eat(m`exponentPart$: <Integer />`, {
|
|
171
|
-
matchSign: /[+-]/
|
|
172
|
-
});
|
|
190
|
+
yield eat(m`exponentPart$: <Integer />`, { matchSign: /[+-]/ });
|
|
173
191
|
} else {
|
|
174
192
|
yield eat(m`exponentPart$: null`);
|
|
175
193
|
}
|
|
176
194
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
matchSign = null,
|
|
180
|
-
noDoubleZero = false
|
|
181
|
-
}
|
|
182
|
-
}) {
|
|
195
|
+
|
|
196
|
+
*Integer({ props: { matchSign = null, noDoubleZero = false } }) {
|
|
183
197
|
if (matchSign) {
|
|
184
|
-
yield eatMatch(m`signToken
|
|
185
|
-
bind: true
|
|
186
|
-
}));
|
|
187
|
-
} else {
|
|
188
|
-
yield eat(m`signToken: null`);
|
|
198
|
+
yield eatMatch(m`signToken*: <* ${buildString(matchSign)} />`);
|
|
189
199
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
*UnsignedInteger({
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
},
|
|
198
|
-
ctx
|
|
199
|
-
}) {
|
|
200
|
-
let firstDigit = ctx.sourceTextFor(yield eat(re`/\d/`));
|
|
200
|
+
|
|
201
|
+
yield eat(m`value$: <*UnsignedInteger />`, o({ noDoubleZero }));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
*UnsignedInteger({ props: { noDoubleZero = false } }) {
|
|
205
|
+
let firstDigit = printSource(yield eat(re`/\d/`));
|
|
206
|
+
|
|
201
207
|
if (!noDoubleZero || firstDigit.value !== '0') {
|
|
202
208
|
yield eatMatch(re`/\d+/`);
|
|
203
209
|
}
|
|
204
210
|
}
|
|
211
|
+
|
|
205
212
|
*UnsignedHexInteger() {
|
|
206
213
|
yield eatMatch(re`/[\da-fA-F]+/`);
|
|
207
214
|
}
|
|
208
|
-
|
|
209
|
-
yield eatMatch(m`signToken: <*Punctuator '-' />`, null, o({
|
|
210
|
-
bind: true
|
|
211
|
-
}));
|
|
212
|
-
yield eat(m`sigilToken: <*Keyword 'Infinity' />`);
|
|
213
|
-
}
|
|
215
|
+
|
|
214
216
|
*Boolean() {
|
|
215
|
-
yield eat(m`sigilToken
|
|
217
|
+
yield eat(m`sigilToken*: <*Keyword /true|false/ />`);
|
|
216
218
|
}
|
|
219
|
+
|
|
217
220
|
*Null() {
|
|
218
|
-
yield eat(m`sigilToken
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
221
|
+
yield eat(m`sigilToken*: <*Keyword 'null' />`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
All(args) {
|
|
225
|
+
return productions.All(args);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
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.0",
|
|
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.22.15"
|
|
21
|
+
"@bablr/agast-helpers": "0.10.0",
|
|
22
|
+
"@bablr/agast-vm-helpers": "0.10.0",
|
|
23
|
+
"@bablr/boot": "0.11.0",
|
|
24
|
+
"@bablr/helpers": "0.25.0",
|
|
25
|
+
"@bablr/language-en-blank-space": "0.10.0"
|
|
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.0",
|
|
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
|
-
const escapables = new Map(
|
|
14
|
-
Object.entries({
|
|
15
|
-
b: '\b', // these two escapes are antiquated
|
|
16
|
-
f: '\f', // but giving their meaning away could be confusing
|
|
17
|
-
n: '\n',
|
|
18
|
-
r: '\r',
|
|
19
|
-
t: '\t',
|
|
20
|
-
0: '\0',
|
|
21
|
-
}),
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
function first(iter) {
|
|
25
|
-
for (let value of iter) return value;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const grammar = basicTriviaEnhancer(
|
|
29
|
-
{
|
|
30
|
-
triviaIsAllowed: (s) => s.span === 'Bare',
|
|
31
|
-
triviaMatcher: m`#: :Space: <*Space /[ \n\r\t]/ />`,
|
|
32
|
-
},
|
|
33
|
-
class JSONGrammar {
|
|
34
|
-
*[Symbol.for('@bablr/fragment')]({ props: { rootMatcher } }) {
|
|
35
|
-
// needed for the trivia plugin
|
|
36
|
-
yield eat(rootMatcher);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@CoveredBy('Element')
|
|
40
|
-
*Expression() {
|
|
41
|
-
yield eat(m`<_Any />`, [
|
|
42
|
-
m`<Array '[' />`,
|
|
43
|
-
m`<Object '{' />`,
|
|
44
|
-
m`<String /['"]/ />`,
|
|
45
|
-
m`<Number /\d|-[\d\g]/ {span: 'Number'} />`,
|
|
46
|
-
m`<Infinity /-?Infinity/ />`,
|
|
47
|
-
m`<Null 'null' />`,
|
|
48
|
-
m`<Boolean /true|false/ />`,
|
|
49
|
-
]);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
@CoveredBy('Expression')
|
|
53
|
-
@Node
|
|
54
|
-
*Array() {
|
|
55
|
-
yield eat(m`openToken: <*Punctuator '[' { balanced: ']' } />`);
|
|
56
|
-
yield eat(
|
|
57
|
-
m`<_List />`,
|
|
58
|
-
o({
|
|
59
|
-
element: m`elements[]+$: <__Expression />`,
|
|
60
|
-
separator: m`separatorTokens[]: <*Punctuator ',' />`,
|
|
61
|
-
allowTrailingSeparator: false,
|
|
62
|
-
}),
|
|
63
|
-
);
|
|
64
|
-
yield eat(m`closeToken: <*Punctuator ']' { balancer: true } />`);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
@CoveredBy('Expression')
|
|
68
|
-
@Node
|
|
69
|
-
*Object() {
|
|
70
|
-
yield eat(m`openToken: <*Punctuator '{' { balanced: '}' } />`);
|
|
71
|
-
let sep = true;
|
|
72
|
-
|
|
73
|
-
yield eatMatch(m`separatorTokens[]: []`);
|
|
74
|
-
yield eatMatch(m`properties[]$: []`);
|
|
75
|
-
|
|
76
|
-
while (sep && (yield match(re`/.|\g/s`))) {
|
|
77
|
-
let suppressGap = !!(yield match(m`<_All />`, [
|
|
78
|
-
m`key: <//>`,
|
|
79
|
-
m`sigilToken: <*Punctuator ':' />`,
|
|
80
|
-
]));
|
|
81
|
-
yield eat(m`properties[]$: <Property />`, null, o({ suppressGap }));
|
|
82
|
-
sep = yield eatMatch(m`separatorTokens[]: <*Punctuator ',' />`);
|
|
83
|
-
}
|
|
84
|
-
yield eat(m`closeToken: <*Punctuator '}' { balancer: true } />`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
@Node
|
|
88
|
-
*Property() {
|
|
89
|
-
yield eat(m`key$: <String />`);
|
|
90
|
-
yield eat(m`sigilToken: <*Punctuator ':' />`);
|
|
91
|
-
yield eat(m`value+$: <__Expression />`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
@CoveredBy('Expression')
|
|
95
|
-
@Node
|
|
96
|
-
*String() {
|
|
97
|
-
yield eat(m`openToken: <*Punctuator '"' { balanced: '"', balancedSpan: 'String:Double' } />`);
|
|
98
|
-
|
|
99
|
-
yield eat(m`content$: <*StringContent />`);
|
|
100
|
-
|
|
101
|
-
yield eat(m`closeToken: <*Punctuator '"' { balancer: true } />`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
@AllowEmpty
|
|
105
|
-
@Node
|
|
106
|
-
*StringContent({ state: { span } }) {
|
|
107
|
-
let esc, lit;
|
|
108
|
-
do {
|
|
109
|
-
esc = (yield match('\\')) && (yield eat(m`@: <EscapeSequence />`));
|
|
110
|
-
lit =
|
|
111
|
-
span === 'String:Single'
|
|
112
|
-
? yield eatMatch(re`/[^\r\n\\'\g]+/`)
|
|
113
|
-
: yield eatMatch(re`/[^\r\n\\"\g]+/`);
|
|
114
|
-
} while (esc || lit);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
@Node
|
|
118
|
-
*EscapeSequence({ state: { span }, ctx }) {
|
|
119
|
-
if (!span.startsWith('String')) {
|
|
120
|
-
yield fail();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
yield eat(m`sigilToken: <*Punctuator '\\' { openSpan: 'Escape' } />`);
|
|
124
|
-
|
|
125
|
-
let match_;
|
|
126
|
-
let cooked;
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
(match_ =
|
|
130
|
-
span === 'String:Single' ? yield match(re`/[\\/nrt0']/`) : yield match(re`/[\\/nrt0"]/`))
|
|
131
|
-
) {
|
|
132
|
-
const matchText = ctx.sourceTextFor(match_);
|
|
133
|
-
yield eat(m`code: <*Keyword ${buildString(matchText)} { closeSpan: 'Escape' } />`);
|
|
134
|
-
|
|
135
|
-
cooked = escapables.get(matchText) || matchText;
|
|
136
|
-
} else if (yield match('u')) {
|
|
137
|
-
let codeNode = yield eat(m`code: <EscapeCode { closeSpan: 'Escape' } />`);
|
|
138
|
-
|
|
139
|
-
if (codeNode && first(codeNode.children)?.value.flags.token) {
|
|
140
|
-
const match_ = ctx.sourceTextFor(codeNode);
|
|
141
|
-
} else {
|
|
142
|
-
const type = ctx.sourceTextFor(codeNode.get('typeToken'));
|
|
143
|
-
|
|
144
|
-
if (type) {
|
|
145
|
-
const value = ctx.sourceTextFor(codeNode.get('value'));
|
|
146
|
-
|
|
147
|
-
if (!span.startsWith('String')) {
|
|
148
|
-
throw new Error('not implemented');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (type === 'u') {
|
|
152
|
-
cooked = String.fromCharCode(parseInt(value, 16));
|
|
153
|
-
} else {
|
|
154
|
-
throw new Error();
|
|
155
|
-
}
|
|
156
|
-
} else {
|
|
157
|
-
let value = ctx.sourceTextFor(codeNode);
|
|
158
|
-
cooked = escapables.get(value) || value;
|
|
159
|
-
}
|
|
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
|
-
);
|