UNPKG

50.3 kBJavaScriptView Raw
1function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
2
3function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
4
5function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
7function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8
9function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
10
11function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
12
13function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
14
15import { codeFrameFromSource } from "@webassemblyjs/helper-code-frame";
16import * as t from "@webassemblyjs/ast";
17import { parse32I } from "@webassemblyjs/helper-numbers";
18import { parseString } from "./string-literals";
19import { tokens, keywords } from "./tokenizer";
20
21function hasPlugin(name) {
22 if (name !== "wast") throw new Error("unknow plugin");
23 return true;
24}
25
26function isKeyword(token, id) {
27 return token.type === tokens.keyword && token.value === id;
28}
29
30function tokenToString(token) {
31 if (token.type === "keyword") {
32 return "keyword (".concat(token.value, ")");
33 }
34
35 return token.type;
36}
37
38function identifierFromToken(token) {
39 var _token$loc = token.loc,
40 end = _token$loc.end,
41 start = _token$loc.start;
42 return t.withLoc(t.identifier(token.value), end, start);
43}
44
45export function parse(tokensList, source) {
46 var current = 0;
47 var getUniqueName = t.getUniqueNameGenerator();
48 var state = {
49 registredExportedElements: []
50 }; // But this time we're going to use recursion instead of a `while` loop. So we
51 // define a `walk` function.
52
53 function walk() {
54 var token = tokensList[current];
55
56 function eatToken() {
57 token = tokensList[++current];
58 }
59
60 function getEndLoc() {
61 var currentToken = token;
62
63 if (typeof currentToken === "undefined") {
64 var lastToken = tokensList[tokensList.length - 1];
65 currentToken = lastToken;
66 }
67
68 return currentToken.loc.end;
69 }
70
71 function getStartLoc() {
72 return token.loc.start;
73 }
74
75 function eatTokenOfType(type) {
76 if (token.type !== type) {
77 throw new Error("\n" + codeFrameFromSource(source, token.loc) + "Assertion error: expected token of type " + type + ", given " + tokenToString(token));
78 }
79
80 eatToken();
81 }
82
83 function parseExportIndex(token) {
84 if (token.type === tokens.identifier) {
85 var index = identifierFromToken(token);
86 eatToken();
87 return index;
88 } else if (token.type === tokens.number) {
89 var _index = t.numberLiteralFromRaw(token.value);
90
91 eatToken();
92 return _index;
93 } else {
94 throw function () {
95 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "unknown export index" + ", given " + tokenToString(token));
96 }();
97 }
98 }
99
100 function lookaheadAndCheck() {
101 var len = arguments.length;
102
103 for (var i = 0; i < len; i++) {
104 var tokenAhead = tokensList[current + i];
105 var expectedToken = i < 0 || arguments.length <= i ? undefined : arguments[i];
106
107 if (tokenAhead.type === "keyword") {
108 if (isKeyword(tokenAhead, expectedToken) === false) {
109 return false;
110 }
111 } else if (expectedToken !== tokenAhead.type) {
112 return false;
113 }
114 }
115
116 return true;
117 } // TODO(sven): there is probably a better way to do this
118 // can refactor it if it get out of hands
119
120
121 function maybeIgnoreComment() {
122 if (typeof token === "undefined") {
123 // Ignore
124 return;
125 }
126
127 while (token.type === tokens.comment) {
128 eatToken();
129
130 if (typeof token === "undefined") {
131 // Hit the end
132 break;
133 }
134 }
135 }
136 /**
137 * Parses a memory instruction
138 *
139 * WAST:
140 *
141 * memory: ( memory <name>? <memory_sig> )
142 * ( memory <name>? ( export <string> ) <...> )
143 * ( memory <name>? ( import <string> <string> ) <memory_sig> )
144 * ( memory <name>? ( export <string> )* ( data <string>* )
145 * memory_sig: <nat> <nat>?
146 *
147 */
148
149
150 function parseMemory() {
151 var id = t.identifier(getUniqueName("memory"));
152 var limits = t.limit(0);
153
154 if (token.type === tokens.string || token.type === tokens.identifier) {
155 id = t.identifier(token.value);
156 eatToken();
157 } else {
158 id = t.withRaw(id, ""); // preserve anonymous
159 }
160 /**
161 * Maybe data
162 */
163
164
165 if (lookaheadAndCheck(tokens.openParen, keywords.data)) {
166 eatToken(); // (
167
168 eatToken(); // data
169 // TODO(sven): do something with the data collected here
170
171 var stringInitializer = token.value;
172 eatTokenOfType(tokens.string); // Update limits accordingly
173
174 limits = t.limit(stringInitializer.length);
175 eatTokenOfType(tokens.closeParen);
176 }
177 /**
178 * Maybe export
179 */
180
181
182 if (lookaheadAndCheck(tokens.openParen, keywords["export"])) {
183 eatToken(); // (
184
185 eatToken(); // export
186
187 if (token.type !== tokens.string) {
188 throw function () {
189 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Expected string in export" + ", given " + tokenToString(token));
190 }();
191 }
192
193 var name = token.value;
194 eatToken();
195 state.registredExportedElements.push({
196 exportType: "Memory",
197 name: name,
198 id: id
199 });
200 eatTokenOfType(tokens.closeParen);
201 }
202 /**
203 * Memory signature
204 */
205
206
207 if (token.type === tokens.number) {
208 limits = t.limit(parse32I(token.value));
209 eatToken();
210
211 if (token.type === tokens.number) {
212 limits.max = parse32I(token.value);
213 eatToken();
214
215 if (token.type === tokens.keyword && token.value === "shared") {
216 limits.shared = true;
217 eatToken();
218 }
219 }
220 }
221
222 return t.memory(limits, id);
223 }
224 /**
225 * Parses a data section
226 * https://webassembly.github.io/spec/core/text/modules.html#data-segments
227 *
228 * WAST:
229 *
230 * data: ( data <index>? <offset> <string> )
231 */
232
233
234 function parseData() {
235 // optional memory index
236 var memidx = 0;
237
238 if (token.type === tokens.number) {
239 memidx = token.value;
240 eatTokenOfType(tokens.number); // .
241 }
242
243 eatTokenOfType(tokens.openParen);
244 var offset;
245
246 if (token.type === tokens.valtype) {
247 eatTokenOfType(tokens.valtype); // i32
248
249 eatTokenOfType(tokens.dot); // .
250
251 if (token.value !== "const") {
252 throw new Error("constant expression required");
253 }
254
255 eatTokenOfType(tokens.name); // const
256
257 var numberLiteral = t.numberLiteralFromRaw(token.value, "i32");
258 offset = t.objectInstruction("const", "i32", [numberLiteral]);
259 eatToken();
260 eatTokenOfType(tokens.closeParen);
261 } else {
262 eatTokenOfType(tokens.name); // get_global
263
264 var _numberLiteral = t.numberLiteralFromRaw(token.value, "i32");
265
266 offset = t.instruction("get_global", [_numberLiteral]);
267 eatToken();
268 eatTokenOfType(tokens.closeParen);
269 }
270
271 var byteArray = parseString(token.value);
272 eatToken(); // "string"
273
274 return t.data(t.memIndexLiteral(memidx), offset, t.byteArray(byteArray));
275 }
276 /**
277 * Parses a table instruction
278 *
279 * WAST:
280 *
281 * table: ( table <name>? <table_type> )
282 * ( table <name>? ( export <string> ) <...> )
283 * ( table <name>? ( import <string> <string> ) <table_type> )
284 * ( table <name>? ( export <string> )* <elem_type> ( elem <var>* ) )
285 *
286 * table_type: <nat> <nat>? <elem_type>
287 * elem_type: anyfunc
288 *
289 * elem: ( elem <var>? (offset <instr>* ) <var>* )
290 * ( elem <var>? <expr> <var>* )
291 */
292
293
294 function parseTable() {
295 var name = t.identifier(getUniqueName("table"));
296 var limit = t.limit(0);
297 var elemIndices = [];
298 var elemType = "anyfunc";
299
300 if (token.type === tokens.string || token.type === tokens.identifier) {
301 name = identifierFromToken(token);
302 eatToken();
303 } else {
304 name = t.withRaw(name, ""); // preserve anonymous
305 }
306
307 while (token.type !== tokens.closeParen) {
308 /**
309 * Maybe export
310 */
311 if (lookaheadAndCheck(tokens.openParen, keywords.elem)) {
312 eatToken(); // (
313
314 eatToken(); // elem
315
316 while (token.type === tokens.identifier) {
317 elemIndices.push(t.identifier(token.value));
318 eatToken();
319 }
320
321 eatTokenOfType(tokens.closeParen);
322 } else if (lookaheadAndCheck(tokens.openParen, keywords["export"])) {
323 eatToken(); // (
324
325 eatToken(); // export
326
327 if (token.type !== tokens.string) {
328 throw function () {
329 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Expected string in export" + ", given " + tokenToString(token));
330 }();
331 }
332
333 var exportName = token.value;
334 eatToken();
335 state.registredExportedElements.push({
336 exportType: "Table",
337 name: exportName,
338 id: name
339 });
340 eatTokenOfType(tokens.closeParen);
341 } else if (isKeyword(token, keywords.anyfunc)) {
342 // It's the default value, we can ignore it
343 eatToken(); // anyfunc
344 } else if (token.type === tokens.number) {
345 /**
346 * Table type
347 */
348 var min = parseInt(token.value);
349 eatToken();
350
351 if (token.type === tokens.number) {
352 var max = parseInt(token.value);
353 eatToken();
354 limit = t.limit(min, max);
355 } else {
356 limit = t.limit(min);
357 }
358
359 eatToken();
360 } else {
361 throw function () {
362 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token" + ", given " + tokenToString(token));
363 }();
364 }
365 }
366
367 if (elemIndices.length > 0) {
368 return t.table(elemType, limit, name, elemIndices);
369 } else {
370 return t.table(elemType, limit, name);
371 }
372 }
373 /**
374 * Parses an import statement
375 *
376 * WAST:
377 *
378 * import: ( import <string> <string> <imkind> )
379 * imkind: ( func <name>? <func_sig> )
380 * ( global <name>? <global_sig> )
381 * ( table <name>? <table_sig> )
382 * ( memory <name>? <memory_sig> )
383 *
384 * global_sig: <type> | ( mut <type> )
385 */
386
387
388 function parseImport() {
389 if (token.type !== tokens.string) {
390 throw new Error("Expected a string, " + token.type + " given.");
391 }
392
393 var moduleName = token.value;
394 eatToken();
395
396 if (token.type !== tokens.string) {
397 throw new Error("Expected a string, " + token.type + " given.");
398 }
399
400 var name = token.value;
401 eatToken();
402 eatTokenOfType(tokens.openParen);
403 var descr;
404
405 if (isKeyword(token, keywords.func)) {
406 eatToken(); // keyword
407
408 var fnParams = [];
409 var fnResult = [];
410 var typeRef;
411 var fnName = t.identifier(getUniqueName("func"));
412
413 if (token.type === tokens.identifier) {
414 fnName = identifierFromToken(token);
415 eatToken();
416 }
417
418 while (token.type === tokens.openParen) {
419 eatToken();
420
421 if (lookaheadAndCheck(keywords.type) === true) {
422 eatToken();
423 typeRef = parseTypeReference();
424 } else if (lookaheadAndCheck(keywords.param) === true) {
425 eatToken();
426 fnParams.push.apply(fnParams, _toConsumableArray(parseFuncParam()));
427 } else if (lookaheadAndCheck(keywords.result) === true) {
428 eatToken();
429 fnResult.push.apply(fnResult, _toConsumableArray(parseFuncResult()));
430 } else {
431 throw function () {
432 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in import of type" + ", given " + tokenToString(token));
433 }();
434 }
435
436 eatTokenOfType(tokens.closeParen);
437 }
438
439 if (typeof fnName === "undefined") {
440 throw new Error("Imported function must have a name");
441 }
442
443 descr = t.funcImportDescr(fnName, typeRef !== undefined ? typeRef : t.signature(fnParams, fnResult));
444 } else if (isKeyword(token, keywords.global)) {
445 eatToken(); // keyword
446
447 if (token.type === tokens.openParen) {
448 eatToken(); // (
449
450 eatTokenOfType(tokens.keyword); // mut keyword
451
452 var valtype = token.value;
453 eatToken();
454 descr = t.globalType(valtype, "var");
455 eatTokenOfType(tokens.closeParen);
456 } else {
457 var _valtype = token.value;
458 eatTokenOfType(tokens.valtype);
459 descr = t.globalType(_valtype, "const");
460 }
461 } else if (isKeyword(token, keywords.memory) === true) {
462 eatToken(); // Keyword
463
464 descr = parseMemory();
465 } else if (isKeyword(token, keywords.table) === true) {
466 eatToken(); // Keyword
467
468 descr = parseTable();
469 } else {
470 throw new Error("Unsupported import type: " + tokenToString(token));
471 }
472
473 eatTokenOfType(tokens.closeParen);
474 return t.moduleImport(moduleName, name, descr);
475 }
476 /**
477 * Parses a block instruction
478 *
479 * WAST:
480 *
481 * expr: ( block <name>? <block_sig> <instr>* )
482 * instr: block <name>? <block_sig> <instr>* end <name>?
483 * block_sig : ( result <type>* )*
484 *
485 */
486
487
488 function parseBlock() {
489 var label = t.identifier(getUniqueName("block"));
490 var blockResult = null;
491 var instr = [];
492
493 if (token.type === tokens.identifier) {
494 label = identifierFromToken(token);
495 eatToken();
496 } else {
497 label = t.withRaw(label, ""); // preserve anonymous
498 }
499
500 while (token.type === tokens.openParen) {
501 eatToken();
502
503 if (lookaheadAndCheck(keywords.result) === true) {
504 eatToken();
505 blockResult = token.value;
506 eatToken();
507 } else if (lookaheadAndCheck(tokens.name) === true || lookaheadAndCheck(tokens.valtype) === true || token.type === "keyword" // is any keyword
508 ) {
509 // Instruction
510 instr.push(parseFuncInstr());
511 } else {
512 throw function () {
513 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in block body of type" + ", given " + tokenToString(token));
514 }();
515 }
516
517 maybeIgnoreComment();
518 eatTokenOfType(tokens.closeParen);
519 }
520
521 return t.blockInstruction(label, instr, blockResult);
522 }
523 /**
524 * Parses a if instruction
525 *
526 * WAST:
527 *
528 * expr:
529 * ( if <name>? <block_sig> ( then <instr>* ) ( else <instr>* )? )
530 * ( if <name>? <block_sig> <expr>+ ( then <instr>* ) ( else <instr>* )? )
531 *
532 * instr:
533 * if <name>? <block_sig> <instr>* end <name>?
534 * if <name>? <block_sig> <instr>* else <name>? <instr>* end <name>?
535 *
536 * block_sig : ( result <type>* )*
537 *
538 */
539
540
541 function parseIf() {
542 var blockResult = null;
543 var label = t.identifier(getUniqueName("if"));
544 var testInstrs = [];
545 var consequent = [];
546 var alternate = [];
547
548 if (token.type === tokens.identifier) {
549 label = identifierFromToken(token);
550 eatToken();
551 } else {
552 label = t.withRaw(label, ""); // preserve anonymous
553 }
554
555 while (token.type === tokens.openParen) {
556 eatToken(); // (
557
558 /**
559 * Block signature
560 */
561
562 if (isKeyword(token, keywords.result) === true) {
563 eatToken();
564 blockResult = token.value;
565 eatTokenOfType(tokens.valtype);
566 eatTokenOfType(tokens.closeParen);
567 continue;
568 }
569 /**
570 * Then
571 */
572
573
574 if (isKeyword(token, keywords.then) === true) {
575 eatToken(); // then
576
577 while (token.type === tokens.openParen) {
578 eatToken(); // Instruction
579
580 if (lookaheadAndCheck(tokens.name) === true || lookaheadAndCheck(tokens.valtype) === true || token.type === "keyword" // is any keyword
581 ) {
582 consequent.push(parseFuncInstr());
583 } else {
584 throw function () {
585 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in consequent body of type" + ", given " + tokenToString(token));
586 }();
587 }
588
589 eatTokenOfType(tokens.closeParen);
590 }
591
592 eatTokenOfType(tokens.closeParen);
593 continue;
594 }
595 /**
596 * Alternate
597 */
598
599
600 if (isKeyword(token, keywords["else"])) {
601 eatToken(); // else
602
603 while (token.type === tokens.openParen) {
604 eatToken(); // Instruction
605
606 if (lookaheadAndCheck(tokens.name) === true || lookaheadAndCheck(tokens.valtype) === true || token.type === "keyword" // is any keyword
607 ) {
608 alternate.push(parseFuncInstr());
609 } else {
610 throw function () {
611 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in alternate body of type" + ", given " + tokenToString(token));
612 }();
613 }
614
615 eatTokenOfType(tokens.closeParen);
616 }
617
618 eatTokenOfType(tokens.closeParen);
619 continue;
620 }
621 /**
622 * Test instruction
623 */
624
625
626 if (lookaheadAndCheck(tokens.name) === true || lookaheadAndCheck(tokens.valtype) === true || token.type === "keyword" // is any keyword
627 ) {
628 testInstrs.push(parseFuncInstr());
629 eatTokenOfType(tokens.closeParen);
630 continue;
631 }
632
633 throw function () {
634 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in if body" + ", given " + tokenToString(token));
635 }();
636 }
637
638 return t.ifInstruction(label, testInstrs, blockResult, consequent, alternate);
639 }
640 /**
641 * Parses a loop instruction
642 *
643 * WAT:
644 *
645 * blockinstr :: 'loop' I:label rt:resulttype (in:instr*) 'end' id?
646 *
647 * WAST:
648 *
649 * instr :: loop <name>? <block_sig> <instr>* end <name>?
650 * expr :: ( loop <name>? <block_sig> <instr>* )
651 * block_sig :: ( result <type>* )*
652 *
653 */
654
655
656 function parseLoop() {
657 var label = t.identifier(getUniqueName("loop"));
658 var blockResult;
659 var instr = [];
660
661 if (token.type === tokens.identifier) {
662 label = identifierFromToken(token);
663 eatToken();
664 } else {
665 label = t.withRaw(label, ""); // preserve anonymous
666 }
667
668 while (token.type === tokens.openParen) {
669 eatToken();
670
671 if (lookaheadAndCheck(keywords.result) === true) {
672 eatToken();
673 blockResult = token.value;
674 eatToken();
675 } else if (lookaheadAndCheck(tokens.name) === true || lookaheadAndCheck(tokens.valtype) === true || token.type === "keyword" // is any keyword
676 ) {
677 // Instruction
678 instr.push(parseFuncInstr());
679 } else {
680 throw function () {
681 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in loop body" + ", given " + tokenToString(token));
682 }();
683 }
684
685 eatTokenOfType(tokens.closeParen);
686 }
687
688 return t.loopInstruction(label, blockResult, instr);
689 }
690
691 function parseCallIndirect() {
692 var typeRef;
693 var params = [];
694 var results = [];
695 var instrs = [];
696
697 while (token.type !== tokens.closeParen) {
698 if (lookaheadAndCheck(tokens.openParen, keywords.type)) {
699 eatToken(); // (
700
701 eatToken(); // type
702
703 typeRef = parseTypeReference();
704 } else if (lookaheadAndCheck(tokens.openParen, keywords.param)) {
705 eatToken(); // (
706
707 eatToken(); // param
708
709 /**
710 * Params can be empty:
711 * (params)`
712 */
713
714 if (token.type !== tokens.closeParen) {
715 params.push.apply(params, _toConsumableArray(parseFuncParam()));
716 }
717 } else if (lookaheadAndCheck(tokens.openParen, keywords.result)) {
718 eatToken(); // (
719
720 eatToken(); // result
721
722 /**
723 * Results can be empty:
724 * (result)`
725 */
726
727 if (token.type !== tokens.closeParen) {
728 results.push.apply(results, _toConsumableArray(parseFuncResult()));
729 }
730 } else {
731 eatTokenOfType(tokens.openParen);
732 instrs.push(parseFuncInstr());
733 }
734
735 eatTokenOfType(tokens.closeParen);
736 }
737
738 return t.callIndirectInstruction(typeRef !== undefined ? typeRef : t.signature(params, results), instrs);
739 }
740 /**
741 * Parses an export instruction
742 *
743 * WAT:
744 *
745 * export: ( export <string> <exkind> )
746 * exkind: ( func <var> )
747 * ( global <var> )
748 * ( table <var> )
749 * ( memory <var> )
750 * var: <nat> | <name>
751 *
752 */
753
754
755 function parseExport() {
756 if (token.type !== tokens.string) {
757 throw new Error("Expected string after export, got: " + token.type);
758 }
759
760 var name = token.value;
761 eatToken();
762 var moduleExportDescr = parseModuleExportDescr();
763 return t.moduleExport(name, moduleExportDescr);
764 }
765
766 function parseModuleExportDescr() {
767 var startLoc = getStartLoc();
768 var type = "";
769 var index;
770 eatTokenOfType(tokens.openParen);
771
772 while (token.type !== tokens.closeParen) {
773 if (isKeyword(token, keywords.func)) {
774 type = "Func";
775 eatToken();
776 index = parseExportIndex(token);
777 } else if (isKeyword(token, keywords.table)) {
778 type = "Table";
779 eatToken();
780 index = parseExportIndex(token);
781 } else if (isKeyword(token, keywords.global)) {
782 type = "Global";
783 eatToken();
784 index = parseExportIndex(token);
785 } else if (isKeyword(token, keywords.memory)) {
786 type = "Memory";
787 eatToken();
788 index = parseExportIndex(token);
789 }
790
791 eatToken();
792 }
793
794 if (type === "") {
795 throw new Error("Unknown export type");
796 }
797
798 if (index === undefined) {
799 throw new Error("Exported function must have a name");
800 }
801
802 var node = t.moduleExportDescr(type, index);
803 var endLoc = getEndLoc();
804 eatTokenOfType(tokens.closeParen);
805 return t.withLoc(node, endLoc, startLoc);
806 }
807
808 function parseModule() {
809 var name = null;
810 var isBinary = false;
811 var isQuote = false;
812 var moduleFields = [];
813
814 if (token.type === tokens.identifier) {
815 name = token.value;
816 eatToken();
817 }
818
819 if (hasPlugin("wast") && token.type === tokens.name && token.value === "binary") {
820 eatToken();
821 isBinary = true;
822 }
823
824 if (hasPlugin("wast") && token.type === tokens.name && token.value === "quote") {
825 eatToken();
826 isQuote = true;
827 }
828
829 if (isBinary === true) {
830 var blob = [];
831
832 while (token.type === tokens.string) {
833 blob.push(token.value);
834 eatToken();
835 maybeIgnoreComment();
836 }
837
838 eatTokenOfType(tokens.closeParen);
839 return t.binaryModule(name, blob);
840 }
841
842 if (isQuote === true) {
843 var string = [];
844
845 while (token.type === tokens.string) {
846 string.push(token.value);
847 eatToken();
848 }
849
850 eatTokenOfType(tokens.closeParen);
851 return t.quoteModule(name, string);
852 }
853
854 while (token.type !== tokens.closeParen) {
855 moduleFields.push(walk());
856
857 if (state.registredExportedElements.length > 0) {
858 state.registredExportedElements.forEach(function (decl) {
859 moduleFields.push(t.moduleExport(decl.name, t.moduleExportDescr(decl.exportType, decl.id)));
860 });
861 state.registredExportedElements = [];
862 }
863
864 token = tokensList[current];
865 }
866
867 eatTokenOfType(tokens.closeParen);
868 return t.module(name, moduleFields);
869 }
870 /**
871 * Parses the arguments of an instruction
872 */
873
874
875 function parseFuncInstrArguments(signature) {
876 var args = [];
877 var namedArgs = {};
878 var signaturePtr = 0;
879
880 while (token.type === tokens.name || isKeyword(token, keywords.offset)) {
881 var key = token.value;
882 eatToken();
883 eatTokenOfType(tokens.equal);
884 var value = void 0;
885
886 if (token.type === tokens.number) {
887 value = t.numberLiteralFromRaw(token.value);
888 } else {
889 throw new Error("Unexpected type for argument: " + token.type);
890 }
891
892 namedArgs[key] = value;
893 eatToken();
894 } // $FlowIgnore
895
896
897 var signatureLength = signature.vector ? Infinity : signature.length;
898
899 while (token.type !== tokens.closeParen && (token.type === tokens.openParen || signaturePtr < signatureLength)) {
900 if (token.type === tokens.identifier) {
901 args.push(t.identifier(token.value));
902 eatToken();
903 } else if (token.type === tokens.valtype) {
904 // Handle locals
905 args.push(t.valtypeLiteral(token.value));
906 eatToken();
907 } else if (token.type === tokens.string) {
908 args.push(t.stringLiteral(token.value));
909 eatToken();
910 } else if (token.type === tokens.number) {
911 args.push( // TODO(sven): refactor the type signature handling
912 // https://github.com/xtuc/webassemblyjs/pull/129 is a good start
913 t.numberLiteralFromRaw(token.value, // $FlowIgnore
914 signature[signaturePtr] || "f64")); // $FlowIgnore
915
916 if (!signature.vector) {
917 ++signaturePtr;
918 }
919
920 eatToken();
921 } else if (token.type === tokens.openParen) {
922 /**
923 * Maybe some nested instructions
924 */
925 eatToken(); // Instruction
926
927 if (lookaheadAndCheck(tokens.name) === true || lookaheadAndCheck(tokens.valtype) === true || token.type === "keyword" // is any keyword
928 ) {
929 // $FlowIgnore
930 args.push(parseFuncInstr());
931 } else {
932 throw function () {
933 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in nested instruction" + ", given " + tokenToString(token));
934 }();
935 }
936
937 if (token.type === tokens.closeParen) {
938 eatToken();
939 }
940 } else {
941 throw function () {
942 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in instruction argument" + ", given " + tokenToString(token));
943 }();
944 }
945 }
946
947 return {
948 args: args,
949 namedArgs: namedArgs
950 };
951 }
952 /**
953 * Parses an instruction
954 *
955 * WAT:
956 *
957 * instr :: plaininst
958 * blockinstr
959 *
960 * blockinstr :: 'block' I:label rt:resulttype (in:instr*) 'end' id?
961 * 'loop' I:label rt:resulttype (in:instr*) 'end' id?
962 * 'if' I:label rt:resulttype (in:instr*) 'else' id? (in2:intr*) 'end' id?
963 *
964 * plaininst :: 'unreachable'
965 * 'nop'
966 * 'br' l:labelidx
967 * 'br_if' l:labelidx
968 * 'br_table' l*:vec(labelidx) ln:labelidx
969 * 'return'
970 * 'call' x:funcidx
971 * 'call_indirect' x, I:typeuse
972 *
973 * WAST:
974 *
975 * instr:
976 * <expr>
977 * <op>
978 * block <name>? <block_sig> <instr>* end <name>?
979 * loop <name>? <block_sig> <instr>* end <name>?
980 * if <name>? <block_sig> <instr>* end <name>?
981 * if <name>? <block_sig> <instr>* else <name>? <instr>* end <name>?
982 *
983 * expr:
984 * ( <op> )
985 * ( <op> <expr>+ )
986 * ( block <name>? <block_sig> <instr>* )
987 * ( loop <name>? <block_sig> <instr>* )
988 * ( if <name>? <block_sig> ( then <instr>* ) ( else <instr>* )? )
989 * ( if <name>? <block_sig> <expr>+ ( then <instr>* ) ( else <instr>* )? )
990 *
991 * op:
992 * unreachable
993 * nop
994 * br <var>
995 * br_if <var>
996 * br_table <var>+
997 * return
998 * call <var>
999 * call_indirect <func_sig>
1000 * drop
1001 * select
1002 * get_local <var>
1003 * set_local <var>
1004 * tee_local <var>
1005 * get_global <var>
1006 * set_global <var>
1007 * <type>.load((8|16|32)_<sign>)? <offset>? <align>?
1008 * <type>.store(8|16|32)? <offset>? <align>?
1009 * current_memory
1010 * grow_memory
1011 * <type>.const <value>
1012 * <type>.<unop>
1013 * <type>.<binop>
1014 * <type>.<testop>
1015 * <type>.<relop>
1016 * <type>.<cvtop>/<type>
1017 *
1018 * func_type: ( type <var> )? <param>* <result>*
1019 */
1020
1021
1022 function parseFuncInstr() {
1023 var startLoc = getStartLoc();
1024 maybeIgnoreComment();
1025 /**
1026 * A simple instruction
1027 */
1028
1029 if (token.type === tokens.name || token.type === tokens.valtype) {
1030 var name = token.value;
1031 var object;
1032 eatToken();
1033
1034 if (token.type === tokens.dot) {
1035 object = name;
1036 var name_parts = [];
1037
1038 do {
1039 eatToken(); // Eat the dot
1040
1041 if (token.type !== tokens.name) {
1042 throw new TypeError("Unknown token: " + token.type + ", name expected");
1043 }
1044
1045 name_parts.push(token.value);
1046 eatToken(); // Eat the name
1047 } while (token.type === tokens.dot);
1048
1049 name = name_parts.join(".");
1050 }
1051
1052 if (token.type === tokens.closeParen) {
1053 var _endLoc = token.loc.end;
1054
1055 if (typeof object === "undefined") {
1056 return t.withLoc(t.instruction(name), _endLoc, startLoc);
1057 } else {
1058 return t.withLoc(t.objectInstruction(name, object, []), _endLoc, startLoc);
1059 }
1060 }
1061
1062 var signature = t.signatureForOpcode(object || "", name);
1063
1064 var _parseFuncInstrArgume = parseFuncInstrArguments(signature),
1065 args = _parseFuncInstrArgume.args,
1066 namedArgs = _parseFuncInstrArgume.namedArgs;
1067
1068 var endLoc = token.loc.end;
1069
1070 if (typeof object === "undefined") {
1071 return t.withLoc(t.instruction(name, args, namedArgs), endLoc, startLoc);
1072 } else {
1073 return t.withLoc(t.objectInstruction(name, object, args, namedArgs), endLoc, startLoc);
1074 }
1075 } else if (isKeyword(token, keywords.loop)) {
1076 /**
1077 * Else a instruction with a keyword (loop or block)
1078 */
1079 eatToken(); // keyword
1080
1081 return parseLoop();
1082 } else if (isKeyword(token, keywords.block)) {
1083 eatToken(); // keyword
1084
1085 return parseBlock();
1086 } else if (isKeyword(token, keywords.call_indirect)) {
1087 eatToken(); // keyword
1088
1089 return parseCallIndirect();
1090 } else if (isKeyword(token, keywords.call)) {
1091 eatToken(); // keyword
1092
1093 var index;
1094
1095 if (token.type === tokens.identifier) {
1096 index = identifierFromToken(token);
1097 eatToken();
1098 } else if (token.type === tokens.number) {
1099 index = t.indexLiteral(token.value);
1100 eatToken();
1101 }
1102
1103 var instrArgs = []; // Nested instruction
1104
1105 while (token.type === tokens.openParen) {
1106 eatToken();
1107 instrArgs.push(parseFuncInstr());
1108 eatTokenOfType(tokens.closeParen);
1109 }
1110
1111 if (typeof index === "undefined") {
1112 throw new Error("Missing argument in call instruciton");
1113 }
1114
1115 if (instrArgs.length > 0) {
1116 return t.callInstruction(index, instrArgs);
1117 } else {
1118 return t.callInstruction(index);
1119 }
1120 } else if (isKeyword(token, keywords["if"])) {
1121 eatToken(); // Keyword
1122
1123 return parseIf();
1124 } else if (isKeyword(token, keywords.module) && hasPlugin("wast")) {
1125 eatToken(); // In WAST you can have a module as an instruction's argument
1126 // we will cast it into a instruction to not break the flow
1127 // $FlowIgnore
1128
1129 var module = parseModule();
1130 return module;
1131 } else {
1132 throw function () {
1133 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected instruction in function body" + ", given " + tokenToString(token));
1134 }();
1135 }
1136 }
1137 /*
1138 * Parses a function
1139 *
1140 * WAT:
1141 *
1142 * functype :: ( 'func' t1:vec(param) t2:vec(result) )
1143 * param :: ( 'param' id? t:valtype )
1144 * result :: ( 'result' t:valtype )
1145 *
1146 * WAST:
1147 *
1148 * func :: ( func <name>? <func_sig> <local>* <instr>* )
1149 * ( func <name>? ( export <string> ) <...> )
1150 * ( func <name>? ( import <string> <string> ) <func_sig> )
1151 * func_sig :: ( type <var> )? <param>* <result>*
1152 * param :: ( param <type>* ) | ( param <name> <type> )
1153 * result :: ( result <type>* )
1154 * local :: ( local <type>* ) | ( local <name> <type> )
1155 *
1156 */
1157
1158
1159 function parseFunc() {
1160 var fnName = t.identifier(getUniqueName("func"));
1161 var typeRef;
1162 var fnBody = [];
1163 var fnParams = [];
1164 var fnResult = []; // name
1165
1166 if (token.type === tokens.identifier) {
1167 fnName = identifierFromToken(token);
1168 eatToken();
1169 } else {
1170 fnName = t.withRaw(fnName, ""); // preserve anonymous
1171 }
1172
1173 maybeIgnoreComment();
1174
1175 while (token.type === tokens.openParen || token.type === tokens.name || token.type === tokens.valtype) {
1176 // Instructions without parens
1177 if (token.type === tokens.name || token.type === tokens.valtype) {
1178 fnBody.push(parseFuncInstr());
1179 continue;
1180 }
1181
1182 eatToken();
1183
1184 if (lookaheadAndCheck(keywords.param) === true) {
1185 eatToken();
1186 fnParams.push.apply(fnParams, _toConsumableArray(parseFuncParam()));
1187 } else if (lookaheadAndCheck(keywords.result) === true) {
1188 eatToken();
1189 fnResult.push.apply(fnResult, _toConsumableArray(parseFuncResult()));
1190 } else if (lookaheadAndCheck(keywords["export"]) === true) {
1191 eatToken();
1192 parseFuncExport(fnName);
1193 } else if (lookaheadAndCheck(keywords.type) === true) {
1194 eatToken();
1195 typeRef = parseTypeReference();
1196 } else if (lookaheadAndCheck(tokens.name) === true || lookaheadAndCheck(tokens.valtype) === true || token.type === "keyword" // is any keyword
1197 ) {
1198 // Instruction
1199 fnBody.push(parseFuncInstr());
1200 } else {
1201 throw function () {
1202 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in func body" + ", given " + tokenToString(token));
1203 }();
1204 }
1205
1206 eatTokenOfType(tokens.closeParen);
1207 }
1208
1209 return t.func(fnName, typeRef !== undefined ? typeRef : t.signature(fnParams, fnResult), fnBody);
1210 }
1211 /**
1212 * Parses shorthand export in func
1213 *
1214 * export :: ( export <string> )
1215 */
1216
1217
1218 function parseFuncExport(funcId) {
1219 if (token.type !== tokens.string) {
1220 throw function () {
1221 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Function export expected a string" + ", given " + tokenToString(token));
1222 }();
1223 }
1224
1225 var name = token.value;
1226 eatToken();
1227 /**
1228 * Func export shorthand, we trait it as a syntaxic sugar.
1229 * A export ModuleField will be added later.
1230 *
1231 * We give the anonymous function a generated name and export it.
1232 */
1233
1234 var id = t.identifier(funcId.value);
1235 state.registredExportedElements.push({
1236 exportType: "Func",
1237 name: name,
1238 id: id
1239 });
1240 }
1241 /**
1242 * Parses a type instruction
1243 *
1244 * WAST:
1245 *
1246 * typedef: ( type <name>? ( func <param>* <result>* ) )
1247 */
1248
1249
1250 function parseType() {
1251 var id;
1252 var params = [];
1253 var result = [];
1254
1255 if (token.type === tokens.identifier) {
1256 id = identifierFromToken(token);
1257 eatToken();
1258 }
1259
1260 if (lookaheadAndCheck(tokens.openParen, keywords.func)) {
1261 eatToken(); // (
1262
1263 eatToken(); // func
1264
1265 if (token.type === tokens.closeParen) {
1266 eatToken(); // function with an empty signature, we can abort here
1267
1268 return t.typeInstruction(id, t.signature([], []));
1269 }
1270
1271 if (lookaheadAndCheck(tokens.openParen, keywords.param)) {
1272 eatToken(); // (
1273
1274 eatToken(); // param
1275
1276 params = parseFuncParam();
1277 eatTokenOfType(tokens.closeParen);
1278 }
1279
1280 if (lookaheadAndCheck(tokens.openParen, keywords.result)) {
1281 eatToken(); // (
1282
1283 eatToken(); // result
1284
1285 result = parseFuncResult();
1286 eatTokenOfType(tokens.closeParen);
1287 }
1288
1289 eatTokenOfType(tokens.closeParen);
1290 }
1291
1292 return t.typeInstruction(id, t.signature(params, result));
1293 }
1294 /**
1295 * Parses a function result
1296 *
1297 * WAST:
1298 *
1299 * result :: ( result <type>* )
1300 */
1301
1302
1303 function parseFuncResult() {
1304 var results = [];
1305
1306 while (token.type !== tokens.closeParen) {
1307 if (token.type !== tokens.valtype) {
1308 throw function () {
1309 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unexpected token in func result" + ", given " + tokenToString(token));
1310 }();
1311 }
1312
1313 var valtype = token.value;
1314 eatToken();
1315 results.push(valtype);
1316 }
1317
1318 return results;
1319 }
1320 /**
1321 * Parses a type reference
1322 *
1323 */
1324
1325
1326 function parseTypeReference() {
1327 var ref;
1328
1329 if (token.type === tokens.identifier) {
1330 ref = identifierFromToken(token);
1331 eatToken();
1332 } else if (token.type === tokens.number) {
1333 ref = t.numberLiteralFromRaw(token.value);
1334 eatToken();
1335 }
1336
1337 return ref;
1338 }
1339 /**
1340 * Parses a global instruction
1341 *
1342 * WAST:
1343 *
1344 * global: ( global <name>? <global_sig> <instr>* )
1345 * ( global <name>? ( export <string> ) <...> )
1346 * ( global <name>? ( import <string> <string> ) <global_sig> )
1347 *
1348 * global_sig: <type> | ( mut <type> )
1349 *
1350 */
1351
1352
1353 function parseGlobal() {
1354 var name = t.identifier(getUniqueName("global"));
1355 var type; // Keep informations in case of a shorthand import
1356
1357 var importing = null;
1358 maybeIgnoreComment();
1359
1360 if (token.type === tokens.identifier) {
1361 name = identifierFromToken(token);
1362 eatToken();
1363 } else {
1364 name = t.withRaw(name, ""); // preserve anonymous
1365 }
1366 /**
1367 * maybe export
1368 */
1369
1370
1371 if (lookaheadAndCheck(tokens.openParen, keywords["export"])) {
1372 eatToken(); // (
1373
1374 eatToken(); // export
1375
1376 var exportName = token.value;
1377 eatTokenOfType(tokens.string);
1378 state.registredExportedElements.push({
1379 exportType: "Global",
1380 name: exportName,
1381 id: name
1382 });
1383 eatTokenOfType(tokens.closeParen);
1384 }
1385 /**
1386 * maybe import
1387 */
1388
1389
1390 if (lookaheadAndCheck(tokens.openParen, keywords["import"])) {
1391 eatToken(); // (
1392
1393 eatToken(); // import
1394
1395 var moduleName = token.value;
1396 eatTokenOfType(tokens.string);
1397 var _name = token.value;
1398 eatTokenOfType(tokens.string);
1399 importing = {
1400 module: moduleName,
1401 name: _name,
1402 descr: undefined
1403 };
1404 eatTokenOfType(tokens.closeParen);
1405 }
1406 /**
1407 * global_sig
1408 */
1409
1410
1411 if (token.type === tokens.valtype) {
1412 type = t.globalType(token.value, "const");
1413 eatToken();
1414 } else if (token.type === tokens.openParen) {
1415 eatToken(); // (
1416
1417 if (isKeyword(token, keywords.mut) === false) {
1418 throw function () {
1419 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unsupported global type, expected mut" + ", given " + tokenToString(token));
1420 }();
1421 }
1422
1423 eatToken(); // mut
1424
1425 type = t.globalType(token.value, "var");
1426 eatToken();
1427 eatTokenOfType(tokens.closeParen);
1428 }
1429
1430 if (type === undefined) {
1431 throw function () {
1432 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Could not determine global type" + ", given " + tokenToString(token));
1433 }();
1434 }
1435
1436 maybeIgnoreComment();
1437 var init = [];
1438
1439 if (importing != null) {
1440 importing.descr = type;
1441 init.push(t.moduleImport(importing.module, importing.name, importing.descr));
1442 }
1443 /**
1444 * instr*
1445 */
1446
1447
1448 while (token.type === tokens.openParen) {
1449 eatToken();
1450 init.push(parseFuncInstr());
1451 eatTokenOfType(tokens.closeParen);
1452 }
1453
1454 return t.global(type, init, name);
1455 }
1456 /**
1457 * Parses a function param
1458 *
1459 * WAST:
1460 *
1461 * param :: ( param <type>* ) | ( param <name> <type> )
1462 */
1463
1464
1465 function parseFuncParam() {
1466 var params = [];
1467 var id;
1468 var valtype;
1469
1470 if (token.type === tokens.identifier) {
1471 id = token.value;
1472 eatToken();
1473 }
1474
1475 if (token.type === tokens.valtype) {
1476 valtype = token.value;
1477 eatToken();
1478 params.push({
1479 id: id,
1480 valtype: valtype
1481 });
1482 /**
1483 * Shorthand notation for multiple anonymous parameters
1484 * @see https://webassembly.github.io/spec/core/text/types.html#function-types
1485 * @see https://github.com/xtuc/webassemblyjs/issues/6
1486 */
1487
1488 if (id === undefined) {
1489 while (token.type === tokens.valtype) {
1490 valtype = token.value;
1491 eatToken();
1492 params.push({
1493 id: undefined,
1494 valtype: valtype
1495 });
1496 }
1497 }
1498 } else {// ignore
1499 }
1500
1501 return params;
1502 }
1503 /**
1504 * Parses an element segments instruction
1505 *
1506 * WAST:
1507 *
1508 * elem: ( elem <var>? (offset <instr>* ) <var>* )
1509 * ( elem <var>? <expr> <var>* )
1510 *
1511 * var: <nat> | <name>
1512 */
1513
1514
1515 function parseElem() {
1516 var tableIndex = t.indexLiteral(0);
1517 var offset = [];
1518 var funcs = [];
1519
1520 if (token.type === tokens.identifier) {
1521 tableIndex = identifierFromToken(token);
1522 eatToken();
1523 }
1524
1525 if (token.type === tokens.number) {
1526 tableIndex = t.indexLiteral(token.value);
1527 eatToken();
1528 }
1529
1530 while (token.type !== tokens.closeParen) {
1531 if (lookaheadAndCheck(tokens.openParen, keywords.offset)) {
1532 eatToken(); // (
1533
1534 eatToken(); // offset
1535
1536 while (token.type !== tokens.closeParen) {
1537 eatTokenOfType(tokens.openParen);
1538 offset.push(parseFuncInstr());
1539 eatTokenOfType(tokens.closeParen);
1540 }
1541
1542 eatTokenOfType(tokens.closeParen);
1543 } else if (token.type === tokens.identifier) {
1544 funcs.push(t.identifier(token.value));
1545 eatToken();
1546 } else if (token.type === tokens.number) {
1547 funcs.push(t.indexLiteral(token.value));
1548 eatToken();
1549 } else if (token.type === tokens.openParen) {
1550 eatToken(); // (
1551
1552 offset.push(parseFuncInstr());
1553 eatTokenOfType(tokens.closeParen);
1554 } else {
1555 throw function () {
1556 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unsupported token in elem" + ", given " + tokenToString(token));
1557 }();
1558 }
1559 }
1560
1561 return t.elem(tableIndex, offset, funcs);
1562 }
1563 /**
1564 * Parses the start instruction in a module
1565 *
1566 * WAST:
1567 *
1568 * start: ( start <var> )
1569 * var: <nat> | <name>
1570 *
1571 * WAT:
1572 * start ::= ‘(’ ‘start’ x:funcidx ‘)’
1573 */
1574
1575
1576 function parseStart() {
1577 if (token.type === tokens.identifier) {
1578 var index = identifierFromToken(token);
1579 eatToken();
1580 return t.start(index);
1581 }
1582
1583 if (token.type === tokens.number) {
1584 var _index2 = t.indexLiteral(token.value);
1585
1586 eatToken();
1587 return t.start(_index2);
1588 }
1589
1590 throw new Error("Unknown start, token: " + tokenToString(token));
1591 }
1592
1593 if (token.type === tokens.openParen) {
1594 eatToken();
1595 var startLoc = getStartLoc();
1596
1597 if (isKeyword(token, keywords["export"])) {
1598 eatToken();
1599 var node = parseExport();
1600
1601 var _endLoc2 = getEndLoc();
1602
1603 return t.withLoc(node, _endLoc2, startLoc);
1604 }
1605
1606 if (isKeyword(token, keywords.loop)) {
1607 eatToken();
1608
1609 var _node = parseLoop();
1610
1611 var _endLoc3 = getEndLoc();
1612
1613 return t.withLoc(_node, _endLoc3, startLoc);
1614 }
1615
1616 if (isKeyword(token, keywords.func)) {
1617 eatToken();
1618
1619 var _node2 = parseFunc();
1620
1621 var _endLoc4 = getEndLoc();
1622
1623 maybeIgnoreComment();
1624 eatTokenOfType(tokens.closeParen);
1625 return t.withLoc(_node2, _endLoc4, startLoc);
1626 }
1627
1628 if (isKeyword(token, keywords.module)) {
1629 eatToken();
1630
1631 var _node3 = parseModule();
1632
1633 var _endLoc5 = getEndLoc();
1634
1635 return t.withLoc(_node3, _endLoc5, startLoc);
1636 }
1637
1638 if (isKeyword(token, keywords["import"])) {
1639 eatToken();
1640
1641 var _node4 = parseImport();
1642
1643 var _endLoc6 = getEndLoc();
1644
1645 eatTokenOfType(tokens.closeParen);
1646 return t.withLoc(_node4, _endLoc6, startLoc);
1647 }
1648
1649 if (isKeyword(token, keywords.block)) {
1650 eatToken();
1651
1652 var _node5 = parseBlock();
1653
1654 var _endLoc7 = getEndLoc();
1655
1656 eatTokenOfType(tokens.closeParen);
1657 return t.withLoc(_node5, _endLoc7, startLoc);
1658 }
1659
1660 if (isKeyword(token, keywords.memory)) {
1661 eatToken();
1662
1663 var _node6 = parseMemory();
1664
1665 var _endLoc8 = getEndLoc();
1666
1667 eatTokenOfType(tokens.closeParen);
1668 return t.withLoc(_node6, _endLoc8, startLoc);
1669 }
1670
1671 if (isKeyword(token, keywords.data)) {
1672 eatToken();
1673
1674 var _node7 = parseData();
1675
1676 var _endLoc9 = getEndLoc();
1677
1678 eatTokenOfType(tokens.closeParen);
1679 return t.withLoc(_node7, _endLoc9, startLoc);
1680 }
1681
1682 if (isKeyword(token, keywords.table)) {
1683 eatToken();
1684
1685 var _node8 = parseTable();
1686
1687 var _endLoc10 = getEndLoc();
1688
1689 eatTokenOfType(tokens.closeParen);
1690 return t.withLoc(_node8, _endLoc10, startLoc);
1691 }
1692
1693 if (isKeyword(token, keywords.global)) {
1694 eatToken();
1695
1696 var _node9 = parseGlobal();
1697
1698 var _endLoc11 = getEndLoc();
1699
1700 eatTokenOfType(tokens.closeParen);
1701 return t.withLoc(_node9, _endLoc11, startLoc);
1702 }
1703
1704 if (isKeyword(token, keywords.type)) {
1705 eatToken();
1706
1707 var _node10 = parseType();
1708
1709 var _endLoc12 = getEndLoc();
1710
1711 eatTokenOfType(tokens.closeParen);
1712 return t.withLoc(_node10, _endLoc12, startLoc);
1713 }
1714
1715 if (isKeyword(token, keywords.start)) {
1716 eatToken();
1717
1718 var _node11 = parseStart();
1719
1720 var _endLoc13 = getEndLoc();
1721
1722 eatTokenOfType(tokens.closeParen);
1723 return t.withLoc(_node11, _endLoc13, startLoc);
1724 }
1725
1726 if (isKeyword(token, keywords.elem)) {
1727 eatToken();
1728
1729 var _node12 = parseElem();
1730
1731 var _endLoc14 = getEndLoc();
1732
1733 eatTokenOfType(tokens.closeParen);
1734 return t.withLoc(_node12, _endLoc14, startLoc);
1735 }
1736
1737 var instruction = parseFuncInstr();
1738 var endLoc = getEndLoc();
1739 maybeIgnoreComment();
1740
1741 if (_typeof(instruction) === "object") {
1742 if (typeof token !== "undefined") {
1743 eatTokenOfType(tokens.closeParen);
1744 }
1745
1746 return t.withLoc(instruction, endLoc, startLoc);
1747 }
1748 }
1749
1750 if (token.type === tokens.comment) {
1751 var _startLoc = getStartLoc();
1752
1753 var builder = token.opts.type === "leading" ? t.leadingComment : t.blockComment;
1754
1755 var _node13 = builder(token.value);
1756
1757 eatToken(); // comment
1758
1759 var _endLoc15 = getEndLoc();
1760
1761 return t.withLoc(_node13, _endLoc15, _startLoc);
1762 }
1763
1764 throw function () {
1765 return new Error("\n" + codeFrameFromSource(source, token.loc) + "\n" + "Unknown token" + ", given " + tokenToString(token));
1766 }();
1767 }
1768
1769 var body = [];
1770
1771 while (current < tokensList.length) {
1772 body.push(walk());
1773 }
1774
1775 return t.program(body);
1776}
\No newline at end of file