1
|
"use strict";
|
2
|
|
3
|
Object.defineProperty(exports, "__esModule", {
|
4
|
value: true
|
5
|
});
|
6
|
exports.tokenize = tokenize;
|
7
|
exports.tokens = exports.keywords = void 0;
|
8
|
|
9
|
var _helperFsm = require("@webassemblyjs/helper-fsm");
|
10
|
|
11
|
var _helperCodeFrame = require("@webassemblyjs/helper-code-frame");
|
12
|
|
13
|
// eslint-disable-next-line
|
14
|
function getCodeFrame(source, line, column) {
|
15
|
var loc = {
|
16
|
start: {
|
17
|
line: line,
|
18
|
column: column
|
19
|
}
|
20
|
};
|
21
|
return "\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, loc) + "\n";
|
22
|
}
|
23
|
|
24
|
var WHITESPACE = /\s/;
|
25
|
var PARENS = /\(|\)/;
|
26
|
var LETTERS = /[a-z0-9_/]/i;
|
27
|
var idchar = /[a-z0-9!#$%&*+./:<=>?@\\[\]^_`|~-]/i;
|
28
|
var valtypes = ["i32", "i64", "f32", "f64"];
|
29
|
var NUMBERS = /[0-9|.|_]/;
|
30
|
var NUMBER_KEYWORDS = /nan|inf/;
|
31
|
|
32
|
function isNewLine(char) {
|
33
|
return char.charCodeAt(0) === 10 || char.charCodeAt(0) === 13;
|
34
|
}
|
35
|
|
36
|
function Token(type, value, start, end) {
|
37
|
var opts = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
|
38
|
var token = {
|
39
|
type: type,
|
40
|
value: value,
|
41
|
loc: {
|
42
|
start: start,
|
43
|
end: end
|
44
|
}
|
45
|
};
|
46
|
|
47
|
if (Object.keys(opts).length > 0) {
|
48
|
// $FlowIgnore
|
49
|
token["opts"] = opts;
|
50
|
}
|
51
|
|
52
|
return token;
|
53
|
}
|
54
|
|
55
|
var tokenTypes = {
|
56
|
openParen: "openParen",
|
57
|
closeParen: "closeParen",
|
58
|
number: "number",
|
59
|
string: "string",
|
60
|
name: "name",
|
61
|
identifier: "identifier",
|
62
|
valtype: "valtype",
|
63
|
dot: "dot",
|
64
|
comment: "comment",
|
65
|
equal: "equal",
|
66
|
keyword: "keyword"
|
67
|
};
|
68
|
var keywords = {
|
69
|
module: "module",
|
70
|
func: "func",
|
71
|
param: "param",
|
72
|
result: "result",
|
73
|
export: "export",
|
74
|
loop: "loop",
|
75
|
block: "block",
|
76
|
if: "if",
|
77
|
then: "then",
|
78
|
else: "else",
|
79
|
call: "call",
|
80
|
call_indirect: "call_indirect",
|
81
|
import: "import",
|
82
|
memory: "memory",
|
83
|
table: "table",
|
84
|
global: "global",
|
85
|
anyfunc: "anyfunc",
|
86
|
mut: "mut",
|
87
|
data: "data",
|
88
|
type: "type",
|
89
|
elem: "elem",
|
90
|
start: "start",
|
91
|
offset: "offset"
|
92
|
};
|
93
|
exports.keywords = keywords;
|
94
|
var NUMERIC_SEPARATOR = "_";
|
95
|
/**
|
96
|
* Build the FSM for number literals
|
97
|
*/
|
98
|
|
99
|
var numberLiteralFSM = new _helperFsm.FSM({
|
100
|
START: [(0, _helperFsm.makeTransition)(/-|\+/, "AFTER_SIGN"), (0, _helperFsm.makeTransition)(/nan:0x/, "NAN_HEX", {
|
101
|
n: 6
|
102
|
}), (0, _helperFsm.makeTransition)(/nan|inf/, "STOP", {
|
103
|
n: 3
|
104
|
}), (0, _helperFsm.makeTransition)(/0x/, "HEX", {
|
105
|
n: 2
|
106
|
}), (0, _helperFsm.makeTransition)(/[0-9]/, "DEC"), (0, _helperFsm.makeTransition)(/\./, "DEC_FRAC")],
|
107
|
AFTER_SIGN: [(0, _helperFsm.makeTransition)(/nan:0x/, "NAN_HEX", {
|
108
|
n: 6
|
109
|
}), (0, _helperFsm.makeTransition)(/nan|inf/, "STOP", {
|
110
|
n: 3
|
111
|
}), (0, _helperFsm.makeTransition)(/0x/, "HEX", {
|
112
|
n: 2
|
113
|
}), (0, _helperFsm.makeTransition)(/[0-9]/, "DEC"), (0, _helperFsm.makeTransition)(/\./, "DEC_FRAC")],
|
114
|
DEC_FRAC: [(0, _helperFsm.makeTransition)(/[0-9]/, "DEC_FRAC", {
|
115
|
allowedSeparator: NUMERIC_SEPARATOR
|
116
|
}), (0, _helperFsm.makeTransition)(/e|E/, "DEC_SIGNED_EXP")],
|
117
|
DEC: [(0, _helperFsm.makeTransition)(/[0-9]/, "DEC", {
|
118
|
allowedSeparator: NUMERIC_SEPARATOR
|
119
|
}), (0, _helperFsm.makeTransition)(/\./, "DEC_FRAC"), (0, _helperFsm.makeTransition)(/e|E/, "DEC_SIGNED_EXP")],
|
120
|
DEC_SIGNED_EXP: [(0, _helperFsm.makeTransition)(/\+|-/, "DEC_EXP"), (0, _helperFsm.makeTransition)(/[0-9]/, "DEC_EXP")],
|
121
|
DEC_EXP: [(0, _helperFsm.makeTransition)(/[0-9]/, "DEC_EXP", {
|
122
|
allowedSeparator: NUMERIC_SEPARATOR
|
123
|
})],
|
124
|
HEX: [(0, _helperFsm.makeTransition)(/[0-9|A-F|a-f]/, "HEX", {
|
125
|
allowedSeparator: NUMERIC_SEPARATOR
|
126
|
}), (0, _helperFsm.makeTransition)(/\./, "HEX_FRAC"), (0, _helperFsm.makeTransition)(/p|P/, "HEX_SIGNED_EXP")],
|
127
|
HEX_FRAC: [(0, _helperFsm.makeTransition)(/[0-9|A-F|a-f]/, "HEX_FRAC", {
|
128
|
allowedSeparator: NUMERIC_SEPARATOR
|
129
|
}), (0, _helperFsm.makeTransition)(/p|P|/, "HEX_SIGNED_EXP")],
|
130
|
HEX_SIGNED_EXP: [(0, _helperFsm.makeTransition)(/[0-9|+|-]/, "HEX_EXP")],
|
131
|
HEX_EXP: [(0, _helperFsm.makeTransition)(/[0-9]/, "HEX_EXP", {
|
132
|
allowedSeparator: NUMERIC_SEPARATOR
|
133
|
})],
|
134
|
NAN_HEX: [(0, _helperFsm.makeTransition)(/[0-9|A-F|a-f]/, "NAN_HEX", {
|
135
|
allowedSeparator: NUMERIC_SEPARATOR
|
136
|
})],
|
137
|
STOP: []
|
138
|
}, "START", "STOP");
|
139
|
|
140
|
function tokenize(input) {
|
141
|
var current = 0;
|
142
|
var char = input[current]; // Used by SourceLocation
|
143
|
|
144
|
var column = 1;
|
145
|
var line = 1;
|
146
|
var tokens = [];
|
147
|
/**
|
148
|
* Creates a pushToken function for a given type
|
149
|
*/
|
150
|
|
151
|
function pushToken(type) {
|
152
|
return function (v) {
|
153
|
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
154
|
var startColumn = opts.startColumn || column - String(v).length;
|
155
|
delete opts.startColumn;
|
156
|
var endColumn = opts.endColumn || startColumn + String(v).length - 1;
|
157
|
delete opts.endColumn;
|
158
|
var start = {
|
159
|
line: line,
|
160
|
column: startColumn
|
161
|
};
|
162
|
var end = {
|
163
|
line: line,
|
164
|
column: endColumn
|
165
|
};
|
166
|
tokens.push(Token(type, v, start, end, opts));
|
167
|
};
|
168
|
}
|
169
|
/**
|
170
|
* Functions to save newly encountered tokens
|
171
|
*/
|
172
|
|
173
|
|
174
|
var pushCloseParenToken = pushToken(tokenTypes.closeParen);
|
175
|
var pushOpenParenToken = pushToken(tokenTypes.openParen);
|
176
|
var pushNumberToken = pushToken(tokenTypes.number);
|
177
|
var pushValtypeToken = pushToken(tokenTypes.valtype);
|
178
|
var pushNameToken = pushToken(tokenTypes.name);
|
179
|
var pushIdentifierToken = pushToken(tokenTypes.identifier);
|
180
|
var pushKeywordToken = pushToken(tokenTypes.keyword);
|
181
|
var pushDotToken = pushToken(tokenTypes.dot);
|
182
|
var pushStringToken = pushToken(tokenTypes.string);
|
183
|
var pushCommentToken = pushToken(tokenTypes.comment);
|
184
|
var pushEqualToken = pushToken(tokenTypes.equal);
|
185
|
/**
|
186
|
* Can be used to look at the next character(s).
|
187
|
*
|
188
|
* The default behavior `lookahead()` simply returns the next character without consuming it.
|
189
|
* Letters are always returned in lowercase.
|
190
|
*
|
191
|
* @param {number} length How many characters to query. Default = 1
|
192
|
* @param {number} offset How many characters to skip forward from current one. Default = 1
|
193
|
*
|
194
|
*/
|
195
|
|
196
|
function lookahead() {
|
197
|
var length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
|
198
|
var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
199
|
return input.substring(current + offset, current + offset + length).toLowerCase();
|
200
|
}
|
201
|
/**
|
202
|
* Advances the cursor in the input by a certain amount
|
203
|
*
|
204
|
* @param {number} amount How many characters to consume. Default = 1
|
205
|
*/
|
206
|
|
207
|
|
208
|
function eatCharacter() {
|
209
|
var amount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
|
210
|
column += amount;
|
211
|
current += amount;
|
212
|
char = input[current];
|
213
|
}
|
214
|
|
215
|
while (current < input.length) {
|
216
|
// ;;
|
217
|
if (char === ";" && lookahead() === ";") {
|
218
|
var startColumn = column;
|
219
|
eatCharacter(2);
|
220
|
var text = "";
|
221
|
|
222
|
while (!isNewLine(char)) {
|
223
|
text += char;
|
224
|
eatCharacter();
|
225
|
|
226
|
if (char === undefined) {
|
227
|
break;
|
228
|
}
|
229
|
}
|
230
|
|
231
|
var endColumn = column;
|
232
|
pushCommentToken(text, {
|
233
|
type: "leading",
|
234
|
startColumn: startColumn,
|
235
|
endColumn: endColumn
|
236
|
});
|
237
|
continue;
|
238
|
} // (;
|
239
|
|
240
|
|
241
|
if (char === "(" && lookahead() === ";") {
|
242
|
var _startColumn = column;
|
243
|
eatCharacter(2);
|
244
|
var _text = ""; // ;)
|
245
|
|
246
|
while (true) {
|
247
|
char = input[current];
|
248
|
|
249
|
if (char === ";" && lookahead() === ")") {
|
250
|
eatCharacter(2);
|
251
|
break;
|
252
|
}
|
253
|
|
254
|
_text += char;
|
255
|
eatCharacter();
|
256
|
|
257
|
if (isNewLine(char)) {
|
258
|
line++;
|
259
|
column = 0;
|
260
|
}
|
261
|
}
|
262
|
|
263
|
var _endColumn = column;
|
264
|
pushCommentToken(_text, {
|
265
|
type: "block",
|
266
|
startColumn: _startColumn,
|
267
|
endColumn: _endColumn
|
268
|
});
|
269
|
continue;
|
270
|
}
|
271
|
|
272
|
if (char === "(") {
|
273
|
pushOpenParenToken(char);
|
274
|
eatCharacter();
|
275
|
continue;
|
276
|
}
|
277
|
|
278
|
if (char === "=") {
|
279
|
pushEqualToken(char);
|
280
|
eatCharacter();
|
281
|
continue;
|
282
|
}
|
283
|
|
284
|
if (char === ")") {
|
285
|
pushCloseParenToken(char);
|
286
|
eatCharacter();
|
287
|
continue;
|
288
|
}
|
289
|
|
290
|
if (isNewLine(char)) {
|
291
|
line++;
|
292
|
eatCharacter();
|
293
|
column = 0;
|
294
|
continue;
|
295
|
}
|
296
|
|
297
|
if (WHITESPACE.test(char)) {
|
298
|
eatCharacter();
|
299
|
continue;
|
300
|
}
|
301
|
|
302
|
if (char === "$") {
|
303
|
var _startColumn2 = column;
|
304
|
eatCharacter();
|
305
|
var value = "";
|
306
|
|
307
|
while (idchar.test(char)) {
|
308
|
value += char;
|
309
|
eatCharacter();
|
310
|
}
|
311
|
|
312
|
var _endColumn2 = column;
|
313
|
pushIdentifierToken(value, {
|
314
|
startColumn: _startColumn2,
|
315
|
endColumn: _endColumn2
|
316
|
});
|
317
|
continue;
|
318
|
}
|
319
|
|
320
|
if (NUMBERS.test(char) || NUMBER_KEYWORDS.test(lookahead(3, 0)) || char === "-" || char === "+") {
|
321
|
var _startColumn3 = column;
|
322
|
|
323
|
var _value = numberLiteralFSM.run(input.slice(current));
|
324
|
|
325
|
if (_value === "") {
|
326
|
throw new Error(getCodeFrame(input, line, column) + "Unexpected character " + JSON.stringify(char));
|
327
|
}
|
328
|
|
329
|
pushNumberToken(_value, {
|
330
|
startColumn: _startColumn3
|
331
|
});
|
332
|
eatCharacter(_value.length);
|
333
|
|
334
|
if (char && !PARENS.test(char) && !WHITESPACE.test(char)) {
|
335
|
throw new Error(getCodeFrame(input, line, column) + "Unexpected character " + JSON.stringify(char));
|
336
|
}
|
337
|
|
338
|
continue;
|
339
|
}
|
340
|
|
341
|
if (char === '"') {
|
342
|
var _startColumn4 = column;
|
343
|
var _value2 = "";
|
344
|
eatCharacter(); // "
|
345
|
|
346
|
while (char !== '"') {
|
347
|
if (isNewLine(char)) {
|
348
|
throw new Error(getCodeFrame(input, line, column) + "Unexpected character " + JSON.stringify(char));
|
349
|
}
|
350
|
|
351
|
_value2 += char;
|
352
|
eatCharacter(); // char
|
353
|
}
|
354
|
|
355
|
eatCharacter(); // "
|
356
|
|
357
|
var _endColumn3 = column;
|
358
|
pushStringToken(_value2, {
|
359
|
startColumn: _startColumn4,
|
360
|
endColumn: _endColumn3
|
361
|
});
|
362
|
continue;
|
363
|
}
|
364
|
|
365
|
if (LETTERS.test(char)) {
|
366
|
var _value3 = "";
|
367
|
var _startColumn5 = column;
|
368
|
|
369
|
while (char && LETTERS.test(char)) {
|
370
|
_value3 += char;
|
371
|
eatCharacter();
|
372
|
}
|
373
|
/*
|
374
|
* Handle MemberAccess
|
375
|
*/
|
376
|
|
377
|
|
378
|
if (char === ".") {
|
379
|
var dotStartColumn = column;
|
380
|
|
381
|
if (valtypes.indexOf(_value3) !== -1) {
|
382
|
pushValtypeToken(_value3, {
|
383
|
startColumn: _startColumn5
|
384
|
});
|
385
|
} else {
|
386
|
pushNameToken(_value3);
|
387
|
}
|
388
|
|
389
|
eatCharacter();
|
390
|
_value3 = "";
|
391
|
var nameStartColumn = column;
|
392
|
|
393
|
while (LETTERS.test(char)) {
|
394
|
_value3 += char;
|
395
|
eatCharacter();
|
396
|
}
|
397
|
|
398
|
pushDotToken(".", {
|
399
|
startColumn: dotStartColumn
|
400
|
});
|
401
|
pushNameToken(_value3, {
|
402
|
startColumn: nameStartColumn
|
403
|
});
|
404
|
continue;
|
405
|
}
|
406
|
/*
|
407
|
* Handle keywords
|
408
|
*/
|
409
|
// $FlowIgnore
|
410
|
|
411
|
|
412
|
if (typeof keywords[_value3] === "string") {
|
413
|
pushKeywordToken(_value3, {
|
414
|
startColumn: _startColumn5
|
415
|
});
|
416
|
continue;
|
417
|
}
|
418
|
/*
|
419
|
* Handle types
|
420
|
*/
|
421
|
|
422
|
|
423
|
if (valtypes.indexOf(_value3) !== -1) {
|
424
|
pushValtypeToken(_value3, {
|
425
|
startColumn: _startColumn5
|
426
|
});
|
427
|
continue;
|
428
|
}
|
429
|
/*
|
430
|
* Handle literals
|
431
|
*/
|
432
|
|
433
|
|
434
|
pushNameToken(_value3, {
|
435
|
startColumn: _startColumn5
|
436
|
});
|
437
|
continue;
|
438
|
}
|
439
|
|
440
|
throw new Error(getCodeFrame(input, line, column) + "Unexpected character " + JSON.stringify(char));
|
441
|
}
|
442
|
|
443
|
return tokens;
|
444
|
}
|
445
|
|
446
|
var tokens = tokenTypes;
|
447
|
exports.tokens = tokens;
|