@aeriajs/compiler 0.0.62 → 0.0.63
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/dist/ast.js +3 -6
- package/dist/codegen/generateContracts.js +15 -19
- package/dist/codegen/generateExports.js +5 -9
- package/dist/codegen/generateJSCollections.js +13 -17
- package/dist/codegen/generateTSCollections.js +13 -17
- package/dist/codegen/index.js +4 -20
- package/dist/codegen/utils.js +25 -37
- package/dist/codegen.js +8 -45
- package/dist/compile.js +19 -58
- package/dist/diagnostic.js +1 -5
- package/dist/guards.js +3 -41
- package/dist/index.js +7 -23
- package/dist/lexer.js +48 -52
- package/dist/parser.js +260 -297
- package/dist/semantic.js +31 -68
- package/dist/token.js +1 -4
- package/dist/types.js +1 -2
- package/dist/utils.js +1 -4
- package/package.json +6 -9
- package/dist/ast.mjs +0 -25
- package/dist/codegen/generateContracts.mjs +0 -85
- package/dist/codegen/generateExports.mjs +0 -42
- package/dist/codegen/generateJSCollections.mjs +0 -103
- package/dist/codegen/generateTSCollections.mjs +0 -114
- package/dist/codegen/index.mjs +0 -5
- package/dist/codegen/utils.mjs +0 -161
- package/dist/codegen.mjs +0 -54
- package/dist/compile.mjs +0 -69
- package/dist/diagnostic.mjs +0 -18
- package/dist/guards.mjs +0 -8
- package/dist/index.mjs +0 -8
- package/dist/lexer.mjs +0 -375
- package/dist/parser.mjs +0 -1304
- package/dist/semantic.mjs +0 -202
- package/dist/token.mjs +0 -24
- package/dist/types.mjs +0 -1
- package/dist/utils.mjs +0 -12
package/dist/parser.js
CHANGED
|
@@ -1,69 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.parse = exports.memoTable = exports.locationMap = void 0;
|
|
37
|
-
const types_1 = require("@aeriajs/types");
|
|
38
|
-
const core_1 = require("@phosphor-icons/core");
|
|
39
|
-
const AST = __importStar(require("./ast.js"));
|
|
40
|
-
const guards = __importStar(require("./guards.js"));
|
|
41
|
-
const lexer = __importStar(require("./lexer.js"));
|
|
42
|
-
const token_js_1 = require("./token.js");
|
|
43
|
-
const diagnostic_js_1 = require("./diagnostic.js");
|
|
44
|
-
const utils_js_1 = require("./utils.js");
|
|
1
|
+
import { DESCRIPTION_PRESETS, LAYOUT_NAMES, PROPERTY_ARRAY_ELEMENTS, PROPERTY_FORMATS, PROPERTY_INPUT_ELEMENTS, PROPERTY_INPUT_TYPES } from '@aeriajs/types';
|
|
2
|
+
import { icons } from '@phosphor-icons/core';
|
|
3
|
+
import * as AST from './ast.js';
|
|
4
|
+
import * as guards from './guards.js';
|
|
5
|
+
import * as lexer from './lexer.js';
|
|
6
|
+
import { TokenType } from './token.js';
|
|
7
|
+
import { Diagnostic } from './diagnostic.js';
|
|
8
|
+
import { DEFAULT_EXPORT_SYMBOLS } from './utils.js';
|
|
45
9
|
const MAX_ERROR_MESSAGE_ITEMS = 20;
|
|
46
|
-
const ICON_NAMES =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
defaultExportSymbols:
|
|
10
|
+
const ICON_NAMES = icons.map((icon) => icon.name);
|
|
11
|
+
export const locationMap = new WeakMap();
|
|
12
|
+
export const memoTable = {
|
|
13
|
+
defaultExportSymbols: DEFAULT_EXPORT_SYMBOLS,
|
|
50
14
|
};
|
|
51
15
|
const isFileProperty = (property) => {
|
|
52
16
|
return property.$ref === 'File';
|
|
53
17
|
};
|
|
54
18
|
const checkForValidRoles = (roles, symbols) => {
|
|
55
|
-
if (
|
|
19
|
+
if (memoTable.roles) {
|
|
56
20
|
for (const [i, role] of roles.entries()) {
|
|
57
21
|
const symbol = symbols[i];
|
|
58
|
-
if (!
|
|
59
|
-
const location =
|
|
60
|
-
throw new
|
|
22
|
+
if (!memoTable.roles.includes(role)) {
|
|
23
|
+
const location = locationMap.get(symbol);
|
|
24
|
+
throw new Diagnostic(`invalid role "${role}"`, location);
|
|
61
25
|
}
|
|
62
26
|
}
|
|
63
27
|
}
|
|
64
28
|
return roles;
|
|
65
29
|
};
|
|
66
|
-
const parse = (tokens) => {
|
|
30
|
+
export const parse = (tokens) => {
|
|
67
31
|
let index = 0;
|
|
68
32
|
const ast = {
|
|
69
33
|
kind: 'program',
|
|
@@ -77,28 +41,28 @@ const parse = (tokens) => {
|
|
|
77
41
|
const next = () => {
|
|
78
42
|
const token = tokens[index + 1];
|
|
79
43
|
if (!token) {
|
|
80
|
-
throw new
|
|
44
|
+
throw new Diagnostic('unexpected EOF', current().location);
|
|
81
45
|
}
|
|
82
46
|
return token;
|
|
83
47
|
};
|
|
84
48
|
const previous = () => {
|
|
85
49
|
const token = tokens[index - 1];
|
|
86
50
|
if (!token) {
|
|
87
|
-
throw new
|
|
51
|
+
throw new Diagnostic('invalid position');
|
|
88
52
|
}
|
|
89
53
|
return token;
|
|
90
54
|
};
|
|
91
55
|
const current = () => {
|
|
92
56
|
const token = tokens[index];
|
|
93
57
|
if (!token) {
|
|
94
|
-
throw new
|
|
58
|
+
throw new Diagnostic('unexpected EOF', previous().location);
|
|
95
59
|
}
|
|
96
60
|
return token;
|
|
97
61
|
};
|
|
98
62
|
const foldBrackets = () => {
|
|
99
|
-
if (match(
|
|
63
|
+
if (match(TokenType.LeftBracket)) {
|
|
100
64
|
advance();
|
|
101
|
-
while (!match(
|
|
65
|
+
while (!match(TokenType.RightBracket)) {
|
|
102
66
|
foldBrackets();
|
|
103
67
|
advance();
|
|
104
68
|
}
|
|
@@ -131,14 +95,14 @@ const parse = (tokens) => {
|
|
|
131
95
|
if (Array.isArray(value) && value.length > MAX_ERROR_MESSAGE_ITEMS) {
|
|
132
96
|
expectedValue += ' | ...';
|
|
133
97
|
}
|
|
134
|
-
throw new
|
|
98
|
+
throw new Diagnostic(expectedValue
|
|
135
99
|
? `expected ${expected} with value ${expectedValue} but found ${token.type} with value "${token.value}" instead`
|
|
136
100
|
: `expected ${expected} but found ${token.type} instead`, token.location);
|
|
137
101
|
};
|
|
138
102
|
const recover = (keywords) => {
|
|
139
103
|
let token;
|
|
140
104
|
while (token = tokens[++index]) {
|
|
141
|
-
if (token.type ===
|
|
105
|
+
if (token.type === TokenType.Keyword && keywords.includes(token.value)) {
|
|
142
106
|
break;
|
|
143
107
|
}
|
|
144
108
|
}
|
|
@@ -146,9 +110,9 @@ const parse = (tokens) => {
|
|
|
146
110
|
const parseArray = (types) => {
|
|
147
111
|
const array = [];
|
|
148
112
|
const symbols = [];
|
|
149
|
-
const { location: openingLocation } = consume(
|
|
150
|
-
if (match(
|
|
151
|
-
consume(
|
|
113
|
+
const { location: openingLocation } = consume(TokenType.LeftSquareBracket);
|
|
114
|
+
if (match(TokenType.RightSquareBracket)) {
|
|
115
|
+
consume(TokenType.RightSquareBracket);
|
|
152
116
|
return {
|
|
153
117
|
value: [],
|
|
154
118
|
symbols: [],
|
|
@@ -162,19 +126,19 @@ const parse = (tokens) => {
|
|
|
162
126
|
}
|
|
163
127
|
}
|
|
164
128
|
if (!type) {
|
|
165
|
-
throw new
|
|
129
|
+
throw new Diagnostic(`array got an invalid type, accepted ones are: ${types.join(' | ')}`, openingLocation);
|
|
166
130
|
}
|
|
167
|
-
while (!match(
|
|
131
|
+
while (!match(TokenType.RightSquareBracket)) {
|
|
168
132
|
const { value, location } = consume(type);
|
|
169
133
|
const elemSymbol = Symbol();
|
|
170
134
|
array.push(value);
|
|
171
135
|
symbols.push(elemSymbol);
|
|
172
|
-
|
|
173
|
-
if (match(
|
|
174
|
-
consume(
|
|
136
|
+
locationMap.set(elemSymbol, location);
|
|
137
|
+
if (match(TokenType.Comma)) {
|
|
138
|
+
consume(TokenType.Comma);
|
|
175
139
|
}
|
|
176
140
|
}
|
|
177
|
-
consume(
|
|
141
|
+
consume(TokenType.RightSquareBracket);
|
|
178
142
|
return {
|
|
179
143
|
value: array,
|
|
180
144
|
symbols,
|
|
@@ -183,18 +147,18 @@ const parse = (tokens) => {
|
|
|
183
147
|
const parseArrayBlock = (value) => {
|
|
184
148
|
const array = [];
|
|
185
149
|
const symbols = [];
|
|
186
|
-
consume(
|
|
187
|
-
while (!match(
|
|
188
|
-
const { value: identifier, location } = consume(
|
|
150
|
+
consume(TokenType.LeftBracket);
|
|
151
|
+
while (!match(TokenType.RightBracket)) {
|
|
152
|
+
const { value: identifier, location } = consume(TokenType.Identifier, value);
|
|
189
153
|
const elemSymbol = Symbol();
|
|
190
154
|
array.push(identifier);
|
|
191
155
|
symbols.push(elemSymbol);
|
|
192
|
-
|
|
193
|
-
if (match(
|
|
194
|
-
consume(
|
|
156
|
+
locationMap.set(elemSymbol, location);
|
|
157
|
+
if (match(TokenType.Comma)) {
|
|
158
|
+
consume(TokenType.Comma);
|
|
195
159
|
}
|
|
196
160
|
}
|
|
197
|
-
consume(
|
|
161
|
+
consume(TokenType.RightBracket);
|
|
198
162
|
return {
|
|
199
163
|
value: array,
|
|
200
164
|
symbols,
|
|
@@ -204,23 +168,23 @@ const parse = (tokens) => {
|
|
|
204
168
|
const array = {};
|
|
205
169
|
const symbols = [];
|
|
206
170
|
let hasAttributes = false;
|
|
207
|
-
consume(
|
|
208
|
-
while (!match(
|
|
209
|
-
const { value: identifier, location } = consume(
|
|
171
|
+
consume(TokenType.LeftBracket);
|
|
172
|
+
while (!match(TokenType.RightBracket)) {
|
|
173
|
+
const { value: identifier, location } = consume(TokenType.Identifier);
|
|
210
174
|
array[identifier] = true;
|
|
211
175
|
const elemSymbol = Symbol();
|
|
212
176
|
symbols.push(elemSymbol);
|
|
213
|
-
|
|
214
|
-
if (match(
|
|
177
|
+
locationMap.set(elemSymbol, location);
|
|
178
|
+
if (match(TokenType.AttributeName)) {
|
|
215
179
|
hasAttributes = true;
|
|
216
180
|
}
|
|
217
|
-
while (match(
|
|
181
|
+
while (match(TokenType.AttributeName)) {
|
|
218
182
|
array[identifier] = {};
|
|
219
|
-
const { value: attributeName } = consume(
|
|
183
|
+
const { value: attributeName } = consume(TokenType.AttributeName, allowedAttributes);
|
|
220
184
|
cb(attributeName, array, identifier);
|
|
221
185
|
}
|
|
222
186
|
}
|
|
223
|
-
consume(
|
|
187
|
+
consume(TokenType.RightBracket);
|
|
224
188
|
const value = hasAttributes
|
|
225
189
|
? array
|
|
226
190
|
: Object.keys(array);
|
|
@@ -231,16 +195,16 @@ const parse = (tokens) => {
|
|
|
231
195
|
};
|
|
232
196
|
const parsePropertyAttributeValue = (attributeName, property, location) => {
|
|
233
197
|
const consumeBoolean = () => {
|
|
234
|
-
if (match(
|
|
235
|
-
const { value } = consume(
|
|
198
|
+
if (match(TokenType.Boolean)) {
|
|
199
|
+
const { value } = consume(TokenType.Boolean);
|
|
236
200
|
return value;
|
|
237
201
|
}
|
|
238
202
|
return true;
|
|
239
203
|
};
|
|
240
204
|
if ('enum' in property && attributeName === 'values') {
|
|
241
205
|
property.enum = parseArray([
|
|
242
|
-
|
|
243
|
-
|
|
206
|
+
TokenType.QuotedString,
|
|
207
|
+
TokenType.Number,
|
|
244
208
|
]).value;
|
|
245
209
|
return;
|
|
246
210
|
}
|
|
@@ -248,27 +212,27 @@ const parse = (tokens) => {
|
|
|
248
212
|
const token = current();
|
|
249
213
|
advance();
|
|
250
214
|
switch (token.type) {
|
|
251
|
-
case
|
|
252
|
-
case
|
|
253
|
-
case
|
|
254
|
-
case
|
|
215
|
+
case TokenType.Number:
|
|
216
|
+
case TokenType.Boolean:
|
|
217
|
+
case TokenType.Null:
|
|
218
|
+
case TokenType.QuotedString: {
|
|
255
219
|
property.const = token.value;
|
|
256
220
|
return;
|
|
257
221
|
}
|
|
258
222
|
default: {
|
|
259
|
-
throw new
|
|
223
|
+
throw new Diagnostic(`const received invalid value: "${token.value}"`, location);
|
|
260
224
|
}
|
|
261
225
|
}
|
|
262
226
|
}
|
|
263
227
|
switch (attributeName) {
|
|
264
228
|
case 'icon': {
|
|
265
|
-
const { value } = consume(
|
|
229
|
+
const { value } = consume(TokenType.QuotedString, ICON_NAMES);
|
|
266
230
|
property[attributeName] = value;
|
|
267
231
|
return;
|
|
268
232
|
}
|
|
269
233
|
case 'hint':
|
|
270
234
|
case 'description': {
|
|
271
|
-
const { value } = consume(
|
|
235
|
+
const { value } = consume(TokenType.QuotedString);
|
|
272
236
|
property[attributeName] = value;
|
|
273
237
|
return;
|
|
274
238
|
}
|
|
@@ -289,11 +253,11 @@ const parse = (tokens) => {
|
|
|
289
253
|
case 'form':
|
|
290
254
|
case 'populate':
|
|
291
255
|
case 'indexes': {
|
|
292
|
-
property[attributeName] = parseArray([
|
|
256
|
+
property[attributeName] = parseArray([TokenType.Identifier]).value;
|
|
293
257
|
return;
|
|
294
258
|
}
|
|
295
259
|
case 'populateDepth': {
|
|
296
|
-
const { value } = consume(
|
|
260
|
+
const { value } = consume(TokenType.Number);
|
|
297
261
|
property[attributeName] = value;
|
|
298
262
|
return;
|
|
299
263
|
}
|
|
@@ -310,7 +274,7 @@ const parse = (tokens) => {
|
|
|
310
274
|
switch (attributeName) {
|
|
311
275
|
case 'extensions':
|
|
312
276
|
case 'accept': {
|
|
313
|
-
property[attributeName] = parseArray([
|
|
277
|
+
property[attributeName] = parseArray([TokenType.QuotedString]).value;
|
|
314
278
|
return;
|
|
315
279
|
}
|
|
316
280
|
}
|
|
@@ -321,44 +285,44 @@ const parse = (tokens) => {
|
|
|
321
285
|
case 'string': {
|
|
322
286
|
switch (attributeName) {
|
|
323
287
|
case 'format': {
|
|
324
|
-
const { value } = consume(
|
|
288
|
+
const { value } = consume(TokenType.QuotedString, PROPERTY_FORMATS);
|
|
325
289
|
property[attributeName] = value;
|
|
326
290
|
return;
|
|
327
291
|
}
|
|
328
292
|
case 'mask': {
|
|
329
|
-
if (match(
|
|
330
|
-
property[attributeName] = parseArray([
|
|
293
|
+
if (match(TokenType.LeftSquareBracket)) {
|
|
294
|
+
property[attributeName] = parseArray([TokenType.QuotedString]).value;
|
|
331
295
|
return;
|
|
332
296
|
}
|
|
333
297
|
else {
|
|
334
|
-
const { value } = consume(
|
|
298
|
+
const { value } = consume(TokenType.QuotedString);
|
|
335
299
|
property[attributeName] = value;
|
|
336
300
|
return;
|
|
337
301
|
}
|
|
338
302
|
}
|
|
339
303
|
case 'maskedValue': {
|
|
340
|
-
const { value } = consume(
|
|
304
|
+
const { value } = consume(TokenType.Boolean);
|
|
341
305
|
property[attributeName] = value;
|
|
342
306
|
return;
|
|
343
307
|
}
|
|
344
308
|
case 'minLength':
|
|
345
309
|
case 'maxLength': {
|
|
346
|
-
const { value } = consume(
|
|
310
|
+
const { value } = consume(TokenType.Number);
|
|
347
311
|
property[attributeName] = value;
|
|
348
312
|
return;
|
|
349
313
|
}
|
|
350
314
|
case 'inputType': {
|
|
351
|
-
const { value } = consume(
|
|
315
|
+
const { value } = consume(TokenType.QuotedString, PROPERTY_INPUT_TYPES);
|
|
352
316
|
property[attributeName] = value;
|
|
353
317
|
return;
|
|
354
318
|
}
|
|
355
319
|
case 'element': {
|
|
356
|
-
const { value } = consume(
|
|
320
|
+
const { value } = consume(TokenType.QuotedString, PROPERTY_INPUT_ELEMENTS);
|
|
357
321
|
property[attributeName] = value;
|
|
358
322
|
return;
|
|
359
323
|
}
|
|
360
324
|
case 'placeholder': {
|
|
361
|
-
const { value } = consume(
|
|
325
|
+
const { value } = consume(TokenType.QuotedString);
|
|
362
326
|
property[attributeName] = value;
|
|
363
327
|
return;
|
|
364
328
|
}
|
|
@@ -372,12 +336,12 @@ const parse = (tokens) => {
|
|
|
372
336
|
case 'exclusiveMaximum':
|
|
373
337
|
case 'minimum':
|
|
374
338
|
case 'maximum': {
|
|
375
|
-
const { value } = consume(
|
|
339
|
+
const { value } = consume(TokenType.Number);
|
|
376
340
|
property[attributeName] = value;
|
|
377
341
|
return;
|
|
378
342
|
}
|
|
379
343
|
case 'placeholder': {
|
|
380
|
-
const { value } = consume(
|
|
344
|
+
const { value } = consume(TokenType.QuotedString);
|
|
381
345
|
property[attributeName] = value;
|
|
382
346
|
return;
|
|
383
347
|
}
|
|
@@ -387,12 +351,12 @@ const parse = (tokens) => {
|
|
|
387
351
|
case 'array': {
|
|
388
352
|
switch (attributeName) {
|
|
389
353
|
case 'uniqueItems': {
|
|
390
|
-
const { value } = consume(
|
|
354
|
+
const { value } = consume(TokenType.Boolean);
|
|
391
355
|
property[attributeName] = value;
|
|
392
356
|
return;
|
|
393
357
|
}
|
|
394
358
|
case 'element': {
|
|
395
|
-
const { value } = consume(
|
|
359
|
+
const { value } = consume(TokenType.QuotedString, PROPERTY_ARRAY_ELEMENTS);
|
|
396
360
|
property[attributeName] = value;
|
|
397
361
|
return;
|
|
398
362
|
}
|
|
@@ -400,7 +364,7 @@ const parse = (tokens) => {
|
|
|
400
364
|
}
|
|
401
365
|
}
|
|
402
366
|
}
|
|
403
|
-
throw new
|
|
367
|
+
throw new Diagnostic(`invalid attribute name "${attributeName}"`, location);
|
|
404
368
|
};
|
|
405
369
|
const parsePropertyType = (options = {
|
|
406
370
|
allowModifiers: false,
|
|
@@ -413,24 +377,24 @@ const parse = (tokens) => {
|
|
|
413
377
|
if (options.allowModifiers) {
|
|
414
378
|
const nextToken = next();
|
|
415
379
|
const currentTokenValue = current().value;
|
|
416
|
-
if (match(
|
|
417
|
-
modifierToken = consume(
|
|
380
|
+
if (match(TokenType.Identifier) && typeof currentTokenValue === 'string' && guards.isValidPropertyModifier(currentTokenValue) && (nextToken.type === TokenType.LeftBracket || nextToken.type === TokenType.LeftSquareBracket || nextToken.type === TokenType.Identifier)) {
|
|
381
|
+
modifierToken = consume(TokenType.Identifier);
|
|
418
382
|
}
|
|
419
383
|
}
|
|
420
|
-
if (match(
|
|
421
|
-
consume(
|
|
384
|
+
if (match(TokenType.LeftSquareBracket)) {
|
|
385
|
+
consume(TokenType.LeftSquareBracket);
|
|
422
386
|
const arrayProperty = {
|
|
423
387
|
type: 'array',
|
|
424
388
|
};
|
|
425
|
-
while (!match(
|
|
389
|
+
while (!match(TokenType.RightSquareBracket)) {
|
|
426
390
|
const attributeSymbol = Symbol();
|
|
427
391
|
arrayProperty[AST.LOCATION_SYMBOL] ??= {
|
|
428
392
|
type: typeSymbol,
|
|
429
393
|
attributes: {},
|
|
430
394
|
arrays: {},
|
|
431
395
|
};
|
|
432
|
-
if (match(
|
|
433
|
-
const { value: rangeSeparator } = consume(
|
|
396
|
+
if (match(TokenType.Range)) {
|
|
397
|
+
const { value: rangeSeparator } = consume(TokenType.Range);
|
|
434
398
|
let attributeName;
|
|
435
399
|
const minItems = rangeSeparator[0];
|
|
436
400
|
if (!isNaN(minItems)) {
|
|
@@ -446,34 +410,34 @@ const parse = (tokens) => {
|
|
|
446
410
|
}
|
|
447
411
|
continue;
|
|
448
412
|
}
|
|
449
|
-
const { value: attributeName, location } = consume(
|
|
450
|
-
if (match(
|
|
451
|
-
consume(
|
|
452
|
-
|
|
413
|
+
const { value: attributeName, location } = consume(TokenType.AttributeName);
|
|
414
|
+
if (match(TokenType.LeftParens)) {
|
|
415
|
+
consume(TokenType.LeftParens);
|
|
416
|
+
locationMap.set(attributeSymbol, next().location);
|
|
453
417
|
arrayProperty[AST.LOCATION_SYMBOL].attributes[attributeName] = attributeSymbol;
|
|
454
418
|
parsePropertyAttributeValue(attributeName, arrayProperty, location);
|
|
455
|
-
consume(
|
|
419
|
+
consume(TokenType.RightParens);
|
|
456
420
|
}
|
|
457
421
|
else {
|
|
458
422
|
parsePropertyAttributeValue(attributeName, arrayProperty, location);
|
|
459
423
|
}
|
|
460
424
|
}
|
|
461
|
-
consume(
|
|
425
|
+
consume(TokenType.RightSquareBracket);
|
|
462
426
|
const { property: items, nestedProperties } = parsePropertyType(options);
|
|
463
427
|
property = {
|
|
464
428
|
...arrayProperty,
|
|
465
429
|
items,
|
|
466
430
|
};
|
|
467
|
-
|
|
431
|
+
locationMap.set(typeSymbol, current().location);
|
|
468
432
|
return {
|
|
469
433
|
kind: 'property',
|
|
470
434
|
property,
|
|
471
435
|
nestedProperties,
|
|
472
436
|
};
|
|
473
437
|
}
|
|
474
|
-
|
|
475
|
-
if (match(
|
|
476
|
-
consume(
|
|
438
|
+
locationMap.set(typeSymbol, current().location);
|
|
439
|
+
if (match(TokenType.LeftBracket)) {
|
|
440
|
+
consume(TokenType.LeftBracket);
|
|
477
441
|
property = {
|
|
478
442
|
type: 'object',
|
|
479
443
|
properties: {},
|
|
@@ -483,8 +447,8 @@ const parse = (tokens) => {
|
|
|
483
447
|
arrays: {},
|
|
484
448
|
},
|
|
485
449
|
};
|
|
486
|
-
while (!match(
|
|
487
|
-
const { value: keyword, location } = consume(
|
|
450
|
+
while (!match(TokenType.RightBracket)) {
|
|
451
|
+
const { value: keyword, location } = consume(TokenType.Keyword, lexer.COLLECTION_KEYWORDS);
|
|
488
452
|
switch (keyword) {
|
|
489
453
|
case 'writable':
|
|
490
454
|
case 'required': {
|
|
@@ -498,8 +462,8 @@ const parse = (tokens) => {
|
|
|
498
462
|
break;
|
|
499
463
|
}
|
|
500
464
|
case 'additionalProperties': {
|
|
501
|
-
if (match(
|
|
502
|
-
nestedAdditionalProperties = consume(
|
|
465
|
+
if (match(TokenType.Boolean)) {
|
|
466
|
+
nestedAdditionalProperties = consume(TokenType.Boolean).value;
|
|
503
467
|
}
|
|
504
468
|
else {
|
|
505
469
|
nestedAdditionalProperties = parsePropertyType();
|
|
@@ -507,13 +471,13 @@ const parse = (tokens) => {
|
|
|
507
471
|
break;
|
|
508
472
|
}
|
|
509
473
|
default:
|
|
510
|
-
throw new
|
|
474
|
+
throw new Diagnostic(`invalid keyword "${keyword}"`, location);
|
|
511
475
|
}
|
|
512
476
|
}
|
|
513
|
-
consume(
|
|
477
|
+
consume(TokenType.RightBracket);
|
|
514
478
|
}
|
|
515
479
|
else {
|
|
516
|
-
const { value: identifier } = consume(
|
|
480
|
+
const { value: identifier } = consume(TokenType.Identifier);
|
|
517
481
|
if (guards.isNativePropertyType(identifier)) {
|
|
518
482
|
switch (identifier) {
|
|
519
483
|
case 'enum': {
|
|
@@ -566,12 +530,12 @@ const parse = (tokens) => {
|
|
|
566
530
|
};
|
|
567
531
|
}
|
|
568
532
|
}
|
|
569
|
-
while (match(
|
|
570
|
-
const { value: attributeName, location } = consume(
|
|
571
|
-
if (match(
|
|
572
|
-
consume(
|
|
533
|
+
while (match(TokenType.AttributeName)) {
|
|
534
|
+
const { value: attributeName, location } = consume(TokenType.AttributeName);
|
|
535
|
+
if (match(TokenType.LeftParens)) {
|
|
536
|
+
consume(TokenType.LeftParens);
|
|
573
537
|
const attributeSymbol = Symbol();
|
|
574
|
-
|
|
538
|
+
locationMap.set(attributeSymbol, next().location);
|
|
575
539
|
property[AST.LOCATION_SYMBOL] ??= {
|
|
576
540
|
type: typeSymbol,
|
|
577
541
|
attributes: {},
|
|
@@ -579,7 +543,7 @@ const parse = (tokens) => {
|
|
|
579
543
|
};
|
|
580
544
|
property[AST.LOCATION_SYMBOL].attributes[attributeName] = attributeSymbol;
|
|
581
545
|
parsePropertyAttributeValue(attributeName, property, location);
|
|
582
|
-
consume(
|
|
546
|
+
consume(TokenType.RightParens);
|
|
583
547
|
}
|
|
584
548
|
else {
|
|
585
549
|
parsePropertyAttributeValue(attributeName, property, location);
|
|
@@ -599,31 +563,31 @@ const parse = (tokens) => {
|
|
|
599
563
|
const parsePropertiesBlock = (options = {
|
|
600
564
|
allowModifiers: false,
|
|
601
565
|
}) => {
|
|
602
|
-
consume(
|
|
566
|
+
consume(TokenType.LeftBracket);
|
|
603
567
|
const properties = {};
|
|
604
|
-
while (!match(
|
|
568
|
+
while (!match(TokenType.RightBracket)) {
|
|
605
569
|
try {
|
|
606
|
-
const { value: propName } = consume(
|
|
570
|
+
const { value: propName } = consume(TokenType.Identifier);
|
|
607
571
|
properties[propName] = parsePropertyType(options);
|
|
608
|
-
if (match(
|
|
609
|
-
consume(
|
|
572
|
+
if (match(TokenType.Comma)) {
|
|
573
|
+
consume(TokenType.Comma);
|
|
610
574
|
}
|
|
611
575
|
}
|
|
612
576
|
catch (err) {
|
|
613
|
-
if (err instanceof
|
|
577
|
+
if (err instanceof Diagnostic) {
|
|
614
578
|
errors.push(err);
|
|
615
579
|
recoverLoop: for (;;) {
|
|
616
580
|
switch (current().type) {
|
|
617
|
-
case
|
|
618
|
-
case
|
|
581
|
+
case TokenType.RightBracket:
|
|
582
|
+
case TokenType.Identifier: {
|
|
619
583
|
break recoverLoop;
|
|
620
584
|
}
|
|
621
585
|
}
|
|
622
|
-
while (match(
|
|
586
|
+
while (match(TokenType.AttributeName)) {
|
|
623
587
|
advance();
|
|
624
|
-
if (match(
|
|
588
|
+
if (match(TokenType.LeftParens)) {
|
|
625
589
|
advance();
|
|
626
|
-
while (!match(
|
|
590
|
+
while (!match(TokenType.RightParens)) {
|
|
627
591
|
advance();
|
|
628
592
|
}
|
|
629
593
|
}
|
|
@@ -636,19 +600,19 @@ const parse = (tokens) => {
|
|
|
636
600
|
throw err;
|
|
637
601
|
}
|
|
638
602
|
}
|
|
639
|
-
consume(
|
|
603
|
+
consume(TokenType.RightBracket);
|
|
640
604
|
return properties;
|
|
641
605
|
};
|
|
642
606
|
const parseMultiplePropertyTypes = (options = {
|
|
643
607
|
allowModifiers: false,
|
|
644
608
|
}) => {
|
|
645
|
-
if (match(
|
|
646
|
-
consume(
|
|
609
|
+
if (match(TokenType.Pipe)) {
|
|
610
|
+
consume(TokenType.Pipe);
|
|
647
611
|
const properties = [];
|
|
648
612
|
while (index < tokens.length) {
|
|
649
613
|
properties.push(parsePropertyType(options));
|
|
650
|
-
if (match(
|
|
651
|
-
consume(
|
|
614
|
+
if (match(TokenType.Pipe)) {
|
|
615
|
+
consume(TokenType.Pipe);
|
|
652
616
|
}
|
|
653
617
|
else {
|
|
654
618
|
break;
|
|
@@ -661,15 +625,15 @@ const parse = (tokens) => {
|
|
|
661
625
|
const parseAccessCondition = (options = {
|
|
662
626
|
arrayBlock: false,
|
|
663
627
|
}) => {
|
|
664
|
-
if (match(
|
|
665
|
-
const { value } = consume(
|
|
628
|
+
if (match(TokenType.Boolean)) {
|
|
629
|
+
const { value } = consume(TokenType.Boolean);
|
|
666
630
|
return value;
|
|
667
631
|
}
|
|
668
|
-
else if (match(
|
|
632
|
+
else if (match(TokenType.QuotedString, [
|
|
669
633
|
'unauthenticated',
|
|
670
634
|
'unauthenticated-only',
|
|
671
635
|
])) {
|
|
672
|
-
const { value } = consume(
|
|
636
|
+
const { value } = consume(TokenType.QuotedString, [
|
|
673
637
|
'unauthenticated',
|
|
674
638
|
'unauthenticated-only',
|
|
675
639
|
]);
|
|
@@ -678,13 +642,13 @@ const parse = (tokens) => {
|
|
|
678
642
|
else {
|
|
679
643
|
const { value, symbols } = options.arrayBlock
|
|
680
644
|
? parseArrayBlock()
|
|
681
|
-
: parseArray([
|
|
645
|
+
: parseArray([TokenType.QuotedString]);
|
|
682
646
|
return checkForValidRoles(value, symbols);
|
|
683
647
|
}
|
|
684
648
|
};
|
|
685
649
|
const parseCollection = () => {
|
|
686
|
-
consume(
|
|
687
|
-
const { value: name } = consume(
|
|
650
|
+
consume(TokenType.Keyword, 'collection');
|
|
651
|
+
const { value: name } = consume(TokenType.Identifier);
|
|
688
652
|
const node = {
|
|
689
653
|
kind: 'collection',
|
|
690
654
|
name,
|
|
@@ -693,22 +657,22 @@ const parse = (tokens) => {
|
|
|
693
657
|
arrays: {},
|
|
694
658
|
},
|
|
695
659
|
};
|
|
696
|
-
if (match(
|
|
697
|
-
consume(
|
|
698
|
-
const { value: packageName } = match(
|
|
699
|
-
? consume(
|
|
700
|
-
: consume(
|
|
701
|
-
consume(
|
|
702
|
-
const { value: symbolName } = consume(
|
|
660
|
+
if (match(TokenType.Keyword, 'extends')) {
|
|
661
|
+
consume(TokenType.Keyword);
|
|
662
|
+
const { value: packageName } = match(TokenType.QuotedString)
|
|
663
|
+
? consume(TokenType.QuotedString)
|
|
664
|
+
: consume(TokenType.Identifier);
|
|
665
|
+
consume(TokenType.Dot);
|
|
666
|
+
const { value: symbolName } = consume(TokenType.Identifier);
|
|
703
667
|
node.extends = {
|
|
704
668
|
packageName,
|
|
705
669
|
importPath: packageName,
|
|
706
670
|
symbolName: symbolName[0].toLowerCase() + symbolName.slice(1),
|
|
707
671
|
};
|
|
708
672
|
}
|
|
709
|
-
consume(
|
|
710
|
-
while (!match(
|
|
711
|
-
const { value: keyword } = consume(
|
|
673
|
+
consume(TokenType.LeftBracket);
|
|
674
|
+
while (!match(TokenType.RightBracket)) {
|
|
675
|
+
const { value: keyword } = consume(TokenType.Keyword, lexer.COLLECTION_KEYWORDS);
|
|
712
676
|
try {
|
|
713
677
|
switch (keyword) {
|
|
714
678
|
case 'middlewares': {
|
|
@@ -716,11 +680,11 @@ const parse = (tokens) => {
|
|
|
716
680
|
break;
|
|
717
681
|
}
|
|
718
682
|
case 'owned': {
|
|
719
|
-
if (match(
|
|
720
|
-
node.owned = consume(
|
|
683
|
+
if (match(TokenType.Boolean)) {
|
|
684
|
+
node.owned = consume(TokenType.Boolean).value;
|
|
721
685
|
}
|
|
722
686
|
else {
|
|
723
|
-
node.owned = consume(
|
|
687
|
+
node.owned = consume(TokenType.QuotedString, [
|
|
724
688
|
'always',
|
|
725
689
|
'on-write',
|
|
726
690
|
]).value;
|
|
@@ -728,7 +692,7 @@ const parse = (tokens) => {
|
|
|
728
692
|
break;
|
|
729
693
|
}
|
|
730
694
|
case 'icon': {
|
|
731
|
-
const { value } = consume(
|
|
695
|
+
const { value } = consume(TokenType.QuotedString, ICON_NAMES);
|
|
732
696
|
node[keyword] = value;
|
|
733
697
|
break;
|
|
734
698
|
}
|
|
@@ -763,7 +727,7 @@ const parse = (tokens) => {
|
|
|
763
727
|
break;
|
|
764
728
|
}
|
|
765
729
|
case 'presets': {
|
|
766
|
-
const { value, symbols } = parseArrayBlock(
|
|
730
|
+
const { value, symbols } = parseArrayBlock(DESCRIPTION_PRESETS);
|
|
767
731
|
node[keyword] = value;
|
|
768
732
|
node[AST.LOCATION_SYMBOL].arrays[keyword] = symbols;
|
|
769
733
|
break;
|
|
@@ -796,7 +760,7 @@ const parse = (tokens) => {
|
|
|
796
760
|
}
|
|
797
761
|
}
|
|
798
762
|
catch (err) {
|
|
799
|
-
if (err instanceof
|
|
763
|
+
if (err instanceof Diagnostic) {
|
|
800
764
|
errors.push(err);
|
|
801
765
|
recover(lexer.COLLECTION_KEYWORDS);
|
|
802
766
|
continue;
|
|
@@ -804,19 +768,19 @@ const parse = (tokens) => {
|
|
|
804
768
|
throw err;
|
|
805
769
|
}
|
|
806
770
|
}
|
|
807
|
-
consume(
|
|
771
|
+
consume(TokenType.RightBracket);
|
|
808
772
|
return node;
|
|
809
773
|
};
|
|
810
774
|
const parseContract = () => {
|
|
811
|
-
consume(
|
|
812
|
-
const { value: name } = consume(
|
|
813
|
-
consume(
|
|
775
|
+
consume(TokenType.Keyword, 'contract');
|
|
776
|
+
const { value: name } = consume(TokenType.Identifier);
|
|
777
|
+
consume(TokenType.LeftBracket);
|
|
814
778
|
const node = {
|
|
815
779
|
kind: 'contract',
|
|
816
780
|
name,
|
|
817
781
|
};
|
|
818
|
-
while (!match(
|
|
819
|
-
const { value: keyword } = consume(
|
|
782
|
+
while (!match(TokenType.RightBracket)) {
|
|
783
|
+
const { value: keyword } = consume(TokenType.Keyword, lexer.CONTRACT_KEYWORDS);
|
|
820
784
|
switch (keyword) {
|
|
821
785
|
case 'roles': {
|
|
822
786
|
node.roles = parseAccessCondition({
|
|
@@ -844,39 +808,39 @@ const parse = (tokens) => {
|
|
|
844
808
|
}
|
|
845
809
|
}
|
|
846
810
|
}
|
|
847
|
-
consume(
|
|
811
|
+
consume(TokenType.RightBracket);
|
|
848
812
|
return node;
|
|
849
813
|
};
|
|
850
814
|
const parseFunctionsBlock = () => {
|
|
851
|
-
consume(
|
|
815
|
+
consume(TokenType.LeftBracket);
|
|
852
816
|
const functions = [];
|
|
853
817
|
const functionSets = [];
|
|
854
|
-
while (!match(
|
|
818
|
+
while (!match(TokenType.RightBracket)) {
|
|
855
819
|
try {
|
|
856
|
-
if (match(
|
|
857
|
-
const { value: macroName } = consume(
|
|
820
|
+
if (match(TokenType.MacroName)) {
|
|
821
|
+
const { value: macroName } = consume(TokenType.MacroName, ['include']);
|
|
858
822
|
switch (macroName) {
|
|
859
823
|
case 'include': {
|
|
860
|
-
const { value: functionSetName, location } = consume(
|
|
824
|
+
const { value: functionSetName, location } = consume(TokenType.Identifier);
|
|
861
825
|
const functionSetSymbol = Symbol();
|
|
862
|
-
|
|
826
|
+
locationMap.set(functionSetSymbol, location);
|
|
863
827
|
functionSets.push([
|
|
864
828
|
functionSetName,
|
|
865
829
|
functionSetSymbol,
|
|
866
830
|
]);
|
|
867
|
-
consume(
|
|
831
|
+
consume(TokenType.RightParens);
|
|
868
832
|
break;
|
|
869
833
|
}
|
|
870
834
|
}
|
|
871
835
|
continue;
|
|
872
836
|
}
|
|
873
837
|
let functionNode;
|
|
874
|
-
if (current().type ===
|
|
875
|
-
const { value: packageName } = match(
|
|
876
|
-
? consume(
|
|
877
|
-
: consume(
|
|
878
|
-
consume(
|
|
879
|
-
const { value: symbolName } = consume(
|
|
838
|
+
if (current().type === TokenType.Identifier && next().type === TokenType.Dot) {
|
|
839
|
+
const { value: packageName } = match(TokenType.QuotedString)
|
|
840
|
+
? consume(TokenType.QuotedString)
|
|
841
|
+
: consume(TokenType.Identifier);
|
|
842
|
+
consume(TokenType.Dot);
|
|
843
|
+
const { value: symbolName } = consume(TokenType.Identifier);
|
|
880
844
|
functionNode = {
|
|
881
845
|
kind: 'function',
|
|
882
846
|
name: symbolName,
|
|
@@ -888,10 +852,10 @@ const parse = (tokens) => {
|
|
|
888
852
|
};
|
|
889
853
|
}
|
|
890
854
|
else {
|
|
891
|
-
const { value: functionName } = consume(
|
|
855
|
+
const { value: functionName } = consume(TokenType.Identifier);
|
|
892
856
|
let exportSymbol;
|
|
893
|
-
if (
|
|
894
|
-
const packageName =
|
|
857
|
+
if (memoTable.defaultExportSymbols && functionName in memoTable.defaultExportSymbols) {
|
|
858
|
+
const packageName = memoTable.defaultExportSymbols[functionName];
|
|
895
859
|
exportSymbol = {
|
|
896
860
|
packageName,
|
|
897
861
|
importPath: packageName,
|
|
@@ -905,12 +869,12 @@ const parse = (tokens) => {
|
|
|
905
869
|
};
|
|
906
870
|
}
|
|
907
871
|
functions.push(functionNode);
|
|
908
|
-
while (match(
|
|
909
|
-
consume(
|
|
910
|
-
if (match(
|
|
911
|
-
consume(
|
|
872
|
+
while (match(TokenType.AttributeName, 'expose')) {
|
|
873
|
+
consume(TokenType.AttributeName, 'expose');
|
|
874
|
+
if (match(TokenType.LeftParens)) {
|
|
875
|
+
consume(TokenType.LeftParens);
|
|
912
876
|
functionNode.accessCondition = parseAccessCondition();
|
|
913
|
-
consume(
|
|
877
|
+
consume(TokenType.RightParens);
|
|
914
878
|
}
|
|
915
879
|
else {
|
|
916
880
|
functionNode.accessCondition = true;
|
|
@@ -918,10 +882,10 @@ const parse = (tokens) => {
|
|
|
918
882
|
}
|
|
919
883
|
}
|
|
920
884
|
catch (err) {
|
|
921
|
-
if (err instanceof
|
|
885
|
+
if (err instanceof Diagnostic) {
|
|
922
886
|
let token;
|
|
923
887
|
while (token = tokens[++index]) {
|
|
924
|
-
if (token.type ===
|
|
888
|
+
if (token.type === TokenType.Identifier || token.type === TokenType.RightBracket) {
|
|
925
889
|
break;
|
|
926
890
|
}
|
|
927
891
|
}
|
|
@@ -931,15 +895,15 @@ const parse = (tokens) => {
|
|
|
931
895
|
throw err;
|
|
932
896
|
}
|
|
933
897
|
}
|
|
934
|
-
consume(
|
|
898
|
+
consume(TokenType.RightBracket);
|
|
935
899
|
return {
|
|
936
900
|
functions,
|
|
937
901
|
functionSets,
|
|
938
902
|
};
|
|
939
903
|
};
|
|
940
904
|
const parseFunctionSet = () => {
|
|
941
|
-
consume(
|
|
942
|
-
const { value: name } = consume(
|
|
905
|
+
consume(TokenType.Keyword, 'functionset');
|
|
906
|
+
const { value: name } = consume(TokenType.Identifier);
|
|
943
907
|
const { functions, functionSets } = parseFunctionsBlock();
|
|
944
908
|
const node = {
|
|
945
909
|
kind: 'functionset',
|
|
@@ -951,10 +915,10 @@ const parse = (tokens) => {
|
|
|
951
915
|
};
|
|
952
916
|
const parseActionsBlock = () => {
|
|
953
917
|
const actions = {};
|
|
954
|
-
consume(
|
|
955
|
-
while (!match(
|
|
956
|
-
const { value: actionName } = consume(
|
|
957
|
-
consume(
|
|
918
|
+
consume(TokenType.LeftBracket);
|
|
919
|
+
while (!match(TokenType.RightBracket)) {
|
|
920
|
+
const { value: actionName } = consume(TokenType.Identifier);
|
|
921
|
+
consume(TokenType.LeftBracket);
|
|
958
922
|
const baseSlots = {};
|
|
959
923
|
const slots = {
|
|
960
924
|
route: {
|
|
@@ -966,28 +930,28 @@ const parse = (tokens) => {
|
|
|
966
930
|
event: {},
|
|
967
931
|
};
|
|
968
932
|
let actionType;
|
|
969
|
-
while (!match(
|
|
970
|
-
const { value: keyword } = consume(
|
|
933
|
+
while (!match(TokenType.RightBracket)) {
|
|
934
|
+
const { value: keyword } = consume(TokenType.Keyword, lexer.COLLECTION_ACTIONS_KEYWORDS);
|
|
971
935
|
switch (keyword) {
|
|
972
936
|
case 'icon': {
|
|
973
|
-
const { value } = consume(
|
|
937
|
+
const { value } = consume(TokenType.QuotedString, ICON_NAMES);
|
|
974
938
|
baseSlots[keyword] = value;
|
|
975
939
|
break;
|
|
976
940
|
}
|
|
977
941
|
case 'label': {
|
|
978
|
-
const { value } = consume(
|
|
942
|
+
const { value } = consume(TokenType.QuotedString);
|
|
979
943
|
baseSlots[keyword] = value;
|
|
980
944
|
break;
|
|
981
945
|
}
|
|
982
946
|
case 'ask':
|
|
983
947
|
case 'button':
|
|
984
948
|
case 'translate': {
|
|
985
|
-
const { value } = consume(
|
|
949
|
+
const { value } = consume(TokenType.Boolean);
|
|
986
950
|
baseSlots[keyword] = value;
|
|
987
951
|
break;
|
|
988
952
|
}
|
|
989
953
|
case 'roles': {
|
|
990
|
-
const { value, symbols } = parseArray([
|
|
954
|
+
const { value, symbols } = parseArray([TokenType.Identifier]);
|
|
991
955
|
const roles = checkForValidRoles(value, symbols);
|
|
992
956
|
baseSlots[keyword] = roles;
|
|
993
957
|
break;
|
|
@@ -998,7 +962,7 @@ const parse = (tokens) => {
|
|
|
998
962
|
break;
|
|
999
963
|
}
|
|
1000
964
|
case 'route': {
|
|
1001
|
-
const { value } = consume(
|
|
965
|
+
const { value } = consume(TokenType.QuotedString);
|
|
1002
966
|
actionType = 'route';
|
|
1003
967
|
slots.route.route.name = value;
|
|
1004
968
|
break;
|
|
@@ -1006,28 +970,28 @@ const parse = (tokens) => {
|
|
|
1006
970
|
case 'setItem':
|
|
1007
971
|
case 'fetchItem':
|
|
1008
972
|
case 'clearItem': {
|
|
1009
|
-
const { value } = consume(
|
|
973
|
+
const { value } = consume(TokenType.Boolean);
|
|
1010
974
|
slots.route.route[keyword] = value;
|
|
1011
975
|
break;
|
|
1012
976
|
}
|
|
1013
977
|
case 'function': {
|
|
1014
|
-
const { value } = consume(
|
|
978
|
+
const { value } = consume(TokenType.QuotedString);
|
|
1015
979
|
actionType = 'function';
|
|
1016
980
|
slots.function.function = value;
|
|
1017
981
|
break;
|
|
1018
982
|
}
|
|
1019
983
|
case 'effect': {
|
|
1020
|
-
const { value } = consume(
|
|
984
|
+
const { value } = consume(TokenType.QuotedString);
|
|
1021
985
|
slots.function.effect = value;
|
|
1022
986
|
break;
|
|
1023
987
|
}
|
|
1024
988
|
case 'selection': {
|
|
1025
|
-
const { value } = consume(
|
|
989
|
+
const { value } = consume(TokenType.Boolean);
|
|
1026
990
|
slots.function.selection = value;
|
|
1027
991
|
break;
|
|
1028
992
|
}
|
|
1029
993
|
case 'event': {
|
|
1030
|
-
const { value } = consume(
|
|
994
|
+
const { value } = consume(TokenType.QuotedString);
|
|
1031
995
|
actionType = 'event';
|
|
1032
996
|
slots.event.event = value;
|
|
1033
997
|
break;
|
|
@@ -1043,17 +1007,17 @@ const parse = (tokens) => {
|
|
|
1043
1007
|
else {
|
|
1044
1008
|
actions[actionName] = baseSlots;
|
|
1045
1009
|
}
|
|
1046
|
-
consume(
|
|
1010
|
+
consume(TokenType.RightBracket);
|
|
1047
1011
|
}
|
|
1048
|
-
consume(
|
|
1012
|
+
consume(TokenType.RightBracket);
|
|
1049
1013
|
return actions;
|
|
1050
1014
|
};
|
|
1051
1015
|
const parseSearchBlock = () => {
|
|
1052
1016
|
const searchSlots = {};
|
|
1053
|
-
const { location } = consume(
|
|
1017
|
+
const { location } = consume(TokenType.LeftBracket);
|
|
1054
1018
|
let indexesSymbols;
|
|
1055
|
-
while (!match(
|
|
1056
|
-
const { value: keyword } = consume(
|
|
1019
|
+
while (!match(TokenType.RightBracket)) {
|
|
1020
|
+
const { value: keyword } = consume(TokenType.Keyword, lexer.COLLECTION_SEARCH_KEYWORDS);
|
|
1057
1021
|
switch (keyword) {
|
|
1058
1022
|
case 'indexes': {
|
|
1059
1023
|
const { value, symbols } = parseArrayBlock();
|
|
@@ -1062,12 +1026,12 @@ const parse = (tokens) => {
|
|
|
1062
1026
|
break;
|
|
1063
1027
|
}
|
|
1064
1028
|
case 'placeholder': {
|
|
1065
|
-
const { value } = consume(
|
|
1029
|
+
const { value } = consume(TokenType.QuotedString);
|
|
1066
1030
|
searchSlots[keyword] = value;
|
|
1067
1031
|
break;
|
|
1068
1032
|
}
|
|
1069
1033
|
case 'exactMatches': {
|
|
1070
|
-
const { value } = consume(
|
|
1034
|
+
const { value } = consume(TokenType.Boolean);
|
|
1071
1035
|
searchSlots[keyword] = value;
|
|
1072
1036
|
break;
|
|
1073
1037
|
}
|
|
@@ -1075,9 +1039,9 @@ const parse = (tokens) => {
|
|
|
1075
1039
|
}
|
|
1076
1040
|
const { indexes } = searchSlots;
|
|
1077
1041
|
if (!indexes) {
|
|
1078
|
-
throw new
|
|
1042
|
+
throw new Diagnostic('"indexes" option is required', location);
|
|
1079
1043
|
}
|
|
1080
|
-
consume(
|
|
1044
|
+
consume(TokenType.RightBracket);
|
|
1081
1045
|
const options = {
|
|
1082
1046
|
...searchSlots,
|
|
1083
1047
|
indexes,
|
|
@@ -1091,62 +1055,62 @@ const parse = (tokens) => {
|
|
|
1091
1055
|
let name;
|
|
1092
1056
|
const options = {};
|
|
1093
1057
|
const optionsSymbols = {};
|
|
1094
|
-
const { location } = consume(
|
|
1095
|
-
while (!match(
|
|
1096
|
-
const { value: keyword } = consume(
|
|
1058
|
+
const { location } = consume(TokenType.LeftBracket);
|
|
1059
|
+
while (!match(TokenType.RightBracket)) {
|
|
1060
|
+
const { value: keyword } = consume(TokenType.Keyword, lexer.COLLECTION_LAYOUT_KEYWORDS);
|
|
1097
1061
|
switch (keyword) {
|
|
1098
1062
|
case 'name': {
|
|
1099
|
-
name = consume(
|
|
1063
|
+
name = consume(TokenType.QuotedString, LAYOUT_NAMES).value;
|
|
1100
1064
|
break;
|
|
1101
1065
|
}
|
|
1102
1066
|
case 'options':
|
|
1103
1067
|
{
|
|
1104
|
-
consume(
|
|
1105
|
-
while (!match(
|
|
1106
|
-
const { value: optionsKeyword } = consume(
|
|
1068
|
+
consume(TokenType.LeftBracket);
|
|
1069
|
+
while (!match(TokenType.RightBracket)) {
|
|
1070
|
+
const { value: optionsKeyword } = consume(TokenType.Keyword, lexer.COLLECTION_LAYOUT_OPTIONS_KEYWORDS);
|
|
1107
1071
|
switch (optionsKeyword) {
|
|
1108
1072
|
case 'active':
|
|
1109
1073
|
case 'title':
|
|
1110
1074
|
case 'picture':
|
|
1111
1075
|
case 'badge': {
|
|
1112
|
-
const { value, location } = consume(
|
|
1076
|
+
const { value, location } = consume(TokenType.Identifier);
|
|
1113
1077
|
const symbol = Symbol();
|
|
1114
1078
|
options[optionsKeyword] = value;
|
|
1115
1079
|
optionsSymbols[optionsKeyword] = symbol;
|
|
1116
|
-
|
|
1080
|
+
locationMap.set(symbol, location);
|
|
1117
1081
|
break;
|
|
1118
1082
|
}
|
|
1119
1083
|
case 'information': {
|
|
1120
|
-
if (match(
|
|
1084
|
+
if (match(TokenType.LeftBracket)) {
|
|
1121
1085
|
const { value, symbols } = parseArrayBlock();
|
|
1122
1086
|
options[optionsKeyword] = value;
|
|
1123
1087
|
optionsSymbols[optionsKeyword] = symbols;
|
|
1124
1088
|
}
|
|
1125
1089
|
else {
|
|
1126
|
-
const { value, location } = consume(
|
|
1090
|
+
const { value, location } = consume(TokenType.Identifier);
|
|
1127
1091
|
const symbol = Symbol();
|
|
1128
1092
|
options[optionsKeyword] = value;
|
|
1129
1093
|
optionsSymbols[optionsKeyword] = symbol;
|
|
1130
|
-
|
|
1094
|
+
locationMap.set(symbol, location);
|
|
1131
1095
|
}
|
|
1132
1096
|
break;
|
|
1133
1097
|
}
|
|
1134
1098
|
case 'translateBadge': {
|
|
1135
|
-
const { value } = consume(
|
|
1099
|
+
const { value } = consume(TokenType.Boolean);
|
|
1136
1100
|
options[optionsKeyword] = value;
|
|
1137
1101
|
break;
|
|
1138
1102
|
}
|
|
1139
1103
|
}
|
|
1140
1104
|
}
|
|
1141
1105
|
}
|
|
1142
|
-
consume(
|
|
1106
|
+
consume(TokenType.RightBracket);
|
|
1143
1107
|
break;
|
|
1144
1108
|
}
|
|
1145
1109
|
}
|
|
1146
1110
|
if (!name) {
|
|
1147
|
-
throw new
|
|
1111
|
+
throw new Diagnostic('layout must have a "name" property', location);
|
|
1148
1112
|
}
|
|
1149
|
-
consume(
|
|
1113
|
+
consume(TokenType.RightBracket);
|
|
1150
1114
|
return {
|
|
1151
1115
|
kind: 'layout',
|
|
1152
1116
|
name,
|
|
@@ -1165,24 +1129,24 @@ const parse = (tokens) => {
|
|
|
1165
1129
|
fields: {},
|
|
1166
1130
|
},
|
|
1167
1131
|
};
|
|
1168
|
-
consume(
|
|
1169
|
-
while (!match(
|
|
1170
|
-
const { value: keyword, location: keywordLocation } = consume(
|
|
1132
|
+
consume(TokenType.LeftBracket);
|
|
1133
|
+
while (!match(TokenType.RightBracket)) {
|
|
1134
|
+
const { value: keyword, location: keywordLocation } = consume(TokenType.Keyword, lexer.COLLECTION_FORM_LAYOUT_KEYWORDS);
|
|
1171
1135
|
switch (keyword) {
|
|
1172
1136
|
case 'fields': {
|
|
1173
|
-
consume(
|
|
1174
|
-
while (!match(
|
|
1175
|
-
const { value: identifier, location: identifierLocation } = consume(
|
|
1137
|
+
consume(TokenType.LeftBracket);
|
|
1138
|
+
while (!match(TokenType.RightBracket)) {
|
|
1139
|
+
const { value: identifier, location: identifierLocation } = consume(TokenType.Identifier);
|
|
1176
1140
|
const identifierSymbol = Symbol();
|
|
1177
|
-
|
|
1141
|
+
locationMap.set(identifierSymbol, identifierLocation);
|
|
1178
1142
|
fields[identifier] ??= {};
|
|
1179
1143
|
node[AST.LOCATION_SYMBOL].fields[identifier] = {
|
|
1180
1144
|
name: identifierSymbol,
|
|
1181
1145
|
field: {},
|
|
1182
1146
|
};
|
|
1183
|
-
consume(
|
|
1184
|
-
while (!match(
|
|
1185
|
-
const { value: keyword, location: keywordLocation } = consume(
|
|
1147
|
+
consume(TokenType.LeftBracket);
|
|
1148
|
+
while (!match(TokenType.RightBracket)) {
|
|
1149
|
+
const { value: keyword, location: keywordLocation } = consume(TokenType.Keyword, lexer.COLLECTION_FORM_LAYOUT_KEYWORDS);
|
|
1186
1150
|
switch (keyword) {
|
|
1187
1151
|
case 'if': {
|
|
1188
1152
|
const ifTerms = [];
|
|
@@ -1192,47 +1156,47 @@ const parse = (tokens) => {
|
|
|
1192
1156
|
}
|
|
1193
1157
|
case 'span':
|
|
1194
1158
|
case 'verticalSpacing': {
|
|
1195
|
-
fields[identifier].span = consume(
|
|
1159
|
+
fields[identifier].span = consume(TokenType.Number).value;
|
|
1196
1160
|
break;
|
|
1197
1161
|
}
|
|
1198
1162
|
case 'separator': {
|
|
1199
|
-
fields[identifier].separator = match(
|
|
1200
|
-
? consume(
|
|
1201
|
-
: consume(
|
|
1163
|
+
fields[identifier].separator = match(TokenType.Boolean)
|
|
1164
|
+
? consume(TokenType.Boolean).value
|
|
1165
|
+
: consume(TokenType.QuotedString, [
|
|
1202
1166
|
'top',
|
|
1203
1167
|
'bottom',
|
|
1204
1168
|
]).value;
|
|
1205
1169
|
break;
|
|
1206
1170
|
}
|
|
1207
1171
|
default: {
|
|
1208
|
-
throw new
|
|
1172
|
+
throw new Diagnostic(`invalid keyword "${keyword}"`, keywordLocation);
|
|
1209
1173
|
}
|
|
1210
1174
|
}
|
|
1211
1175
|
}
|
|
1212
|
-
consume(
|
|
1176
|
+
consume(TokenType.RightBracket);
|
|
1213
1177
|
}
|
|
1214
|
-
consume(
|
|
1178
|
+
consume(TokenType.RightBracket);
|
|
1215
1179
|
break;
|
|
1216
1180
|
}
|
|
1217
1181
|
default: {
|
|
1218
|
-
throw new
|
|
1182
|
+
throw new Diagnostic(`invalid keyword "${keyword}"`, keywordLocation);
|
|
1219
1183
|
}
|
|
1220
1184
|
}
|
|
1221
1185
|
}
|
|
1222
|
-
consume(
|
|
1186
|
+
consume(TokenType.RightBracket);
|
|
1223
1187
|
return node;
|
|
1224
1188
|
};
|
|
1225
1189
|
const parseCondition = (symbols = []) => {
|
|
1226
|
-
if (match(
|
|
1227
|
-
consume(
|
|
1190
|
+
if (match(TokenType.LeftParens)) {
|
|
1191
|
+
consume(TokenType.LeftParens);
|
|
1228
1192
|
let operatorType, newOp = operatorType;
|
|
1229
1193
|
const conditions = [];
|
|
1230
|
-
while (!match(
|
|
1194
|
+
while (!match(TokenType.RightParens)) {
|
|
1231
1195
|
conditions.push(parseCondition(symbols));
|
|
1232
|
-
if (match(
|
|
1196
|
+
if (match(TokenType.RightParens)) {
|
|
1233
1197
|
break;
|
|
1234
1198
|
}
|
|
1235
|
-
const { value: operatorSymbol, location } = consume(
|
|
1199
|
+
const { value: operatorSymbol, location } = consume(TokenType.Operator);
|
|
1236
1200
|
switch (operatorSymbol) {
|
|
1237
1201
|
case '&&':
|
|
1238
1202
|
newOp = 'and';
|
|
@@ -1241,15 +1205,15 @@ const parse = (tokens) => {
|
|
|
1241
1205
|
newOp = 'or';
|
|
1242
1206
|
break;
|
|
1243
1207
|
default: {
|
|
1244
|
-
throw new
|
|
1208
|
+
throw new Diagnostic(`unsupported operator: "${operatorSymbol}"`, location);
|
|
1245
1209
|
}
|
|
1246
1210
|
}
|
|
1247
1211
|
if (operatorType && operatorType !== newOp) {
|
|
1248
|
-
throw new
|
|
1212
|
+
throw new Diagnostic('having "and" or "or" in the same expression is not supported, please use parenthesis', location);
|
|
1249
1213
|
}
|
|
1250
1214
|
operatorType = newOp;
|
|
1251
1215
|
}
|
|
1252
|
-
consume(
|
|
1216
|
+
consume(TokenType.RightParens);
|
|
1253
1217
|
switch (operatorType) {
|
|
1254
1218
|
case 'and': {
|
|
1255
1219
|
return {
|
|
@@ -1266,34 +1230,34 @@ const parse = (tokens) => {
|
|
|
1266
1230
|
}
|
|
1267
1231
|
}
|
|
1268
1232
|
}
|
|
1269
|
-
if (match(
|
|
1270
|
-
consume(
|
|
1233
|
+
if (match(TokenType.Operator, '!')) {
|
|
1234
|
+
consume(TokenType.Operator);
|
|
1271
1235
|
return {
|
|
1272
1236
|
not: parseCondition(symbols),
|
|
1273
1237
|
};
|
|
1274
1238
|
}
|
|
1275
|
-
const { value: term1, location: term1Location } = consume(
|
|
1239
|
+
const { value: term1, location: term1Location } = consume(TokenType.Identifier);
|
|
1276
1240
|
const term1Symbol = Symbol();
|
|
1277
|
-
|
|
1241
|
+
locationMap.set(term1Symbol, term1Location);
|
|
1278
1242
|
symbols.push([
|
|
1279
1243
|
term1,
|
|
1280
1244
|
term1Symbol,
|
|
1281
1245
|
]);
|
|
1282
|
-
if (!match(
|
|
1246
|
+
if (!match(TokenType.Operator, lexer.FINAL_OPERATORS)) {
|
|
1283
1247
|
return {
|
|
1284
1248
|
operator: 'truthy',
|
|
1285
1249
|
term1,
|
|
1286
1250
|
};
|
|
1287
1251
|
}
|
|
1288
|
-
const { value: operatorSymbol, location } = consume(
|
|
1252
|
+
const { value: operatorSymbol, location } = consume(TokenType.Operator);
|
|
1289
1253
|
let term2;
|
|
1290
|
-
if (match(
|
|
1254
|
+
if (match(TokenType.LeftParens)) {
|
|
1291
1255
|
term2 = parseCondition(symbols);
|
|
1292
1256
|
}
|
|
1293
|
-
else if (match(
|
|
1257
|
+
else if (match(TokenType.LeftSquareBracket)) {
|
|
1294
1258
|
term2 = parseArray([
|
|
1295
|
-
|
|
1296
|
-
|
|
1259
|
+
TokenType.QuotedString,
|
|
1260
|
+
TokenType.Number,
|
|
1297
1261
|
]).value;
|
|
1298
1262
|
}
|
|
1299
1263
|
else {
|
|
@@ -1321,7 +1285,7 @@ const parse = (tokens) => {
|
|
|
1321
1285
|
operator = 'lt';
|
|
1322
1286
|
break;
|
|
1323
1287
|
default: {
|
|
1324
|
-
throw new
|
|
1288
|
+
throw new Diagnostic(`unsupported operator: "${operatorSymbol}"`, location);
|
|
1325
1289
|
}
|
|
1326
1290
|
}
|
|
1327
1291
|
return {
|
|
@@ -1339,7 +1303,7 @@ const parse = (tokens) => {
|
|
|
1339
1303
|
if (collection.name === 'User') {
|
|
1340
1304
|
const { properties } = collection;
|
|
1341
1305
|
if ('roles' in properties && 'items' in properties.roles.property && 'enum' in properties.roles.property.items) {
|
|
1342
|
-
|
|
1306
|
+
memoTable.roles = properties.roles.property.items.enum;
|
|
1343
1307
|
}
|
|
1344
1308
|
}
|
|
1345
1309
|
ast.collections.push(collection);
|
|
@@ -1354,11 +1318,11 @@ const parse = (tokens) => {
|
|
|
1354
1318
|
break;
|
|
1355
1319
|
}
|
|
1356
1320
|
default:
|
|
1357
|
-
throw new
|
|
1321
|
+
throw new Diagnostic(`invalid declaration type: "${declType}"`, location);
|
|
1358
1322
|
}
|
|
1359
1323
|
}
|
|
1360
1324
|
catch (err) {
|
|
1361
|
-
if (err instanceof
|
|
1325
|
+
if (err instanceof Diagnostic) {
|
|
1362
1326
|
errors.push(err);
|
|
1363
1327
|
recover(lexer.TOPLEVEL_KEYWORDS);
|
|
1364
1328
|
continue;
|
|
@@ -1371,4 +1335,3 @@ const parse = (tokens) => {
|
|
|
1371
1335
|
errors,
|
|
1372
1336
|
};
|
|
1373
1337
|
};
|
|
1374
|
-
exports.parse = parse;
|