'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /* eslint max-len: 0 */ // This is a trick taken from Esprima. It turns out that, on // non-Chrome browsers, to check whether a string is in a set, a // predicate containing a big ugly `switch` statement is faster than // a regular expression, and on Chrome the two are about on par. // This function uses `eval` (non-lexical) to produce such a // predicate from a space-separated string of words. // // It starts by sorting the words by length. function makePredicate(words) { words = words.split(" "); return function (str) { return words.indexOf(str) >= 0; }; } // Reserved word lists for various dialects of the language var reservedWords = { 6: makePredicate("enum await"), strict: makePredicate("implements interface let package private protected public static yield"), strictBind: makePredicate("eval arguments") }; // And the keywords var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this let const class extends export import yield super"); // ## Character categories // Big ugly regular expressions that match characters in the // whitespace, identifier, and identifier-start categories. These // are only applied when a character is found to actually have a // code point above 128. // Generated by `bin/generate-identifier-regex.js`. var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC"; var nonASCIIidentifierChars = "\u200C\u200D\xB7\u0300-\u036F\u0387\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D4-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19D0-\u19DA\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFB-\u1DFF\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F1\uA900-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F"; var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; // These are a run-length and offset encoded representation of the // >0xffff code points that are a valid part of identifiers. The // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by `bin/generate-identifier-regex.js`. // eslint-disable-next-line comma-spacing var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 17, 26, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 26, 45, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 785, 52, 76, 44, 33, 24, 27, 35, 42, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 54, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 86, 25, 391, 63, 32, 0, 449, 56, 264, 8, 2, 36, 18, 0, 50, 29, 881, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 881, 68, 12, 0, 67, 12, 65, 0, 32, 6124, 20, 754, 9486, 1, 3071, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 4149, 196, 60, 67, 1213, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 3, 5761, 10591, 541]; // eslint-disable-next-line comma-spacing var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 1306, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 52, 0, 13, 2, 49, 13, 10, 2, 4, 9, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 57, 0, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 87, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 423, 9, 838, 7, 2, 7, 17, 9, 57, 21, 2, 13, 19882, 9, 135, 4, 60, 6, 26, 9, 1016, 45, 17, 3, 19723, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 2214, 6, 110, 6, 6, 9, 792487, 239]; // This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare. function isInAstralSet(code, set) { var pos = 0x10000; for (var i = 0; i < set.length; i += 2) { pos += set[i]; if (pos > code) return false; pos += set[i + 1]; if (pos >= code) return true; } } // Test whether a given character code starts an identifier. function isIdentifierStart(code) { if (code < 65) return code === 36; if (code < 91) return true; if (code < 97) return code === 95; if (code < 123) return true; if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); return isInAstralSet(code, astralIdentifierStartCodes); } // Test whether a given character is part of an identifier. function isIdentifierChar(code) { if (code < 48) return code === 36; if (code < 58) return true; if (code < 65) return false; if (code < 91) return true; if (code < 97) return code === 95; if (code < 123) return true; if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); } // A second optional argument can be given to further configure var defaultOptions = { // Source type ("script" or "module") for different semantics sourceType: "script", // Source filename. sourceFilename: undefined, // Line from which to start counting source. Useful for // integration with other tools. startLine: 1, // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, // When enabled, import/export statements are not constrained to // appearing at the top of the program. allowImportExportEverywhere: false, // TODO allowSuperOutsideMethod: false, // An array of plugins to enable plugins: [], // TODO strictMode: null }; // Interpret and default an options object function getOptions(opts) { var options = {}; for (var key in defaultOptions) { options[key] = opts && key in opts ? opts[key] : defaultOptions[key]; } return options; } var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; // ## Token types // The assignment of fine-grained, information-carrying type objects // allows the tokenizer to store the information it has about a // token in a way that is very cheap for the parser to look up. // All token type variables start with an underscore, to make them // easy to recognize. // The `beforeExpr` property is used to disambiguate between regular // expressions and divisions. It is set on all token types that can // be followed by an expression (thus, a slash after them would be a // regular expression). // // `isLoop` marks a keyword as starting a loop, which is important // to know when parsing a label, in order to allow or disallow // continue jumps to that label. var beforeExpr = true; var startsExpr = true; var isLoop = true; var isAssign = true; var prefix = true; var postfix = true; var TokenType = function TokenType(label) { var conf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; classCallCheck(this, TokenType); this.label = label; this.keyword = conf.keyword; this.beforeExpr = !!conf.beforeExpr; this.startsExpr = !!conf.startsExpr; this.rightAssociative = !!conf.rightAssociative; this.isLoop = !!conf.isLoop; this.isAssign = !!conf.isAssign; this.prefix = !!conf.prefix; this.postfix = !!conf.postfix; this.binop = conf.binop || null; this.updateContext = null; }; var KeywordTokenType = function (_TokenType) { inherits(KeywordTokenType, _TokenType); function KeywordTokenType(name) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; classCallCheck(this, KeywordTokenType); options.keyword = name; return possibleConstructorReturn(this, _TokenType.call(this, name, options)); } return KeywordTokenType; }(TokenType); var BinopTokenType = function (_TokenType2) { inherits(BinopTokenType, _TokenType2); function BinopTokenType(name, prec) { classCallCheck(this, BinopTokenType); return possibleConstructorReturn(this, _TokenType2.call(this, name, { beforeExpr: beforeExpr, binop: prec })); } return BinopTokenType; }(TokenType); var types = { num: new TokenType("num", { startsExpr: startsExpr }), regexp: new TokenType("regexp", { startsExpr: startsExpr }), string: new TokenType("string", { startsExpr: startsExpr }), name: new TokenType("name", { startsExpr: startsExpr }), eof: new TokenType("eof"), // Punctuation token types. bracketL: new TokenType("[", { beforeExpr: beforeExpr, startsExpr: startsExpr }), bracketR: new TokenType("]"), braceL: new TokenType("{", { beforeExpr: beforeExpr, startsExpr: startsExpr }), braceBarL: new TokenType("{|", { beforeExpr: beforeExpr, startsExpr: startsExpr }), braceR: new TokenType("}"), braceBarR: new TokenType("|}"), parenL: new TokenType("(", { beforeExpr: beforeExpr, startsExpr: startsExpr }), parenR: new TokenType(")"), comma: new TokenType(",", { beforeExpr: beforeExpr }), semi: new TokenType(";", { beforeExpr: beforeExpr }), colon: new TokenType(":", { beforeExpr: beforeExpr }), doubleColon: new TokenType("::", { beforeExpr: beforeExpr }), dot: new TokenType("."), question: new TokenType("?", { beforeExpr: beforeExpr }), arrow: new TokenType("=>", { beforeExpr: beforeExpr }), template: new TokenType("template"), ellipsis: new TokenType("...", { beforeExpr: beforeExpr }), backQuote: new TokenType("`", { startsExpr: startsExpr }), dollarBraceL: new TokenType("${", { beforeExpr: beforeExpr, startsExpr: startsExpr }), at: new TokenType("@"), // Operators. These carry several kinds of properties to help the // parser use them properly (the presence of these properties is // what categorizes them as operators). // // `binop`, when present, specifies that this operator is a binary // operator, and will refer to its precedence. // // `prefix` and `postfix` mark the operator as a prefix or postfix // unary operator. // // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as // binary operators with a very low precedence, that should result // in AssignmentExpression nodes. eq: new TokenType("=", { beforeExpr: beforeExpr, isAssign: isAssign }), assign: new TokenType("_=", { beforeExpr: beforeExpr, isAssign: isAssign }), incDec: new TokenType("++/--", { prefix: prefix, postfix: postfix, startsExpr: startsExpr }), prefix: new TokenType("prefix", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), logicalOR: new BinopTokenType("||", 1), logicalAND: new BinopTokenType("&&", 2), bitwiseOR: new BinopTokenType("|", 3), bitwiseXOR: new BinopTokenType("^", 4), bitwiseAND: new BinopTokenType("&", 5), equality: new BinopTokenType("==/!=", 6), relational: new BinopTokenType("", 7), bitShift: new BinopTokenType("<>", 8), plusMin: new TokenType("+/-", { beforeExpr: beforeExpr, binop: 9, prefix: prefix, startsExpr: startsExpr }), modulo: new BinopTokenType("%", 10), star: new BinopTokenType("*", 10), slash: new BinopTokenType("/", 10), exponent: new TokenType("**", { beforeExpr: beforeExpr, binop: 11, rightAssociative: true }) }; var keywords = { "break": new KeywordTokenType("break"), "case": new KeywordTokenType("case", { beforeExpr: beforeExpr }), "catch": new KeywordTokenType("catch"), "continue": new KeywordTokenType("continue"), "debugger": new KeywordTokenType("debugger"), "default": new KeywordTokenType("default", { beforeExpr: beforeExpr }), "do": new KeywordTokenType("do", { isLoop: isLoop, beforeExpr: beforeExpr }), "else": new KeywordTokenType("else", { beforeExpr: beforeExpr }), "finally": new KeywordTokenType("finally"), "for": new KeywordTokenType("for", { isLoop: isLoop }), "function": new KeywordTokenType("function", { startsExpr: startsExpr }), "if": new KeywordTokenType("if"), "return": new KeywordTokenType("return", { beforeExpr: beforeExpr }), "switch": new KeywordTokenType("switch"), "throw": new KeywordTokenType("throw", { beforeExpr: beforeExpr }), "try": new KeywordTokenType("try"), "var": new KeywordTokenType("var"), "let": new KeywordTokenType("let"), "const": new KeywordTokenType("const"), "while": new KeywordTokenType("while", { isLoop: isLoop }), "with": new KeywordTokenType("with"), "new": new KeywordTokenType("new", { beforeExpr: beforeExpr, startsExpr: startsExpr }), "this": new KeywordTokenType("this", { startsExpr: startsExpr }), "super": new KeywordTokenType("super", { startsExpr: startsExpr }), "class": new KeywordTokenType("class"), "extends": new KeywordTokenType("extends", { beforeExpr: beforeExpr }), "export": new KeywordTokenType("export"), "import": new KeywordTokenType("import"), "yield": new KeywordTokenType("yield", { beforeExpr: beforeExpr, startsExpr: startsExpr }), "null": new KeywordTokenType("null", { startsExpr: startsExpr }), "true": new KeywordTokenType("true", { startsExpr: startsExpr }), "false": new KeywordTokenType("false", { startsExpr: startsExpr }), "in": new KeywordTokenType("in", { beforeExpr: beforeExpr, binop: 7 }), "instanceof": new KeywordTokenType("instanceof", { beforeExpr: beforeExpr, binop: 7 }), "typeof": new KeywordTokenType("typeof", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), "void": new KeywordTokenType("void", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }), "delete": new KeywordTokenType("delete", { beforeExpr: beforeExpr, prefix: prefix, startsExpr: startsExpr }) }; // Map keyword names to token types. Object.keys(keywords).forEach(function (name) { types["_" + name] = keywords[name]; }); // Matches a whole line break (where CRLF is considered a single // line break). Used to count lines. var lineBreak = /\r\n?|\n|\u2028|\u2029/; var lineBreakG = new RegExp(lineBreak.source, "g"); function isNewLine(code) { return code === 10 || code === 13 || code === 0x2028 || code === 0x2029; } var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; // The algorithm used to determine whether a regexp can appear at a // given point in the program is loosely based on sweet.js' approach. // See https://github.com/mozilla/sweet.js/wiki/design var TokContext = function TokContext(token, isExpr, preserveSpace, override) { classCallCheck(this, TokContext); this.token = token; this.isExpr = !!isExpr; this.preserveSpace = !!preserveSpace; this.override = override; }; var types$1 = { braceStatement: new TokContext("{", false), braceExpression: new TokContext("{", true), templateQuasi: new TokContext("${", true), parenStatement: new TokContext("(", false), parenExpression: new TokContext("(", true), template: new TokContext("`", true, true, function (p) { return p.readTmplToken(); }), functionExpression: new TokContext("function", true) }; // Token-specific context update code types.parenR.updateContext = types.braceR.updateContext = function () { if (this.state.context.length === 1) { this.state.exprAllowed = true; return; } var out = this.state.context.pop(); if (out === types$1.braceStatement && this.curContext() === types$1.functionExpression) { this.state.context.pop(); this.state.exprAllowed = false; } else if (out === types$1.templateQuasi) { this.state.exprAllowed = true; } else { this.state.exprAllowed = !out.isExpr; } }; types.name.updateContext = function (prevType) { this.state.exprAllowed = false; if (prevType === types._let || prevType === types._const || prevType === types._var) { if (lineBreak.test(this.input.slice(this.state.end))) { this.state.exprAllowed = true; } } }; types.braceL.updateContext = function (prevType) { this.state.context.push(this.braceIsBlock(prevType) ? types$1.braceStatement : types$1.braceExpression); this.state.exprAllowed = true; }; types.dollarBraceL.updateContext = function () { this.state.context.push(types$1.templateQuasi); this.state.exprAllowed = true; }; types.parenL.updateContext = function (prevType) { var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; this.state.context.push(statementParens ? types$1.parenStatement : types$1.parenExpression); this.state.exprAllowed = true; }; types.incDec.updateContext = function () { // tokExprAllowed stays unchanged }; types._function.updateContext = function () { if (this.curContext() !== types$1.braceStatement) { this.state.context.push(types$1.functionExpression); } this.state.exprAllowed = false; }; types.backQuote.updateContext = function () { if (this.curContext() === types$1.template) { this.state.context.pop(); } else { this.state.context.push(types$1.template); } this.state.exprAllowed = false; }; // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. var Position = function Position(line, col) { classCallCheck(this, Position); this.line = line; this.column = col; }; var SourceLocation = function SourceLocation(start, end) { classCallCheck(this, SourceLocation); this.start = start; this.end = end; }; // The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character // offset. `input` should be the code string that the offset refers // into. function getLineInfo(input, offset) { for (var line = 1, cur = 0;;) { lineBreakG.lastIndex = cur; var match = lineBreakG.exec(input); if (match && match.index < offset) { ++line; cur = match.index + match[0].length; } else { return new Position(line, offset - cur); } } } var State = function () { function State() { classCallCheck(this, State); } State.prototype.init = function init(options, input) { this.strict = options.strictMode === false ? false : options.sourceType === "module"; this.input = input; this.potentialArrowAt = -1; this.inMethod = this.inFunction = this.inGenerator = this.inAsync = this.inPropertyName = this.inType = this.noAnonFunctionType = false; this.labels = []; this.decorators = []; this.tokens = []; this.comments = []; this.trailingComments = []; this.leadingComments = []; this.commentStack = []; this.pos = this.lineStart = 0; this.curLine = options.startLine; this.type = types.eof; this.value = null; this.start = this.end = this.pos; this.startLoc = this.endLoc = this.curPosition(); this.lastTokEndLoc = this.lastTokStartLoc = null; this.lastTokStart = this.lastTokEnd = this.pos; this.context = [types$1.braceStatement]; this.exprAllowed = true; this.containsEsc = this.containsOctal = false; this.octalPosition = null; this.exportedIdentifiers = []; return this; }; // TODO // TODO // Used to signify the start of a potential arrow function // Flags to track whether we are in a function, a generator. // Labels in scope. // Leading decorators. // Token store. // Comment store. // Comment attachment store // The current position of the tokenizer in the input. // Properties of the current token: // Its type // For tokens that include more information than their type, the value // Its start and end offset // And, if locations are used, the {line, column} object // corresponding to those offsets // Position information for the previous token // The context stack is used to superficially track syntactic // context to predict whether a regular expression is allowed in a // given position. // Used to signal to callers of `readWord1` whether the word // contained any escape sequences. This is needed because words with // escape sequences must not be interpreted as keywords. // TODO // Names of exports store. `default` is stored as a name for both // `export default foo;` and `export { foo as default };`. State.prototype.curPosition = function curPosition() { return new Position(this.curLine, this.pos - this.lineStart); }; State.prototype.clone = function clone(skipArrays) { var state = new State(); for (var key in this) { var val = this[key]; if ((!skipArrays || key === "context") && Array.isArray(val)) { val = val.slice(); } state[key] = val; } return state; }; return State; }(); // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer. var Token = function Token(state) { classCallCheck(this, Token); this.type = state.type; this.value = state.value; this.start = state.start; this.end = state.end; this.loc = new SourceLocation(state.startLoc, state.endLoc); }; // ## Tokenizer function codePointToString(code) { // UTF-16 Decoding if (code <= 0xFFFF) { return String.fromCharCode(code); } else { return String.fromCharCode((code - 0x10000 >> 10) + 0xD800, (code - 0x10000 & 1023) + 0xDC00); } } var Tokenizer = function () { function Tokenizer(options, input) { classCallCheck(this, Tokenizer); this.state = new State(); this.state.init(options, input); } // Move to the next token Tokenizer.prototype.next = function next() { if (!this.isLookahead) { this.state.tokens.push(new Token(this.state)); } this.state.lastTokEnd = this.state.end; this.state.lastTokStart = this.state.start; this.state.lastTokEndLoc = this.state.endLoc; this.state.lastTokStartLoc = this.state.startLoc; this.nextToken(); }; // TODO Tokenizer.prototype.eat = function eat(type) { if (this.match(type)) { this.next(); return true; } else { return false; } }; // TODO Tokenizer.prototype.match = function match(type) { return this.state.type === type; }; // TODO Tokenizer.prototype.isKeyword = function isKeyword$$1(word) { return isKeyword(word); }; // TODO Tokenizer.prototype.lookahead = function lookahead() { var old = this.state; this.state = old.clone(true); this.isLookahead = true; this.next(); this.isLookahead = false; var curr = this.state.clone(true); this.state = old; return curr; }; // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). Tokenizer.prototype.setStrict = function setStrict(strict) { this.state.strict = strict; if (!this.match(types.num) && !this.match(types.string)) return; this.state.pos = this.state.start; while (this.state.pos < this.state.lineStart) { this.state.lineStart = this.input.lastIndexOf("\n", this.state.lineStart - 2) + 1; --this.state.curLine; } this.nextToken(); }; Tokenizer.prototype.curContext = function curContext() { return this.state.context[this.state.context.length - 1]; }; // Read a single token, updating the parser object's token-related // properties. Tokenizer.prototype.nextToken = function nextToken() { var curContext = this.curContext(); if (!curContext || !curContext.preserveSpace) this.skipSpace(); this.state.containsOctal = false; this.state.octalPosition = null; this.state.start = this.state.pos; this.state.startLoc = this.state.curPosition(); if (this.state.pos >= this.input.length) return this.finishToken(types.eof); if (curContext.override) { return curContext.override(this); } else { return this.readToken(this.fullCharCodeAtPos()); } }; Tokenizer.prototype.readToken = function readToken(code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (isIdentifierStart(code) || code === 92 /* '\' */) { return this.readWord(); } else { return this.getTokenFromCode(code); } }; Tokenizer.prototype.fullCharCodeAtPos = function fullCharCodeAtPos() { var code = this.input.charCodeAt(this.state.pos); if (code <= 0xd7ff || code >= 0xe000) return code; var next = this.input.charCodeAt(this.state.pos + 1); return (code << 10) + next - 0x35fdc00; }; Tokenizer.prototype.pushComment = function pushComment(block, text, start, end, startLoc, endLoc) { var comment = { type: block ? "CommentBlock" : "CommentLine", value: text, start: start, end: end, loc: new SourceLocation(startLoc, endLoc) }; if (!this.isLookahead) { this.state.tokens.push(comment); this.state.comments.push(comment); this.addComment(comment); } }; Tokenizer.prototype.skipBlockComment = function skipBlockComment() { var startLoc = this.state.curPosition(); var start = this.state.pos; var end = this.input.indexOf("*/", this.state.pos += 2); if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment"); this.state.pos = end + 2; lineBreakG.lastIndex = start; var match = void 0; while ((match = lineBreakG.exec(this.input)) && match.index < this.state.pos) { ++this.state.curLine; this.state.lineStart = match.index + match[0].length; } this.pushComment(true, this.input.slice(start + 2, end), start, this.state.pos, startLoc, this.state.curPosition()); }; Tokenizer.prototype.skipLineComment = function skipLineComment(startSkip) { var start = this.state.pos; var startLoc = this.state.curPosition(); var ch = this.input.charCodeAt(this.state.pos += startSkip); while (this.state.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++this.state.pos; ch = this.input.charCodeAt(this.state.pos); } this.pushComment(false, this.input.slice(start + startSkip, this.state.pos), start, this.state.pos, startLoc, this.state.curPosition()); }; // Called at the start of the parse and after every token. Skips // whitespace and comments, and. Tokenizer.prototype.skipSpace = function skipSpace() { loop: while (this.state.pos < this.input.length) { var ch = this.input.charCodeAt(this.state.pos); switch (ch) { case 32:case 160: // ' ' ++this.state.pos; break; case 13: if (this.input.charCodeAt(this.state.pos + 1) === 10) { ++this.state.pos; } case 10:case 8232:case 8233: ++this.state.pos; ++this.state.curLine; this.state.lineStart = this.state.pos; break; case 47: // '/' switch (this.input.charCodeAt(this.state.pos + 1)) { case 42: // '*' this.skipBlockComment(); break; case 47: this.skipLineComment(2); break; default: break loop; } break; default: if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { ++this.state.pos; } else { break loop; } } } }; // Called at the end of every token. Sets `end`, `val`, and // maintains `context` and `exprAllowed`, and skips the space after // the token, so that the next one's `start` will point at the // right position. Tokenizer.prototype.finishToken = function finishToken(type, val) { this.state.end = this.state.pos; this.state.endLoc = this.state.curPosition(); var prevType = this.state.type; this.state.type = type; this.state.value = val; this.updateContext(prevType); }; // ### Token reading // This is the function that is called to fetch the next token. It // is somewhat obscure, because it works in character codes rather // than characters, and because operator parsing has been inlined // into it. // // All in the name of speed. // Tokenizer.prototype.readToken_dot = function readToken_dot() { var next = this.input.charCodeAt(this.state.pos + 1); if (next >= 48 && next <= 57) { return this.readNumber(true); } var next2 = this.input.charCodeAt(this.state.pos + 2); if (next === 46 && next2 === 46) { // 46 = dot '.' this.state.pos += 3; return this.finishToken(types.ellipsis); } else { ++this.state.pos; return this.finishToken(types.dot); } }; Tokenizer.prototype.readToken_slash = function readToken_slash() { // '/' if (this.state.exprAllowed) { ++this.state.pos; return this.readRegexp(); } var next = this.input.charCodeAt(this.state.pos + 1); if (next === 61) { return this.finishOp(types.assign, 2); } else { return this.finishOp(types.slash, 1); } }; Tokenizer.prototype.readToken_mult_modulo = function readToken_mult_modulo(code) { // '%*' var type = code === 42 ? types.star : types.modulo; var width = 1; var next = this.input.charCodeAt(this.state.pos + 1); if (next === 42) { // '*' width++; next = this.input.charCodeAt(this.state.pos + 2); type = types.exponent; } if (next === 61) { width++; type = types.assign; } return this.finishOp(type, width); }; Tokenizer.prototype.readToken_pipe_amp = function readToken_pipe_amp(code) { // '|&' var next = this.input.charCodeAt(this.state.pos + 1); if (next === code) return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2); if (next === 61) return this.finishOp(types.assign, 2); if (code === 124 && next === 125 && this.hasPlugin("flow")) return this.finishOp(types.braceBarR, 2); return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1); }; Tokenizer.prototype.readToken_caret = function readToken_caret() { // '^' var next = this.input.charCodeAt(this.state.pos + 1); if (next === 61) { return this.finishOp(types.assign, 2); } else { return this.finishOp(types.bitwiseXOR, 1); } }; Tokenizer.prototype.readToken_plus_min = function readToken_plus_min(code) { // '+-' var next = this.input.charCodeAt(this.state.pos + 1); if (next === code) { if (next === 45 && this.input.charCodeAt(this.state.pos + 2) === 62 && lineBreak.test(this.input.slice(this.state.lastTokEnd, this.state.pos))) { // A `-->` line comment this.skipLineComment(3); this.skipSpace(); return this.nextToken(); } return this.finishOp(types.incDec, 2); } if (next === 61) { return this.finishOp(types.assign, 2); } else { return this.finishOp(types.plusMin, 1); } }; Tokenizer.prototype.readToken_lt_gt = function readToken_lt_gt(code) { // '<>' var next = this.input.charCodeAt(this.state.pos + 1); var size = 1; if (next === code) { size = code === 62 && this.input.charCodeAt(this.state.pos + 2) === 62 ? 3 : 2; if (this.input.charCodeAt(this.state.pos + size) === 61) return this.finishOp(types.assign, size + 1); return this.finishOp(types.bitShift, size); } if (next === 33 && code === 60 && this.input.charCodeAt(this.state.pos + 2) === 45 && this.input.charCodeAt(this.state.pos + 3) === 45) { if (this.inModule) this.unexpected(); // `