@bablr/language-en-json 0.12.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 +154 -147
- package/package.json +11 -14
- package/lib/grammar.macro.js +0 -285
package/lib/grammar.js
CHANGED
|
@@ -1,222 +1,229 @@
|
|
|
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
|
|
102
|
+
yield* eatMatchTrivia();
|
|
103
|
+
yield eat(m`sigilToken*: <* ':' />`);
|
|
104
|
+
yield* eatMatchTrivia();
|
|
81
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
|
-
if (!span.startsWith('String')) {
|
|
106
|
-
yield fail();
|
|
107
|
-
}
|
|
108
|
-
yield eat(m`sigilToken: <*Punctuator '\\' { openSpan: 'Escape' } />`);
|
|
123
|
+
|
|
124
|
+
*EscapeSequence() {
|
|
125
|
+
yield startSpan('Escape');
|
|
126
|
+
yield eat(m`sigilToken*: <* '\\' />`);
|
|
127
|
+
|
|
109
128
|
let match_;
|
|
110
129
|
let cooked;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
130
|
+
|
|
131
|
+
if ((match_ = yield match(re`/[\\/bfnrt0"]/`))) {
|
|
132
|
+
const matchText = printSource(match_);
|
|
133
|
+
yield eat(m`code*: <*Keyword ${buildString(matchText)} />`);
|
|
134
|
+
|
|
114
135
|
cooked = escapables.get(matchText) || matchText;
|
|
115
136
|
} else if (yield match('u')) {
|
|
116
|
-
let codeNode = yield eat(m`code
|
|
117
|
-
|
|
137
|
+
let codeNode = yield eat(m`code*: <EscapeCode />`);
|
|
138
|
+
|
|
139
|
+
const type = printSource(get('typeToken', codeNode.node));
|
|
140
|
+
|
|
118
141
|
if (type) {
|
|
119
|
-
const value =
|
|
120
|
-
|
|
121
|
-
throw new Error('not implemented');
|
|
122
|
-
}
|
|
142
|
+
const value = printSource(get('value', codeNode.node));
|
|
143
|
+
|
|
123
144
|
if (type === 'u') {
|
|
124
145
|
cooked = String.fromCharCode(parseInt(value, 16));
|
|
125
146
|
} else {
|
|
126
147
|
throw new Error();
|
|
127
148
|
}
|
|
128
149
|
} else {
|
|
129
|
-
let value =
|
|
150
|
+
let value = printSource(codeNode.node);
|
|
130
151
|
cooked = escapables.get(value) || value;
|
|
131
152
|
}
|
|
132
153
|
} else {
|
|
133
154
|
yield fail();
|
|
134
155
|
}
|
|
156
|
+
|
|
157
|
+
// TODO error if we don't see the span ended
|
|
158
|
+
yield endSpan();
|
|
159
|
+
|
|
135
160
|
yield defineAttribute('cooked', cooked);
|
|
136
161
|
}
|
|
162
|
+
|
|
137
163
|
*EscapeCode() {
|
|
138
|
-
if (yield eatMatch(m`typeToken
|
|
139
|
-
if (yield eatMatch(m`openToken
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
yield
|
|
143
|
-
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*: <* '}' />`);
|
|
144
170
|
} else {
|
|
145
|
-
yield eat(m`value
|
|
146
|
-
yield eat(m`closeToken: null`);
|
|
171
|
+
yield eat(m`value: <*UnsignedHexInteger /[\da-fA-F]{4}/ />`);
|
|
147
172
|
}
|
|
148
173
|
}
|
|
149
174
|
}
|
|
175
|
+
|
|
150
176
|
*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
|
-
}));
|
|
177
|
+
yield eat(m`wholePart$: <Integer />`, o({ noDoubleZero: true, matchSign: '-' }));
|
|
178
|
+
|
|
179
|
+
let fs = yield eatMatch(m`fractionalSeparatorToken*: <* '.' />`);
|
|
180
|
+
|
|
158
181
|
if (fs) {
|
|
159
182
|
yield eat(m`fractionalPart$: <*UnsignedInteger />`);
|
|
160
183
|
} else {
|
|
161
184
|
yield eat(m`fractionalPart$: null`);
|
|
162
185
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
186
|
+
|
|
187
|
+
let es = yield eatMatch(m`exponentSeparatorToken*: <* /[eE]/ />`);
|
|
188
|
+
|
|
166
189
|
if (es) {
|
|
167
|
-
yield eat(m`exponentPart$: <Integer />`, {
|
|
168
|
-
matchSign: /[+-]/
|
|
169
|
-
});
|
|
190
|
+
yield eat(m`exponentPart$: <Integer />`, { matchSign: /[+-]/ });
|
|
170
191
|
} else {
|
|
171
192
|
yield eat(m`exponentPart$: null`);
|
|
172
193
|
}
|
|
173
194
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
matchSign = null,
|
|
177
|
-
noDoubleZero = false
|
|
178
|
-
}
|
|
179
|
-
}) {
|
|
195
|
+
|
|
196
|
+
*Integer({ props: { matchSign = null, noDoubleZero = false } }) {
|
|
180
197
|
if (matchSign) {
|
|
181
|
-
yield eatMatch(m`signToken
|
|
182
|
-
bind: true
|
|
183
|
-
}));
|
|
184
|
-
} else {
|
|
185
|
-
yield eat(m`signToken: null`);
|
|
198
|
+
yield eatMatch(m`signToken*: <* ${buildString(matchSign)} />`);
|
|
186
199
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
*UnsignedInteger({
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
},
|
|
195
|
-
ctx
|
|
196
|
-
}) {
|
|
197
|
-
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
|
+
|
|
198
207
|
if (!noDoubleZero || firstDigit.value !== '0') {
|
|
199
208
|
yield eatMatch(re`/\d+/`);
|
|
200
209
|
}
|
|
201
210
|
}
|
|
211
|
+
|
|
202
212
|
*UnsignedHexInteger() {
|
|
203
213
|
yield eatMatch(re`/[\da-fA-F]+/`);
|
|
204
214
|
}
|
|
205
|
-
|
|
206
|
-
yield eatMatch(m`signToken: <*Punctuator '-' />`, null, o({
|
|
207
|
-
bind: true
|
|
208
|
-
}));
|
|
209
|
-
yield eat(m`sigilToken: <*Keyword 'Infinity' />`);
|
|
210
|
-
}
|
|
215
|
+
|
|
211
216
|
*Boolean() {
|
|
212
|
-
yield eat(m`sigilToken
|
|
217
|
+
yield eat(m`sigilToken*: <*Keyword /true|false/ />`);
|
|
213
218
|
}
|
|
219
|
+
|
|
214
220
|
*Null() {
|
|
215
|
-
yield eat(m`sigilToken
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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.28.2"
|
|
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
|
-
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
|
-
);
|