esprima.js 130 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156
  1. /*
  2. Copyright (C) 2013 Ariya Hidayat <[email protected]>
  3. Copyright (C) 2013 Thaddee Tyl <[email protected]>
  4. Copyright (C) 2013 Mathias Bynens <[email protected]>
  5. Copyright (C) 2012 Ariya Hidayat <[email protected]>
  6. Copyright (C) 2012 Mathias Bynens <[email protected]>
  7. Copyright (C) 2012 Joost-Wim Boekesteijn <[email protected]>
  8. Copyright (C) 2012 Kris Kowal <[email protected]>
  9. Copyright (C) 2012 Yusuke Suzuki <[email protected]>
  10. Copyright (C) 2012 Arpad Borsos <[email protected]>
  11. Copyright (C) 2011 Ariya Hidayat <[email protected]>
  12. Redistribution and use in source and binary forms, with or without
  13. modification, are permitted provided that the following conditions are met:
  14. * Redistributions of source code must retain the above copyright
  15. notice, this list of conditions and the following disclaimer.
  16. * Redistributions in binary form must reproduce the above copyright
  17. notice, this list of conditions and the following disclaimer in the
  18. documentation and/or other materials provided with the distribution.
  19. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  23. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. (function (root, factory) {
  31. 'use strict';
  32. // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
  33. // Rhino, and plain browser loading.
  34. /* istanbul ignore next */
  35. if (typeof define === 'function' && define.amd) {
  36. define(['exports'], factory);
  37. } else if (typeof exports !== 'undefined') {
  38. factory(exports);
  39. } else {
  40. factory((root.esprima = {}));
  41. }
  42. }(this, function (exports) {
  43. 'use strict';
  44. var Token,
  45. TokenName,
  46. FnExprTokens,
  47. Syntax,
  48. PlaceHolders,
  49. PropertyKind,
  50. Messages,
  51. Regex,
  52. source,
  53. strict,
  54. index,
  55. lineNumber,
  56. lineStart,
  57. length,
  58. lookahead,
  59. state,
  60. extra;
  61. Token = {
  62. BooleanLiteral: 1,
  63. EOF: 2,
  64. Identifier: 3,
  65. Keyword: 4,
  66. NullLiteral: 5,
  67. NumericLiteral: 6,
  68. Punctuator: 7,
  69. StringLiteral: 8,
  70. RegularExpression: 9
  71. };
  72. TokenName = {};
  73. TokenName[Token.BooleanLiteral] = 'Boolean';
  74. TokenName[Token.EOF] = '<end>';
  75. TokenName[Token.Identifier] = 'Identifier';
  76. TokenName[Token.Keyword] = 'Keyword';
  77. TokenName[Token.NullLiteral] = 'Null';
  78. TokenName[Token.NumericLiteral] = 'Numeric';
  79. TokenName[Token.Punctuator] = 'Punctuator';
  80. TokenName[Token.StringLiteral] = 'String';
  81. TokenName[Token.RegularExpression] = 'RegularExpression';
  82. // A function following one of those tokens is an expression.
  83. FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
  84. 'return', 'case', 'delete', 'throw', 'void',
  85. // assignment operators
  86. '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
  87. '&=', '|=', '^=', ',',
  88. // binary/unary operators
  89. '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
  90. '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
  91. '<=', '<', '>', '!=', '!=='];
  92. Syntax = {
  93. AssignmentExpression: 'AssignmentExpression',
  94. ArrayExpression: 'ArrayExpression',
  95. ArrowFunctionExpression: 'ArrowFunctionExpression',
  96. BlockStatement: 'BlockStatement',
  97. BinaryExpression: 'BinaryExpression',
  98. BreakStatement: 'BreakStatement',
  99. CallExpression: 'CallExpression',
  100. CatchClause: 'CatchClause',
  101. ConditionalExpression: 'ConditionalExpression',
  102. ContinueStatement: 'ContinueStatement',
  103. DoWhileStatement: 'DoWhileStatement',
  104. DebuggerStatement: 'DebuggerStatement',
  105. EmptyStatement: 'EmptyStatement',
  106. ExpressionStatement: 'ExpressionStatement',
  107. ForStatement: 'ForStatement',
  108. ForInStatement: 'ForInStatement',
  109. FunctionDeclaration: 'FunctionDeclaration',
  110. FunctionExpression: 'FunctionExpression',
  111. Identifier: 'Identifier',
  112. IfStatement: 'IfStatement',
  113. Literal: 'Literal',
  114. LabeledStatement: 'LabeledStatement',
  115. LogicalExpression: 'LogicalExpression',
  116. MemberExpression: 'MemberExpression',
  117. NewExpression: 'NewExpression',
  118. ObjectExpression: 'ObjectExpression',
  119. Program: 'Program',
  120. Property: 'Property',
  121. ReturnStatement: 'ReturnStatement',
  122. SequenceExpression: 'SequenceExpression',
  123. SwitchStatement: 'SwitchStatement',
  124. SwitchCase: 'SwitchCase',
  125. ThisExpression: 'ThisExpression',
  126. ThrowStatement: 'ThrowStatement',
  127. TryStatement: 'TryStatement',
  128. UnaryExpression: 'UnaryExpression',
  129. UpdateExpression: 'UpdateExpression',
  130. VariableDeclaration: 'VariableDeclaration',
  131. VariableDeclarator: 'VariableDeclarator',
  132. WhileStatement: 'WhileStatement',
  133. WithStatement: 'WithStatement'
  134. };
  135. PlaceHolders = {
  136. ArrowParameterPlaceHolder: {
  137. type: 'ArrowParameterPlaceHolder'
  138. }
  139. };
  140. PropertyKind = {
  141. Data: 1,
  142. Get: 2,
  143. Set: 4
  144. };
  145. // Error messages should be identical to V8.
  146. Messages = {
  147. UnexpectedToken: 'Unexpected token %0',
  148. UnexpectedNumber: 'Unexpected number',
  149. UnexpectedString: 'Unexpected string',
  150. UnexpectedIdentifier: 'Unexpected identifier',
  151. UnexpectedReserved: 'Unexpected reserved word',
  152. UnexpectedEOS: 'Unexpected end of input',
  153. NewlineAfterThrow: 'Illegal newline after throw',
  154. InvalidRegExp: 'Invalid regular expression',
  155. UnterminatedRegExp: 'Invalid regular expression: missing /',
  156. InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
  157. InvalidLHSInForIn: 'Invalid left-hand side in for-in',
  158. MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
  159. NoCatchOrFinally: 'Missing catch or finally after try',
  160. UnknownLabel: 'Undefined label \'%0\'',
  161. Redeclaration: '%0 \'%1\' has already been declared',
  162. IllegalContinue: 'Illegal continue statement',
  163. IllegalBreak: 'Illegal break statement',
  164. IllegalReturn: 'Illegal return statement',
  165. StrictModeWith: 'Strict mode code may not include a with statement',
  166. StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
  167. StrictVarName: 'Variable name may not be eval or arguments in strict mode',
  168. StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
  169. StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
  170. StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
  171. StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
  172. StrictDelete: 'Delete of an unqualified identifier in strict mode.',
  173. StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
  174. AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
  175. AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
  176. StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
  177. StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
  178. StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
  179. StrictReservedWord: 'Use of future reserved word in strict mode'
  180. };
  181. // See also tools/generate-unicode-regex.py.
  182. Regex = {
  183. NonAsciiIdentifierStart: new RegExp('[\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-\u08B2\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\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\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\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-\u13F4\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\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\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\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\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\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\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-\uAB5F\uAB64\uAB65\uABC0-\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]'),
  184. NonAsciiIdentifierPart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\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\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\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\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]')
  185. };
  186. // Ensure the condition is true, otherwise throw an error.
  187. // This is only to have a better contract semantic, i.e. another safety net
  188. // to catch a logic error. The condition shall be fulfilled in normal case.
  189. // Do NOT use this to enforce a certain condition on any user input.
  190. function assert(condition, message) {
  191. /* istanbul ignore if */
  192. if (!condition) {
  193. throw new Error('ASSERT: ' + message);
  194. }
  195. }
  196. function isDecimalDigit(ch) {
  197. return (ch >= 0x30 && ch <= 0x39); // 0..9
  198. }
  199. function isHexDigit(ch) {
  200. return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
  201. }
  202. function isOctalDigit(ch) {
  203. return '01234567'.indexOf(ch) >= 0;
  204. }
  205. // 7.2 White Space
  206. function isWhiteSpace(ch) {
  207. return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
  208. (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
  209. }
  210. // 7.3 Line Terminators
  211. function isLineTerminator(ch) {
  212. return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
  213. }
  214. // 7.6 Identifier Names and Identifiers
  215. function isIdentifierStart(ch) {
  216. return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
  217. (ch >= 0x41 && ch <= 0x5A) || // A..Z
  218. (ch >= 0x61 && ch <= 0x7A) || // a..z
  219. (ch === 0x5C) || // \ (backslash)
  220. ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
  221. }
  222. function isIdentifierPart(ch) {
  223. return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
  224. (ch >= 0x41 && ch <= 0x5A) || // A..Z
  225. (ch >= 0x61 && ch <= 0x7A) || // a..z
  226. (ch >= 0x30 && ch <= 0x39) || // 0..9
  227. (ch === 0x5C) || // \ (backslash)
  228. ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
  229. }
  230. // 7.6.1.2 Future Reserved Words
  231. function isFutureReservedWord(id) {
  232. switch (id) {
  233. case 'class':
  234. case 'enum':
  235. case 'export':
  236. case 'extends':
  237. case 'import':
  238. case 'super':
  239. return true;
  240. default:
  241. return false;
  242. }
  243. }
  244. function isStrictModeReservedWord(id) {
  245. switch (id) {
  246. case 'implements':
  247. case 'interface':
  248. case 'package':
  249. case 'private':
  250. case 'protected':
  251. case 'public':
  252. case 'static':
  253. case 'yield':
  254. case 'let':
  255. return true;
  256. default:
  257. return false;
  258. }
  259. }
  260. function isRestrictedWord(id) {
  261. return id === 'eval' || id === 'arguments';
  262. }
  263. // 7.6.1.1 Keywords
  264. function isKeyword(id) {
  265. if (strict && isStrictModeReservedWord(id)) {
  266. return true;
  267. }
  268. // 'const' is specialized as Keyword in V8.
  269. // 'yield' and 'let' are for compatibility with SpiderMonkey and ES.next.
  270. // Some others are from future reserved words.
  271. switch (id.length) {
  272. case 2:
  273. return (id === 'if') || (id === 'in') || (id === 'do');
  274. case 3:
  275. return (id === 'var') || (id === 'for') || (id === 'new') ||
  276. (id === 'try') || (id === 'let');
  277. case 4:
  278. return (id === 'this') || (id === 'else') || (id === 'case') ||
  279. (id === 'void') || (id === 'with') || (id === 'enum');
  280. case 5:
  281. return (id === 'while') || (id === 'break') || (id === 'catch') ||
  282. (id === 'throw') || (id === 'const') || (id === 'yield') ||
  283. (id === 'class') || (id === 'super');
  284. case 6:
  285. return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
  286. (id === 'switch') || (id === 'export') || (id === 'import');
  287. case 7:
  288. return (id === 'default') || (id === 'finally') || (id === 'extends');
  289. case 8:
  290. return (id === 'function') || (id === 'continue') || (id === 'debugger');
  291. case 10:
  292. return (id === 'instanceof');
  293. default:
  294. return false;
  295. }
  296. }
  297. // 7.4 Comments
  298. function addComment(type, value, start, end, loc) {
  299. var comment;
  300. assert(typeof start === 'number', 'Comment must have valid position');
  301. // Because the way the actual token is scanned, often the comments
  302. // (if any) are skipped twice during the lexical analysis.
  303. // Thus, we need to skip adding a comment if the comment array already
  304. // handled it.
  305. if (state.lastCommentStart >= start) {
  306. return;
  307. }
  308. state.lastCommentStart = start;
  309. comment = {
  310. type: type,
  311. value: value
  312. };
  313. if (extra.range) {
  314. comment.range = [start, end];
  315. }
  316. if (extra.loc) {
  317. comment.loc = loc;
  318. }
  319. extra.comments.push(comment);
  320. if (extra.attachComment) {
  321. extra.leadingComments.push(comment);
  322. extra.trailingComments.push(comment);
  323. }
  324. }
  325. function skipSingleLineComment(offset) {
  326. var start, loc, ch, comment;
  327. start = index - offset;
  328. loc = {
  329. start: {
  330. line: lineNumber,
  331. column: index - lineStart - offset
  332. }
  333. };
  334. while (index < length) {
  335. ch = source.charCodeAt(index);
  336. ++index;
  337. if (isLineTerminator(ch)) {
  338. if (extra.comments) {
  339. comment = source.slice(start + offset, index - 1);
  340. loc.end = {
  341. line: lineNumber,
  342. column: index - lineStart - 1
  343. };
  344. addComment('Line', comment, start, index - 1, loc);
  345. }
  346. if (ch === 13 && source.charCodeAt(index) === 10) {
  347. ++index;
  348. }
  349. ++lineNumber;
  350. lineStart = index;
  351. return;
  352. }
  353. }
  354. if (extra.comments) {
  355. comment = source.slice(start + offset, index);
  356. loc.end = {
  357. line: lineNumber,
  358. column: index - lineStart
  359. };
  360. addComment('Line', comment, start, index, loc);
  361. }
  362. }
  363. function skipMultiLineComment() {
  364. var start, loc, ch, comment;
  365. if (extra.comments) {
  366. start = index - 2;
  367. loc = {
  368. start: {
  369. line: lineNumber,
  370. column: index - lineStart - 2
  371. }
  372. };
  373. }
  374. while (index < length) {
  375. ch = source.charCodeAt(index);
  376. if (isLineTerminator(ch)) {
  377. if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) {
  378. ++index;
  379. }
  380. ++lineNumber;
  381. ++index;
  382. lineStart = index;
  383. if (index >= length) {
  384. throwUnexpectedToken();
  385. }
  386. } else if (ch === 0x2A) {
  387. // Block comment ends with '*/'.
  388. if (source.charCodeAt(index + 1) === 0x2F) {
  389. ++index;
  390. ++index;
  391. if (extra.comments) {
  392. comment = source.slice(start + 2, index - 2);
  393. loc.end = {
  394. line: lineNumber,
  395. column: index - lineStart
  396. };
  397. addComment('Block', comment, start, index, loc);
  398. }
  399. return;
  400. }
  401. ++index;
  402. } else {
  403. ++index;
  404. }
  405. }
  406. throwUnexpectedToken();
  407. }
  408. function skipComment() {
  409. var ch, start;
  410. start = (index === 0);
  411. while (index < length) {
  412. ch = source.charCodeAt(index);
  413. if (isWhiteSpace(ch)) {
  414. ++index;
  415. } else if (isLineTerminator(ch)) {
  416. ++index;
  417. if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
  418. ++index;
  419. }
  420. ++lineNumber;
  421. lineStart = index;
  422. start = true;
  423. } else if (ch === 0x2F) { // U+002F is '/'
  424. ch = source.charCodeAt(index + 1);
  425. if (ch === 0x2F) {
  426. ++index;
  427. ++index;
  428. skipSingleLineComment(2);
  429. start = true;
  430. } else if (ch === 0x2A) { // U+002A is '*'
  431. ++index;
  432. ++index;
  433. skipMultiLineComment();
  434. } else {
  435. break;
  436. }
  437. } else if (start && ch === 0x2D) { // U+002D is '-'
  438. // U+003E is '>'
  439. if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) {
  440. // '-->' is a single-line comment
  441. index += 3;
  442. skipSingleLineComment(3);
  443. } else {
  444. break;
  445. }
  446. } else if (ch === 0x3C) { // U+003C is '<'
  447. if (source.slice(index + 1, index + 4) === '!--') {
  448. ++index; // `<`
  449. ++index; // `!`
  450. ++index; // `-`
  451. ++index; // `-`
  452. skipSingleLineComment(4);
  453. } else {
  454. break;
  455. }
  456. } else {
  457. break;
  458. }
  459. }
  460. }
  461. function scanHexEscape(prefix) {
  462. var i, len, ch, code = 0;
  463. len = (prefix === 'u') ? 4 : 2;
  464. for (i = 0; i < len; ++i) {
  465. if (index < length && isHexDigit(source[index])) {
  466. ch = source[index++];
  467. code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
  468. } else {
  469. return '';
  470. }
  471. }
  472. return String.fromCharCode(code);
  473. }
  474. function scanUnicodeCodePointEscape() {
  475. var ch, code, cu1, cu2;
  476. ch = source[index];
  477. code = 0;
  478. // At least, one hex digit is required.
  479. if (ch === '}') {
  480. throwUnexpectedToken();
  481. }
  482. while (index < length) {
  483. ch = source[index++];
  484. if (!isHexDigit(ch)) {
  485. break;
  486. }
  487. code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
  488. }
  489. if (code > 0x10FFFF || ch !== '}') {
  490. throwUnexpectedToken();
  491. }
  492. // UTF-16 Encoding
  493. if (code <= 0xFFFF) {
  494. return String.fromCharCode(code);
  495. }
  496. cu1 = ((code - 0x10000) >> 10) + 0xD800;
  497. cu2 = ((code - 0x10000) & 1023) + 0xDC00;
  498. return String.fromCharCode(cu1, cu2);
  499. }
  500. function getEscapedIdentifier() {
  501. var ch, id;
  502. ch = source.charCodeAt(index++);
  503. id = String.fromCharCode(ch);
  504. // '\u' (U+005C, U+0075) denotes an escaped character.
  505. if (ch === 0x5C) {
  506. if (source.charCodeAt(index) !== 0x75) {
  507. throwUnexpectedToken();
  508. }
  509. ++index;
  510. ch = scanHexEscape('u');
  511. if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
  512. throwUnexpectedToken();
  513. }
  514. id = ch;
  515. }
  516. while (index < length) {
  517. ch = source.charCodeAt(index);
  518. if (!isIdentifierPart(ch)) {
  519. break;
  520. }
  521. ++index;
  522. id += String.fromCharCode(ch);
  523. // '\u' (U+005C, U+0075) denotes an escaped character.
  524. if (ch === 0x5C) {
  525. id = id.substr(0, id.length - 1);
  526. if (source.charCodeAt(index) !== 0x75) {
  527. throwUnexpectedToken();
  528. }
  529. ++index;
  530. ch = scanHexEscape('u');
  531. if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
  532. throwUnexpectedToken();
  533. }
  534. id += ch;
  535. }
  536. }
  537. return id;
  538. }
  539. function getIdentifier() {
  540. var start, ch;
  541. start = index++;
  542. while (index < length) {
  543. ch = source.charCodeAt(index);
  544. if (ch === 0x5C) {
  545. // Blackslash (U+005C) marks Unicode escape sequence.
  546. index = start;
  547. return getEscapedIdentifier();
  548. }
  549. if (isIdentifierPart(ch)) {
  550. ++index;
  551. } else {
  552. break;
  553. }
  554. }
  555. return source.slice(start, index);
  556. }
  557. function scanIdentifier() {
  558. var start, id, type;
  559. start = index;
  560. // Backslash (U+005C) starts an escaped character.
  561. id = (source.charCodeAt(index) === 0x5C) ? getEscapedIdentifier() : getIdentifier();
  562. // There is no keyword or literal with only one character.
  563. // Thus, it must be an identifier.
  564. if (id.length === 1) {
  565. type = Token.Identifier;
  566. } else if (isKeyword(id)) {
  567. type = Token.Keyword;
  568. } else if (id === 'null') {
  569. type = Token.NullLiteral;
  570. } else if (id === 'true' || id === 'false') {
  571. type = Token.BooleanLiteral;
  572. } else {
  573. type = Token.Identifier;
  574. }
  575. return {
  576. type: type,
  577. value: id,
  578. lineNumber: lineNumber,
  579. lineStart: lineStart,
  580. start: start,
  581. end: index
  582. };
  583. }
  584. // 7.7 Punctuators
  585. function scanPunctuator() {
  586. var start = index,
  587. code = source.charCodeAt(index),
  588. code2,
  589. ch1 = source[index],
  590. ch2,
  591. ch3,
  592. ch4;
  593. switch (code) {
  594. // Check for most common single-character punctuators.
  595. case 0x2E: // . dot
  596. case 0x28: // ( open bracket
  597. case 0x29: // ) close bracket
  598. case 0x3B: // ; semicolon
  599. case 0x2C: // , comma
  600. case 0x7B: // { open curly brace
  601. case 0x7D: // } close curly brace
  602. case 0x5B: // [
  603. case 0x5D: // ]
  604. case 0x3A: // :
  605. case 0x3F: // ?
  606. case 0x7E: // ~
  607. ++index;
  608. if (extra.tokenize) {
  609. if (code === 0x28) {
  610. extra.openParenToken = extra.tokens.length;
  611. } else if (code === 0x7B) {
  612. extra.openCurlyToken = extra.tokens.length;
  613. }
  614. }
  615. return {
  616. type: Token.Punctuator,
  617. value: String.fromCharCode(code),
  618. lineNumber: lineNumber,
  619. lineStart: lineStart,
  620. start: start,
  621. end: index
  622. };
  623. default:
  624. code2 = source.charCodeAt(index + 1);
  625. // '=' (U+003D) marks an assignment or comparison operator.
  626. if (code2 === 0x3D) {
  627. switch (code) {
  628. case 0x2B: // +
  629. case 0x2D: // -
  630. case 0x2F: // /
  631. case 0x3C: // <
  632. case 0x3E: // >
  633. case 0x5E: // ^
  634. case 0x7C: // |
  635. case 0x25: // %
  636. case 0x26: // &
  637. case 0x2A: // *
  638. index += 2;
  639. return {
  640. type: Token.Punctuator,
  641. value: String.fromCharCode(code) + String.fromCharCode(code2),
  642. lineNumber: lineNumber,
  643. lineStart: lineStart,
  644. start: start,
  645. end: index
  646. };
  647. case 0x21: // !
  648. case 0x3D: // =
  649. index += 2;
  650. // !== and ===
  651. if (source.charCodeAt(index) === 0x3D) {
  652. ++index;
  653. }
  654. return {
  655. type: Token.Punctuator,
  656. value: source.slice(start, index),
  657. lineNumber: lineNumber,
  658. lineStart: lineStart,
  659. start: start,
  660. end: index
  661. };
  662. }
  663. }
  664. }
  665. // 4-character punctuator: >>>=
  666. ch4 = source.substr(index, 4);
  667. if (ch4 === '>>>=') {
  668. index += 4;
  669. return {
  670. type: Token.Punctuator,
  671. value: ch4,
  672. lineNumber: lineNumber,
  673. lineStart: lineStart,
  674. start: start,
  675. end: index
  676. };
  677. }
  678. // 3-character punctuators: === !== >>> <<= >>=
  679. ch3 = ch4.substr(0, 3);
  680. if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') {
  681. index += 3;
  682. return {
  683. type: Token.Punctuator,
  684. value: ch3,
  685. lineNumber: lineNumber,
  686. lineStart: lineStart,
  687. start: start,
  688. end: index
  689. };
  690. }
  691. // Other 2-character punctuators: ++ -- << >> && ||
  692. ch2 = ch3.substr(0, 2);
  693. if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') {
  694. index += 2;
  695. return {
  696. type: Token.Punctuator,
  697. value: ch2,
  698. lineNumber: lineNumber,
  699. lineStart: lineStart,
  700. start: start,
  701. end: index
  702. };
  703. }
  704. // 1-character punctuators: < > = ! + - * % & | ^ /
  705. if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
  706. ++index;
  707. return {
  708. type: Token.Punctuator,
  709. value: ch1,
  710. lineNumber: lineNumber,
  711. lineStart: lineStart,
  712. start: start,
  713. end: index
  714. };
  715. }
  716. throwUnexpectedToken();
  717. }
  718. // 7.8.3 Numeric Literals
  719. function scanHexLiteral(start) {
  720. var number = '';
  721. while (index < length) {
  722. if (!isHexDigit(source[index])) {
  723. break;
  724. }
  725. number += source[index++];
  726. }
  727. if (number.length === 0) {
  728. throwUnexpectedToken();
  729. }
  730. if (isIdentifierStart(source.charCodeAt(index))) {
  731. throwUnexpectedToken();
  732. }
  733. return {
  734. type: Token.NumericLiteral,
  735. value: parseInt('0x' + number, 16),
  736. lineNumber: lineNumber,
  737. lineStart: lineStart,
  738. start: start,
  739. end: index
  740. };
  741. }
  742. function scanBinaryLiteral(start) {
  743. var ch, number;
  744. number = '';
  745. while (index < length) {
  746. ch = source[index];
  747. if (ch !== '0' && ch !== '1') {
  748. break;
  749. }
  750. number += source[index++];
  751. }
  752. if (number.length === 0) {
  753. // only 0b or 0B
  754. throwUnexpectedToken();
  755. }
  756. if (index < length) {
  757. ch = source.charCodeAt(index);
  758. /* istanbul ignore else */
  759. if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
  760. throwUnexpectedToken();
  761. }
  762. }
  763. return {
  764. type: Token.NumericLiteral,
  765. value: parseInt(number, 2),
  766. lineNumber: lineNumber,
  767. lineStart: lineStart,
  768. start: start,
  769. end: index
  770. };
  771. }
  772. function scanOctalLiteral(prefix, start) {
  773. var number, octal;
  774. if (isOctalDigit(prefix)) {
  775. octal = true;
  776. number = '0' + source[index++];
  777. } else {
  778. octal = false;
  779. ++index;
  780. number = '';
  781. }
  782. while (index < length) {
  783. if (!isOctalDigit(source[index])) {
  784. break;
  785. }
  786. number += source[index++];
  787. }
  788. if (!octal && number.length === 0) {
  789. // only 0o or 0O
  790. throwUnexpectedToken();
  791. }
  792. if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
  793. throwUnexpectedToken();
  794. }
  795. return {
  796. type: Token.NumericLiteral,
  797. value: parseInt(number, 8),
  798. octal: octal,
  799. lineNumber: lineNumber,
  800. lineStart: lineStart,
  801. start: start,
  802. end: index
  803. };
  804. }
  805. function isImplicitOctalLiteral() {
  806. var i, ch;
  807. // Implicit octal, unless there is a non-octal digit.
  808. // (Annex B.1.1 on Numeric Literals)
  809. for (i = index + 1; i < length; ++i) {
  810. ch = source[i];
  811. if (ch === '8' || ch === '9') {
  812. return false;
  813. }
  814. if (!isOctalDigit(ch)) {
  815. return true;
  816. }
  817. }
  818. return true;
  819. }
  820. function scanNumericLiteral() {
  821. var number, start, ch;
  822. ch = source[index];
  823. assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
  824. 'Numeric literal must start with a decimal digit or a decimal point');
  825. start = index;
  826. number = '';
  827. if (ch !== '.') {
  828. number = source[index++];
  829. ch = source[index];
  830. // Hex number starts with '0x'.
  831. // Octal number starts with '0'.
  832. // Octal number in ES6 starts with '0o'.
  833. // Binary number in ES6 starts with '0b'.
  834. if (number === '0') {
  835. if (ch === 'x' || ch === 'X') {
  836. ++index;
  837. return scanHexLiteral(start);
  838. }
  839. if (ch === 'b' || ch === 'B') {
  840. ++index;
  841. return scanBinaryLiteral(start);
  842. }
  843. if (ch === 'o' || ch === 'O') {
  844. return scanOctalLiteral(ch, start);
  845. }
  846. if (isOctalDigit(ch)) {
  847. if (isImplicitOctalLiteral()) {
  848. return scanOctalLiteral(ch, start);
  849. }
  850. }
  851. }
  852. while (isDecimalDigit(source.charCodeAt(index))) {
  853. number += source[index++];
  854. }
  855. ch = source[index];
  856. }
  857. if (ch === '.') {
  858. number += source[index++];
  859. while (isDecimalDigit(source.charCodeAt(index))) {
  860. number += source[index++];
  861. }
  862. ch = source[index];
  863. }
  864. if (ch === 'e' || ch === 'E') {
  865. number += source[index++];
  866. ch = source[index];
  867. if (ch === '+' || ch === '-') {
  868. number += source[index++];
  869. }
  870. if (isDecimalDigit(source.charCodeAt(index))) {
  871. while (isDecimalDigit(source.charCodeAt(index))) {
  872. number += source[index++];
  873. }
  874. } else {
  875. throwUnexpectedToken();
  876. }
  877. }
  878. if (isIdentifierStart(source.charCodeAt(index))) {
  879. throwUnexpectedToken();
  880. }
  881. return {
  882. type: Token.NumericLiteral,
  883. value: parseFloat(number),
  884. lineNumber: lineNumber,
  885. lineStart: lineStart,
  886. start: start,
  887. end: index
  888. };
  889. }
  890. // 7.8.4 String Literals
  891. function scanStringLiteral() {
  892. var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart;
  893. startLineNumber = lineNumber;
  894. startLineStart = lineStart;
  895. quote = source[index];
  896. assert((quote === '\'' || quote === '"'),
  897. 'String literal must starts with a quote');
  898. start = index;
  899. ++index;
  900. while (index < length) {
  901. ch = source[index++];
  902. if (ch === quote) {
  903. quote = '';
  904. break;
  905. } else if (ch === '\\') {
  906. ch = source[index++];
  907. if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
  908. switch (ch) {
  909. case 'u':
  910. case 'x':
  911. if (source[index] === '{') {
  912. ++index;
  913. str += scanUnicodeCodePointEscape();
  914. } else {
  915. restore = index;
  916. unescaped = scanHexEscape(ch);
  917. if (unescaped) {
  918. str += unescaped;
  919. } else {
  920. index = restore;
  921. str += ch;
  922. }
  923. }
  924. break;
  925. case 'n':
  926. str += '\n';
  927. break;
  928. case 'r':
  929. str += '\r';
  930. break;
  931. case 't':
  932. str += '\t';
  933. break;
  934. case 'b':
  935. str += '\b';
  936. break;
  937. case 'f':
  938. str += '\f';
  939. break;
  940. case 'v':
  941. str += '\x0B';
  942. break;
  943. default:
  944. if (isOctalDigit(ch)) {
  945. code = '01234567'.indexOf(ch);
  946. // \0 is not octal escape sequence
  947. if (code !== 0) {
  948. octal = true;
  949. }
  950. if (index < length && isOctalDigit(source[index])) {
  951. octal = true;
  952. code = code * 8 + '01234567'.indexOf(source[index++]);
  953. // 3 digits are only allowed when string starts
  954. // with 0, 1, 2, 3
  955. if ('0123'.indexOf(ch) >= 0 &&
  956. index < length &&
  957. isOctalDigit(source[index])) {
  958. code = code * 8 + '01234567'.indexOf(source[index++]);
  959. }
  960. }
  961. str += String.fromCharCode(code);
  962. } else {
  963. str += ch;
  964. }
  965. break;
  966. }
  967. } else {
  968. ++lineNumber;
  969. if (ch === '\r' && source[index] === '\n') {
  970. ++index;
  971. }
  972. lineStart = index;
  973. }
  974. } else if (isLineTerminator(ch.charCodeAt(0))) {
  975. break;
  976. } else {
  977. str += ch;
  978. }
  979. }
  980. if (quote !== '') {
  981. throwUnexpectedToken();
  982. }
  983. return {
  984. type: Token.StringLiteral,
  985. value: str,
  986. octal: octal,
  987. startLineNumber: startLineNumber,
  988. startLineStart: startLineStart,
  989. lineNumber: lineNumber,
  990. lineStart: lineStart,
  991. start: start,
  992. end: index
  993. };
  994. }
  995. function testRegExp(pattern, flags) {
  996. var tmp = pattern,
  997. value;
  998. if (flags.indexOf('u') >= 0) {
  999. // Replace each astral symbol and every Unicode code point
  1000. // escape sequence with a single ASCII symbol to avoid throwing on
  1001. // regular expressions that are only valid in combination with the
  1002. // `/u` flag.
  1003. // Note: replacing with the ASCII symbol `x` might cause false
  1004. // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
  1005. // perfectly valid pattern that is equivalent to `[a-b]`, but it
  1006. // would be replaced by `[x-b]` which throws an error.
  1007. tmp = tmp
  1008. .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) {
  1009. if (parseInt($1, 16) <= 0x10FFFF) {
  1010. return 'x';
  1011. }
  1012. throwError(Messages.InvalidRegExp);
  1013. })
  1014. .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
  1015. }
  1016. // First, detect invalid regular expressions.
  1017. try {
  1018. value = new RegExp(tmp);
  1019. } catch (e) {
  1020. throwError(Messages.InvalidRegExp);
  1021. }
  1022. // Return a regular expression object for this pattern-flag pair, or
  1023. // `null` in case the current environment doesn't support the flags it
  1024. // uses.
  1025. try {
  1026. return new RegExp(pattern, flags);
  1027. } catch (exception) {
  1028. return null;
  1029. }
  1030. }
  1031. function scanRegExpBody() {
  1032. var ch, str, classMarker, terminated, body;
  1033. ch = source[index];
  1034. assert(ch === '/', 'Regular expression literal must start with a slash');
  1035. str = source[index++];
  1036. classMarker = false;
  1037. terminated = false;
  1038. while (index < length) {
  1039. ch = source[index++];
  1040. str += ch;
  1041. if (ch === '\\') {
  1042. ch = source[index++];
  1043. // ECMA-262 7.8.5
  1044. if (isLineTerminator(ch.charCodeAt(0))) {
  1045. throwError(Messages.UnterminatedRegExp);
  1046. }
  1047. str += ch;
  1048. } else if (isLineTerminator(ch.charCodeAt(0))) {
  1049. throwError(Messages.UnterminatedRegExp);
  1050. } else if (classMarker) {
  1051. if (ch === ']') {
  1052. classMarker = false;
  1053. }
  1054. } else {
  1055. if (ch === '/') {
  1056. terminated = true;
  1057. break;
  1058. } else if (ch === '[') {
  1059. classMarker = true;
  1060. }
  1061. }
  1062. }
  1063. if (!terminated) {
  1064. throwError(Messages.UnterminatedRegExp);
  1065. }
  1066. // Exclude leading and trailing slash.
  1067. body = str.substr(1, str.length - 2);
  1068. return {
  1069. value: body,
  1070. literal: str
  1071. };
  1072. }
  1073. function scanRegExpFlags() {
  1074. var ch, str, flags, restore;
  1075. str = '';
  1076. flags = '';
  1077. while (index < length) {
  1078. ch = source[index];
  1079. if (!isIdentifierPart(ch.charCodeAt(0))) {
  1080. break;
  1081. }
  1082. ++index;
  1083. if (ch === '\\' && index < length) {
  1084. ch = source[index];
  1085. if (ch === 'u') {
  1086. ++index;
  1087. restore = index;
  1088. ch = scanHexEscape('u');
  1089. if (ch) {
  1090. flags += ch;
  1091. for (str += '\\u'; restore < index; ++restore) {
  1092. str += source[restore];
  1093. }
  1094. } else {
  1095. index = restore;
  1096. flags += 'u';
  1097. str += '\\u';
  1098. }
  1099. tolerateUnexpectedToken();
  1100. } else {
  1101. str += '\\';
  1102. tolerateUnexpectedToken();
  1103. }
  1104. } else {
  1105. flags += ch;
  1106. str += ch;
  1107. }
  1108. }
  1109. return {
  1110. value: flags,
  1111. literal: str
  1112. };
  1113. }
  1114. function scanRegExp() {
  1115. var start, body, flags, value;
  1116. lookahead = null;
  1117. skipComment();
  1118. start = index;
  1119. body = scanRegExpBody();
  1120. flags = scanRegExpFlags();
  1121. value = testRegExp(body.value, flags.value);
  1122. if (extra.tokenize) {
  1123. return {
  1124. type: Token.RegularExpression,
  1125. value: value,
  1126. regex: {
  1127. pattern: body.value,
  1128. flags: flags.value
  1129. },
  1130. lineNumber: lineNumber,
  1131. lineStart: lineStart,
  1132. start: start,
  1133. end: index
  1134. };
  1135. }
  1136. return {
  1137. literal: body.literal + flags.literal,
  1138. value: value,
  1139. regex: {
  1140. pattern: body.value,
  1141. flags: flags.value
  1142. },
  1143. start: start,
  1144. end: index
  1145. };
  1146. }
  1147. function collectRegex() {
  1148. var pos, loc, regex, token;
  1149. skipComment();
  1150. pos = index;
  1151. loc = {
  1152. start: {
  1153. line: lineNumber,
  1154. column: index - lineStart
  1155. }
  1156. };
  1157. regex = scanRegExp();
  1158. loc.end = {
  1159. line: lineNumber,
  1160. column: index - lineStart
  1161. };
  1162. /* istanbul ignore next */
  1163. if (!extra.tokenize) {
  1164. // Pop the previous token, which is likely '/' or '/='
  1165. if (extra.tokens.length > 0) {
  1166. token = extra.tokens[extra.tokens.length - 1];
  1167. if (token.range[0] === pos && token.type === 'Punctuator') {
  1168. if (token.value === '/' || token.value === '/=') {
  1169. extra.tokens.pop();
  1170. }
  1171. }
  1172. }
  1173. extra.tokens.push({
  1174. type: 'RegularExpression',
  1175. value: regex.literal,
  1176. regex: regex.regex,
  1177. range: [pos, index],
  1178. loc: loc
  1179. });
  1180. }
  1181. return regex;
  1182. }
  1183. function isIdentifierName(token) {
  1184. return token.type === Token.Identifier ||
  1185. token.type === Token.Keyword ||
  1186. token.type === Token.BooleanLiteral ||
  1187. token.type === Token.NullLiteral;
  1188. }
  1189. function advanceSlash() {
  1190. var prevToken,
  1191. checkToken;
  1192. // Using the following algorithm:
  1193. // https://github.com/mozilla/sweet.js/wiki/design
  1194. prevToken = extra.tokens[extra.tokens.length - 1];
  1195. if (!prevToken) {
  1196. // Nothing before that: it cannot be a division.
  1197. return collectRegex();
  1198. }
  1199. if (prevToken.type === 'Punctuator') {
  1200. if (prevToken.value === ']') {
  1201. return scanPunctuator();
  1202. }
  1203. if (prevToken.value === ')') {
  1204. checkToken = extra.tokens[extra.openParenToken - 1];
  1205. if (checkToken &&
  1206. checkToken.type === 'Keyword' &&
  1207. (checkToken.value === 'if' ||
  1208. checkToken.value === 'while' ||
  1209. checkToken.value === 'for' ||
  1210. checkToken.value === 'with')) {
  1211. return collectRegex();
  1212. }
  1213. return scanPunctuator();
  1214. }
  1215. if (prevToken.value === '}') {
  1216. // Dividing a function by anything makes little sense,
  1217. // but we have to check for that.
  1218. if (extra.tokens[extra.openCurlyToken - 3] &&
  1219. extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
  1220. // Anonymous function.
  1221. checkToken = extra.tokens[extra.openCurlyToken - 4];
  1222. if (!checkToken) {
  1223. return scanPunctuator();
  1224. }
  1225. } else if (extra.tokens[extra.openCurlyToken - 4] &&
  1226. extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
  1227. // Named function.
  1228. checkToken = extra.tokens[extra.openCurlyToken - 5];
  1229. if (!checkToken) {
  1230. return collectRegex();
  1231. }
  1232. } else {
  1233. return scanPunctuator();
  1234. }
  1235. // checkToken determines whether the function is
  1236. // a declaration or an expression.
  1237. if (FnExprTokens.indexOf(checkToken.value) >= 0) {
  1238. // It is an expression.
  1239. return scanPunctuator();
  1240. }
  1241. // It is a declaration.
  1242. return collectRegex();
  1243. }
  1244. return collectRegex();
  1245. }
  1246. if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
  1247. return collectRegex();
  1248. }
  1249. return scanPunctuator();
  1250. }
  1251. function advance() {
  1252. var ch;
  1253. skipComment();
  1254. if (index >= length) {
  1255. return {
  1256. type: Token.EOF,
  1257. lineNumber: lineNumber,
  1258. lineStart: lineStart,
  1259. start: index,
  1260. end: index
  1261. };
  1262. }
  1263. ch = source.charCodeAt(index);
  1264. if (isIdentifierStart(ch)) {
  1265. return scanIdentifier();
  1266. }
  1267. // Very common: ( and ) and ;
  1268. if (ch === 0x28 || ch === 0x29 || ch === 0x3B) {
  1269. return scanPunctuator();
  1270. }
  1271. // String literal starts with single quote (U+0027) or double quote (U+0022).
  1272. if (ch === 0x27 || ch === 0x22) {
  1273. return scanStringLiteral();
  1274. }
  1275. // Dot (.) U+002E can also start a floating-point number, hence the need
  1276. // to check the next character.
  1277. if (ch === 0x2E) {
  1278. if (isDecimalDigit(source.charCodeAt(index + 1))) {
  1279. return scanNumericLiteral();
  1280. }
  1281. return scanPunctuator();
  1282. }
  1283. if (isDecimalDigit(ch)) {
  1284. return scanNumericLiteral();
  1285. }
  1286. // Slash (/) U+002F can also start a regex.
  1287. if (extra.tokenize && ch === 0x2F) {
  1288. return advanceSlash();
  1289. }
  1290. return scanPunctuator();
  1291. }
  1292. function collectToken() {
  1293. var loc, token, value, entry;
  1294. skipComment();
  1295. loc = {
  1296. start: {
  1297. line: lineNumber,
  1298. column: index - lineStart
  1299. }
  1300. };
  1301. token = advance();
  1302. loc.end = {
  1303. line: lineNumber,
  1304. column: index - lineStart
  1305. };
  1306. if (token.type !== Token.EOF) {
  1307. value = source.slice(token.start, token.end);
  1308. entry = {
  1309. type: TokenName[token.type],
  1310. value: value,
  1311. range: [token.start, token.end],
  1312. loc: loc
  1313. };
  1314. if (token.regex) {
  1315. entry.regex = {
  1316. pattern: token.regex.pattern,
  1317. flags: token.regex.flags
  1318. };
  1319. }
  1320. extra.tokens.push(entry);
  1321. }
  1322. return token;
  1323. }
  1324. function lex() {
  1325. var token;
  1326. token = lookahead;
  1327. index = token.end;
  1328. lineNumber = token.lineNumber;
  1329. lineStart = token.lineStart;
  1330. lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
  1331. index = token.end;
  1332. lineNumber = token.lineNumber;
  1333. lineStart = token.lineStart;
  1334. return token;
  1335. }
  1336. function peek() {
  1337. var pos, line, start;
  1338. pos = index;
  1339. line = lineNumber;
  1340. start = lineStart;
  1341. lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
  1342. index = pos;
  1343. lineNumber = line;
  1344. lineStart = start;
  1345. }
  1346. function Position() {
  1347. this.line = lineNumber;
  1348. this.column = index - lineStart;
  1349. }
  1350. function SourceLocation() {
  1351. this.start = new Position();
  1352. this.end = null;
  1353. }
  1354. function WrappingSourceLocation(startToken) {
  1355. if (startToken.type === Token.StringLiteral) {
  1356. this.start = {
  1357. line: startToken.startLineNumber,
  1358. column: startToken.start - startToken.startLineStart
  1359. };
  1360. } else {
  1361. this.start = {
  1362. line: startToken.lineNumber,
  1363. column: startToken.start - startToken.lineStart
  1364. };
  1365. }
  1366. this.end = null;
  1367. }
  1368. function Node() {
  1369. // Skip comment.
  1370. index = lookahead.start;
  1371. if (lookahead.type === Token.StringLiteral) {
  1372. lineNumber = lookahead.startLineNumber;
  1373. lineStart = lookahead.startLineStart;
  1374. } else {
  1375. lineNumber = lookahead.lineNumber;
  1376. lineStart = lookahead.lineStart;
  1377. }
  1378. if (extra.range) {
  1379. this.range = [index, 0];
  1380. }
  1381. if (extra.loc) {
  1382. this.loc = new SourceLocation();
  1383. }
  1384. }
  1385. function WrappingNode(startToken) {
  1386. if (extra.range) {
  1387. this.range = [startToken.start, 0];
  1388. }
  1389. if (extra.loc) {
  1390. this.loc = new WrappingSourceLocation(startToken);
  1391. }
  1392. }
  1393. WrappingNode.prototype = Node.prototype = {
  1394. processComment: function () {
  1395. var lastChild,
  1396. leadingComments,
  1397. trailingComments,
  1398. bottomRight = extra.bottomRightStack,
  1399. i,
  1400. comment,
  1401. last = bottomRight[bottomRight.length - 1];
  1402. if (this.type === Syntax.Program) {
  1403. if (this.body.length > 0) {
  1404. return;
  1405. }
  1406. }
  1407. if (extra.trailingComments.length > 0) {
  1408. trailingComments = [];
  1409. for (i = extra.trailingComments.length - 1; i >= 0; --i) {
  1410. comment = extra.trailingComments[i];
  1411. if (comment.range[0] >= this.range[1]) {
  1412. trailingComments.unshift(comment);
  1413. extra.trailingComments.splice(i, 1);
  1414. }
  1415. }
  1416. extra.trailingComments = [];
  1417. } else {
  1418. if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) {
  1419. trailingComments = last.trailingComments;
  1420. delete last.trailingComments;
  1421. }
  1422. }
  1423. // Eating the stack.
  1424. if (last) {
  1425. while (last && last.range[0] >= this.range[0]) {
  1426. lastChild = last;
  1427. last = bottomRight.pop();
  1428. }
  1429. }
  1430. if (lastChild) {
  1431. if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= this.range[0]) {
  1432. this.leadingComments = lastChild.leadingComments;
  1433. lastChild.leadingComments = undefined;
  1434. }
  1435. } else if (extra.leadingComments.length > 0) {
  1436. leadingComments = [];
  1437. for (i = extra.leadingComments.length - 1; i >= 0; --i) {
  1438. comment = extra.leadingComments[i];
  1439. if (comment.range[1] <= this.range[0]) {
  1440. leadingComments.unshift(comment);
  1441. extra.leadingComments.splice(i, 1);
  1442. }
  1443. }
  1444. }
  1445. if (leadingComments && leadingComments.length > 0) {
  1446. this.leadingComments = leadingComments;
  1447. }
  1448. if (trailingComments && trailingComments.length > 0) {
  1449. this.trailingComments = trailingComments;
  1450. }
  1451. bottomRight.push(this);
  1452. },
  1453. finish: function () {
  1454. if (extra.range) {
  1455. this.range[1] = index;
  1456. }
  1457. if (extra.loc) {
  1458. this.loc.end = new Position();
  1459. if (extra.source) {
  1460. this.loc.source = extra.source;
  1461. }
  1462. }
  1463. if (extra.attachComment) {
  1464. this.processComment();
  1465. }
  1466. },
  1467. finishArrayExpression: function (elements) {
  1468. this.type = Syntax.ArrayExpression;
  1469. this.elements = elements;
  1470. this.finish();
  1471. return this;
  1472. },
  1473. finishArrowFunctionExpression: function (params, defaults, body, expression) {
  1474. this.type = Syntax.ArrowFunctionExpression;
  1475. this.id = null;
  1476. this.params = params;
  1477. this.defaults = defaults;
  1478. this.body = body;
  1479. this.rest = null;
  1480. this.generator = false;
  1481. this.expression = expression;
  1482. this.finish();
  1483. return this;
  1484. },
  1485. finishAssignmentExpression: function (operator, left, right) {
  1486. this.type = Syntax.AssignmentExpression;
  1487. this.operator = operator;
  1488. this.left = left;
  1489. this.right = right;
  1490. this.finish();
  1491. return this;
  1492. },
  1493. finishBinaryExpression: function (operator, left, right) {
  1494. this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
  1495. this.operator = operator;
  1496. this.left = left;
  1497. this.right = right;
  1498. this.finish();
  1499. return this;
  1500. },
  1501. finishBlockStatement: function (body) {
  1502. this.type = Syntax.BlockStatement;
  1503. this.body = body;
  1504. this.finish();
  1505. return this;
  1506. },
  1507. finishBreakStatement: function (label) {
  1508. this.type = Syntax.BreakStatement;
  1509. this.label = label;
  1510. this.finish();
  1511. return this;
  1512. },
  1513. finishCallExpression: function (callee, args) {
  1514. this.type = Syntax.CallExpression;
  1515. this.callee = callee;
  1516. this.arguments = args;
  1517. this.finish();
  1518. return this;
  1519. },
  1520. finishCatchClause: function (param, body) {
  1521. this.type = Syntax.CatchClause;
  1522. this.param = param;
  1523. this.body = body;
  1524. this.finish();
  1525. return this;
  1526. },
  1527. finishConditionalExpression: function (test, consequent, alternate) {
  1528. this.type = Syntax.ConditionalExpression;
  1529. this.test = test;
  1530. this.consequent = consequent;
  1531. this.alternate = alternate;
  1532. this.finish();
  1533. return this;
  1534. },
  1535. finishContinueStatement: function (label) {
  1536. this.type = Syntax.ContinueStatement;
  1537. this.label = label;
  1538. this.finish();
  1539. return this;
  1540. },
  1541. finishDebuggerStatement: function () {
  1542. this.type = Syntax.DebuggerStatement;
  1543. this.finish();
  1544. return this;
  1545. },
  1546. finishDoWhileStatement: function (body, test) {
  1547. this.type = Syntax.DoWhileStatement;
  1548. this.body = body;
  1549. this.test = test;
  1550. this.finish();
  1551. return this;
  1552. },
  1553. finishEmptyStatement: function () {
  1554. this.type = Syntax.EmptyStatement;
  1555. this.finish();
  1556. return this;
  1557. },
  1558. finishExpressionStatement: function (expression) {
  1559. this.type = Syntax.ExpressionStatement;
  1560. this.expression = expression;
  1561. this.finish();
  1562. return this;
  1563. },
  1564. finishForStatement: function (init, test, update, body) {
  1565. this.type = Syntax.ForStatement;
  1566. this.init = init;
  1567. this.test = test;
  1568. this.update = update;
  1569. this.body = body;
  1570. this.finish();
  1571. return this;
  1572. },
  1573. finishForInStatement: function (left, right, body) {
  1574. this.type = Syntax.ForInStatement;
  1575. this.left = left;
  1576. this.right = right;
  1577. this.body = body;
  1578. this.each = false;
  1579. this.finish();
  1580. return this;
  1581. },
  1582. finishFunctionDeclaration: function (id, params, defaults, body) {
  1583. this.type = Syntax.FunctionDeclaration;
  1584. this.id = id;
  1585. this.params = params;
  1586. this.defaults = defaults;
  1587. this.body = body;
  1588. this.rest = null;
  1589. this.generator = false;
  1590. this.expression = false;
  1591. this.finish();
  1592. return this;
  1593. },
  1594. finishFunctionExpression: function (id, params, defaults, body) {
  1595. this.type = Syntax.FunctionExpression;
  1596. this.id = id;
  1597. this.params = params;
  1598. this.defaults = defaults;
  1599. this.body = body;
  1600. this.rest = null;
  1601. this.generator = false;
  1602. this.expression = false;
  1603. this.finish();
  1604. return this;
  1605. },
  1606. finishIdentifier: function (name) {
  1607. this.type = Syntax.Identifier;
  1608. this.name = name;
  1609. this.finish();
  1610. return this;
  1611. },
  1612. finishIfStatement: function (test, consequent, alternate) {
  1613. this.type = Syntax.IfStatement;
  1614. this.test = test;
  1615. this.consequent = consequent;
  1616. this.alternate = alternate;
  1617. this.finish();
  1618. return this;
  1619. },
  1620. finishLabeledStatement: function (label, body) {
  1621. this.type = Syntax.LabeledStatement;
  1622. this.label = label;
  1623. this.body = body;
  1624. this.finish();
  1625. return this;
  1626. },
  1627. finishLiteral: function (token) {
  1628. this.type = Syntax.Literal;
  1629. this.value = token.value;
  1630. this.raw = source.slice(token.start, token.end);
  1631. if (token.regex) {
  1632. this.regex = token.regex;
  1633. }
  1634. this.finish();
  1635. return this;
  1636. },
  1637. finishMemberExpression: function (accessor, object, property) {
  1638. this.type = Syntax.MemberExpression;
  1639. this.computed = accessor === '[';
  1640. this.object = object;
  1641. this.property = property;
  1642. this.finish();
  1643. return this;
  1644. },
  1645. finishNewExpression: function (callee, args) {
  1646. this.type = Syntax.NewExpression;
  1647. this.callee = callee;
  1648. this.arguments = args;
  1649. this.finish();
  1650. return this;
  1651. },
  1652. finishObjectExpression: function (properties) {
  1653. this.type = Syntax.ObjectExpression;
  1654. this.properties = properties;
  1655. this.finish();
  1656. return this;
  1657. },
  1658. finishPostfixExpression: function (operator, argument) {
  1659. this.type = Syntax.UpdateExpression;
  1660. this.operator = operator;
  1661. this.argument = argument;
  1662. this.prefix = false;
  1663. this.finish();
  1664. return this;
  1665. },
  1666. finishProgram: function (body) {
  1667. this.type = Syntax.Program;
  1668. this.body = body;
  1669. this.finish();
  1670. return this;
  1671. },
  1672. finishProperty: function (kind, key, value, method, shorthand) {
  1673. this.type = Syntax.Property;
  1674. this.key = key;
  1675. this.value = value;
  1676. this.kind = kind;
  1677. this.method = method;
  1678. this.shorthand = shorthand;
  1679. this.finish();
  1680. return this;
  1681. },
  1682. finishReturnStatement: function (argument) {
  1683. this.type = Syntax.ReturnStatement;
  1684. this.argument = argument;
  1685. this.finish();
  1686. return this;
  1687. },
  1688. finishSequenceExpression: function (expressions) {
  1689. this.type = Syntax.SequenceExpression;
  1690. this.expressions = expressions;
  1691. this.finish();
  1692. return this;
  1693. },
  1694. finishSwitchCase: function (test, consequent) {
  1695. this.type = Syntax.SwitchCase;
  1696. this.test = test;
  1697. this.consequent = consequent;
  1698. this.finish();
  1699. return this;
  1700. },
  1701. finishSwitchStatement: function (discriminant, cases) {
  1702. this.type = Syntax.SwitchStatement;
  1703. this.discriminant = discriminant;
  1704. this.cases = cases;
  1705. this.finish();
  1706. return this;
  1707. },
  1708. finishThisExpression: function () {
  1709. this.type = Syntax.ThisExpression;
  1710. this.finish();
  1711. return this;
  1712. },
  1713. finishThrowStatement: function (argument) {
  1714. this.type = Syntax.ThrowStatement;
  1715. this.argument = argument;
  1716. this.finish();
  1717. return this;
  1718. },
  1719. finishTryStatement: function (block, guardedHandlers, handlers, finalizer) {
  1720. this.type = Syntax.TryStatement;
  1721. this.block = block;
  1722. this.guardedHandlers = guardedHandlers;
  1723. this.handlers = handlers;
  1724. this.finalizer = finalizer;
  1725. this.finish();
  1726. return this;
  1727. },
  1728. finishUnaryExpression: function (operator, argument) {
  1729. this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression;
  1730. this.operator = operator;
  1731. this.argument = argument;
  1732. this.prefix = true;
  1733. this.finish();
  1734. return this;
  1735. },
  1736. finishVariableDeclaration: function (declarations, kind) {
  1737. this.type = Syntax.VariableDeclaration;
  1738. this.declarations = declarations;
  1739. this.kind = kind;
  1740. this.finish();
  1741. return this;
  1742. },
  1743. finishVariableDeclarator: function (id, init) {
  1744. this.type = Syntax.VariableDeclarator;
  1745. this.id = id;
  1746. this.init = init;
  1747. this.finish();
  1748. return this;
  1749. },
  1750. finishWhileStatement: function (test, body) {
  1751. this.type = Syntax.WhileStatement;
  1752. this.test = test;
  1753. this.body = body;
  1754. this.finish();
  1755. return this;
  1756. },
  1757. finishWithStatement: function (object, body) {
  1758. this.type = Syntax.WithStatement;
  1759. this.object = object;
  1760. this.body = body;
  1761. this.finish();
  1762. return this;
  1763. }
  1764. };
  1765. // Return true if there is a line terminator before the next token.
  1766. function peekLineTerminator() {
  1767. var pos, line, start, found;
  1768. pos = index;
  1769. line = lineNumber;
  1770. start = lineStart;
  1771. skipComment();
  1772. found = lineNumber !== line;
  1773. index = pos;
  1774. lineNumber = line;
  1775. lineStart = start;
  1776. return found;
  1777. }
  1778. function createError(line, pos, description) {
  1779. var error = new Error('Line ' + line + ': ' + description);
  1780. error.index = pos;
  1781. error.lineNumber = line;
  1782. error.column = pos - lineStart + 1;
  1783. error.description = description;
  1784. return error;
  1785. }
  1786. // Throw an exception
  1787. function throwError(messageFormat) {
  1788. var args, msg;
  1789. args = Array.prototype.slice.call(arguments, 1);
  1790. msg = messageFormat.replace(/%(\d)/g,
  1791. function (whole, idx) {
  1792. assert(idx < args.length, 'Message reference must be in range');
  1793. return args[idx];
  1794. }
  1795. );
  1796. throw createError(lineNumber, index, msg);
  1797. }
  1798. function tolerateError(messageFormat) {
  1799. var args, msg, error;
  1800. args = Array.prototype.slice.call(arguments, 1);
  1801. /* istanbul ignore next */
  1802. msg = messageFormat.replace(/%(\d)/g,
  1803. function (whole, idx) {
  1804. assert(idx < args.length, 'Message reference must be in range');
  1805. return args[idx];
  1806. }
  1807. );
  1808. error = createError(lineNumber, index, msg);
  1809. if (extra.errors) {
  1810. extra.errors.push(error);
  1811. } else {
  1812. throw error;
  1813. }
  1814. }
  1815. // Throw an exception because of the token.
  1816. function unexpectedTokenError(token, message) {
  1817. var msg = Messages.UnexpectedToken;
  1818. if (token) {
  1819. msg = message ? message :
  1820. (token.type === Token.EOF) ? Messages.UnexpectedEOS :
  1821. (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier :
  1822. (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber :
  1823. (token.type === Token.StringLiteral) ? Messages.UnexpectedString :
  1824. Messages.UnexpectedToken;
  1825. if (token.type === Token.Keyword) {
  1826. if (isFutureReservedWord(token.value)) {
  1827. msg = Messages.UnexpectedReserved;
  1828. } else if (strict && isStrictModeReservedWord(token.value)) {
  1829. msg = Messages.StrictReservedWord;
  1830. }
  1831. }
  1832. }
  1833. msg = msg.replace('%0', token ? token.value : 'ILLEGAL');
  1834. return (token && typeof token.lineNumber === 'number') ?
  1835. createError(token.lineNumber, token.start, msg) :
  1836. createError(lineNumber, index, msg);
  1837. }
  1838. function throwUnexpectedToken(token, message) {
  1839. throw unexpectedTokenError(token, message);
  1840. }
  1841. function tolerateUnexpectedToken(token, message) {
  1842. var error = unexpectedTokenError(token, message);
  1843. if (extra.errors) {
  1844. extra.errors.push(error);
  1845. } else {
  1846. throw error;
  1847. }
  1848. }
  1849. // Expect the next token to match the specified punctuator.
  1850. // If not, an exception will be thrown.
  1851. function expect(value) {
  1852. var token = lex();
  1853. if (token.type !== Token.Punctuator || token.value !== value) {
  1854. throwUnexpectedToken(token);
  1855. }
  1856. }
  1857. /**
  1858. * @name expectCommaSeparator
  1859. * @description Quietly expect a comma when in tolerant mode, otherwise delegates
  1860. * to <code>expect(value)</code>
  1861. * @since 2.0
  1862. */
  1863. function expectCommaSeparator() {
  1864. var token;
  1865. if (extra.errors) {
  1866. token = lookahead;
  1867. if (token.type === Token.Punctuator && token.value === ',') {
  1868. lex();
  1869. } else if (token.type === Token.Punctuator && token.value === ';') {
  1870. lex();
  1871. tolerateUnexpectedToken(token);
  1872. } else {
  1873. tolerateUnexpectedToken(token, Messages.UnexpectedToken);
  1874. }
  1875. } else {
  1876. expect(',');
  1877. }
  1878. }
  1879. // Expect the next token to match the specified keyword.
  1880. // If not, an exception will be thrown.
  1881. function expectKeyword(keyword) {
  1882. var token = lex();
  1883. if (token.type !== Token.Keyword || token.value !== keyword) {
  1884. throwUnexpectedToken(token);
  1885. }
  1886. }
  1887. // Return true if the next token matches the specified punctuator.
  1888. function match(value) {
  1889. return lookahead.type === Token.Punctuator && lookahead.value === value;
  1890. }
  1891. // Return true if the next token matches the specified keyword
  1892. function matchKeyword(keyword) {
  1893. return lookahead.type === Token.Keyword && lookahead.value === keyword;
  1894. }
  1895. // Return true if the next token is an assignment operator
  1896. function matchAssign() {
  1897. var op;
  1898. if (lookahead.type !== Token.Punctuator) {
  1899. return false;
  1900. }
  1901. op = lookahead.value;
  1902. return op === '=' ||
  1903. op === '*=' ||
  1904. op === '/=' ||
  1905. op === '%=' ||
  1906. op === '+=' ||
  1907. op === '-=' ||
  1908. op === '<<=' ||
  1909. op === '>>=' ||
  1910. op === '>>>=' ||
  1911. op === '&=' ||
  1912. op === '^=' ||
  1913. op === '|=';
  1914. }
  1915. function consumeSemicolon() {
  1916. var line, oldIndex = index, oldLineNumber = lineNumber,
  1917. oldLineStart = lineStart, oldLookahead = lookahead;
  1918. // Catch the very common case first: immediately a semicolon (U+003B).
  1919. if (source.charCodeAt(index) === 0x3B || match(';')) {
  1920. lex();
  1921. return;
  1922. }
  1923. line = lineNumber;
  1924. skipComment();
  1925. if (lineNumber !== line) {
  1926. index = oldIndex;
  1927. lineNumber = oldLineNumber;
  1928. lineStart = oldLineStart;
  1929. lookahead = oldLookahead;
  1930. return;
  1931. }
  1932. if (lookahead.type !== Token.EOF && !match('}')) {
  1933. throwUnexpectedToken(lookahead);
  1934. }
  1935. }
  1936. // Return true if provided expression is LeftHandSideExpression
  1937. function isLeftHandSide(expr) {
  1938. return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
  1939. }
  1940. // 11.1.4 Array Initialiser
  1941. function parseArrayInitialiser() {
  1942. var elements = [], node = new Node();
  1943. expect('[');
  1944. while (!match(']')) {
  1945. if (match(',')) {
  1946. lex();
  1947. elements.push(null);
  1948. } else {
  1949. elements.push(parseAssignmentExpression());
  1950. if (!match(']')) {
  1951. expect(',');
  1952. }
  1953. }
  1954. }
  1955. lex();
  1956. return node.finishArrayExpression(elements);
  1957. }
  1958. // 11.1.5 Object Initialiser
  1959. function parsePropertyFunction(param, first) {
  1960. var previousStrict, body, node = new Node();
  1961. previousStrict = strict;
  1962. body = parseFunctionSourceElements();
  1963. if (first && strict && isRestrictedWord(param[0].name)) {
  1964. tolerateUnexpectedToken(first, Messages.StrictParamName);
  1965. }
  1966. strict = previousStrict;
  1967. return node.finishFunctionExpression(null, param, [], body);
  1968. }
  1969. function parsePropertyMethodFunction() {
  1970. var previousStrict, param, method;
  1971. previousStrict = strict;
  1972. strict = true;
  1973. param = parseParams();
  1974. method = parsePropertyFunction(param.params);
  1975. strict = previousStrict;
  1976. return method;
  1977. }
  1978. function parseObjectPropertyKey() {
  1979. var token, node = new Node();
  1980. token = lex();
  1981. // Note: This function is called only from parseObjectProperty(), where
  1982. // EOF and Punctuator tokens are already filtered out.
  1983. if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
  1984. if (strict && token.octal) {
  1985. tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
  1986. }
  1987. return node.finishLiteral(token);
  1988. }
  1989. return node.finishIdentifier(token.value);
  1990. }
  1991. function parseObjectProperty() {
  1992. var token, key, id, value, param, node = new Node();
  1993. token = lookahead;
  1994. if (token.type === Token.Identifier) {
  1995. id = parseObjectPropertyKey();
  1996. // Property Assignment: Getter and Setter.
  1997. if (token.value === 'get' && !(match(':') || match('('))) {
  1998. key = parseObjectPropertyKey();
  1999. expect('(');
  2000. expect(')');
  2001. value = parsePropertyFunction([]);
  2002. return node.finishProperty('get', key, value, false, false);
  2003. }
  2004. if (token.value === 'set' && !(match(':') || match('('))) {
  2005. key = parseObjectPropertyKey();
  2006. expect('(');
  2007. token = lookahead;
  2008. if (token.type !== Token.Identifier) {
  2009. expect(')');
  2010. tolerateUnexpectedToken(token);
  2011. value = parsePropertyFunction([]);
  2012. } else {
  2013. param = [ parseVariableIdentifier() ];
  2014. expect(')');
  2015. value = parsePropertyFunction(param, token);
  2016. }
  2017. return node.finishProperty('set', key, value, false, false);
  2018. }
  2019. if (match(':')) {
  2020. lex();
  2021. value = parseAssignmentExpression();
  2022. return node.finishProperty('init', id, value, false, false);
  2023. }
  2024. if (match('(')) {
  2025. value = parsePropertyMethodFunction();
  2026. return node.finishProperty('init', id, value, true, false);
  2027. }
  2028. value = id;
  2029. return node.finishProperty('init', id, value, false, true);
  2030. }
  2031. if (token.type === Token.EOF || token.type === Token.Punctuator) {
  2032. throwUnexpectedToken(token);
  2033. } else {
  2034. key = parseObjectPropertyKey();
  2035. if (match(':')) {
  2036. lex();
  2037. value = parseAssignmentExpression();
  2038. return node.finishProperty('init', key, value, false, false);
  2039. }
  2040. if (match('(')) {
  2041. value = parsePropertyMethodFunction();
  2042. return node.finishProperty('init', key, value, true, false);
  2043. }
  2044. throwUnexpectedToken(lex());
  2045. }
  2046. }
  2047. function parseObjectInitialiser() {
  2048. var properties = [], property, name, key, kind, map = {}, toString = String, node = new Node();
  2049. expect('{');
  2050. while (!match('}')) {
  2051. property = parseObjectProperty();
  2052. if (property.key.type === Syntax.Identifier) {
  2053. name = property.key.name;
  2054. } else {
  2055. name = toString(property.key.value);
  2056. }
  2057. kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
  2058. key = '$' + name;
  2059. if (Object.prototype.hasOwnProperty.call(map, key)) {
  2060. if (map[key] === PropertyKind.Data) {
  2061. if (strict && kind === PropertyKind.Data) {
  2062. tolerateError(Messages.StrictDuplicateProperty);
  2063. } else if (kind !== PropertyKind.Data) {
  2064. tolerateError(Messages.AccessorDataProperty);
  2065. }
  2066. } else {
  2067. if (kind === PropertyKind.Data) {
  2068. tolerateError(Messages.AccessorDataProperty);
  2069. } else if (map[key] & kind) {
  2070. tolerateError(Messages.AccessorGetSet);
  2071. }
  2072. }
  2073. map[key] |= kind;
  2074. } else {
  2075. map[key] = kind;
  2076. }
  2077. properties.push(property);
  2078. if (!match('}')) {
  2079. expectCommaSeparator();
  2080. }
  2081. }
  2082. expect('}');
  2083. return node.finishObjectExpression(properties);
  2084. }
  2085. // 11.1.6 The Grouping Operator
  2086. function parseGroupExpression() {
  2087. var expr;
  2088. expect('(');
  2089. if (match(')')) {
  2090. lex();
  2091. return PlaceHolders.ArrowParameterPlaceHolder;
  2092. }
  2093. ++state.parenthesisCount;
  2094. expr = parseExpression();
  2095. expect(')');
  2096. return expr;
  2097. }
  2098. // 11.1 Primary Expressions
  2099. function parsePrimaryExpression() {
  2100. var type, token, expr, node;
  2101. if (match('(')) {
  2102. return parseGroupExpression();
  2103. }
  2104. if (match('[')) {
  2105. return parseArrayInitialiser();
  2106. }
  2107. if (match('{')) {
  2108. return parseObjectInitialiser();
  2109. }
  2110. type = lookahead.type;
  2111. node = new Node();
  2112. if (type === Token.Identifier) {
  2113. expr = node.finishIdentifier(lex().value);
  2114. } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
  2115. if (strict && lookahead.octal) {
  2116. tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral);
  2117. }
  2118. expr = node.finishLiteral(lex());
  2119. } else if (type === Token.Keyword) {
  2120. if (matchKeyword('function')) {
  2121. return parseFunctionExpression();
  2122. }
  2123. if (matchKeyword('this')) {
  2124. lex();
  2125. expr = node.finishThisExpression();
  2126. } else {
  2127. throwUnexpectedToken(lex());
  2128. }
  2129. } else if (type === Token.BooleanLiteral) {
  2130. token = lex();
  2131. token.value = (token.value === 'true');
  2132. expr = node.finishLiteral(token);
  2133. } else if (type === Token.NullLiteral) {
  2134. token = lex();
  2135. token.value = null;
  2136. expr = node.finishLiteral(token);
  2137. } else if (match('/') || match('/=')) {
  2138. if (typeof extra.tokens !== 'undefined') {
  2139. expr = node.finishLiteral(collectRegex());
  2140. } else {
  2141. expr = node.finishLiteral(scanRegExp());
  2142. }
  2143. peek();
  2144. } else {
  2145. throwUnexpectedToken(lex());
  2146. }
  2147. return expr;
  2148. }
  2149. // 11.2 Left-Hand-Side Expressions
  2150. function parseArguments() {
  2151. var args = [];
  2152. expect('(');
  2153. if (!match(')')) {
  2154. while (index < length) {
  2155. args.push(parseAssignmentExpression());
  2156. if (match(')')) {
  2157. break;
  2158. }
  2159. expectCommaSeparator();
  2160. }
  2161. }
  2162. expect(')');
  2163. return args;
  2164. }
  2165. function parseNonComputedProperty() {
  2166. var token, node = new Node();
  2167. token = lex();
  2168. if (!isIdentifierName(token)) {
  2169. throwUnexpectedToken(token);
  2170. }
  2171. return node.finishIdentifier(token.value);
  2172. }
  2173. function parseNonComputedMember() {
  2174. expect('.');
  2175. return parseNonComputedProperty();
  2176. }
  2177. function parseComputedMember() {
  2178. var expr;
  2179. expect('[');
  2180. expr = parseExpression();
  2181. expect(']');
  2182. return expr;
  2183. }
  2184. function parseNewExpression() {
  2185. var callee, args, node = new Node();
  2186. expectKeyword('new');
  2187. callee = parseLeftHandSideExpression();
  2188. args = match('(') ? parseArguments() : [];
  2189. return node.finishNewExpression(callee, args);
  2190. }
  2191. function parseLeftHandSideExpressionAllowCall() {
  2192. var expr, args, property, startToken, previousAllowIn = state.allowIn;
  2193. startToken = lookahead;
  2194. state.allowIn = true;
  2195. expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
  2196. for (;;) {
  2197. if (match('.')) {
  2198. property = parseNonComputedMember();
  2199. expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
  2200. } else if (match('(')) {
  2201. args = parseArguments();
  2202. expr = new WrappingNode(startToken).finishCallExpression(expr, args);
  2203. } else if (match('[')) {
  2204. property = parseComputedMember();
  2205. expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
  2206. } else {
  2207. break;
  2208. }
  2209. }
  2210. state.allowIn = previousAllowIn;
  2211. return expr;
  2212. }
  2213. function parseLeftHandSideExpression() {
  2214. var expr, property, startToken;
  2215. assert(state.allowIn, 'callee of new expression always allow in keyword.');
  2216. startToken = lookahead;
  2217. expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
  2218. for (;;) {
  2219. if (match('[')) {
  2220. property = parseComputedMember();
  2221. expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
  2222. } else if (match('.')) {
  2223. property = parseNonComputedMember();
  2224. expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
  2225. } else {
  2226. break;
  2227. }
  2228. }
  2229. return expr;
  2230. }
  2231. // 11.3 Postfix Expressions
  2232. function parsePostfixExpression() {
  2233. var expr, token, startToken = lookahead;
  2234. expr = parseLeftHandSideExpressionAllowCall();
  2235. if (lookahead.type === Token.Punctuator) {
  2236. if ((match('++') || match('--')) && !peekLineTerminator()) {
  2237. // 11.3.1, 11.3.2
  2238. if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
  2239. tolerateError(Messages.StrictLHSPostfix);
  2240. }
  2241. if (!isLeftHandSide(expr)) {
  2242. tolerateError(Messages.InvalidLHSInAssignment);
  2243. }
  2244. token = lex();
  2245. expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
  2246. }
  2247. }
  2248. return expr;
  2249. }
  2250. // 11.4 Unary Operators
  2251. function parseUnaryExpression() {
  2252. var token, expr, startToken;
  2253. if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
  2254. expr = parsePostfixExpression();
  2255. } else if (match('++') || match('--')) {
  2256. startToken = lookahead;
  2257. token = lex();
  2258. expr = parseUnaryExpression();
  2259. // 11.4.4, 11.4.5
  2260. if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
  2261. tolerateError(Messages.StrictLHSPrefix);
  2262. }
  2263. if (!isLeftHandSide(expr)) {
  2264. tolerateError(Messages.InvalidLHSInAssignment);
  2265. }
  2266. expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
  2267. } else if (match('+') || match('-') || match('~') || match('!')) {
  2268. startToken = lookahead;
  2269. token = lex();
  2270. expr = parseUnaryExpression();
  2271. expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
  2272. } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
  2273. startToken = lookahead;
  2274. token = lex();
  2275. expr = parseUnaryExpression();
  2276. expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
  2277. if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
  2278. tolerateError(Messages.StrictDelete);
  2279. }
  2280. } else {
  2281. expr = parsePostfixExpression();
  2282. }
  2283. return expr;
  2284. }
  2285. function binaryPrecedence(token, allowIn) {
  2286. var prec = 0;
  2287. if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
  2288. return 0;
  2289. }
  2290. switch (token.value) {
  2291. case '||':
  2292. prec = 1;
  2293. break;
  2294. case '&&':
  2295. prec = 2;
  2296. break;
  2297. case '|':
  2298. prec = 3;
  2299. break;
  2300. case '^':
  2301. prec = 4;
  2302. break;
  2303. case '&':
  2304. prec = 5;
  2305. break;
  2306. case '==':
  2307. case '!=':
  2308. case '===':
  2309. case '!==':
  2310. prec = 6;
  2311. break;
  2312. case '<':
  2313. case '>':
  2314. case '<=':
  2315. case '>=':
  2316. case 'instanceof':
  2317. prec = 7;
  2318. break;
  2319. case 'in':
  2320. prec = allowIn ? 7 : 0;
  2321. break;
  2322. case '<<':
  2323. case '>>':
  2324. case '>>>':
  2325. prec = 8;
  2326. break;
  2327. case '+':
  2328. case '-':
  2329. prec = 9;
  2330. break;
  2331. case '*':
  2332. case '/':
  2333. case '%':
  2334. prec = 11;
  2335. break;
  2336. default:
  2337. break;
  2338. }
  2339. return prec;
  2340. }
  2341. // 11.5 Multiplicative Operators
  2342. // 11.6 Additive Operators
  2343. // 11.7 Bitwise Shift Operators
  2344. // 11.8 Relational Operators
  2345. // 11.9 Equality Operators
  2346. // 11.10 Binary Bitwise Operators
  2347. // 11.11 Binary Logical Operators
  2348. function parseBinaryExpression() {
  2349. var marker, markers, expr, token, prec, stack, right, operator, left, i;
  2350. marker = lookahead;
  2351. left = parseUnaryExpression();
  2352. if (left === PlaceHolders.ArrowParameterPlaceHolder) {
  2353. return left;
  2354. }
  2355. token = lookahead;
  2356. prec = binaryPrecedence(token, state.allowIn);
  2357. if (prec === 0) {
  2358. return left;
  2359. }
  2360. token.prec = prec;
  2361. lex();
  2362. markers = [marker, lookahead];
  2363. right = parseUnaryExpression();
  2364. stack = [left, token, right];
  2365. while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
  2366. // Reduce: make a binary expression from the three topmost entries.
  2367. while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
  2368. right = stack.pop();
  2369. operator = stack.pop().value;
  2370. left = stack.pop();
  2371. markers.pop();
  2372. expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
  2373. stack.push(expr);
  2374. }
  2375. // Shift.
  2376. token = lex();
  2377. token.prec = prec;
  2378. stack.push(token);
  2379. markers.push(lookahead);
  2380. expr = parseUnaryExpression();
  2381. stack.push(expr);
  2382. }
  2383. // Final reduce to clean-up the stack.
  2384. i = stack.length - 1;
  2385. expr = stack[i];
  2386. markers.pop();
  2387. while (i > 1) {
  2388. expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
  2389. i -= 2;
  2390. }
  2391. return expr;
  2392. }
  2393. // 11.12 Conditional Operator
  2394. function parseConditionalExpression() {
  2395. var expr, previousAllowIn, consequent, alternate, startToken;
  2396. startToken = lookahead;
  2397. expr = parseBinaryExpression();
  2398. if (expr === PlaceHolders.ArrowParameterPlaceHolder) {
  2399. return expr;
  2400. }
  2401. if (match('?')) {
  2402. lex();
  2403. previousAllowIn = state.allowIn;
  2404. state.allowIn = true;
  2405. consequent = parseAssignmentExpression();
  2406. state.allowIn = previousAllowIn;
  2407. expect(':');
  2408. alternate = parseAssignmentExpression();
  2409. expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
  2410. }
  2411. return expr;
  2412. }
  2413. // [ES6] 14.2 Arrow Function
  2414. function parseConciseBody() {
  2415. if (match('{')) {
  2416. return parseFunctionSourceElements();
  2417. }
  2418. return parseAssignmentExpression();
  2419. }
  2420. function reinterpretAsCoverFormalsList(expressions) {
  2421. var i, len, param, params, defaults, defaultCount, options, rest, token;
  2422. params = [];
  2423. defaults = [];
  2424. defaultCount = 0;
  2425. rest = null;
  2426. options = {
  2427. paramSet: {}
  2428. };
  2429. for (i = 0, len = expressions.length; i < len; i += 1) {
  2430. param = expressions[i];
  2431. if (param.type === Syntax.Identifier) {
  2432. params.push(param);
  2433. defaults.push(null);
  2434. validateParam(options, param, param.name);
  2435. } else if (param.type === Syntax.AssignmentExpression) {
  2436. params.push(param.left);
  2437. defaults.push(param.right);
  2438. ++defaultCount;
  2439. validateParam(options, param.left, param.left.name);
  2440. } else {
  2441. return null;
  2442. }
  2443. }
  2444. if (options.message === Messages.StrictParamDupe) {
  2445. token = strict ? options.stricted : options.firstRestricted;
  2446. throwUnexpectedToken(token, options.message);
  2447. }
  2448. if (defaultCount === 0) {
  2449. defaults = [];
  2450. }
  2451. return {
  2452. params: params,
  2453. defaults: defaults,
  2454. rest: rest,
  2455. stricted: options.stricted,
  2456. firstRestricted: options.firstRestricted,
  2457. message: options.message
  2458. };
  2459. }
  2460. function parseArrowFunctionExpression(options, node) {
  2461. var previousStrict, body;
  2462. expect('=>');
  2463. previousStrict = strict;
  2464. body = parseConciseBody();
  2465. if (strict && options.firstRestricted) {
  2466. throwUnexpectedToken(options.firstRestricted, options.message);
  2467. }
  2468. if (strict && options.stricted) {
  2469. tolerateUnexpectedToken(options.stricted, options.message);
  2470. }
  2471. strict = previousStrict;
  2472. return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
  2473. }
  2474. // 11.13 Assignment Operators
  2475. function parseAssignmentExpression() {
  2476. var oldParenthesisCount, token, expr, right, list, startToken;
  2477. oldParenthesisCount = state.parenthesisCount;
  2478. startToken = lookahead;
  2479. token = lookahead;
  2480. expr = parseConditionalExpression();
  2481. if (expr === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) {
  2482. if (state.parenthesisCount === oldParenthesisCount ||
  2483. state.parenthesisCount === (oldParenthesisCount + 1)) {
  2484. if (expr.type === Syntax.Identifier) {
  2485. list = reinterpretAsCoverFormalsList([ expr ]);
  2486. } else if (expr.type === Syntax.AssignmentExpression) {
  2487. list = reinterpretAsCoverFormalsList([ expr ]);
  2488. } else if (expr.type === Syntax.SequenceExpression) {
  2489. list = reinterpretAsCoverFormalsList(expr.expressions);
  2490. } else if (expr === PlaceHolders.ArrowParameterPlaceHolder) {
  2491. list = reinterpretAsCoverFormalsList([]);
  2492. }
  2493. if (list) {
  2494. return parseArrowFunctionExpression(list, new WrappingNode(startToken));
  2495. }
  2496. }
  2497. }
  2498. if (matchAssign()) {
  2499. // LeftHandSideExpression
  2500. if (!isLeftHandSide(expr)) {
  2501. tolerateError(Messages.InvalidLHSInAssignment);
  2502. }
  2503. // 11.13.1
  2504. if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
  2505. tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
  2506. }
  2507. token = lex();
  2508. right = parseAssignmentExpression();
  2509. expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right);
  2510. }
  2511. return expr;
  2512. }
  2513. // 11.14 Comma Operator
  2514. function parseExpression() {
  2515. var expr, startToken = lookahead, expressions;
  2516. expr = parseAssignmentExpression();
  2517. if (match(',')) {
  2518. expressions = [expr];
  2519. while (index < length) {
  2520. if (!match(',')) {
  2521. break;
  2522. }
  2523. lex();
  2524. expressions.push(parseAssignmentExpression());
  2525. }
  2526. expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
  2527. }
  2528. return expr;
  2529. }
  2530. // 12.1 Block
  2531. function parseStatementList() {
  2532. var list = [],
  2533. statement;
  2534. while (index < length) {
  2535. if (match('}')) {
  2536. break;
  2537. }
  2538. statement = parseSourceElement();
  2539. if (typeof statement === 'undefined') {
  2540. break;
  2541. }
  2542. list.push(statement);
  2543. }
  2544. return list;
  2545. }
  2546. function parseBlock() {
  2547. var block, node = new Node();
  2548. expect('{');
  2549. block = parseStatementList();
  2550. expect('}');
  2551. return node.finishBlockStatement(block);
  2552. }
  2553. // 12.2 Variable Statement
  2554. function parseVariableIdentifier() {
  2555. var token, node = new Node();
  2556. token = lex();
  2557. if (token.type !== Token.Identifier) {
  2558. if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) {
  2559. tolerateUnexpectedToken(token, Messages.StrictReservedWord);
  2560. } else {
  2561. throwUnexpectedToken(token);
  2562. }
  2563. }
  2564. return node.finishIdentifier(token.value);
  2565. }
  2566. function parseVariableDeclaration(kind) {
  2567. var init = null, id, node = new Node();
  2568. id = parseVariableIdentifier();
  2569. // 12.2.1
  2570. if (strict && isRestrictedWord(id.name)) {
  2571. tolerateError(Messages.StrictVarName);
  2572. }
  2573. if (kind === 'const') {
  2574. expect('=');
  2575. init = parseAssignmentExpression();
  2576. } else if (match('=')) {
  2577. lex();
  2578. init = parseAssignmentExpression();
  2579. }
  2580. return node.finishVariableDeclarator(id, init);
  2581. }
  2582. function parseVariableDeclarationList(kind) {
  2583. var list = [];
  2584. do {
  2585. list.push(parseVariableDeclaration(kind));
  2586. if (!match(',')) {
  2587. break;
  2588. }
  2589. lex();
  2590. } while (index < length);
  2591. return list;
  2592. }
  2593. function parseVariableStatement(node) {
  2594. var declarations;
  2595. expectKeyword('var');
  2596. declarations = parseVariableDeclarationList();
  2597. consumeSemicolon();
  2598. return node.finishVariableDeclaration(declarations, 'var');
  2599. }
  2600. // kind may be `const` or `let`
  2601. // Both are experimental and not in the specification yet.
  2602. // see http://wiki.ecmascript.org/doku.php?id=harmony:const
  2603. // and http://wiki.ecmascript.org/doku.php?id=harmony:let
  2604. function parseConstLetDeclaration(kind) {
  2605. var declarations, node = new Node();
  2606. expectKeyword(kind);
  2607. declarations = parseVariableDeclarationList(kind);
  2608. consumeSemicolon();
  2609. return node.finishVariableDeclaration(declarations, kind);
  2610. }
  2611. // 12.3 Empty Statement
  2612. function parseEmptyStatement() {
  2613. var node = new Node();
  2614. expect(';');
  2615. return node.finishEmptyStatement();
  2616. }
  2617. // 12.4 Expression Statement
  2618. function parseExpressionStatement(node) {
  2619. var expr = parseExpression();
  2620. consumeSemicolon();
  2621. return node.finishExpressionStatement(expr);
  2622. }
  2623. // 12.5 If statement
  2624. function parseIfStatement(node) {
  2625. var test, consequent, alternate;
  2626. expectKeyword('if');
  2627. expect('(');
  2628. test = parseExpression();
  2629. expect(')');
  2630. consequent = parseStatement();
  2631. if (matchKeyword('else')) {
  2632. lex();
  2633. alternate = parseStatement();
  2634. } else {
  2635. alternate = null;
  2636. }
  2637. return node.finishIfStatement(test, consequent, alternate);
  2638. }
  2639. // 12.6 Iteration Statements
  2640. function parseDoWhileStatement(node) {
  2641. var body, test, oldInIteration;
  2642. expectKeyword('do');
  2643. oldInIteration = state.inIteration;
  2644. state.inIteration = true;
  2645. body = parseStatement();
  2646. state.inIteration = oldInIteration;
  2647. expectKeyword('while');
  2648. expect('(');
  2649. test = parseExpression();
  2650. expect(')');
  2651. if (match(';')) {
  2652. lex();
  2653. }
  2654. return node.finishDoWhileStatement(body, test);
  2655. }
  2656. function parseWhileStatement(node) {
  2657. var test, body, oldInIteration;
  2658. expectKeyword('while');
  2659. expect('(');
  2660. test = parseExpression();
  2661. expect(')');
  2662. oldInIteration = state.inIteration;
  2663. state.inIteration = true;
  2664. body = parseStatement();
  2665. state.inIteration = oldInIteration;
  2666. return node.finishWhileStatement(test, body);
  2667. }
  2668. function parseForVariableDeclaration() {
  2669. var token, declarations, node = new Node();
  2670. token = lex();
  2671. declarations = parseVariableDeclarationList();
  2672. return node.finishVariableDeclaration(declarations, token.value);
  2673. }
  2674. function parseForStatement(node) {
  2675. var init, test, update, left, right, body, oldInIteration, previousAllowIn = state.allowIn;
  2676. init = test = update = null;
  2677. expectKeyword('for');
  2678. expect('(');
  2679. if (match(';')) {
  2680. lex();
  2681. } else {
  2682. if (matchKeyword('var') || matchKeyword('let')) {
  2683. state.allowIn = false;
  2684. init = parseForVariableDeclaration();
  2685. state.allowIn = previousAllowIn;
  2686. if (init.declarations.length === 1 && matchKeyword('in')) {
  2687. lex();
  2688. left = init;
  2689. right = parseExpression();
  2690. init = null;
  2691. }
  2692. } else {
  2693. state.allowIn = false;
  2694. init = parseExpression();
  2695. state.allowIn = previousAllowIn;
  2696. if (matchKeyword('in')) {
  2697. // LeftHandSideExpression
  2698. if (!isLeftHandSide(init)) {
  2699. tolerateError(Messages.InvalidLHSInForIn);
  2700. }
  2701. lex();
  2702. left = init;
  2703. right = parseExpression();
  2704. init = null;
  2705. }
  2706. }
  2707. if (typeof left === 'undefined') {
  2708. expect(';');
  2709. }
  2710. }
  2711. if (typeof left === 'undefined') {
  2712. if (!match(';')) {
  2713. test = parseExpression();
  2714. }
  2715. expect(';');
  2716. if (!match(')')) {
  2717. update = parseExpression();
  2718. }
  2719. }
  2720. expect(')');
  2721. oldInIteration = state.inIteration;
  2722. state.inIteration = true;
  2723. body = parseStatement();
  2724. state.inIteration = oldInIteration;
  2725. return (typeof left === 'undefined') ?
  2726. node.finishForStatement(init, test, update, body) :
  2727. node.finishForInStatement(left, right, body);
  2728. }
  2729. // 12.7 The continue statement
  2730. function parseContinueStatement(node) {
  2731. var label = null, key;
  2732. expectKeyword('continue');
  2733. // Optimize the most common form: 'continue;'.
  2734. if (source.charCodeAt(index) === 0x3B) {
  2735. lex();
  2736. if (!state.inIteration) {
  2737. throwError(Messages.IllegalContinue);
  2738. }
  2739. return node.finishContinueStatement(null);
  2740. }
  2741. if (peekLineTerminator()) {
  2742. if (!state.inIteration) {
  2743. throwError(Messages.IllegalContinue);
  2744. }
  2745. return node.finishContinueStatement(null);
  2746. }
  2747. if (lookahead.type === Token.Identifier) {
  2748. label = parseVariableIdentifier();
  2749. key = '$' + label.name;
  2750. if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
  2751. throwError(Messages.UnknownLabel, label.name);
  2752. }
  2753. }
  2754. consumeSemicolon();
  2755. if (label === null && !state.inIteration) {
  2756. throwError(Messages.IllegalContinue);
  2757. }
  2758. return node.finishContinueStatement(label);
  2759. }
  2760. // 12.8 The break statement
  2761. function parseBreakStatement(node) {
  2762. var label = null, key;
  2763. expectKeyword('break');
  2764. // Catch the very common case first: immediately a semicolon (U+003B).
  2765. if (source.charCodeAt(index) === 0x3B) {
  2766. lex();
  2767. if (!(state.inIteration || state.inSwitch)) {
  2768. throwError(Messages.IllegalBreak);
  2769. }
  2770. return node.finishBreakStatement(null);
  2771. }
  2772. if (peekLineTerminator()) {
  2773. if (!(state.inIteration || state.inSwitch)) {
  2774. throwError(Messages.IllegalBreak);
  2775. }
  2776. return node.finishBreakStatement(null);
  2777. }
  2778. if (lookahead.type === Token.Identifier) {
  2779. label = parseVariableIdentifier();
  2780. key = '$' + label.name;
  2781. if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
  2782. throwError(Messages.UnknownLabel, label.name);
  2783. }
  2784. }
  2785. consumeSemicolon();
  2786. if (label === null && !(state.inIteration || state.inSwitch)) {
  2787. throwError(Messages.IllegalBreak);
  2788. }
  2789. return node.finishBreakStatement(label);
  2790. }
  2791. // 12.9 The return statement
  2792. function parseReturnStatement(node) {
  2793. var argument = null;
  2794. expectKeyword('return');
  2795. if (!state.inFunctionBody) {
  2796. tolerateError(Messages.IllegalReturn);
  2797. }
  2798. // 'return' followed by a space and an identifier is very common.
  2799. if (source.charCodeAt(index) === 0x20) {
  2800. if (isIdentifierStart(source.charCodeAt(index + 1))) {
  2801. argument = parseExpression();
  2802. consumeSemicolon();
  2803. return node.finishReturnStatement(argument);
  2804. }
  2805. }
  2806. if (peekLineTerminator()) {
  2807. return node.finishReturnStatement(null);
  2808. }
  2809. if (!match(';')) {
  2810. if (!match('}') && lookahead.type !== Token.EOF) {
  2811. argument = parseExpression();
  2812. }
  2813. }
  2814. consumeSemicolon();
  2815. return node.finishReturnStatement(argument);
  2816. }
  2817. // 12.10 The with statement
  2818. function parseWithStatement(node) {
  2819. var object, body;
  2820. if (strict) {
  2821. // TODO(ikarienator): Should we update the test cases instead?
  2822. skipComment();
  2823. tolerateError(Messages.StrictModeWith);
  2824. }
  2825. expectKeyword('with');
  2826. expect('(');
  2827. object = parseExpression();
  2828. expect(')');
  2829. body = parseStatement();
  2830. return node.finishWithStatement(object, body);
  2831. }
  2832. // 12.10 The swith statement
  2833. function parseSwitchCase() {
  2834. var test, consequent = [], statement, node = new Node();
  2835. if (matchKeyword('default')) {
  2836. lex();
  2837. test = null;
  2838. } else {
  2839. expectKeyword('case');
  2840. test = parseExpression();
  2841. }
  2842. expect(':');
  2843. while (index < length) {
  2844. if (match('}') || matchKeyword('default') || matchKeyword('case')) {
  2845. break;
  2846. }
  2847. statement = parseStatement();
  2848. consequent.push(statement);
  2849. }
  2850. return node.finishSwitchCase(test, consequent);
  2851. }
  2852. function parseSwitchStatement(node) {
  2853. var discriminant, cases, clause, oldInSwitch, defaultFound;
  2854. expectKeyword('switch');
  2855. expect('(');
  2856. discriminant = parseExpression();
  2857. expect(')');
  2858. expect('{');
  2859. cases = [];
  2860. if (match('}')) {
  2861. lex();
  2862. return node.finishSwitchStatement(discriminant, cases);
  2863. }
  2864. oldInSwitch = state.inSwitch;
  2865. state.inSwitch = true;
  2866. defaultFound = false;
  2867. while (index < length) {
  2868. if (match('}')) {
  2869. break;
  2870. }
  2871. clause = parseSwitchCase();
  2872. if (clause.test === null) {
  2873. if (defaultFound) {
  2874. throwError(Messages.MultipleDefaultsInSwitch);
  2875. }
  2876. defaultFound = true;
  2877. }
  2878. cases.push(clause);
  2879. }
  2880. state.inSwitch = oldInSwitch;
  2881. expect('}');
  2882. return node.finishSwitchStatement(discriminant, cases);
  2883. }
  2884. // 12.13 The throw statement
  2885. function parseThrowStatement(node) {
  2886. var argument;
  2887. expectKeyword('throw');
  2888. if (peekLineTerminator()) {
  2889. throwError(Messages.NewlineAfterThrow);
  2890. }
  2891. argument = parseExpression();
  2892. consumeSemicolon();
  2893. return node.finishThrowStatement(argument);
  2894. }
  2895. // 12.14 The try statement
  2896. function parseCatchClause() {
  2897. var param, body, node = new Node();
  2898. expectKeyword('catch');
  2899. expect('(');
  2900. if (match(')')) {
  2901. throwUnexpectedToken(lookahead);
  2902. }
  2903. param = parseVariableIdentifier();
  2904. // 12.14.1
  2905. if (strict && isRestrictedWord(param.name)) {
  2906. tolerateError(Messages.StrictCatchVariable);
  2907. }
  2908. expect(')');
  2909. body = parseBlock();
  2910. return node.finishCatchClause(param, body);
  2911. }
  2912. function parseTryStatement(node) {
  2913. var block, handlers = [], finalizer = null;
  2914. expectKeyword('try');
  2915. block = parseBlock();
  2916. if (matchKeyword('catch')) {
  2917. handlers.push(parseCatchClause());
  2918. }
  2919. if (matchKeyword('finally')) {
  2920. lex();
  2921. finalizer = parseBlock();
  2922. }
  2923. if (handlers.length === 0 && !finalizer) {
  2924. throwError(Messages.NoCatchOrFinally);
  2925. }
  2926. return node.finishTryStatement(block, [], handlers, finalizer);
  2927. }
  2928. // 12.15 The debugger statement
  2929. function parseDebuggerStatement(node) {
  2930. expectKeyword('debugger');
  2931. consumeSemicolon();
  2932. return node.finishDebuggerStatement();
  2933. }
  2934. // 12 Statements
  2935. function parseStatement() {
  2936. var type = lookahead.type,
  2937. expr,
  2938. labeledBody,
  2939. key,
  2940. node;
  2941. if (type === Token.EOF) {
  2942. throwUnexpectedToken(lookahead);
  2943. }
  2944. if (type === Token.Punctuator && lookahead.value === '{') {
  2945. return parseBlock();
  2946. }
  2947. node = new Node();
  2948. if (type === Token.Punctuator) {
  2949. switch (lookahead.value) {
  2950. case ';':
  2951. return parseEmptyStatement(node);
  2952. case '(':
  2953. return parseExpressionStatement(node);
  2954. default:
  2955. break;
  2956. }
  2957. } else if (type === Token.Keyword) {
  2958. switch (lookahead.value) {
  2959. case 'break':
  2960. return parseBreakStatement(node);
  2961. case 'continue':
  2962. return parseContinueStatement(node);
  2963. case 'debugger':
  2964. return parseDebuggerStatement(node);
  2965. case 'do':
  2966. return parseDoWhileStatement(node);
  2967. case 'for':
  2968. return parseForStatement(node);
  2969. case 'function':
  2970. return parseFunctionDeclaration(node);
  2971. case 'if':
  2972. return parseIfStatement(node);
  2973. case 'return':
  2974. return parseReturnStatement(node);
  2975. case 'switch':
  2976. return parseSwitchStatement(node);
  2977. case 'throw':
  2978. return parseThrowStatement(node);
  2979. case 'try':
  2980. return parseTryStatement(node);
  2981. case 'var':
  2982. return parseVariableStatement(node);
  2983. case 'while':
  2984. return parseWhileStatement(node);
  2985. case 'with':
  2986. return parseWithStatement(node);
  2987. default:
  2988. break;
  2989. }
  2990. }
  2991. expr = parseExpression();
  2992. // 12.12 Labelled Statements
  2993. if ((expr.type === Syntax.Identifier) && match(':')) {
  2994. lex();
  2995. key = '$' + expr.name;
  2996. if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
  2997. throwError(Messages.Redeclaration, 'Label', expr.name);
  2998. }
  2999. state.labelSet[key] = true;
  3000. labeledBody = parseStatement();
  3001. delete state.labelSet[key];
  3002. return node.finishLabeledStatement(expr, labeledBody);
  3003. }
  3004. consumeSemicolon();
  3005. return node.finishExpressionStatement(expr);
  3006. }
  3007. // 13 Function Definition
  3008. function parseFunctionSourceElements() {
  3009. var sourceElement, sourceElements = [], token, directive, firstRestricted,
  3010. oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesisCount,
  3011. node = new Node();
  3012. expect('{');
  3013. while (index < length) {
  3014. if (lookahead.type !== Token.StringLiteral) {
  3015. break;
  3016. }
  3017. token = lookahead;
  3018. sourceElement = parseSourceElement();
  3019. sourceElements.push(sourceElement);
  3020. if (sourceElement.expression.type !== Syntax.Literal) {
  3021. // this is not directive
  3022. break;
  3023. }
  3024. directive = source.slice(token.start + 1, token.end - 1);
  3025. if (directive === 'use strict') {
  3026. strict = true;
  3027. if (firstRestricted) {
  3028. tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
  3029. }
  3030. } else {
  3031. if (!firstRestricted && token.octal) {
  3032. firstRestricted = token;
  3033. }
  3034. }
  3035. }
  3036. oldLabelSet = state.labelSet;
  3037. oldInIteration = state.inIteration;
  3038. oldInSwitch = state.inSwitch;
  3039. oldInFunctionBody = state.inFunctionBody;
  3040. oldParenthesisCount = state.parenthesizedCount;
  3041. state.labelSet = {};
  3042. state.inIteration = false;
  3043. state.inSwitch = false;
  3044. state.inFunctionBody = true;
  3045. state.parenthesizedCount = 0;
  3046. while (index < length) {
  3047. if (match('}')) {
  3048. break;
  3049. }
  3050. sourceElement = parseSourceElement();
  3051. if (typeof sourceElement === 'undefined') {
  3052. break;
  3053. }
  3054. sourceElements.push(sourceElement);
  3055. }
  3056. expect('}');
  3057. state.labelSet = oldLabelSet;
  3058. state.inIteration = oldInIteration;
  3059. state.inSwitch = oldInSwitch;
  3060. state.inFunctionBody = oldInFunctionBody;
  3061. state.parenthesizedCount = oldParenthesisCount;
  3062. return node.finishBlockStatement(sourceElements);
  3063. }
  3064. function validateParam(options, param, name) {
  3065. var key = '$' + name;
  3066. if (strict) {
  3067. if (isRestrictedWord(name)) {
  3068. options.stricted = param;
  3069. options.message = Messages.StrictParamName;
  3070. }
  3071. if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
  3072. options.stricted = param;
  3073. options.message = Messages.StrictParamDupe;
  3074. }
  3075. } else if (!options.firstRestricted) {
  3076. if (isRestrictedWord(name)) {
  3077. options.firstRestricted = param;
  3078. options.message = Messages.StrictParamName;
  3079. } else if (isStrictModeReservedWord(name)) {
  3080. options.firstRestricted = param;
  3081. options.message = Messages.StrictReservedWord;
  3082. } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
  3083. options.firstRestricted = param;
  3084. options.message = Messages.StrictParamDupe;
  3085. }
  3086. }
  3087. options.paramSet[key] = true;
  3088. }
  3089. function parseParam(options) {
  3090. var token, param, def;
  3091. token = lookahead;
  3092. param = parseVariableIdentifier();
  3093. validateParam(options, token, token.value);
  3094. if (match('=')) {
  3095. lex();
  3096. def = parseAssignmentExpression();
  3097. ++options.defaultCount;
  3098. }
  3099. options.params.push(param);
  3100. options.defaults.push(def);
  3101. return !match(')');
  3102. }
  3103. function parseParams(firstRestricted) {
  3104. var options;
  3105. options = {
  3106. params: [],
  3107. defaultCount: 0,
  3108. defaults: [],
  3109. firstRestricted: firstRestricted
  3110. };
  3111. expect('(');
  3112. if (!match(')')) {
  3113. options.paramSet = {};
  3114. while (index < length) {
  3115. if (!parseParam(options)) {
  3116. break;
  3117. }
  3118. expect(',');
  3119. }
  3120. }
  3121. expect(')');
  3122. if (options.defaultCount === 0) {
  3123. options.defaults = [];
  3124. }
  3125. return {
  3126. params: options.params,
  3127. defaults: options.defaults,
  3128. stricted: options.stricted,
  3129. firstRestricted: options.firstRestricted,
  3130. message: options.message
  3131. };
  3132. }
  3133. function parseFunctionDeclaration() {
  3134. var id, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, node = new Node();
  3135. expectKeyword('function');
  3136. token = lookahead;
  3137. id = parseVariableIdentifier();
  3138. if (strict) {
  3139. if (isRestrictedWord(token.value)) {
  3140. tolerateUnexpectedToken(token, Messages.StrictFunctionName);
  3141. }
  3142. } else {
  3143. if (isRestrictedWord(token.value)) {
  3144. firstRestricted = token;
  3145. message = Messages.StrictFunctionName;
  3146. } else if (isStrictModeReservedWord(token.value)) {
  3147. firstRestricted = token;
  3148. message = Messages.StrictReservedWord;
  3149. }
  3150. }
  3151. tmp = parseParams(firstRestricted);
  3152. params = tmp.params;
  3153. defaults = tmp.defaults;
  3154. stricted = tmp.stricted;
  3155. firstRestricted = tmp.firstRestricted;
  3156. if (tmp.message) {
  3157. message = tmp.message;
  3158. }
  3159. previousStrict = strict;
  3160. body = parseFunctionSourceElements();
  3161. if (strict && firstRestricted) {
  3162. throwUnexpectedToken(firstRestricted, message);
  3163. }
  3164. if (strict && stricted) {
  3165. tolerateUnexpectedToken(stricted, message);
  3166. }
  3167. strict = previousStrict;
  3168. return node.finishFunctionDeclaration(id, params, defaults, body);
  3169. }
  3170. function parseFunctionExpression() {
  3171. var token, id = null, stricted, firstRestricted, message, tmp,
  3172. params = [], defaults = [], body, previousStrict, node = new Node();
  3173. expectKeyword('function');
  3174. if (!match('(')) {
  3175. token = lookahead;
  3176. id = parseVariableIdentifier();
  3177. if (strict) {
  3178. if (isRestrictedWord(token.value)) {
  3179. tolerateUnexpectedToken(token, Messages.StrictFunctionName);
  3180. }
  3181. } else {
  3182. if (isRestrictedWord(token.value)) {
  3183. firstRestricted = token;
  3184. message = Messages.StrictFunctionName;
  3185. } else if (isStrictModeReservedWord(token.value)) {
  3186. firstRestricted = token;
  3187. message = Messages.StrictReservedWord;
  3188. }
  3189. }
  3190. }
  3191. tmp = parseParams(firstRestricted);
  3192. params = tmp.params;
  3193. defaults = tmp.defaults;
  3194. stricted = tmp.stricted;
  3195. firstRestricted = tmp.firstRestricted;
  3196. if (tmp.message) {
  3197. message = tmp.message;
  3198. }
  3199. previousStrict = strict;
  3200. body = parseFunctionSourceElements();
  3201. if (strict && firstRestricted) {
  3202. throwUnexpectedToken(firstRestricted, message);
  3203. }
  3204. if (strict && stricted) {
  3205. tolerateUnexpectedToken(stricted, message);
  3206. }
  3207. strict = previousStrict;
  3208. return node.finishFunctionExpression(id, params, defaults, body);
  3209. }
  3210. // 14 Program
  3211. function parseSourceElement() {
  3212. if (lookahead.type === Token.Keyword) {
  3213. switch (lookahead.value) {
  3214. case 'const':
  3215. case 'let':
  3216. return parseConstLetDeclaration(lookahead.value);
  3217. case 'function':
  3218. return parseFunctionDeclaration();
  3219. default:
  3220. return parseStatement();
  3221. }
  3222. }
  3223. if (lookahead.type !== Token.EOF) {
  3224. return parseStatement();
  3225. }
  3226. }
  3227. function parseSourceElements() {
  3228. var sourceElement, sourceElements = [], token, directive, firstRestricted;
  3229. while (index < length) {
  3230. token = lookahead;
  3231. if (token.type !== Token.StringLiteral) {
  3232. break;
  3233. }
  3234. sourceElement = parseSourceElement();
  3235. sourceElements.push(sourceElement);
  3236. if (sourceElement.expression.type !== Syntax.Literal) {
  3237. // this is not directive
  3238. break;
  3239. }
  3240. directive = source.slice(token.start + 1, token.end - 1);
  3241. if (directive === 'use strict') {
  3242. strict = true;
  3243. if (firstRestricted) {
  3244. tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
  3245. }
  3246. } else {
  3247. if (!firstRestricted && token.octal) {
  3248. firstRestricted = token;
  3249. }
  3250. }
  3251. }
  3252. while (index < length) {
  3253. sourceElement = parseSourceElement();
  3254. /* istanbul ignore if */
  3255. if (typeof sourceElement === 'undefined') {
  3256. break;
  3257. }
  3258. sourceElements.push(sourceElement);
  3259. }
  3260. return sourceElements;
  3261. }
  3262. function parseProgram() {
  3263. var body, node;
  3264. skipComment();
  3265. peek();
  3266. node = new Node();
  3267. strict = false;
  3268. body = parseSourceElements();
  3269. return node.finishProgram(body);
  3270. }
  3271. function filterTokenLocation() {
  3272. var i, entry, token, tokens = [];
  3273. for (i = 0; i < extra.tokens.length; ++i) {
  3274. entry = extra.tokens[i];
  3275. token = {
  3276. type: entry.type,
  3277. value: entry.value
  3278. };
  3279. if (entry.regex) {
  3280. token.regex = {
  3281. pattern: entry.regex.pattern,
  3282. flags: entry.regex.flags
  3283. };
  3284. }
  3285. if (extra.range) {
  3286. token.range = entry.range;
  3287. }
  3288. if (extra.loc) {
  3289. token.loc = entry.loc;
  3290. }
  3291. tokens.push(token);
  3292. }
  3293. extra.tokens = tokens;
  3294. }
  3295. function tokenize(code, options) {
  3296. var toString,
  3297. tokens;
  3298. toString = String;
  3299. if (typeof code !== 'string' && !(code instanceof String)) {
  3300. code = toString(code);
  3301. }
  3302. source = code;
  3303. index = 0;
  3304. lineNumber = (source.length > 0) ? 1 : 0;
  3305. lineStart = 0;
  3306. length = source.length;
  3307. lookahead = null;
  3308. state = {
  3309. allowIn: true,
  3310. labelSet: {},
  3311. inFunctionBody: false,
  3312. inIteration: false,
  3313. inSwitch: false,
  3314. lastCommentStart: -1
  3315. };
  3316. extra = {};
  3317. // Options matching.
  3318. options = options || {};
  3319. // Of course we collect tokens here.
  3320. options.tokens = true;
  3321. extra.tokens = [];
  3322. extra.tokenize = true;
  3323. // The following two fields are necessary to compute the Regex tokens.
  3324. extra.openParenToken = -1;
  3325. extra.openCurlyToken = -1;
  3326. extra.range = (typeof options.range === 'boolean') && options.range;
  3327. extra.loc = (typeof options.loc === 'boolean') && options.loc;
  3328. if (typeof options.comment === 'boolean' && options.comment) {
  3329. extra.comments = [];
  3330. }
  3331. if (typeof options.tolerant === 'boolean' && options.tolerant) {
  3332. extra.errors = [];
  3333. }
  3334. try {
  3335. peek();
  3336. if (lookahead.type === Token.EOF) {
  3337. return extra.tokens;
  3338. }
  3339. lex();
  3340. while (lookahead.type !== Token.EOF) {
  3341. try {
  3342. lex();
  3343. } catch (lexError) {
  3344. if (extra.errors) {
  3345. extra.errors.push(lexError);
  3346. // We have to break on the first error
  3347. // to avoid infinite loops.
  3348. break;
  3349. } else {
  3350. throw lexError;
  3351. }
  3352. }
  3353. }
  3354. filterTokenLocation();
  3355. tokens = extra.tokens;
  3356. if (typeof extra.comments !== 'undefined') {
  3357. tokens.comments = extra.comments;
  3358. }
  3359. if (typeof extra.errors !== 'undefined') {
  3360. tokens.errors = extra.errors;
  3361. }
  3362. } catch (e) {
  3363. throw e;
  3364. } finally {
  3365. extra = {};
  3366. }
  3367. return tokens;
  3368. }
  3369. function parse(code, options) {
  3370. var program, toString;
  3371. toString = String;
  3372. if (typeof code !== 'string' && !(code instanceof String)) {
  3373. code = toString(code);
  3374. }
  3375. source = code;
  3376. index = 0;
  3377. lineNumber = (source.length > 0) ? 1 : 0;
  3378. lineStart = 0;
  3379. length = source.length;
  3380. lookahead = null;
  3381. state = {
  3382. allowIn: true,
  3383. labelSet: {},
  3384. parenthesisCount: 0,
  3385. inFunctionBody: false,
  3386. inIteration: false,
  3387. inSwitch: false,
  3388. lastCommentStart: -1
  3389. };
  3390. extra = {};
  3391. if (typeof options !== 'undefined') {
  3392. extra.range = (typeof options.range === 'boolean') && options.range;
  3393. extra.loc = (typeof options.loc === 'boolean') && options.loc;
  3394. extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;
  3395. if (extra.loc && options.source !== null && options.source !== undefined) {
  3396. extra.source = toString(options.source);
  3397. }
  3398. if (typeof options.tokens === 'boolean' && options.tokens) {
  3399. extra.tokens = [];
  3400. }
  3401. if (typeof options.comment === 'boolean' && options.comment) {
  3402. extra.comments = [];
  3403. }
  3404. if (typeof options.tolerant === 'boolean' && options.tolerant) {
  3405. extra.errors = [];
  3406. }
  3407. if (extra.attachComment) {
  3408. extra.range = true;
  3409. extra.comments = [];
  3410. extra.bottomRightStack = [];
  3411. extra.trailingComments = [];
  3412. extra.leadingComments = [];
  3413. }
  3414. }
  3415. try {
  3416. program = parseProgram();
  3417. if (typeof extra.comments !== 'undefined') {
  3418. program.comments = extra.comments;
  3419. }
  3420. if (typeof extra.tokens !== 'undefined') {
  3421. filterTokenLocation();
  3422. program.tokens = extra.tokens;
  3423. }
  3424. if (typeof extra.errors !== 'undefined') {
  3425. program.errors = extra.errors;
  3426. }
  3427. } catch (e) {
  3428. throw e;
  3429. } finally {
  3430. extra = {};
  3431. }
  3432. return program;
  3433. }
  3434. // Sync with *.json manifests.
  3435. exports.version = '2.0.0';
  3436. exports.tokenize = tokenize;
  3437. exports.parse = parse;
  3438. // Deep copy.
  3439. /* istanbul ignore next */
  3440. exports.Syntax = (function () {
  3441. var name, types = {};
  3442. if (typeof Object.create === 'function') {
  3443. types = Object.create(null);
  3444. }
  3445. for (name in Syntax) {
  3446. if (Syntax.hasOwnProperty(name)) {
  3447. types[name] = Syntax[name];
  3448. }
  3449. }
  3450. if (typeof Object.freeze === 'function') {
  3451. Object.freeze(types);
  3452. }
  3453. return types;
  3454. }());
  3455. }));
  3456. /* vim: set sw=4 ts=4 et tw=80 : */