2012-08-22 18:28:59 +00:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
A JavaScript tokenizer / parser / beautifier / compressor .
https : //github.com/mishoo/UglifyJS2
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ( C ) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
Author : Mihai Bazon
< mihai . bazon @ gmail . com >
http : //mihai.bazon.net/blog
Distributed under the BSD license :
2012-08-27 08:01:27 +00:00
Copyright 2012 ( c ) Mihai Bazon < mihai . bazon @ gmail . com >
2012-08-22 18:28:59 +00:00
Parser based on parse - js ( http : //marijn.haverbeke.nl/parse-js/).
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
* Redistributions of source code must retain the above
copyright notice , this list of conditions and the following
disclaimer .
* Redistributions in binary form must reproduce the above
copyright notice , this list of conditions and the following
disclaimer in the documentation and / or other materials
provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “ AS IS ” AND ANY
EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY ,
OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO ,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR
PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR
TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2012-10-02 09:45:31 +00:00
"use strict" ;
2017-09-28 10:43:09 +00:00
var KEYWORDS = 'break case catch class const continue debugger default delete do else export extends finally for function if in instanceof let new return switch throw try typeof var void while with' ;
2012-10-11 08:52:05 +00:00
var KEYWORDS _ATOM = 'false null true' ;
2017-09-28 10:43:09 +00:00
var RESERVED _WORDS = 'enum implements import interface package private protected public static super this ' + KEYWORDS _ATOM + " " + KEYWORDS ;
2017-06-14 22:15:48 +00:00
var KEYWORDS _BEFORE _EXPRESSION = 'return new delete throw else case yield await' ;
2012-05-27 11:09:01 +00:00
2012-10-11 08:52:05 +00:00
KEYWORDS = makePredicate ( KEYWORDS ) ;
RESERVED _WORDS = makePredicate ( RESERVED _WORDS ) ;
KEYWORDS _BEFORE _EXPRESSION = makePredicate ( KEYWORDS _BEFORE _EXPRESSION ) ;
KEYWORDS _ATOM = makePredicate ( KEYWORDS _ATOM ) ;
2012-05-27 11:09:01 +00:00
2012-10-11 08:52:05 +00:00
var OPERATOR _CHARS = makePredicate ( characters ( "+-*&%=<>!?|~^" ) ) ;
2012-05-27 11:09:01 +00:00
2016-06-22 15:12:23 +00:00
var RE _NUM _LITERAL = /[0-9a-f]/i ;
2012-05-27 11:09:01 +00:00
var RE _HEX _NUMBER = /^0x[0-9a-f]+$/i ;
var RE _OCT _NUMBER = /^0[0-7]+$/ ;
2015-08-17 10:50:56 +00:00
var RE _ES6 _OCT _NUMBER = /^0o[0-7]+$/i ;
var RE _BIN _NUMBER = /^0b[01]+$/i ;
2012-05-27 11:09:01 +00:00
var RE _DEC _NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i ;
2012-10-11 08:52:05 +00:00
var OPERATORS = makePredicate ( [
2012-05-27 11:09:01 +00:00
"in" ,
"instanceof" ,
"typeof" ,
"new" ,
"void" ,
"delete" ,
"++" ,
"--" ,
"+" ,
"-" ,
"!" ,
"~" ,
"&" ,
"|" ,
"^" ,
"*" ,
2016-06-17 22:25:18 +00:00
"**" ,
2012-05-27 11:09:01 +00:00
"/" ,
"%" ,
">>" ,
"<<" ,
">>>" ,
"<" ,
">" ,
"<=" ,
">=" ,
"==" ,
"===" ,
"!=" ,
"!==" ,
"?" ,
"=" ,
"+=" ,
"-=" ,
"/=" ,
"*=" ,
2016-06-17 22:25:18 +00:00
"**=" ,
2012-05-27 11:09:01 +00:00
"%=" ,
">>=" ,
"<<=" ,
">>>=" ,
"|=" ,
"^=" ,
"&=" ,
"&&" ,
"||"
] ) ;
2016-06-13 10:36:47 +00:00
var WHITESPACE _CHARS = makePredicate ( characters ( " \u00a0\n\r\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\uFEFF" ) ) ;
var NEWLINE _CHARS = makePredicate ( characters ( "\n\r\u2028\u2029" ) ) ;
2012-05-27 11:09:01 +00:00
2016-05-26 15:00:37 +00:00
var PUNC _AFTER _EXPRESSION = makePredicate ( characters ( ";]),:" ) ) ;
2017-04-18 20:27:13 +00:00
var PUNC _BEFORE _EXPRESSION = makePredicate ( characters ( "[{(,;:" ) ) ;
2012-05-27 11:09:01 +00:00
2016-06-22 17:24:03 +00:00
var PUNC _CHARS = makePredicate ( characters ( "[]{}(),;:" ) ) ;
2012-05-27 11:09:01 +00:00
/* -----[ Tokenizer ]----- */
2016-06-22 15:12:23 +00:00
// surrogate safe regexps adapted from https://github.com/mathiasbynens/unicode-8.0.0/tree/89b412d8a71ecca9ed593d9e9fa073ab64acfebe/Binary_Property
2012-05-27 11:09:01 +00:00
var UNICODE = {
2016-06-22 15:12:23 +00:00
ID _Start : / [ A - Z a - z \ x A A \ x B 5 \ x B A \ x C 0 - \ x D 6 \ x D 8 - \ x F 6 \ x F 8 - \ u 0 2 C 1 \ u 0 2 C 6 - \ u 0 2 D 1 \ u 0 2 E 0 - \ u 0 2 E 4 \ u 0 2 E C \ u 0 2 E E \ u 0 3 7 0 - \ u 0 3 7 4 \ u 0 3 7 6 \ u 0 3 7 7 \ u 0 3 7 A - \ u 0 3 7 D \ u 0 3 7 F \ u 0 3 8 6 \ u 0 3 8 8 - \ u 0 3 8 A \ u 0 3 8 C \ u 0 3 8 E - \ u 0 3 A 1 \ u 0 3 A 3 - \ u 0 3 F 5 \ u 0 3 F 7 - \ u 0 4 8 1 \ u 0 4 8 A - \ u 0 5 2 F \ u 0 5 3 1 - \ u 0 5 5 6 \ u 0 5 5 9 \ u 0 5 6 1 - \ u 0 5 8 7 \ u 0 5 D 0 - \ u 0 5 E A \ u 0 5 F 0 - \ u 0 5 F 2 \ u 0 6 2 0 - \ u 0 6 4 A \ u 0 6 6 E \ u 0 6 6 F \ u 0 6 7 1 - \ u 0 6 D 3 \ u 0 6 D 5 \ u 0 6 E 5 \ u 0 6 E 6 \ u 0 6 E E \ u 0 6 E F \ u 0 6 F A - \ u 0 6 F C \ u 0 6 F F \ u 0 7 1 0 \ u 0 7 1 2 - \ u 0 7 2 F \ u 0 7 4 D - \ u 0 7 A 5 \ u 0 7 B 1 \ u 0 7 C A - \ u 0 7 E A \ u 0 7 F 4 \ u 0 7 F 5 \ u 0 7 F A \ u 0 8 0 0 - \ u 0 8 1 5 \ u 0 8 1 A \ u 0 8 2 4 \ u 0 8 2 8 \ u 0 8 4 0 - \ u 0 8 5 8 \ u 0 8 A 0 - \ u 0 8 B 4 \ u 0 9 0 4 - \ u 0 9 3 9 \ u 0 9 3 D \ u 0 9 5 0 \ u 0 9 5 8 - \ u 0 9 6 1 \ u 0 9 7 1 - \ u 0 9 8 0 \ u 0 9 8 5 - \ u 0 9 8 C \ u 0 9 8 F \ u 0 9 9 0 \ u 0 9 9 3 - \ u 0 9 A 8 \ u 0 9 A A - \ u 0 9 B 0 \ u 0 9 B 2 \ u 0 9 B 6 - \ u 0 9 B 9 \ u 0 9 B D \ u 0 9 C E \ u 0 9 D C \ u 0 9 D D \ u 0 9 D F - \ u 0 9 E 1 \ u 0 9 F 0 \ u 0 9 F 1 \ u 0 A 0 5 - \ u 0 A 0 A \ u 0 A 0 F \ u 0 A 1 0 \ u 0 A 1 3 - \ u 0 A 2 8 \ u 0 A 2 A - \ u 0 A 3 0 \ u 0 A 3 2 \ u 0 A 3 3 \ u 0 A 3 5 \ u 0 A 3 6 \ u 0 A 3 8 \ u 0 A 3 9 \ u 0 A 5 9 - \ u 0 A 5 C \ u 0 A 5 E \ u 0 A 7 2 - \ u 0 A 7 4 \ u 0 A 8 5 - \ u 0 A 8 D \ u 0 A 8 F - \ u 0 A 9 1 \ u 0 A 9 3 - \ u 0 A A 8 \ u 0 A A A - \ u 0 A B 0 \ u 0 A B 2 \ u 0 A B 3 \ u 0 A B 5 - \ u 0 A B 9 \ u 0 A B D \ u 0 A D 0 \ u 0 A E 0 \ u 0 A E 1 \ u 0 A F 9 \ u 0 B 0 5 - \ u 0 B 0 C \ u 0 B 0 F \ u 0 B 1 0 \ u 0 B 1 3 - \ u 0 B 2 8 \ u 0 B 2 A - \ u 0 B 3 0 \ u 0 B 3 2 \ u 0 B 3 3 \ u 0 B 3 5 - \ u 0 B 3 9 \ u 0 B 3 D \ u 0 B 5 C \ u 0 B 5 D \ u 0 B 5 F - \ u 0 B 6 1 \ u 0 B 7 1 \ u 0 B 8 3 \ u 0 B 8 5 - \ u 0 B 8 A \ u 0 B 8 E - \ u 0 B 9 0 \ u 0 B 9 2 - \ u 0 B 9 5 \ u 0 B 9 9 \ u 0 B 9 A \ u 0 B 9 C \ u 0 B 9 E \ u 0 B 9 F \ u 0 B A 3 \ u 0 B A 4 \ u 0 B A 8 - \ u 0 B A A \ u 0 B A E - \ u 0 B B 9 \ u 0 B D 0 \ u 0 C 0 5 - \ u 0 C 0 C \ u 0 C 0 E - \ u 0 C 1 0 \ u 0 C 1 2 - \ u 0 C 2 8 \ u 0 C 2 A - \ u 0 C 3 9 \ u 0 C 3 D \ u 0 C 5 8 - \ u 0 C 5 A \ u 0 C 6 0 \ u 0 C 6 1 \ u 0 C 8 5 - \ u 0 C 8 C \ u 0 C 8 E - \ u 0 C 9 0 \ u 0 C 9 2 - \ u 0 C A 8 \ u 0 C A A - \ u 0 C B 3 \ u 0 C B 5 - \ u 0 C B 9 \ u 0 C B D \ u 0 C D E \ u 0 C E 0 \ u 0 C E 1 \ u 0 C F 1 \ u 0 C F 2 \ u 0 D 0 5 - \ u 0 D 0 C \ u 0 D 0 E - \ u 0 D 1 0 \ u 0 D 1 2 - \ u 0 D 3 A \ u 0 D 3 D \ u 0 D 4 E \ u 0 D 5 F - \ u 0 D 6 1 \ u 0 D 7 A - \ u 0 D 7 F \ u 0 D 8 5 - \ u 0 D 9 6 \ u 0 D 9 A - \ u 0 D B 1 \ u 0 D B 3 - \ u 0 D B B \ u 0 D B D \ u 0 D C 0 - \ u 0 D C 6 \ u 0 E 0 1 - \ u 0 E 3 0 \ u 0 E 3 2 \ u 0 E 3 3 \ u 0 E 4 0 - \ u 0 E 4 6 \ u 0 E 8 1 \ u 0 E 8 2 \ u 0 E 8 4 \ u 0 E 8 7 \ u 0 E 8 8 \ u 0 E 8 A \ u 0 E 8 D \ u 0 E 9 4 - \ u 0 E 9 7 \ u 0 E 9 9 - \ u 0 E 9 F \ u 0 E A 1 - \ u 0 E A 3 \ u 0 E A 5 \ u 0 E A 7 \ u 0 E A A \ u 0 E A B \ u 0 E A D - \ u 0 E B 0 \ u 0 E B 2 \ u 0 E B 3 \ u 0 E B D \ u 0 E C 0 - \ u 0 E C 4 \ u 0 E C 6 \ u 0 E D C - \ u 0 E D F \ u 0 F 0 0 \ u 0 F 4 0 - \ u 0 F 4 7 \ u 0 F 4 9 - \ u 0 F 6 C \ u 0 F 8 8 - \ u 0 F 8 C \ u 1 0 0 0 - \ u 1 0 2 A \ u 1 0 3 F \ u 1 0 5 0 - \ u 1 0 5 5 \ u 1 0 5 A - \ u 1 0 5 D \ u 1 0 6 1 \ u 1 0 6 5 \ u 1 0 6 6 \ u 1 0 6 E - \ u 1 0 7 0 \ u 1 0 7 5 - \ u 1 0 8 1 \ u 1 0 8 E \ u 1 0 A 0 - \ u 1 0 C 5 \ u 1 0 C 7 \ u 1 0 C D \ u 1 0 D 0 - \ u 1 0 F A \ u 1 0 F C - \ u 1 2 4 8 \ u 1 2 4 A - \ u 1 2 4 D \ u 1 2 5 0 - \ u 1 2 5 6 \ u 1 2 5 8 \ u 1 2 5 A - \ u 1 2 5 D \ u 1 2 6 0 - \ u 1 2 8 8 \ u 1 2 8 A - \ u 1 2 8 D \ u 1 2 9 0 - \ u 1 2 B 0 \ u 1 2 B 2 - \ u 1 2 B 5 \ u 1 2 B 8 - \ u 1 2 B E \ u 1 2 C 0 \ u 1 2 C 2 - \ u 1 2 C 5 \ u 1 2 C 8 - \ u 1 2 D 6 \ u 1 2 D 8 - \ u 1 3 1 0 \ u 1 3 1 2 - \ u 1 3 1 5 \ u 1 3 1 8 - \ u 1 3 5 A \ u 1 3 8 0 - \ u 1 3 8 F \ u 1 3 A 0 - \ u 1 3 F 5 \ u 1 3 F 8 - \ u 1 3 F D \ u 1 4 0 1 - \ u 1 6 6 C \ u 1 6 6 F - \ u 1 6 7 F \ u 1 6 8 1 - \ u 1 6 9 A \ u 1 6 A 0 - \ u 1 6 E A \ u 1 6 E E - \ u 1 6 F 8 \ u 1 7 0 0 - \ u 1 7 0 C \ u 1 7 0 E - \ u 1 7 1 1 \ u 1 7 2 0 - \ u 1 7 3 1 \ u 1 7 4 0 - \ u 1 7 5 1 \ u 1 7 6 0 - \ u 1 7 6 C \ u 1 7 6 E - \ u 1 7 7 0 \ u 1 7 8 0 - \ u 1 7 B 3 \ u 1 7 D 7 \ u 1 7 D C \ u 1 8 2 0 - \ u 1 8 7 7 \ u 1 8 8 0 - \ u 1 8 A 8 \ u 1 8 A A \ u 1 8 B 0 - \ u 1 8 F 5 \ u 1 9 0 0 - \ u 1 9 1 E \ u 1 9 5 0 - \ u 1 9 6 D \ u 1 9 7 0 - \ u 1 9 7 4 \ u 1 9 8 0 - \ u 1 9 A B \ u 1 9 B 0 - \ u 1 9 C 9 \ u 1 A 0 0 - \ u 1 A 1 6 \ u 1 A 2 0 - \ u 1 A 5 4 \ u 1 A A 7 \ u 1 B 0 5 - \ u 1 B 3 3 \ u 1 B 4 5 - \ u 1 B 4 B \ u 1 B 8 3 - \ u 1 B A 0 \ u 1 B A E \ u 1 B A F \ u 1 B B A - \ u 1 B E 5 \ u 1 C 0 0 - \ u 1 C 2 3 \ u 1 C 4 D - \ u 1 C 4 F \ u 1 C 5 A - \ u 1 C 7 D \ u 1 C E 9 - \ u 1 C E C \ u 1 C E E - \ u 1 C F 1 \ u 1 C F 5 \ u 1 C F 6 \ u 1 D 0 0 - \ u 1 D B F \ u 1 E 0 0 - \ u 1 F 1 5 \ u 1 F 1 8 - \ u 1 F 1 D \ u 1 F 2 0 - \ u 1 F 4 5 \ u 1 F 4 8 - \ u 1 F 4 D \ u 1 F 5 0 - \ u 1 F 5 7 \ u 1 F 5 9 \ u 1 F 5 B \ u 1 F 5 D \ u 1 F 5 F - \ u 1 F 7 D \ u 1 F 8 0 - \ u 1 F B 4 \ u 1 F B 6 - \ u 1 F B C \ u 1 F B E \ u 1 F C 2 - \ u 1 F C 4 \ u 1 F C 6 - \ u 1 F C C \ u 1 F D 0 - \ u 1 F D 3 \ u 1 F D 6 - \ u 1 F D B \ u 1 F E 0 - \ u 1 F E C \ u 1 F F 2 - \ u 1 F F 4 \ u 1 F F 6 - \ u 1 F F C \ u 2 0 7 1 \ u 2 0 7 F \ u 2 0 9 0 - \ u 2 0 9 C \ u 2 1 0 2 \ u 2 1 0 7 \ u 2 1 0 A - \ u 2 1 1 3 \ u 2 1 1 5 \ u 2 1 1 8 - \ u 2 1 1 D \ u 2 1 2 4 \ u 2 1 2 6 \ u 2 1 2 8 \ u 2 1 2 A - \ u 2 1 3 9 \ u 2 1 3 C - \ u 2 1 3 F \ u 2 1 4 5 - \ u 2 1 4 9 \ u 2 1 4 E \ u 2 1 6 0 - \ u 2 1 8 8 \ u 2 C 0 0 - \ u 2 C 2 E \ u 2 C 3 0 - \ u 2 C 5 E \ u 2 C 6 0 - \ u 2 C E 4 \ u 2 C E B - \ u 2 C E E \ u 2 C F 2 \ u 2 C F 3 \ u 2 D 0 0 - \ u 2 D 2 5 \ u 2 D 2 7 \ u 2 D 2 D \ u 2 D 3 0 - \ u 2 D 6 7 \ u 2 D 6 F \ u 2 D 8 0 - \ u 2 D 9 6 \ u 2 D A 0 - \ u 2 D A 6 \ u 2 D A 8 - \ u 2 D A E \ u 2 D B 0 - \ u 2 D B 6 \ u 2 D B 8 - \ u 2 D B E \ u 2 D C 0 - \ u 2 D C 6 \ u 2 D C 8 - \ u 2 D C E \ u 2 D D 0 - \ u 2 D D 6 \ u 2 D D 8 - \ u 2 D D E \ u 3 0 0 5 - \ u 3 0 0 7 \ u 3 0 2 1 - \ u 3 0 2 9 \ u 3 0 3 1 - \ u 3 0 3 5 \ u 3 0 3 8 - \ u 3 0 3 C \ u 3 0 4 1 - \ u 3 0 9 6 \ u 3 0 9 B - \ u 3 0 9 F \ u 3 0 A 1 - \ u 3 0 F A \ u 3 0 F C - \ u 3 0 F F \ u 3 1 0 5 - \ u 3 1 2 D \ u 3 1 3 1 - \ u 3 1 8 E \ u 3 1 A 0 - \ u 3 1 B A \ u 3 1 F 0 - \ u 3 1 F F \ u 3 4 0 0 - \ u 4 D B 5 \ u 4 E 0 0 - \ u 9 F D 5 \ u A 0 0 0 - \ u A 4 8 C \ u A 4 D 0 - \ u A 4 F D \ u A 5 0 0 - \ u A 6 0 C \ u A 6 1 0 - \ u A 6 1 F \ u A 6 2 A \ u A 6 2 B \ u A 6 4 0 - \ u A 6 6 E \ u A 6 7 F - \ u A 6 9 D \ u A 6 A 0 - \ u A 6 E F \ u A 7 1 7 - \ u A 7 1 F \ u A 7 2 2 - \ u A 7 8 8 \ u A 7 8 B - \ u A 7 A D \ u A 7 B 0 - \ u A 7 B 7 \ u A 7 F 7 - \ u A 8 0 1 \ u A 8 0 3 - \ u A 8 0 5 \ u A 8 0 7 - \ u A 8 0 A \ u A 8 0 C - \ u A 8 2 2 \ u A 8 4 0 - \ u A 8 7 3 \ u A 8 8 2 - \ u A 8 B 3 \ u A 8 F 2 - \ u A 8 F 7 \ u A 8 F B \ u A 8 F D \ u A 9 0 A - \ u A 9 2 5 \ u A 9 3 0 - \ u A 9 4 6 \ u A 9 6 0 - \ u A 9 7 C \ u A 9 8 4 - \ u A 9 B 2 \ u A 9 C F \ u A 9 E 0 - \ u A 9 E 4 \ u A 9 E 6 - \ u A 9 E F \ u A 9 F A - \ u A 9 F E \ u A A 0 0 - \ u A A 2 8 \ u A A 4 0 - \ u A A 4 2 \ u A A 4 4 - \ u A A 4 B \ u A A 6 0 - \ u A A 7 6 \ u A A 7 A \ u A A 7 E - \ u A A A F \ u A A B 1 \ u A A B 5 \ u A A B 6 \ u A A B 9 - \ u A A B D \ u A A C 0 \ u A A C 2 \ u A A D B - \ u A A D D \ u A A E 0 - \ u A A E A \ u A A F 2 - \ u A A F 4 \ u A B 0 1 - \ u A B 0 6 \ u A B 0 9 - \ u A B 0 E \ u A B 1 1 - \ u A B 1 6 \ u A B 2 0 - \ u A B 2 6 \ u A B 2 8 - \ u A B 2 E \ u A B 3 0 - \ u A B 5 A \ u A B 5 C - \ u A B 6 5 \ u A B 7 0 - \ u A B E 2 \ u A C 0 0 - \ u D 7 A 3 \ u D 7 B 0 - \ u D 7 C 6 \ u D 7 C B - \ u D 7 F B \ u F 9 0 0 - \ u F A 6 D \ u F A 7 0 - \ u F A D 9 \ u F B 0 0 - \ u F B 0 6 \ u F B 1 3 - \ u F B 1 7 \ u F B 1 D \ u F B 1 F - \ u F B 2 8 \ u F B 2 A - \ u F B 3 6 \ u F B 3 8 - \ u F B 3 C \ u F B 3 E \ u F B 4 0 \ u F B 4 1 \ u F B 4 3 \ u F B 4 4 \ u F B 4 6 - \ u F B B 1 \ u F B D 3 - \ u F D 3
ID _Continue : / [ 0 - 9 A - Z _ a - z \ x A A \ x B 5 \ x B 7 \ x B A \ x C 0 - \ x D 6 \ x D 8 - \ x F 6 \ x F 8 - \ u 0 2 C 1 \ u 0 2 C 6 - \ u 0 2 D 1 \ u 0 2 E 0 - \ u 0 2 E 4 \ u 0 2 E C \ u 0 2 E E \ u 0 3 0 0 - \ u 0 3 7 4 \ u 0 3 7 6 \ u 0 3 7 7 \ u 0 3 7 A - \ u 0 3 7 D \ u 0 3 7 F \ u 0 3 8 6 - \ u 0 3 8 A \ u 0 3 8 C \ u 0 3 8 E - \ u 0 3 A 1 \ u 0 3 A 3 - \ u 0 3 F 5 \ u 0 3 F 7 - \ u 0 4 8 1 \ u 0 4 8 3 - \ u 0 4 8 7 \ u 0 4 8 A - \ u 0 5 2 F \ u 0 5 3 1 - \ u 0 5 5 6 \ u 0 5 5 9 \ u 0 5 6 1 - \ u 0 5 8 7 \ u 0 5 9 1 - \ u 0 5 B D \ u 0 5 B F \ u 0 5 C 1 \ u 0 5 C 2 \ u 0 5 C 4 \ u 0 5 C 5 \ u 0 5 C 7 \ u 0 5 D 0 - \ u 0 5 E A \ u 0 5 F 0 - \ u 0 5 F 2 \ u 0 6 1 0 - \ u 0 6 1 A \ u 0 6 2 0 - \ u 0 6 6 9 \ u 0 6 6 E - \ u 0 6 D 3 \ u 0 6 D 5 - \ u 0 6 D C \ u 0 6 D F - \ u 0 6 E 8 \ u 0 6 E A - \ u 0 6 F C \ u 0 6 F F \ u 0 7 1 0 - \ u 0 7 4 A \ u 0 7 4 D - \ u 0 7 B 1 \ u 0 7 C 0 - \ u 0 7 F 5 \ u 0 7 F A \ u 0 8 0 0 - \ u 0 8 2 D \ u 0 8 4 0 - \ u 0 8 5 B \ u 0 8 A 0 - \ u 0 8 B 4 \ u 0 8 E 3 - \ u 0 9 6 3 \ u 0 9 6 6 - \ u 0 9 6 F \ u 0 9 7 1 - \ u 0 9 8 3 \ u 0 9 8 5 - \ u 0 9 8 C \ u 0 9 8 F \ u 0 9 9 0 \ u 0 9 9 3 - \ u 0 9 A 8 \ u 0 9 A A - \ u 0 9 B 0 \ u 0 9 B 2 \ u 0 9 B 6 - \ u 0 9 B 9 \ u 0 9 B C - \ u 0 9 C 4 \ u 0 9 C 7 \ u 0 9 C 8 \ u 0 9 C B - \ u 0 9 C E \ u 0 9 D 7 \ u 0 9 D C \ u 0 9 D D \ u 0 9 D F - \ u 0 9 E 3 \ u 0 9 E 6 - \ u 0 9 F 1 \ u 0 A 0 1 - \ u 0 A 0 3 \ u 0 A 0 5 - \ u 0 A 0 A \ u 0 A 0 F \ u 0 A 1 0 \ u 0 A 1 3 - \ u 0 A 2 8 \ u 0 A 2 A - \ u 0 A 3 0 \ u 0 A 3 2 \ u 0 A 3 3 \ u 0 A 3 5 \ u 0 A 3 6 \ u 0 A 3 8 \ u 0 A 3 9 \ u 0 A 3 C \ u 0 A 3 E - \ u 0 A 4 2 \ u 0 A 4 7 \ u 0 A 4 8 \ u 0 A 4 B - \ u 0 A 4 D \ u 0 A 5 1 \ u 0 A 5 9 - \ u 0 A 5 C \ u 0 A 5 E \ u 0 A 6 6 - \ u 0 A 7 5 \ u 0 A 8 1 - \ u 0 A 8 3 \ u 0 A 8 5 - \ u 0 A 8 D \ u 0 A 8 F - \ u 0 A 9 1 \ u 0 A 9 3 - \ u 0 A A 8 \ u 0 A A A - \ u 0 A B 0 \ u 0 A B 2 \ u 0 A B 3 \ u 0 A B 5 - \ u 0 A B 9 \ u 0 A B C - \ u 0 A C 5 \ u 0 A C 7 - \ u 0 A C 9 \ u 0 A C B - \ u 0 A C D \ u 0 A D 0 \ u 0 A E 0 - \ u 0 A E 3 \ u 0 A E 6 - \ u 0 A E F \ u 0 A F 9 \ u 0 B 0 1 - \ u 0 B 0 3 \ u 0 B 0 5 - \ u 0 B 0 C \ u 0 B 0 F \ u 0 B 1 0 \ u 0 B 1 3 - \ u 0 B 2 8 \ u 0 B 2 A - \ u 0 B 3 0 \ u 0 B 3 2 \ u 0 B 3 3 \ u 0 B 3 5 - \ u 0 B 3 9 \ u 0 B 3 C - \ u 0 B 4 4 \ u 0 B 4 7 \ u 0 B 4 8 \ u 0 B 4 B - \ u 0 B 4 D \ u 0 B 5 6 \ u 0 B 5 7 \ u 0 B 5 C \ u 0 B 5 D \ u 0 B 5 F - \ u 0 B 6 3 \ u 0 B 6 6 - \ u 0 B 6 F \ u 0 B 7 1 \ u 0 B 8 2 \ u 0 B 8 3 \ u 0 B 8 5 - \ u 0 B 8 A \ u 0 B 8 E - \ u 0 B 9 0 \ u 0 B 9 2 - \ u 0 B 9 5 \ u 0 B 9 9 \ u 0 B 9 A \ u 0 B 9 C \ u 0 B 9 E \ u 0 B 9 F \ u 0 B A 3 \ u 0 B A 4 \ u 0 B A 8 - \ u 0 B A A \ u 0 B A E - \ u 0 B B 9 \ u 0 B B E - \ u 0 B C 2 \ u 0 B C 6 - \ u 0 B C 8 \ u 0 B C A - \ u 0 B C D \ u 0 B D 0 \ u 0 B D 7 \ u 0 B E 6 - \ u 0 B E F \ u 0 C 0 0 - \ u 0 C 0 3 \ u 0 C 0 5 - \ u 0 C 0 C \ u 0 C 0 E - \ u 0 C 1 0 \ u 0 C 1 2 - \ u 0 C 2 8 \ u 0 C 2 A - \ u 0 C 3 9 \ u 0 C 3 D - \ u 0 C 4 4 \ u 0 C 4 6 - \ u 0 C 4 8 \ u 0 C 4 A - \ u 0 C 4 D \ u 0 C 5 5 \ u 0 C 5 6 \ u 0 C 5 8 - \ u 0 C 5 A \ u 0 C 6 0 - \ u 0 C 6 3 \ u 0 C 6 6 - \ u 0 C 6 F \ u 0 C 8 1 - \ u 0 C 8 3 \ u 0 C 8 5 - \ u 0 C 8 C \ u 0 C 8 E - \ u 0 C 9 0 \ u 0 C 9 2 - \ u 0 C A 8 \ u 0 C A A - \ u 0 C B 3 \ u 0 C B 5 - \ u 0 C B 9 \ u 0 C B C - \ u 0 C C 4 \ u 0 C C 6 - \ u 0 C C 8 \ u 0 C C A - \ u 0 C C D \ u 0 C D 5 \ u 0 C D 6 \ u 0 C D E \ u 0 C E 0 - \ u 0 C E 3 \ u 0 C E 6 - \ u 0 C E F \ u 0 C F 1 \ u 0 C F 2 \ u 0 D 0 1 - \ u 0 D 0 3 \ u 0 D 0 5 - \ u 0 D 0 C \ u 0 D 0 E - \ u 0 D 1 0 \ u 0 D 1 2 - \ u 0 D 3 A \ u 0 D 3 D - \ u 0 D 4 4 \ u 0 D 4 6 - \ u 0 D 4 8 \ u 0 D 4 A - \ u 0 D 4 E \ u 0 D 5 7 \ u 0 D 5 F - \ u 0 D 6 3 \ u 0 D 6 6 - \ u 0 D 6 F \ u 0 D 7 A - \ u 0 D 7 F \ u 0 D 8 2 \ u 0 D 8 3 \ u 0 D 8 5 - \ u 0 D 9 6 \ u 0 D 9 A - \ u 0 D B 1 \ u 0 D B 3 - \ u 0 D B B \ u 0 D B D \ u 0 D C 0 - \ u 0 D C 6 \ u 0 D C A \ u 0 D C F - \ u 0 D D 4 \ u 0 D D 6 \ u 0 D D 8 - \ u 0 D D F \ u 0 D E 6 - \ u 0 D E F \ u 0 D F 2 \ u 0 D F 3 \ u 0 E 0 1 - \ u 0 E 3 A \ u 0 E 4 0 - \ u 0 E 4 E \ u 0 E 5 0 - \ u 0 E 5 9 \ u 0 E 8 1 \ u 0 E 8 2 \ u 0 E 8 4 \ u 0 E 8 7 \ u 0 E 8 8 \ u 0 E 8 A \ u 0 E 8 D \ u 0 E 9 4 - \ u 0 E 9 7 \ u 0 E 9 9 - \ u 0 E 9 F \ u 0 E A 1 - \ u 0 E A 3 \ u 0 E A 5 \ u 0 E A 7 \ u 0 E A A \ u 0 E A B \ u 0 E A D - \ u 0 E B 9 \ u 0 E B B - \ u 0 E B D \ u 0 E C 0 - \ u 0 E C 4 \ u 0 E C 6 \ u 0 E C 8 - \ u 0 E C D \ u 0 E D 0 - \ u 0 E D 9 \ u 0 E D C - \ u 0 E D F \ u 0 F 0 0 \ u 0 F 1 8 \ u 0 F 1 9 \ u 0 F 2 0 - \ u 0 F 2 9 \ u 0 F 3 5 \ u 0 F 3 7 \ u 0 F 3 9 \ u 0 F 3 E - \ u 0 F 4 7 \ u 0 F 4 9 - \ u 0 F 6 C \ u 0 F 7 1 - \ u 0 F 8 4 \ u 0 F 8 6 - \ u 0 F 9 7 \ u 0 F 9 9 - \ u 0 F B C \ u 0 F C 6 \ u 1 0 0 0 - \ u 1 0 4 9 \ u 1 0 5 0 - \ u 1 0 9 D \ u 1 0 A 0 - \ u 1 0 C 5 \ u 1 0 C 7 \ u 1 0 C D \ u 1 0 D 0 - \ u 1 0 F A \ u 1 0 F C - \ u 1 2 4 8 \ u 1 2 4 A - \ u 1 2 4 D \ u 1 2 5 0 - \ u 1 2 5 6 \ u 1 2 5 8 \ u 1 2 5 A - \ u 1 2 5 D \ u 1 2 6 0 - \ u 1 2 8 8 \ u 1 2 8 A - \ u 1 2 8 D \ u 1 2 9 0 - \ u 1 2 B 0 \ u 1 2 B 2 - \ u 1 2 B 5 \ u 1 2 B 8 - \ u 1 2 B E \ u 1 2 C 0 \ u 1 2 C 2 - \ u 1 2 C 5 \ u 1 2 C 8 - \ u 1 2 D 6 \ u 1 2 D 8 - \ u 1 3 1 0 \ u 1 3 1 2 - \ u 1 3 1 5 \ u 1 3 1 8 - \ u 1 3 5 A \ u 1 3 5 D - \ u 1 3 5 F \ u 1 3 6 9 - \ u 1 3 7 1 \ u 1 3 8 0 - \ u 1 3 8 F \ u 1 3 A 0 - \ u 1 3 F 5 \ u 1 3 F 8 - \ u 1 3 F D \ u 1 4 0 1 - \ u 1 6 6 C \ u 1 6 6 F - \ u 1 6 7 F \ u 1 6 8 1 - \ u 1 6 9 A \ u 1 6 A 0 - \ u 1 6 E A \ u 1 6 E E - \ u 1 6 F 8 \ u 1 7 0 0 - \ u 1 7 0 C \ u 1 7 0 E - \ u 1 7 1 4 \ u 1 7 2 0 - \ u 1 7 3 4 \ u 1 7 4 0 - \ u 1 7 5 3 \ u 1 7 6 0 - \ u 1 7 6 C \ u 1 7 6 E - \ u 1 7 7 0 \ u 1 7 7 2 \ u 1 7 7 3 \ u 1 7 8 0 - \ u 1 7 D 3 \ u 1 7 D 7 \ u 1 7 D C \ u 1 7 D D \ u 1 7 E 0 - \ u 1 7 E 9 \ u 1 8 0 B - \ u 1 8 0 D \ u 1 8 1 0 - \ u 1 8 1 9 \ u 1 8 2 0 - \ u 1 8 7 7 \ u 1 8 8 0 - \ u 1 8 A A \ u 1 8 B 0 - \ u 1 8 F 5 \ u 1 9 0 0 - \ u 1 9 1 E \ u 1 9 2 0 - \ u 1 9 2 B \ u 1 9 3 0 - \ u 1 9 3 B \ u 1 9 4 6 - \ u 1 9 6 D \ u 1 9 7 0 - \ u 1 9 7 4 \ u 1 9 8 0 - \ u 1 9 A B \ u 1 9 B 0 - \ u 1 9 C 9 \ u 1 9 D 0 - \ u 1 9 D A \ u 1 A 0 0 - \ u 1 A 1 B \ u 1 A 2 0 - \ u 1 A 5 E \ u 1 A 6 0 - \ u 1 A 7 C \ u 1 A 7 F - \ u 1 A 8 9 \ u 1 A 9 0 - \ u 1 A 9 9 \ u 1 A A 7 \ u 1 A B 0 - \ u 1 A B D \ u 1 B 0 0 - \ u 1 B 4 B \ u 1 B 5 0 - \ u 1 B 5 9 \ u 1 B 6 B - \ u 1 B 7 3 \ u 1 B 8 0 - \ u 1 B F 3 \ u 1 C 0 0 - \ u 1 C 3 7 \ u 1 C 4 0 - \ u 1 C 4 9 \ u 1 C 4 D - \ u 1 C 7 D \ u 1 C D 0 - \ u 1 C D 2 \ u 1 C D 4 - \ u 1 C F 6 \ u 1 C F 8 \ u 1 C F 9 \ u 1 D 0 0 - \ u 1 D F 5 \ u 1 D F C - \ u 1 F 1 5 \ u 1 F 1 8 - \ u 1 F 1 D \ u 1 F 2 0 - \ u 1 F 4 5 \ u 1 F 4 8 - \ u 1 F 4 D \ u 1 F 5 0 - \ u 1 F 5 7 \ u 1 F 5 9 \ u 1 F 5 B \ u 1 F 5 D \ u 1 F 5 F - \ u 1 F 7 D \ u 1 F 8 0 - \ u 1 F B 4 \ u 1 F B 6 - \ u 1 F B C \ u 1 F B E \ u 1 F C 2 - \ u 1 F C 4 \ u 1 F C 6 - \ u 1 F C C \ u 1 F D 0 - \ u 1 F D 3 \ u 1 F D 6 - \ u 1 F D B \ u 1 F E 0 - \ u 1 F E C \ u 1 F F 2 - \ u 1 F F 4 \ u 1 F F 6 - \ u 1 F F C \ u 2 0 3 F \ u 2 0 4 0 \ u 2 0 5 4 \ u 2 0 7 1 \ u 2 0 7 F \ u 2 0 9 0 - \ u 2 0 9 C \ u 2 0 D 0 - \ u 2 0 D C \ u 2 0 E 1 \ u 2 0 E 5 - \ u 2 0 F 0 \ u 2 1 0 2 \ u 2 1 0 7 \ u 2 1 0 A - \ u 2 1 1 3 \ u 2 1 1 5 \ u 2 1 1 8 - \ u 2 1 1 D \ u 2 1 2 4 \ u 2 1 2 6 \ u 2 1 2 8 \ u 2 1 2 A - \ u 2 1 3 9 \ u 2 1 3 C - \ u 2 1 3 F \ u 2 1 4 5 - \ u 2 1 4 9 \ u 2 1 4 E \ u 2 1 6 0 - \ u 2 1 8 8 \ u 2 C 0 0 - \ u 2 C 2 E \ u 2 C 3 0 - \ u 2 C 5 E \ u 2 C 6 0 - \ u 2 C E 4 \ u 2 C E B - \ u 2 C F 3 \ u 2 D 0 0 - \ u 2 D 2 5 \ u 2 D 2 7 \ u 2 D 2 D \ u 2 D 3 0 - \ u 2 D 6 7 \ u 2 D 6 F \ u 2 D 7 F - \ u 2 D 9 6 \ u 2 D A 0 - \ u 2 D A 6 \ u 2 D A 8 - \ u 2 D A E \ u 2 D B 0 - \ u 2 D B 6 \ u 2 D B 8 - \ u 2 D B E \ u 2 D C 0 - \ u 2 D C 6 \ u 2 D C 8 - \ u 2 D C E \ u 2 D D 0 - \ u 2 D D 6 \ u 2 D D 8 - \ u 2 D D E \ u 2 D E 0 - \ u 2 D F F \ u 3 0 0 5 - \ u 3 0 0 7 \ u 3 0 2 1 - \ u 3 0 2 F \ u 3 0 3 1 - \ u 3 0 3 5 \ u 3 0 3 8 - \ u 3 0 3 C \ u 3 0 4 1 - \ u 3 0 9 6 \ u 3 0 9 9 - \ u 3 0 9 F \ u 3 0 A 1 - \ u 3 0 F A \ u 3 0 F C - \ u 3 0 F F \ u 3 1 0 5 - \ u 3 1 2 D \ u 3 1 3 1 - \ u 3 1 8 E \ u 3 1 A 0 - \ u 3 1 B A \ u 3 1 F 0 - \ u 3 1 F F \ u 3 4 0 0 - \ u 4 D B 5 \ u 4
2012-05-27 11:09:01 +00:00
} ;
2016-06-22 15:12:23 +00:00
function get _full _char ( str , pos ) {
var char = str . charAt ( pos ) ;
2017-05-08 17:58:31 +00:00
if ( is _surrogate _pair _head ( char ) ) {
var next = str . charAt ( pos + 1 ) ;
if ( is _surrogate _pair _tail ( next ) ) {
return char + next ;
}
}
if ( is _surrogate _pair _tail ( char ) ) {
var prev = str . charAt ( pos - 1 ) ;
if ( is _surrogate _pair _head ( prev ) ) {
return prev + char ;
}
2016-06-22 15:12:23 +00:00
}
return char ;
}
2012-05-27 11:09:01 +00:00
2016-06-22 15:12:23 +00:00
function get _full _char _code ( str , pos ) {
// https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Surrogates
if ( is _surrogate _pair _head ( str . charAt ( pos ) ) ) {
return 0x10000 + ( str . charCodeAt ( pos ) - 0xd800 << 10 ) + str . charCodeAt ( pos + 1 ) - 0xdc00 ;
}
return str . charCodeAt ( pos ) ;
}
2012-05-27 11:09:01 +00:00
2016-07-04 12:30:27 +00:00
function get _full _char _length ( str ) {
var surrogates = 0 ;
for ( var i = 0 ; i < str . length ; i ++ ) {
2017-05-08 17:58:31 +00:00
if ( is _surrogate _pair _head ( str . charCodeAt ( i ) ) ) {
if ( is _surrogate _pair _tail ( str . charCodeAt ( i + 1 ) ) ) {
2016-07-04 12:30:27 +00:00
surrogates ++ ;
i ++ ;
}
}
}
return str . length - surrogates ;
}
2016-06-22 15:12:23 +00:00
function from _char _code ( code ) {
// Based on https://github.com/mathiasbynens/String.fromCodePoint/blob/master/fromcodepoint.js
if ( code > 0xFFFF ) {
code -= 0x10000 ;
return ( String . fromCharCode ( ( code >> 10 ) + 0xD800 ) +
String . fromCharCode ( ( code % 0x400 ) + 0xDC00 ) ) ;
}
return String . fromCharCode ( code ) ;
}
function is _surrogate _pair _head ( code ) {
if ( typeof code === "string" )
code = code . charCodeAt ( 0 ) ;
2012-05-27 11:09:01 +00:00
2016-06-22 15:12:23 +00:00
return code >= 0xd800 && code <= 0xdbff ;
2015-01-19 20:35:53 +00:00
}
2016-06-22 15:12:23 +00:00
function is _surrogate _pair _tail ( code ) {
if ( typeof code === "string" )
code = code . charCodeAt ( 0 ) ;
return code >= 0xdc00 && code <= 0xdfff ;
}
2012-05-27 11:09:01 +00:00
2016-06-22 15:12:23 +00:00
function is _digit ( code ) {
return code >= 48 && code <= 57 ;
2012-05-27 11:09:01 +00:00
} ;
2012-08-17 12:59:42 +00:00
function is _identifier ( name ) {
2016-06-22 15:12:23 +00:00
if ( typeof name !== "string" || RESERVED _WORDS ( name ) )
return false ;
return true ;
2012-08-17 12:59:42 +00:00
} ;
2016-06-22 15:12:23 +00:00
function is _identifier _start ( ch ) {
var code = ch . charCodeAt ( 0 ) ;
return UNICODE . ID _Start . test ( ch ) || code == 36 || code == 95 ;
2012-05-27 11:09:01 +00:00
} ;
function is _identifier _char ( ch ) {
2012-10-11 10:00:58 +00:00
var code = ch . charCodeAt ( 0 ) ;
2016-06-22 15:12:23 +00:00
return UNICODE . ID _Continue . test ( ch )
|| code == 36
|| code == 95
2012-10-11 10:00:58 +00:00
|| code == 8204 // \u200c: zero-width non-joiner <ZWNJ>
|| code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
2012-05-27 11:09:01 +00:00
;
} ;
2013-05-05 18:45:41 +00:00
function is _identifier _string ( str ) {
2014-04-18 07:47:38 +00:00
return /^[a-z_$][a-z0-9_$]*$/i . test ( str ) ;
2013-05-05 18:45:41 +00:00
} ;
2012-05-27 11:09:01 +00:00
function parse _js _number ( num ) {
if ( RE _HEX _NUMBER . test ( num ) ) {
return parseInt ( num . substr ( 2 ) , 16 ) ;
} else if ( RE _OCT _NUMBER . test ( num ) ) {
return parseInt ( num . substr ( 1 ) , 8 ) ;
2015-08-17 10:50:56 +00:00
} else if ( RE _ES6 _OCT _NUMBER . test ( num ) ) {
return parseInt ( num . substr ( 2 ) , 8 ) ;
2015-08-14 02:24:54 +00:00
} else if ( RE _BIN _NUMBER . test ( num ) ) {
return parseInt ( num . substr ( 2 ) , 2 ) ;
2012-05-27 11:09:01 +00:00
} else if ( RE _DEC _NUMBER . test ( num ) ) {
return parseFloat ( num ) ;
2015-11-09 10:28:27 +00:00
} else {
2015-11-09 11:15:20 +00:00
var val = parseFloat ( num ) ;
if ( val == num ) return val ;
2012-05-27 11:09:01 +00:00
}
} ;
2014-08-11 11:40:01 +00:00
function JS _Parse _Error ( message , filename , line , col , pos ) {
2012-05-27 11:09:01 +00:00
this . message = message ;
2014-08-11 11:40:01 +00:00
this . filename = filename ;
2012-10-02 13:39:53 +00:00
this . line = line ;
this . col = col ;
2012-10-11 12:25:38 +00:00
this . pos = pos ;
2012-05-27 11:09:01 +00:00
} ;
2017-02-26 19:40:54 +00:00
JS _Parse _Error . prototype = Object . create ( Error . prototype ) ;
JS _Parse _Error . prototype . constructor = JS _Parse _Error ;
JS _Parse _Error . prototype . name = "SyntaxError" ;
configure _error _stack ( JS _Parse _Error ) ;
2012-05-27 11:09:01 +00:00
2012-09-21 11:38:52 +00:00
function js _error ( message , filename , line , col , pos ) {
2014-08-11 11:40:01 +00:00
throw new JS _Parse _Error ( message , filename , line , col , pos ) ;
2012-05-27 11:09:01 +00:00
} ;
function is _token ( token , type , val ) {
return token . type == type && ( val == null || token . value == val ) ;
} ;
var EX _EOF = { } ;
2015-02-20 15:08:01 +00:00
function tokenizer ( $TEXT , filename , html5 _comments , shebang ) {
2012-05-27 11:09:01 +00:00
var S = {
2015-05-20 13:17:46 +00:00
text : $TEXT ,
2012-09-21 11:38:52 +00:00
filename : filename ,
2013-07-15 08:59:23 +00:00
pos : 0 ,
tokpos : 0 ,
line : 1 ,
tokline : 0 ,
col : 0 ,
tokcol : 0 ,
2012-05-27 11:09:01 +00:00
newline _before : false ,
regex _allowed : false ,
2016-06-22 17:24:03 +00:00
brace _counter : 0 ,
template _braces : [ ] ,
2016-05-20 08:25:35 +00:00
comments _before : [ ] ,
directives : { } ,
directive _stack : [ ]
2012-05-27 11:09:01 +00:00
} ;
2016-06-22 15:12:23 +00:00
function peek ( ) { return get _full _char ( S . text , S . pos ) ; } ;
2012-05-27 11:09:01 +00:00
function next ( signal _eof , in _string ) {
2016-06-22 15:12:23 +00:00
var ch = get _full _char ( S . text , S . pos ++ ) ;
2012-05-27 11:09:01 +00:00
if ( signal _eof && ! ch )
throw EX _EOF ;
2016-06-13 10:36:47 +00:00
if ( NEWLINE _CHARS ( ch ) ) {
2012-05-27 11:09:01 +00:00
S . newline _before = S . newline _before || ! in _string ;
++ S . line ;
S . col = 0 ;
2015-01-05 10:14:42 +00:00
if ( ! in _string && ch == "\r" && peek ( ) == "\n" ) {
// treat a \r\n sequence as a single \n
++ S . pos ;
ch = "\n" ;
}
2012-05-27 11:09:01 +00:00
} else {
2017-05-08 17:58:31 +00:00
if ( ch . length > 1 ) {
2016-06-22 15:12:23 +00:00
++ S . pos ;
++ S . col ;
}
2012-05-27 11:09:01 +00:00
++ S . col ;
}
return ch ;
} ;
2013-09-06 06:54:30 +00:00
function forward ( i ) {
while ( i -- > 0 ) next ( ) ;
} ;
function looking _at ( str ) {
return S . text . substr ( S . pos , str . length ) == str ;
} ;
2016-04-25 04:42:18 +00:00
function find _eol ( ) {
var text = S . text ;
for ( var i = S . pos , n = S . text . length ; i < n ; ++ i ) {
var ch = text [ i ] ;
2016-06-13 10:36:47 +00:00
if ( NEWLINE _CHARS ( ch ) )
2016-04-25 04:42:18 +00:00
return i ;
}
return - 1 ;
} ;
2012-05-27 11:09:01 +00:00
function find ( what , signal _eof ) {
var pos = S . text . indexOf ( what , S . pos ) ;
if ( signal _eof && pos == - 1 ) throw EX _EOF ;
return pos ;
} ;
function start _token ( ) {
S . tokline = S . line ;
S . tokcol = S . col ;
S . tokpos = S . pos ;
} ;
2013-09-02 08:09:54 +00:00
var prev _was _dot = false ;
2012-05-27 11:09:01 +00:00
function token ( type , value , is _comment ) {
2013-07-12 06:56:58 +00:00
S . regex _allowed = ( ( type == "operator" && ! UNARY _POSTFIX ( value ) ) ||
2013-09-02 08:36:48 +00:00
( type == "keyword" && KEYWORDS _BEFORE _EXPRESSION ( value ) ) ||
2017-01-26 11:06:46 +00:00
( type == "punc" && PUNC _BEFORE _EXPRESSION ( value ) ) ) ||
( type == "arrow" ) ;
2017-05-15 21:40:49 +00:00
if ( type == "punc" && value == "." ) {
prev _was _dot = true ;
} else if ( ! is _comment ) {
prev _was _dot = false ;
}
2012-05-27 11:09:01 +00:00
var ret = {
2014-08-08 11:15:43 +00:00
type : type ,
value : value ,
line : S . tokline ,
col : S . tokcol ,
pos : S . tokpos ,
endline : S . line ,
endcol : S . col ,
endpos : S . pos ,
nlb : S . newline _before ,
file : filename
2012-05-27 11:09:01 +00:00
} ;
2015-11-11 20:15:25 +00:00
if ( /^(?:num|string|regexp)$/i . test ( type ) ) {
2015-11-12 10:18:25 +00:00
ret . raw = $TEXT . substring ( ret . pos , ret . endpos ) ;
2015-11-11 20:15:25 +00:00
}
2012-05-27 11:09:01 +00:00
if ( ! is _comment ) {
ret . comments _before = S . comments _before ;
2017-12-21 20:59:54 +00:00
ret . comments _after = S . comments _before = [ ] ;
2012-05-27 11:09:01 +00:00
}
S . newline _before = false ;
return new AST _Token ( ret ) ;
} ;
function skip _whitespace ( ) {
2016-06-13 10:36:47 +00:00
while ( WHITESPACE _CHARS ( peek ( ) ) )
2012-05-27 11:09:01 +00:00
next ( ) ;
} ;
function read _while ( pred ) {
2012-10-11 10:00:58 +00:00
var ret = "" , ch , i = 0 ;
while ( ( ch = peek ( ) ) && pred ( ch , i ++ ) )
2012-05-27 11:09:01 +00:00
ret += next ( ) ;
return ret ;
} ;
function parse _error ( err ) {
2012-09-21 11:38:52 +00:00
js _error ( err , filename , S . tokline , S . tokcol , S . tokpos ) ;
2012-05-27 11:09:01 +00:00
} ;
function read _num ( prefix ) {
var has _e = false , after _e = false , has _x = false , has _dot = prefix == "." ;
var num = read _while ( function ( ch , i ) {
2012-10-11 10:00:58 +00:00
var code = ch . charCodeAt ( 0 ) ;
switch ( code ) {
2016-06-22 15:12:23 +00:00
case 98 : case 66 : // bB
return ( has _x = true ) ; // Can occur in hex sequence, don't return false yet
case 111 : case 79 : // oO
2012-10-11 10:00:58 +00:00
case 120 : case 88 : // xX
return has _x ? false : ( has _x = true ) ;
case 101 : case 69 : // eE
return has _x ? true : has _e ? false : ( has _e = after _e = true ) ;
case 45 : // -
return after _e || ( i == 0 && ! prefix ) ;
case 43 : // +
return after _e ;
case ( after _e = false , 46 ) : // .
return ( ! has _dot && ! has _x && ! has _e ) ? ( has _dot = true ) : false ;
2012-05-27 11:09:01 +00:00
}
2016-06-22 15:12:23 +00:00
return RE _NUM _LITERAL . test ( ch ) ;
2012-05-27 11:09:01 +00:00
} ) ;
2012-10-11 10:00:58 +00:00
if ( prefix ) num = prefix + num ;
2016-07-21 01:19:24 +00:00
if ( RE _OCT _NUMBER . test ( num ) && next _token . has _directive ( "use strict" ) ) {
2017-02-26 19:40:54 +00:00
parse _error ( "Legacy octal literals are not allowed in strict mode" ) ;
2016-07-21 01:19:24 +00:00
}
2012-05-27 11:09:01 +00:00
var valid = parse _js _number ( num ) ;
if ( ! isNaN ( valid ) ) {
2015-11-11 20:15:25 +00:00
return token ( "num" , valid ) ;
2012-05-27 11:09:01 +00:00
} else {
2017-02-26 19:40:54 +00:00
parse _error ( "Invalid syntax: " + num ) ;
2012-05-27 11:09:01 +00:00
}
} ;
function read _escaped _char ( in _string ) {
var ch = next ( true , in _string ) ;
2012-10-11 10:00:58 +00:00
switch ( ch . charCodeAt ( 0 ) ) {
case 110 : return "\n" ;
case 114 : return "\r" ;
case 116 : return "\t" ;
case 98 : return "\b" ;
case 118 : return "\u000b" ; // \v
case 102 : return "\f" ;
case 120 : return String . fromCharCode ( hex _bytes ( 2 ) ) ; // \x
2016-06-22 15:12:23 +00:00
case 117 : // \u
if ( peek ( ) == "{" ) {
next ( true ) ;
if ( peek ( ) === "}" )
2017-02-26 20:37:48 +00:00
parse _error ( "Expecting hex-character between {}" ) ;
2016-06-22 15:12:23 +00:00
while ( peek ( ) == "0" ) next ( true ) ; // No significance
var result , length = find ( "}" , true ) - S . pos ;
// Avoid 32 bit integer overflow (1 << 32 === 1)
// We know first character isn't 0 and thus out of range anyway
if ( length > 6 || ( result = hex _bytes ( length ) ) > 0x10FFFF ) {
2017-02-26 20:37:48 +00:00
parse _error ( "Unicode reference out of bounce" ) ;
2016-06-22 15:12:23 +00:00
}
next ( true ) ;
return from _char _code ( result ) ;
}
return String . fromCharCode ( hex _bytes ( 4 ) ) ;
2012-10-11 10:00:58 +00:00
case 10 : return "" ; // newline
2015-04-23 09:08:19 +00:00
case 13 : // \r
if ( peek ( ) == "\n" ) { // DOS newline
next ( true , in _string ) ;
return "" ;
}
2012-05-27 11:09:01 +00:00
}
2016-06-23 14:53:48 +00:00
if ( ch >= "0" && ch <= "7" )
return read _octal _escape _sequence ( ch ) ;
2015-04-23 09:08:19 +00:00
return ch ;
2012-05-27 11:09:01 +00:00
} ;
2016-06-23 14:53:48 +00:00
function read _octal _escape _sequence ( ch ) {
// Read
var p = peek ( ) ;
if ( p >= "0" && p <= "7" ) {
ch += next ( true ) ;
if ( ch [ 0 ] <= "3" && ( p = peek ( ) ) >= "0" && p <= "7" )
ch += next ( true ) ;
}
// Parse
if ( ch === "0" ) return "\0" ;
if ( ch . length > 0 && next _token . has _directive ( "use strict" ) )
2017-02-26 19:40:54 +00:00
parse _error ( "Legacy octal escape sequences are not allowed in strict mode" ) ;
2016-06-23 14:53:48 +00:00
return String . fromCharCode ( parseInt ( ch , 8 ) ) ;
}
2012-05-27 11:09:01 +00:00
function hex _bytes ( n ) {
var num = 0 ;
for ( ; n > 0 ; -- n ) {
var digit = parseInt ( next ( true ) , 16 ) ;
if ( isNaN ( digit ) )
2017-02-26 19:40:54 +00:00
parse _error ( "Invalid hex-character pattern in string" ) ;
2012-05-27 11:09:01 +00:00
num = ( num << 4 ) | digit ;
}
return num ;
} ;
2017-02-26 19:40:54 +00:00
var read _string = with _eof _error ( "Unterminated string constant" , function ( quote _char ) {
2012-10-11 10:00:58 +00:00
var quote = next ( ) , ret = "" ;
for ( ; ; ) {
2015-04-23 09:08:19 +00:00
var ch = next ( true , true ) ;
2016-06-23 14:53:48 +00:00
if ( ch == "\\" ) ch = read _escaped _char ( true ) ;
2017-02-26 19:40:54 +00:00
else if ( NEWLINE _CHARS ( ch ) ) parse _error ( "Unterminated string constant" ) ;
2012-10-11 10:00:58 +00:00
else if ( ch == quote ) break ;
ret += ch ;
}
2015-01-27 20:26:27 +00:00
var tok = token ( "string" , ret ) ;
tok . quote = quote _char ;
return tok ;
2012-10-11 10:00:58 +00:00
} ) ;
2012-05-27 11:09:01 +00:00
2017-02-26 20:37:48 +00:00
var read _template _characters = with _eof _error ( "Unterminated template" , function ( begin ) {
2016-06-22 17:24:03 +00:00
if ( begin ) {
S . template _braces . push ( S . brace _counter ) ;
}
var content = "" , raw = "" , ch , tok ;
2016-10-28 21:47:03 +00:00
next ( true , true ) ;
2017-06-28 14:52:29 +00:00
while ( ( ch = next ( true , true ) ) != "`" ) {
if ( ch == "\r" ) {
if ( peek ( ) == "\n" ) ++ S . pos ;
ch = "\n" ;
} else if ( ch == "$" && peek ( ) == "{" ) {
2016-10-28 21:47:03 +00:00
next ( true , true ) ;
2016-06-22 17:24:03 +00:00
S . brace _counter ++ ;
tok = token ( begin ? "template_head" : "template_substitution" , content ) ;
tok . begin = begin ;
tok . raw = raw ;
tok . end = false ;
return tok ;
}
raw += ch ;
2017-06-28 14:52:29 +00:00
if ( ch == "\\" ) {
2016-06-22 17:24:03 +00:00
var tmp = S . pos ;
ch = read _escaped _char ( ) ;
raw += S . text . substr ( tmp , S . pos - tmp ) ;
}
content += ch ;
}
S . template _braces . pop ( ) ;
tok = token ( begin ? "template_head" : "template_substitution" , content ) ;
tok . begin = begin ;
tok . raw = raw ;
tok . end = true ;
return tok ;
} ) ;
2013-09-06 06:54:30 +00:00
function skip _line _comment ( type ) {
var regex _allowed = S . regex _allowed ;
2016-04-25 04:42:18 +00:00
var i = find _eol ( ) , ret ;
2012-05-27 11:09:01 +00:00
if ( i == - 1 ) {
ret = S . text . substr ( S . pos ) ;
S . pos = S . text . length ;
} else {
ret = S . text . substring ( S . pos , i ) ;
S . pos = i ;
}
2014-08-08 11:15:43 +00:00
S . col = S . tokcol + ( S . pos - S . tokpos ) ;
2013-09-06 06:54:30 +00:00
S . comments _before . push ( token ( type , ret , true ) ) ;
S . regex _allowed = regex _allowed ;
2016-04-15 23:58:46 +00:00
return next _token ;
2012-05-27 11:09:01 +00:00
} ;
2017-02-26 19:40:54 +00:00
var skip _multiline _comment = with _eof _error ( "Unterminated multiline comment" , function ( ) {
2013-09-06 06:54:30 +00:00
var regex _allowed = S . regex _allowed ;
2012-10-11 10:00:58 +00:00
var i = find ( "*/" , true ) ;
2016-06-13 10:36:47 +00:00
var text = S . text . substring ( S . pos , i ) . replace ( /\r\n|\r|\u2028|\u2029/g , '\n' ) ;
2012-10-11 10:00:58 +00:00
// update stream position
2016-07-04 12:30:27 +00:00
forward ( get _full _char _length ( text ) /* text length doesn't count \r\n as 2 char while S.pos - i does */ + 2 ) ;
2013-09-06 06:54:30 +00:00
S . comments _before . push ( token ( "comment2" , text , true ) ) ;
2016-07-04 12:30:27 +00:00
S . newline _before = S . newline _before || text . indexOf ( "\n" ) >= 0 ;
2013-09-06 06:54:30 +00:00
S . regex _allowed = regex _allowed ;
2016-04-15 23:58:46 +00:00
return next _token ;
2012-10-11 10:00:58 +00:00
} ) ;
2012-05-27 11:09:01 +00:00
2017-02-26 20:37:48 +00:00
var read _name = with _eof _error ( "Unterminated identifier name" , function ( ) {
2016-06-22 15:12:23 +00:00
var name = "" , ch , escaped = false , hex ;
var read _escaped _identifier _char = function ( ) {
escaped = true ;
next ( ) ;
if ( peek ( ) !== "u" ) {
2017-02-26 20:37:48 +00:00
parse _error ( "Expecting UnicodeEscapeSequence -- uXXXX or u{XXXX}" ) ;
2016-06-22 15:12:23 +00:00
}
return read _escaped _char ( ) ;
}
// Read first character (ID_Start)
if ( ( name = peek ( ) ) === "\\" ) {
name = read _escaped _identifier _char ( ) ;
if ( ! is _identifier _start ( name ) ) {
2017-02-26 20:37:48 +00:00
parse _error ( "First identifier char is an invalid identifier char" ) ;
2012-05-27 11:09:01 +00:00
}
2016-06-22 15:12:23 +00:00
} else if ( is _identifier _start ( name ) ) {
next ( ) ;
} else {
return "" ;
}
// Read ID_Continue
while ( ( ch = peek ( ) ) != null ) {
if ( ( ch = peek ( ) ) === "\\" ) {
ch = read _escaped _identifier _char ( ) ;
if ( ! is _identifier _char ( ch ) ) {
2017-02-26 20:37:48 +00:00
parse _error ( "Invalid escaped identifier char" ) ;
2016-06-22 15:12:23 +00:00
}
} else {
if ( ! is _identifier _char ( ch ) ) {
break ;
}
next ( ) ;
2012-05-27 11:09:01 +00:00
}
2016-06-22 15:12:23 +00:00
name += ch ;
2012-05-27 11:09:01 +00:00
}
2016-06-26 23:17:53 +00:00
if ( RESERVED _WORDS ( name ) && escaped ) {
2017-02-26 20:37:48 +00:00
parse _error ( "Escaped characters are not allowed in keywords" ) ;
2012-05-27 11:09:01 +00:00
}
return name ;
2016-07-22 15:33:24 +00:00
} ) ;
2012-05-27 11:09:01 +00:00
2017-05-17 12:10:50 +00:00
var read _regexp = with _eof _error ( "Unterminated regular expression" , function ( source ) {
2012-10-11 10:00:58 +00:00
var prev _backslash = false , ch , in _class = false ;
2016-06-13 10:36:47 +00:00
while ( ( ch = next ( true ) ) ) if ( NEWLINE _CHARS ( ch ) ) {
2017-02-26 19:40:54 +00:00
parse _error ( "Unexpected line terminator" ) ;
2016-06-13 10:36:47 +00:00
} else if ( prev _backslash ) {
2017-05-17 12:10:50 +00:00
source += "\\" + ch ;
2012-10-11 10:00:58 +00:00
prev _backslash = false ;
} else if ( ch == "[" ) {
in _class = true ;
2017-05-17 12:10:50 +00:00
source += ch ;
2012-10-11 10:00:58 +00:00
} else if ( ch == "]" && in _class ) {
in _class = false ;
2017-05-17 12:10:50 +00:00
source += ch ;
2012-10-11 10:00:58 +00:00
} else if ( ch == "/" && ! in _class ) {
break ;
} else if ( ch == "\\" ) {
prev _backslash = true ;
} else {
2017-05-17 12:10:50 +00:00
source += ch ;
2012-10-11 10:00:58 +00:00
}
var mods = read _name ( ) ;
2015-05-14 19:03:54 +00:00
try {
2017-05-17 12:10:50 +00:00
var regexp = new RegExp ( source , mods ) ;
regexp . raw _source = source ;
return token ( "regexp" , regexp ) ;
2015-05-14 19:03:54 +00:00
} catch ( e ) {
2017-05-17 12:10:50 +00:00
parse _error ( e . message ) ;
2015-05-14 19:03:54 +00:00
}
2012-10-11 10:00:58 +00:00
} ) ;
2012-05-27 11:09:01 +00:00
function read _operator ( prefix ) {
function grow ( op ) {
if ( ! peek ( ) ) return op ;
var bigger = op + peek ( ) ;
2012-10-11 08:52:05 +00:00
if ( OPERATORS ( bigger ) ) {
2012-05-27 11:09:01 +00:00
next ( ) ;
return grow ( bigger ) ;
} else {
return op ;
}
} ;
return token ( "operator" , grow ( prefix || next ( ) ) ) ;
} ;
function handle _slash ( ) {
next ( ) ;
switch ( peek ( ) ) {
case "/" :
2013-09-06 06:54:30 +00:00
next ( ) ;
return skip _line _comment ( "comment1" ) ;
2012-05-27 11:09:01 +00:00
case "*" :
2013-09-06 06:54:30 +00:00
next ( ) ;
return skip _multiline _comment ( ) ;
2012-05-27 11:09:01 +00:00
}
return S . regex _allowed ? read _regexp ( "" ) : read _operator ( "/" ) ;
} ;
2015-01-11 20:07:19 +00:00
function handle _eq _sign ( ) {
next ( ) ;
if ( peek ( ) === ">" ) {
next ( ) ;
return token ( "arrow" , "=>" ) ;
} else {
return read _operator ( "=" ) ;
}
} ;
2012-05-27 11:09:01 +00:00
function handle _dot ( ) {
next ( ) ;
2015-04-13 00:26:26 +00:00
if ( is _digit ( peek ( ) . charCodeAt ( 0 ) ) ) {
return read _num ( "." ) ;
}
if ( peek ( ) === "." ) {
next ( ) ; // Consume second dot
next ( ) ; // Consume third dot
return token ( "expand" , "..." ) ;
}
return token ( "punc" , "." ) ;
2012-05-27 11:09:01 +00:00
} ;
function read _word ( ) {
var word = read _name ( ) ;
2013-09-02 08:36:48 +00:00
if ( prev _was _dot ) return token ( "name" , word ) ;
2012-10-11 08:52:05 +00:00
return KEYWORDS _ATOM ( word ) ? token ( "atom" , word )
: ! KEYWORDS ( word ) ? token ( "name" , word )
: OPERATORS ( word ) ? token ( "operator" , word )
2012-05-27 11:09:01 +00:00
: token ( "keyword" , word ) ;
} ;
function with _eof _error ( eof _error , cont ) {
2012-10-11 10:00:58 +00:00
return function ( x ) {
try {
return cont ( x ) ;
} catch ( ex ) {
if ( ex === EX _EOF ) parse _error ( eof _error ) ;
else throw ex ;
}
} ;
2012-05-27 11:09:01 +00:00
} ;
function next _token ( force _regexp ) {
if ( force _regexp != null )
return read _regexp ( force _regexp ) ;
2017-03-05 04:16:02 +00:00
if ( shebang && S . pos == 0 && looking _at ( "#!" ) ) {
start _token ( ) ;
forward ( 2 ) ;
skip _line _comment ( "comment5" ) ;
}
2016-04-15 23:58:46 +00:00
for ( ; ; ) {
skip _whitespace ( ) ;
start _token ( ) ;
if ( html5 _comments ) {
if ( looking _at ( "<!--" ) ) {
forward ( 4 ) ;
skip _line _comment ( "comment3" ) ;
continue ;
}
if ( looking _at ( "-->" ) && S . newline _before ) {
forward ( 3 ) ;
skip _line _comment ( "comment4" ) ;
continue ;
}
2013-09-06 06:54:30 +00:00
}
2016-04-15 23:58:46 +00:00
var ch = peek ( ) ;
if ( ! ch ) return token ( "eof" ) ;
var code = ch . charCodeAt ( 0 ) ;
switch ( code ) {
case 34 : case 39 : return read _string ( ch ) ;
case 46 : return handle _dot ( ) ;
case 47 : {
var tok = handle _slash ( ) ;
if ( tok === next _token ) continue ;
return tok ;
}
2016-04-17 11:37:01 +00:00
case 61 : return handle _eq _sign ( ) ;
2016-06-22 17:24:03 +00:00
case 96 : return read _template _characters ( true ) ;
case 123 :
S . brace _counter ++ ;
break ;
case 125 :
S . brace _counter -- ;
if ( S . template _braces . length > 0
&& S . template _braces [ S . template _braces . length - 1 ] === S . brace _counter )
return read _template _characters ( false ) ;
break ;
2013-09-06 06:54:30 +00:00
}
2016-04-15 23:58:46 +00:00
if ( is _digit ( code ) ) return read _num ( ) ;
if ( PUNC _CHARS ( ch ) ) return token ( "punc" , next ( ) ) ;
if ( OPERATOR _CHARS ( ch ) ) return read _operator ( ) ;
2016-06-22 15:12:23 +00:00
if ( code == 92 || is _identifier _start ( ch ) ) return read _word ( ) ;
2016-04-15 23:58:46 +00:00
break ;
2015-02-20 15:08:01 +00:00
}
2017-02-26 19:40:54 +00:00
parse _error ( "Unexpected character '" + ch + "'" ) ;
2012-05-27 11:09:01 +00:00
} ;
2015-09-05 21:32:57 +00:00
next _token . next = next ;
next _token . peek = peek ;
2012-05-27 11:09:01 +00:00
next _token . context = function ( nc ) {
if ( nc ) S = nc ;
return S ;
} ;
2016-05-20 08:25:35 +00:00
next _token . add _directive = function ( directive ) {
S . directive _stack [ S . directive _stack . length - 1 ] . push ( directive ) ;
if ( S . directives [ directive ] === undefined ) {
S . directives [ directive ] = 1 ;
} else {
S . directives [ directive ] ++ ;
}
}
next _token . push _directives _stack = function ( ) {
S . directive _stack . push ( [ ] ) ;
}
next _token . pop _directives _stack = function ( ) {
var directives = S . directive _stack [ S . directive _stack . length - 1 ] ;
for ( var i = 0 ; i < directives . length ; i ++ ) {
S . directives [ directives [ i ] ] -- ;
}
S . directive _stack . pop ( ) ;
}
next _token . has _directive = function ( directive ) {
2017-04-23 12:05:22 +00:00
return S . directives [ directive ] > 0 ;
2016-05-20 08:25:35 +00:00
}
2012-05-27 11:09:01 +00:00
return next _token ;
} ;
/* -----[ Parser (constants) ]----- */
2012-10-11 10:00:58 +00:00
var UNARY _PREFIX = makePredicate ( [
2012-05-27 11:09:01 +00:00
"typeof" ,
"void" ,
"delete" ,
"--" ,
"++" ,
"!" ,
"~" ,
"-" ,
"+"
] ) ;
2012-10-11 10:00:58 +00:00
var UNARY _POSTFIX = makePredicate ( [ "--" , "++" ] ) ;
2012-05-27 11:09:01 +00:00
2016-06-17 22:25:18 +00:00
var ASSIGNMENT = makePredicate ( [ "=" , "+=" , "-=" , "/=" , "*=" , "**=" , "%=" , ">>=" , "<<=" , ">>>=" , "|=" , "^=" , "&=" ] ) ;
2012-05-27 11:09:01 +00:00
var PRECEDENCE = ( function ( a , ret ) {
2013-10-30 07:10:56 +00:00
for ( var i = 0 ; i < a . length ; ++ i ) {
2012-05-27 11:09:01 +00:00
var b = a [ i ] ;
for ( var j = 0 ; j < b . length ; ++ j ) {
2013-10-30 07:10:56 +00:00
ret [ b [ j ] ] = i + 1 ;
2012-05-27 11:09:01 +00:00
}
}
return ret ;
} ) (
[
[ "||" ] ,
[ "&&" ] ,
[ "|" ] ,
[ "^" ] ,
[ "&" ] ,
[ "==" , "===" , "!=" , "!==" ] ,
[ "<" , ">" , "<=" , ">=" , "in" , "instanceof" ] ,
[ ">>" , "<<" , ">>>" ] ,
[ "+" , "-" ] ,
2016-06-17 22:25:18 +00:00
[ "*" , "/" , "%" ] ,
[ "**" ]
2012-05-27 11:09:01 +00:00
] ,
{ }
) ;
2017-06-03 06:00:59 +00:00
var ATOMIC _START _TOKEN = makePredicate ( [ "atom" , "num" , "string" , "regexp" , "name" ] ) ;
2012-05-27 11:09:01 +00:00
/* -----[ Parser ]----- */
2012-09-21 11:19:05 +00:00
function parse ( $TEXT , options ) {
options = defaults ( options , {
2017-03-31 08:41:04 +00:00
bare _returns : false ,
2017-06-24 09:34:14 +00:00
ecma : 8 ,
2013-09-06 06:54:30 +00:00
expression : false ,
2017-03-31 08:41:04 +00:00
filename : null ,
2013-09-06 06:54:30 +00:00
html5 _comments : true ,
2015-02-20 15:08:01 +00:00
shebang : true ,
2017-03-31 08:41:04 +00:00
strict : false ,
toplevel : null ,
2017-05-28 10:21:44 +00:00
} , true ) ;
2012-05-27 11:09:01 +00:00
var S = {
2013-09-06 06:54:30 +00:00
input : ( typeof $TEXT == "string"
? tokenizer ( $TEXT , options . filename ,
2015-02-20 15:08:01 +00:00
options . html5 _comments , options . shebang )
2013-09-06 06:54:30 +00:00
: $TEXT ) ,
2012-05-27 11:09:01 +00:00
token : null ,
prev : null ,
peeked : null ,
in _function : 0 ,
2017-06-14 22:15:48 +00:00
in _async : - 1 ,
2016-05-26 15:00:37 +00:00
in _generator : - 1 ,
2012-05-27 11:09:01 +00:00
in _directives : true ,
in _loop : 0 ,
labels : [ ]
} ;
S . token = next ( ) ;
function is ( type , value ) {
return is _token ( S . token , type , value ) ;
} ;
function peek ( ) { return S . peeked || ( S . peeked = S . input ( ) ) ; } ;
function next ( ) {
S . prev = S . token ;
if ( S . peeked ) {
S . token = S . peeked ;
S . peeked = null ;
} else {
S . token = S . input ( ) ;
}
S . in _directives = S . in _directives && (
S . token . type == "string" || is ( "punc" , ";" )
) ;
return S . token ;
} ;
function prev ( ) {
return S . prev ;
} ;
function croak ( msg , line , col , pos ) {
var ctx = S . input . context ( ) ;
js _error ( msg ,
2012-09-21 11:38:52 +00:00
ctx . filename ,
2012-05-27 11:09:01 +00:00
line != null ? line : ctx . tokline ,
col != null ? col : ctx . tokcol ,
pos != null ? pos : ctx . tokpos ) ;
} ;
function token _error ( token , msg ) {
croak ( msg , token . line , token . col ) ;
} ;
function unexpected ( token ) {
if ( token == null )
token = S . token ;
2017-02-26 19:40:54 +00:00
token _error ( token , "Unexpected token: " + token . type + " (" + token . value + ")" ) ;
2012-05-27 11:09:01 +00:00
} ;
function expect _token ( type , val ) {
if ( is ( type , val ) ) {
return next ( ) ;
}
2017-02-26 19:40:54 +00:00
token _error ( S . token , "Unexpected token " + S . token . type + " «" + S . token . value + "»" + ", expected " + type + " «" + val + "»" ) ;
2012-05-27 11:09:01 +00:00
} ;
function expect ( punc ) { return expect _token ( "punc" , punc ) ; } ;
2017-12-25 17:38:01 +00:00
function has _newline _before ( token ) {
return token . nlb || ! all ( token . comments _before , function ( comment ) {
return ! comment . nlb ;
} ) ;
}
2012-05-27 11:09:01 +00:00
function can _insert _semicolon ( ) {
2017-12-25 17:38:01 +00:00
return ! options . strict
&& ( is ( "eof" ) || is ( "punc" , "}" ) || has _newline _before ( S . token ) ) ;
2012-05-27 11:09:01 +00:00
} ;
2016-05-26 15:00:37 +00:00
function is _in _generator ( ) {
return S . in _generator === S . in _function ;
}
2017-06-14 22:15:48 +00:00
function is _in _async ( ) {
return S . in _async === S . in _function ;
}
2015-12-17 22:02:35 +00:00
function semicolon ( optional ) {
2012-05-27 11:09:01 +00:00
if ( is ( "punc" , ";" ) ) next ( ) ;
2015-12-17 22:02:35 +00:00
else if ( ! optional && ! can _insert _semicolon ( ) ) unexpected ( ) ;
2012-05-27 11:09:01 +00:00
} ;
function parenthesised ( ) {
2012-08-17 12:59:42 +00:00
expect ( "(" ) ;
2012-10-11 10:00:58 +00:00
var exp = expression ( true ) ;
2012-08-17 12:59:42 +00:00
expect ( ")" ) ;
return exp ;
2012-05-27 11:09:01 +00:00
} ;
function embed _tokens ( parser ) {
return function ( ) {
var start = S . token ;
2015-08-14 00:16:54 +00:00
var expr = parser . apply ( null , arguments ) ;
2012-05-27 11:09:01 +00:00
var end = prev ( ) ;
expr . start = start ;
expr . end = end ;
return expr ;
} ;
} ;
2013-09-02 06:56:27 +00:00
function handle _regexp ( ) {
2012-05-27 11:09:01 +00:00
if ( is ( "operator" , "/" ) || is ( "operator" , "/=" ) ) {
S . peeked = null ;
S . token = S . input ( S . token . value . substr ( 1 ) ) ; // force regexp
}
2013-09-02 06:56:27 +00:00
} ;
2017-12-17 16:11:52 +00:00
var statement = embed _tokens ( function ( is _export _default ) {
2013-09-02 06:56:27 +00:00
handle _regexp ( ) ;
2012-05-27 11:09:01 +00:00
switch ( S . token . type ) {
case "string" :
2017-05-14 18:37:53 +00:00
if ( S . in _directives ) {
2017-05-15 15:02:55 +00:00
var token = peek ( ) ;
2017-05-14 18:37:53 +00:00
if ( S . token . raw . indexOf ( "\\" ) == - 1
2017-12-25 17:38:01 +00:00
&& ( is _token ( token , "punc" , ";" )
|| is _token ( token , "punc" , "}" )
|| has _newline _before ( token )
|| is _token ( token , "eof" ) ) ) {
2016-06-13 19:11:08 +00:00
S . input . add _directive ( S . token . value ) ;
2016-05-20 08:25:35 +00:00
} else {
S . in _directives = false ;
}
}
2012-05-27 11:09:01 +00:00
var dir = S . in _directives , stat = simple _statement ( ) ;
2017-05-14 18:37:53 +00:00
return dir ? new AST _Directive ( stat . body ) : stat ;
2016-06-22 17:24:03 +00:00
case "template_head" :
2012-05-27 11:09:01 +00:00
case "num" :
case "regexp" :
case "operator" :
case "atom" :
return simple _statement ( ) ;
case "name" :
2017-06-14 22:15:48 +00:00
if ( S . token . value == "async" && is _token ( peek ( ) , "keyword" , "function" ) ) {
next ( ) ;
next ( ) ;
2017-12-17 16:11:52 +00:00
return function _ ( AST _Defun , false , true , is _export _default ) ;
2017-06-14 22:15:48 +00:00
}
2017-09-28 10:43:09 +00:00
if ( S . token . value == "import" && ! is _token ( peek ( ) , "punc" , "(" ) ) {
next ( ) ;
var node = import _ ( ) ;
semicolon ( ) ;
return node ;
}
2012-05-27 11:09:01 +00:00
return is _token ( peek ( ) , "punc" , ":" )
? labeled _statement ( )
: simple _statement ( ) ;
case "punc" :
switch ( S . token . value ) {
case "{" :
2012-09-05 08:31:02 +00:00
return new AST _BlockStatement ( {
start : S . token ,
body : block _ ( ) ,
end : prev ( )
} ) ;
2012-05-27 11:09:01 +00:00
case "[" :
case "(" :
return simple _statement ( ) ;
case ";" :
2016-06-13 19:11:08 +00:00
S . in _directives = false ;
2012-05-27 11:09:01 +00:00
next ( ) ;
2012-08-15 10:32:37 +00:00
return new AST _EmptyStatement ( ) ;
2012-05-27 11:09:01 +00:00
default :
unexpected ( ) ;
}
case "keyword" :
2017-05-15 15:02:55 +00:00
switch ( S . token . value ) {
2012-05-27 11:09:01 +00:00
case "break" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
return break _cont ( AST _Break ) ;
case "continue" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
return break _cont ( AST _Continue ) ;
case "debugger" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
semicolon ( ) ;
return new AST _Debugger ( ) ;
case "do" :
2017-05-15 15:02:55 +00:00
next ( ) ;
var body = in _loop ( statement ) ;
expect _token ( "keyword" , "while" ) ;
var condition = parenthesised ( ) ;
semicolon ( true ) ;
2012-05-27 11:09:01 +00:00
return new AST _Do ( {
2017-05-15 15:02:55 +00:00
body : body ,
condition : condition
2012-05-27 11:09:01 +00:00
} ) ;
case "while" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
return new AST _While ( {
condition : parenthesised ( ) ,
body : in _loop ( statement )
} ) ;
case "for" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
return for _ ( ) ;
2015-10-27 00:40:46 +00:00
case "class" :
2017-05-15 22:48:23 +00:00
next ( ) ;
2015-11-21 09:17:32 +00:00
return class _ ( AST _DefClass ) ;
2015-10-27 00:40:46 +00:00
2012-05-27 11:09:01 +00:00
case "function" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2017-12-17 16:11:52 +00:00
return function _ ( AST _Defun , false , false , is _export _default ) ;
2012-05-27 11:09:01 +00:00
case "if" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
return if _ ( ) ;
case "return" :
2014-10-20 15:12:13 +00:00
if ( S . in _function == 0 && ! options . bare _returns )
2017-02-26 19:40:54 +00:00
croak ( "'return' outside of function" ) ;
2017-05-15 15:02:55 +00:00
next ( ) ;
var value = null ;
if ( is ( "punc" , ";" ) ) {
next ( ) ;
} else if ( ! can _insert _semicolon ( ) ) {
value = expression ( true ) ;
semicolon ( ) ;
}
2012-05-27 11:09:01 +00:00
return new AST _Return ( {
2017-05-15 15:02:55 +00:00
value : value
2012-05-27 11:09:01 +00:00
} ) ;
case "switch" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
return new AST _Switch ( {
expression : parenthesised ( ) ,
2012-10-11 10:00:58 +00:00
body : in _loop ( switch _body _ )
2012-05-27 11:09:01 +00:00
} ) ;
case "throw" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2017-12-25 17:38:01 +00:00
if ( has _newline _before ( S . token ) )
2017-02-26 19:40:54 +00:00
croak ( "Illegal newline after 'throw'" ) ;
2017-05-15 15:02:55 +00:00
var value = expression ( true ) ;
semicolon ( ) ;
2012-05-27 11:09:01 +00:00
return new AST _Throw ( {
2017-05-15 15:02:55 +00:00
value : value
2012-05-27 11:09:01 +00:00
} ) ;
case "try" :
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
return try _ ( ) ;
case "var" :
2017-05-15 15:02:55 +00:00
next ( ) ;
var node = var _ ( ) ;
semicolon ( ) ;
return node ;
2012-05-27 11:09:01 +00:00
2015-09-06 20:33:17 +00:00
case "let" :
2017-05-15 22:48:23 +00:00
next ( ) ;
var node = let _ ( ) ;
semicolon ( ) ;
return node ;
2015-09-06 20:33:17 +00:00
2012-05-27 11:09:01 +00:00
case "const" :
2017-05-15 22:48:23 +00:00
next ( ) ;
var node = const _ ( ) ;
semicolon ( ) ;
return node ;
2012-05-27 11:09:01 +00:00
case "with" :
2016-06-12 16:58:20 +00:00
if ( S . input . has _directive ( "use strict" ) ) {
2017-02-26 19:40:54 +00:00
croak ( "Strict mode may not include a with statement" ) ;
2016-06-12 16:58:20 +00:00
}
2017-05-15 15:02:55 +00:00
next ( ) ;
2012-05-27 11:09:01 +00:00
return new AST _With ( {
expression : parenthesised ( ) ,
body : statement ( )
} ) ;
2016-02-27 12:24:18 +00:00
case "export" :
2017-09-28 10:43:09 +00:00
if ( ! is _token ( peek ( ) , "punc" , "(" ) ) {
next ( ) ;
return export _ ( ) ;
}
2012-05-27 11:09:01 +00:00
}
}
2017-02-24 00:49:19 +00:00
unexpected ( ) ;
2012-05-27 11:09:01 +00:00
} ) ;
function labeled _statement ( ) {
2012-08-19 12:57:50 +00:00
var label = as _symbol ( AST _Label ) ;
2016-05-26 15:00:37 +00:00
if ( label . name === "yield" && is _in _generator ( ) ) {
// Ecma-262, 12.1.1 Static Semantics: Early Errors
2017-02-26 20:37:48 +00:00
token _error ( S . prev , "Yield cannot be used as label inside generators" ) ;
2016-05-26 15:00:37 +00:00
}
2017-06-14 22:15:48 +00:00
if ( label . name === "await" && is _in _async ( ) ) {
token _error ( S . prev , "await cannot be used as label inside async function" ) ;
}
2012-08-19 12:57:50 +00:00
if ( find _if ( function ( l ) { return l . name == label . name } , S . labels ) ) {
// ECMA-262, 12.12: An ECMAScript program is considered
// syntactically incorrect if it contains a
// LabelledStatement that is enclosed by a
// LabelledStatement with the same Identifier as label.
2017-02-26 19:40:54 +00:00
croak ( "Label " + label . name + " defined twice" ) ;
2012-08-19 12:57:50 +00:00
}
2012-05-27 11:09:01 +00:00
expect ( ":" ) ;
S . labels . push ( label ) ;
2012-10-04 05:49:18 +00:00
var stat = statement ( ) ;
2012-05-27 11:09:01 +00:00
S . labels . pop ( ) ;
2013-09-02 16:36:16 +00:00
if ( ! ( stat instanceof AST _IterationStatement ) ) {
// check for `continue` that refers to this label.
// those should be reported as syntax errors.
// https://github.com/mishoo/UglifyJS2/issues/287
label . references . forEach ( function ( ref ) {
if ( ref instanceof AST _Continue ) {
ref = ref . label . start ;
2017-02-26 19:40:54 +00:00
croak ( "Continue label `" + label . name + "` refers to non-IterationStatement." ,
2013-09-02 16:36:16 +00:00
ref . line , ref . col , ref . pos ) ;
}
} ) ;
}
2012-09-03 09:05:10 +00:00
return new AST _LabeledStatement ( { body : stat , label : label } ) ;
2012-05-27 11:09:01 +00:00
} ;
2012-10-11 10:00:58 +00:00
function simple _statement ( tmp ) {
return new AST _SimpleStatement ( { body : ( tmp = expression ( true ) , semicolon ( ) , tmp ) } ) ;
2012-05-27 11:09:01 +00:00
} ;
function break _cont ( type ) {
2013-09-02 16:36:16 +00:00
var label = null , ldef ;
2012-05-27 11:09:01 +00:00
if ( ! can _insert _semicolon ( ) ) {
2012-08-19 12:57:50 +00:00
label = as _symbol ( AST _LabelRef , true ) ;
2012-05-27 11:09:01 +00:00
}
2012-08-19 12:57:50 +00:00
if ( label != null ) {
2013-09-02 16:36:16 +00:00
ldef = find _if ( function ( l ) { return l . name == label . name } , S . labels ) ;
if ( ! ldef )
2017-02-26 19:40:54 +00:00
croak ( "Undefined label " + label . name ) ;
2013-09-02 16:36:16 +00:00
label . thedef = ldef ;
2012-05-27 11:09:01 +00:00
}
else if ( S . in _loop == 0 )
2017-02-26 19:40:54 +00:00
croak ( type . TYPE + " not inside a loop or switch" ) ;
2012-05-27 11:09:01 +00:00
semicolon ( ) ;
2013-09-02 16:36:16 +00:00
var stat = new type ( { label : label } ) ;
if ( ldef ) ldef . references . push ( stat ) ;
return stat ;
2012-05-27 11:09:01 +00:00
} ;
function for _ ( ) {
expect ( "(" ) ;
var init = null ;
if ( ! is ( "punc" , ";" ) ) {
2015-09-06 20:33:17 +00:00
init =
is ( "keyword" , "var" ) ? ( next ( ) , var _ ( true ) ) :
is ( "keyword" , "let" ) ? ( next ( ) , let _ ( true ) ) :
2016-03-27 11:21:39 +00:00
is ( "keyword" , "const" ) ? ( next ( ) , const _ ( true ) ) :
2015-09-06 20:33:17 +00:00
expression ( true , true ) ;
2015-04-13 00:25:46 +00:00
var is _in = is ( "operator" , "in" ) ;
2015-10-26 20:56:59 +00:00
var is _of = is ( "name" , "of" ) ;
2015-04-13 00:25:46 +00:00
if ( is _in || is _of ) {
2017-06-25 08:02:46 +00:00
if ( init instanceof AST _Definitions ) {
2017-06-22 20:14:30 +00:00
if ( init . definitions . length > 1 )
croak ( "Only one variable declaration allowed in for..in loop" , init . start . line , init . start . col , init . start . pos ) ;
2017-06-25 08:02:46 +00:00
} else if ( ! ( is _assignable ( init ) || ( init = to _destructuring ( init ) ) instanceof AST _Destructuring ) ) {
2017-06-22 20:14:30 +00:00
croak ( "Invalid left-hand side in for..in loop" , init . start . line , init . start . col , init . start . pos ) ;
}
2012-05-27 11:09:01 +00:00
next ( ) ;
2015-04-13 00:25:46 +00:00
if ( is _in ) {
return for _in ( init ) ;
} else {
return for _of ( init ) ;
}
2012-05-27 11:09:01 +00:00
}
}
return regular _for ( init ) ;
} ;
function regular _for ( init ) {
expect ( ";" ) ;
2012-10-11 10:00:58 +00:00
var test = is ( "punc" , ";" ) ? null : expression ( true ) ;
2012-05-27 11:09:01 +00:00
expect ( ";" ) ;
2012-10-11 10:00:58 +00:00
var step = is ( "punc" , ")" ) ? null : expression ( true ) ;
2012-05-27 11:09:01 +00:00
expect ( ")" ) ;
return new AST _For ( {
init : init ,
condition : test ,
step : step ,
body : in _loop ( statement )
} ) ;
} ;
2015-04-13 00:25:46 +00:00
function for _of ( init ) {
2016-03-27 11:21:39 +00:00
var lhs = init instanceof AST _Definitions ? init . definitions [ 0 ] . name : null ;
2015-04-13 00:25:46 +00:00
var obj = expression ( true ) ;
expect ( ")" ) ;
return new AST _ForOf ( {
init : init ,
name : lhs ,
object : obj ,
body : in _loop ( statement )
} ) ;
} ;
2012-05-27 11:09:01 +00:00
function for _in ( init ) {
2016-03-27 11:21:39 +00:00
var lhs = init instanceof AST _Definitions ? init . definitions [ 0 ] . name : null ;
2012-10-11 10:00:58 +00:00
var obj = expression ( true ) ;
2012-05-27 11:09:01 +00:00
expect ( ")" ) ;
return new AST _ForIn ( {
init : init ,
2012-05-27 14:25:31 +00:00
name : lhs ,
2012-05-27 11:09:01 +00:00
object : obj ,
body : in _loop ( statement )
} ) ;
} ;
2017-06-23 21:26:35 +00:00
var arrow _function = function ( start , argnames , is _async ) {
2017-12-25 17:46:22 +00:00
if ( has _newline _before ( S . token ) ) {
2017-02-26 20:37:48 +00:00
croak ( "Unexpected newline before arrow (=>)" ) ;
2016-09-06 23:00:07 +00:00
}
2015-01-11 20:07:19 +00:00
expect _token ( "arrow" , "=>" ) ;
2017-06-23 21:26:35 +00:00
var body = _function _body ( is ( "punc" , "{" ) , false , is _async ) ;
2015-01-11 20:07:19 +00:00
return new AST _Arrow ( {
2017-05-24 09:45:18 +00:00
start : start ,
2015-08-03 23:14:18 +00:00
end : body . end ,
2017-06-23 21:26:35 +00:00
async : is _async ,
2015-08-03 23:14:18 +00:00
argnames : argnames ,
body : body
2015-01-11 20:07:19 +00:00
} ) ;
} ;
2017-12-17 16:11:52 +00:00
var function _ = function ( ctor , is _generator _property , is _async , is _export _default ) {
2017-06-14 22:15:48 +00:00
if ( is _generator _property && is _async ) croak ( "generators cannot be async" ) ;
2017-12-17 16:11:52 +00:00
var start = S . token ;
2015-01-15 03:03:38 +00:00
2013-10-30 09:50:22 +00:00
var in _statement = ctor === AST _Defun ;
2016-02-04 21:19:48 +00:00
var is _generator = is ( "operator" , "*" ) ;
if ( is _generator ) {
2017-06-14 22:15:48 +00:00
next ( ) ;
2016-02-04 21:19:48 +00:00
}
2013-10-30 09:50:22 +00:00
var name = is ( "name" ) ? as _symbol ( in _statement ? AST _SymbolDefun : AST _SymbolLambda ) : null ;
2017-12-17 16:11:52 +00:00
if ( in _statement && ! name ) {
if ( is _export _default ) {
ctor = AST _Function ;
} else {
unexpected ( ) ;
}
}
2015-01-15 03:03:38 +00:00
2017-09-30 18:10:41 +00:00
if ( name && ctor !== AST _Accessor && ! ( name instanceof AST _SymbolDeclaration ) )
unexpected ( prev ( ) ) ;
2017-10-01 04:42:40 +00:00
2016-08-20 20:32:29 +00:00
var args = parameters ( ) ;
2017-06-14 22:15:48 +00:00
var body = _function _body ( true , is _generator || is _generator _property , is _async , name , args ) ;
2012-05-27 11:09:01 +00:00
return new ctor ( {
2015-01-15 03:03:38 +00:00
start : args . start ,
end : body . end ,
2016-02-04 21:19:48 +00:00
is _generator : is _generator ,
2017-06-14 22:15:48 +00:00
async : is _async ,
2015-01-15 03:03:38 +00:00
name : name ,
argnames : args ,
body : body
2012-05-27 11:09:01 +00:00
} ) ;
} ;
2016-08-20 20:32:29 +00:00
function track _used _binding _identifiers ( is _parameter , strict ) {
var parameters = { } ;
var duplicate = false ;
var default _assignment = false ;
var spread = false ;
var strict _mode = ! ! strict ;
var tracker = {
add _parameter : function ( token ) {
if ( parameters [ "$" + token . value ] !== undefined ) {
if ( duplicate === false ) {
duplicate = token ;
}
tracker . check _strict ( ) ;
} else {
parameters [ "$" + token . value ] = true ;
if ( is _parameter ) {
switch ( token . value ) {
case "arguments" :
case "eval" :
case "yield" :
if ( strict _mode ) {
2017-02-26 20:37:48 +00:00
token _error ( token , "Unexpected " + token . value + " identifier as parameter inside strict mode" ) ;
2016-08-20 20:32:29 +00:00
}
break ;
default :
if ( RESERVED _WORDS ( token . value ) ) {
unexpected ( ) ;
}
}
}
}
} ,
mark _default _assignment : function ( token ) {
if ( default _assignment === false ) {
default _assignment = token ;
}
} ,
mark _spread : function ( token ) {
if ( spread === false ) {
spread = token ;
}
} ,
mark _strict _mode : function ( ) {
strict _mode = true ;
} ,
is _strict : function ( ) {
return default _assignment !== false || spread !== false || strict _mode
} ,
check _strict : function ( ) {
if ( tracker . is _strict ( ) && duplicate !== false ) {
2017-02-26 20:37:48 +00:00
token _error ( duplicate , "Parameter " + duplicate . value + " was used already" ) ;
2016-08-20 20:32:29 +00:00
}
}
} ;
return tracker ;
}
function parameters ( ) {
var start = S . token ;
var params = [ ] ;
var used _parameters = track _used _binding _identifiers ( true , S . input . has _directive ( "use strict" ) ) ;
expect ( "(" ) ;
while ( ! is ( "punc" , ")" ) ) {
var param = parameter ( used _parameters ) ;
params . push ( param ) ;
2017-06-24 09:34:14 +00:00
if ( ! is ( "punc" , ")" ) ) {
expect ( "," ) ;
if ( is ( "punc" , ")" ) && options . ecma < 8 ) unexpected ( ) ;
}
2016-08-20 20:32:29 +00:00
if ( param instanceof AST _Expansion ) {
break ;
}
}
next ( ) ;
return params ;
}
function parameter ( used _parameters , symbol _type ) {
var param ;
var expand = false ;
if ( used _parameters === undefined ) {
used _parameters = track _used _binding _identifiers ( true , S . input . has _directive ( "use strict" ) ) ;
}
if ( is ( "expand" , "..." ) ) {
expand = S . token ;
used _parameters . mark _spread ( S . token ) ;
next ( ) ;
}
param = binding _element ( used _parameters , symbol _type ) ;
if ( is ( "operator" , "=" ) && expand === false ) {
used _parameters . mark _default _assignment ( S . token ) ;
next ( ) ;
2017-02-24 00:49:19 +00:00
param = new AST _DefaultAssign ( {
start : param . start ,
left : param ,
operator : "=" ,
right : expression ( false ) ,
end : S . token
} ) ;
2016-08-20 20:32:29 +00:00
}
if ( expand !== false ) {
if ( ! is ( "punc" , ")" ) ) {
unexpected ( ) ;
}
param = new AST _Expansion ( {
start : expand ,
expression : param ,
end : expand
} ) ;
}
used _parameters . check _strict ( ) ;
return param ;
}
function binding _element ( used _parameters , symbol _type ) {
var elements = [ ] ;
var first = true ;
var is _expand = false ;
var expand _token ;
var first _token = S . token ;
if ( used _parameters === undefined ) {
used _parameters = track _used _binding _identifiers ( false , S . input . has _directive ( "use strict" ) ) ;
}
symbol _type = symbol _type === undefined ? AST _SymbolFunarg : symbol _type ;
if ( is ( "punc" , "[" ) ) {
next ( ) ;
while ( ! is ( "punc" , "]" ) ) {
if ( first ) {
first = false ;
} else {
expect ( "," ) ;
}
if ( is ( "expand" , "..." ) ) {
is _expand = true ;
expand _token = S . token ;
used _parameters . mark _spread ( S . token ) ;
next ( ) ;
}
if ( is ( "punc" ) ) {
switch ( S . token . value ) {
case "," :
elements . push ( new AST _Hole ( {
start : S . token ,
end : S . token
} ) ) ;
continue ;
2016-09-06 23:00:07 +00:00
case "]" : // Trailing comma after last element
break ;
2016-08-20 20:32:29 +00:00
case "[" :
case "{" :
elements . push ( binding _element ( used _parameters , symbol _type ) ) ;
break ;
default :
unexpected ( ) ;
}
} else if ( is ( "name" ) ) {
used _parameters . add _parameter ( S . token ) ;
elements . push ( new symbol _type ( {
start : S . token ,
name : S . token . value ,
end : S . token
} ) ) ;
next ( ) ;
} else {
2017-02-26 20:37:48 +00:00
croak ( "Invalid function parameter" ) ;
2016-08-20 20:32:29 +00:00
}
if ( is ( "operator" , "=" ) && is _expand === false ) {
used _parameters . mark _default _assignment ( S . token ) ;
next ( ) ;
2017-02-24 00:49:19 +00:00
elements [ elements . length - 1 ] = new AST _DefaultAssign ( {
start : elements [ elements . length - 1 ] . start ,
left : elements [ elements . length - 1 ] ,
operator : "=" ,
right : expression ( false ) ,
end : S . token
} ) ;
2016-08-20 20:32:29 +00:00
}
if ( is _expand ) {
if ( ! is ( "punc" , "]" ) ) {
2017-08-02 05:47:58 +00:00
croak ( "Rest element must be last element" ) ;
2016-08-20 20:32:29 +00:00
}
elements [ elements . length - 1 ] = new AST _Expansion ( {
start : expand _token ,
expression : elements [ elements . length - 1 ] ,
end : expand _token
} ) ;
}
}
expect ( "]" ) ;
used _parameters . check _strict ( ) ;
return new AST _Destructuring ( {
start : first _token ,
names : elements ,
is _array : true ,
end : prev ( )
} ) ;
} else if ( is ( "punc" , "{" ) ) {
next ( ) ;
while ( ! is ( "punc" , "}" ) ) {
if ( first ) {
first = false ;
} else {
expect ( "," ) ;
}
2017-08-02 05:47:58 +00:00
if ( is ( "expand" , "..." ) ) {
is _expand = true ;
expand _token = S . token ;
used _parameters . mark _spread ( S . token ) ;
next ( ) ;
}
2016-08-20 20:32:29 +00:00
if ( is ( "name" ) && ( is _token ( peek ( ) , "punc" ) || is _token ( peek ( ) , "operator" ) ) && [ "," , "}" , "=" ] . indexOf ( peek ( ) . value ) !== - 1 ) {
used _parameters . add _parameter ( S . token ) ;
2017-08-02 05:47:58 +00:00
var value = new symbol _type ( {
start : S . token ,
name : S . token . value ,
end : S . token ,
} ) ;
if ( is _expand ) {
elements . push ( new AST _Expansion ( {
start : expand _token ,
expression : value ,
end : value . end ,
} ) ) ;
} else {
elements . push ( new AST _ObjectKeyVal ( {
start : prev ( ) ,
key : S . token . value ,
value : value ,
end : value . end ,
} ) ) ;
}
2016-08-20 20:32:29 +00:00
next ( ) ;
} else if ( is ( "punc" , "}" ) ) {
continue ; // Allow trailing hole
} else {
var property _token = S . token ;
var property = as _property _name ( ) ;
if ( property === null ) {
unexpected ( prev ( ) ) ;
} else if ( prev ( ) . type === "name" && ! is ( "punc" , ":" ) ) {
2017-02-24 00:49:19 +00:00
elements . push ( new AST _ObjectKeyVal ( {
2016-08-20 20:32:29 +00:00
start : prev ( ) ,
2017-02-24 00:49:19 +00:00
key : property ,
value : new symbol _type ( {
start : prev ( ) ,
name : property ,
end : prev ( )
} ) ,
2016-08-20 20:32:29 +00:00
end : prev ( )
} ) ) ;
} else {
expect ( ":" ) ;
elements . push ( new AST _ObjectKeyVal ( {
start : property _token ,
quote : property _token . quote ,
key : property ,
2017-02-24 00:49:19 +00:00
value : binding _element ( used _parameters , symbol _type ) ,
end : prev ( )
2016-08-20 20:32:29 +00:00
} ) ) ;
}
}
2017-08-02 05:47:58 +00:00
if ( is _expand ) {
if ( ! is ( "punc" , "}" ) ) {
croak ( "Rest element must be last element" ) ;
}
}
else if ( is ( "operator" , "=" ) ) {
2016-08-20 20:32:29 +00:00
used _parameters . mark _default _assignment ( S . token ) ;
next ( ) ;
2017-02-24 00:49:19 +00:00
elements [ elements . length - 1 ] . value = new AST _DefaultAssign ( {
start : elements [ elements . length - 1 ] . value . start ,
left : elements [ elements . length - 1 ] . value ,
operator : "=" ,
right : expression ( false ) ,
end : S . token
} ) ;
2016-08-20 20:32:29 +00:00
}
}
expect ( "}" ) ;
used _parameters . check _strict ( ) ;
return new AST _Destructuring ( {
start : first _token ,
names : elements ,
is _array : false ,
end : prev ( )
} ) ;
} else if ( is ( "name" ) ) {
used _parameters . add _parameter ( S . token ) ;
next ( ) ;
return new symbol _type ( {
start : prev ( ) ,
name : prev ( ) . value ,
end : prev ( )
} ) ;
} else {
2017-02-26 20:37:48 +00:00
croak ( "Invalid function parameter" ) ;
2016-08-20 20:32:29 +00:00
}
}
2017-06-24 09:34:14 +00:00
function params _or _seq _ ( allow _arrows , maybe _sequence ) {
var spread _token ;
var invalid _sequence ;
var trailing _comma ;
2015-01-15 03:03:38 +00:00
var a = [ ] ;
2017-06-24 09:34:14 +00:00
expect ( "(" ) ;
2015-01-15 03:03:38 +00:00
while ( ! is ( "punc" , ")" ) ) {
2017-06-24 09:34:14 +00:00
if ( spread _token ) unexpected ( spread _token ) ;
2015-04-13 00:26:26 +00:00
if ( is ( "expand" , "..." ) ) {
2017-06-24 09:34:14 +00:00
spread _token = S . token ;
if ( maybe _sequence ) invalid _sequence = S . token ;
2015-04-13 00:26:26 +00:00
next ( ) ;
a . push ( new AST _Expansion ( {
start : prev ( ) ,
2017-05-24 09:45:18 +00:00
expression : expression ( ) ,
2015-04-13 00:26:26 +00:00
end : S . token ,
} ) ) ;
} else {
2017-05-24 09:45:18 +00:00
a . push ( expression ( ) ) ;
2015-04-13 00:26:26 +00:00
}
2017-06-24 09:34:14 +00:00
if ( ! is ( "punc" , ")" ) ) {
expect ( "," ) ;
if ( is ( "punc" , ")" ) ) {
if ( options . ecma < 8 ) unexpected ( ) ;
trailing _comma = prev ( ) ;
if ( maybe _sequence ) invalid _sequence = trailing _comma ;
}
}
}
expect ( ")" ) ;
if ( allow _arrows && is ( "arrow" , "=>" ) ) {
if ( spread _token && trailing _comma ) unexpected ( trailing _comma ) ;
} else if ( invalid _sequence ) {
unexpected ( invalid _sequence ) ;
2015-01-15 03:03:38 +00:00
}
2017-05-24 09:45:18 +00:00
return a ;
2015-01-15 03:03:38 +00:00
}
2017-06-14 22:15:48 +00:00
function _function _body ( block , generator , is _async , name , args ) {
2015-01-15 03:03:38 +00:00
var loop = S . in _loop ;
var labels = S . labels ;
2016-05-26 15:00:37 +00:00
var current _generator = S . in _generator ;
2017-06-14 22:15:48 +00:00
var current _async = S . in _async ;
2015-01-15 03:03:38 +00:00
++ S . in _function ;
2016-05-26 15:00:37 +00:00
if ( generator )
S . in _generator = S . in _function ;
2017-06-14 22:15:48 +00:00
if ( is _async )
S . in _async = S . in _function ;
2015-08-03 23:14:18 +00:00
if ( block )
S . in _directives = true ;
2015-01-15 03:03:38 +00:00
S . in _loop = 0 ;
S . labels = [ ] ;
2016-06-12 15:29:42 +00:00
if ( block ) {
S . input . push _directives _stack ( ) ;
2015-08-03 23:14:18 +00:00
var a = block _ ( ) ;
2017-05-06 23:18:15 +00:00
if ( S . input . has _directive ( "use strict" ) ) {
if ( name ) strict _verify _symbol ( name ) ;
if ( args ) args . forEach ( strict _verify _symbol ) ;
}
2016-06-12 15:29:42 +00:00
S . input . pop _directives _stack ( ) ;
} else {
2015-08-03 23:14:18 +00:00
var a = expression ( false ) ;
2016-06-12 15:29:42 +00:00
}
2015-01-15 03:03:38 +00:00
-- S . in _function ;
S . in _loop = loop ;
S . labels = labels ;
2016-05-26 15:00:37 +00:00
S . in _generator = current _generator ;
2017-06-14 22:15:48 +00:00
S . in _async = current _async ;
2015-01-15 03:03:38 +00:00
return a ;
}
2017-06-14 22:15:48 +00:00
function _await _expression ( ) {
// Previous token must be "await" and not be interpreted as an identifier
if ( ! is _in _async ( ) ) {
croak ( "Unexpected await expression outside async function" ,
S . prev . line , S . prev . col , S . prev . pos ) ;
}
// the await expression is parsed as a unary expression in Babel
return new AST _Await ( {
expression : maybe _unary ( true ) ,
} ) ;
}
2016-05-26 15:00:37 +00:00
function _yield _expression ( ) {
// Previous token must be keyword yield and not be interpret as an identifier
if ( ! is _in _generator ( ) ) {
2017-02-26 20:37:48 +00:00
croak ( "Unexpected yield expression outside generator function" ,
2016-06-22 15:12:23 +00:00
S . prev . line , S . prev . col , S . prev . pos ) ;
2016-05-26 15:00:37 +00:00
}
var star = false ;
var has _expression = true ;
2016-06-11 19:41:16 +00:00
// Attempt to get expression or star (and then the mandatory expression)
// behind yield on the same line.
//
// If nothing follows on the same line of the yieldExpression,
// it should default to the value `undefined` for yield to return.
// In that case, the `undefined` stored as `null` in ast.
//
// Note 1: It isn't allowed for yield* to close without an expression
// Note 2: If there is a nlb between yield and star, it is interpret as
// yield <explicit undefined> <inserted automatic semicolon> *
if ( can _insert _semicolon ( ) ||
2016-05-26 15:00:37 +00:00
( is ( "punc" ) && PUNC _AFTER _EXPRESSION ( S . token . value ) ) ) {
has _expression = false ;
2016-06-11 19:41:16 +00:00
} else if ( is ( "operator" , "*" ) ) {
star = true ;
next ( ) ;
2016-05-26 15:00:37 +00:00
}
return new AST _Yield ( {
is _star : star ,
expression : has _expression ? expression ( ) : null
} ) ;
}
2012-05-27 11:09:01 +00:00
function if _ ( ) {
var cond = parenthesised ( ) , body = statement ( ) , belse = null ;
if ( is ( "keyword" , "else" ) ) {
next ( ) ;
belse = statement ( ) ;
}
return new AST _If ( {
condition : cond ,
2012-09-03 09:11:44 +00:00
body : body ,
2012-05-27 11:09:01 +00:00
alternative : belse
} ) ;
} ;
2012-09-05 08:31:02 +00:00
function block _ ( ) {
2012-05-27 11:09:01 +00:00
expect ( "{" ) ;
var a = [ ] ;
while ( ! is ( "punc" , "}" ) ) {
if ( is ( "eof" ) ) unexpected ( ) ;
a . push ( statement ( ) ) ;
}
next ( ) ;
2012-09-05 08:31:02 +00:00
return a ;
2012-05-27 11:09:01 +00:00
} ;
2012-10-11 10:00:58 +00:00
function switch _body _ ( ) {
2012-05-27 11:09:01 +00:00
expect ( "{" ) ;
2012-10-11 10:00:58 +00:00
var a = [ ] , cur = null , branch = null , tmp ;
2012-05-27 11:09:01 +00:00
while ( ! is ( "punc" , "}" ) ) {
if ( is ( "eof" ) ) unexpected ( ) ;
if ( is ( "keyword" , "case" ) ) {
2012-05-27 14:25:31 +00:00
if ( branch ) branch . end = prev ( ) ;
2012-05-27 11:09:01 +00:00
cur = [ ] ;
2012-05-27 14:25:31 +00:00
branch = new AST _Case ( {
2012-10-11 10:00:58 +00:00
start : ( tmp = S . token , next ( ) , tmp ) ,
expression : expression ( true ) ,
2012-05-27 14:25:31 +00:00
body : cur
} ) ;
a . push ( branch ) ;
2012-05-27 11:09:01 +00:00
expect ( ":" ) ;
}
else if ( is ( "keyword" , "default" ) ) {
2012-05-27 14:25:31 +00:00
if ( branch ) branch . end = prev ( ) ;
2012-05-27 11:09:01 +00:00
cur = [ ] ;
2012-05-27 14:25:31 +00:00
branch = new AST _Default ( {
2012-10-11 10:00:58 +00:00
start : ( tmp = S . token , next ( ) , expect ( ":" ) , tmp ) ,
2012-05-27 14:25:31 +00:00
body : cur
2012-10-11 10:00:58 +00:00
} ) ;
2012-05-27 14:25:31 +00:00
a . push ( branch ) ;
2012-05-27 11:09:01 +00:00
}
else {
if ( ! cur ) unexpected ( ) ;
cur . push ( statement ( ) ) ;
}
}
2012-05-27 14:25:31 +00:00
if ( branch ) branch . end = prev ( ) ;
2012-05-27 11:09:01 +00:00
next ( ) ;
2012-10-03 12:52:01 +00:00
return a ;
2012-10-11 10:00:58 +00:00
} ;
2012-05-27 11:09:01 +00:00
function try _ ( ) {
2012-09-05 08:31:02 +00:00
var body = block _ ( ) , bcatch = null , bfinally = null ;
2012-05-27 11:09:01 +00:00
if ( is ( "keyword" , "catch" ) ) {
2012-05-27 14:25:31 +00:00
var start = S . token ;
2012-05-27 11:09:01 +00:00
next ( ) ;
expect ( "(" ) ;
2016-08-20 20:32:29 +00:00
var name = parameter ( undefined , AST _SymbolCatch ) ;
2012-05-27 11:09:01 +00:00
expect ( ")" ) ;
bcatch = new AST _Catch ( {
2012-05-27 14:25:31 +00:00
start : start ,
2012-05-27 11:09:01 +00:00
argname : name ,
2012-09-05 08:31:02 +00:00
body : block _ ( ) ,
2012-05-27 14:25:31 +00:00
end : prev ( )
2012-05-27 11:09:01 +00:00
} ) ;
}
if ( is ( "keyword" , "finally" ) ) {
2012-05-27 14:25:31 +00:00
var start = S . token ;
2012-05-27 11:09:01 +00:00
next ( ) ;
2012-05-27 14:25:31 +00:00
bfinally = new AST _Finally ( {
start : start ,
2012-09-05 08:31:02 +00:00
body : block _ ( ) ,
2012-05-27 14:25:31 +00:00
end : prev ( )
} ) ;
2012-05-27 11:09:01 +00:00
}
if ( ! bcatch && ! bfinally )
2017-02-26 19:40:54 +00:00
croak ( "Missing catch/finally blocks" ) ;
2012-05-27 11:09:01 +00:00
return new AST _Try ( {
2012-09-05 08:31:02 +00:00
body : body ,
2012-05-27 11:09:01 +00:00
bcatch : bcatch ,
bfinally : bfinally
} ) ;
} ;
2016-02-28 14:06:51 +00:00
function vardefs ( no _in , kind ) {
2012-05-27 11:09:01 +00:00
var a = [ ] ;
2015-08-13 23:20:21 +00:00
var def ;
2012-05-27 11:09:01 +00:00
for ( ; ; ) {
2016-02-28 14:06:51 +00:00
var sym _type =
kind === "var" ? AST _SymbolVar :
kind === "const" ? AST _SymbolConst :
kind === "let" ? AST _SymbolLet : null ;
2015-08-13 23:20:21 +00:00
if ( is ( "punc" , "{" ) || is ( "punc" , "[" ) ) {
def = new AST _VarDef ( {
start : S . token ,
2016-08-20 20:32:29 +00:00
name : binding _element ( undefined , sym _type ) ,
2015-08-14 01:11:38 +00:00
value : is ( "operator" , "=" ) ? ( expect _token ( "operator" , "=" ) , expression ( false , no _in ) ) : null ,
2015-08-13 23:20:21 +00:00
end : prev ( )
} ) ;
} else {
def = new AST _VarDef ( {
start : S . token ,
2015-08-14 00:16:54 +00:00
name : as _symbol ( sym _type ) ,
2017-05-06 23:18:15 +00:00
value : is ( "operator" , "=" )
? ( next ( ) , expression ( false , no _in ) )
2017-05-10 03:36:03 +00:00
: ! no _in && kind === "const" && S . input . has _directive ( "use strict" )
2017-05-06 23:18:15 +00:00
? croak ( "Missing initializer in const declaration" ) : null ,
2015-08-13 23:20:21 +00:00
end : prev ( )
2017-09-28 10:43:09 +00:00
} ) ;
if ( def . name . name == "import" ) croak ( "Unexpected token: import" ) ;
2015-08-13 23:20:21 +00:00
}
a . push ( def ) ;
2012-05-27 11:09:01 +00:00
if ( ! is ( "punc" , "," ) )
break ;
next ( ) ;
}
return a ;
} ;
2012-05-27 14:25:31 +00:00
var var _ = function ( no _in ) {
2012-05-27 11:09:01 +00:00
return new AST _Var ( {
2012-05-27 14:25:31 +00:00
start : prev ( ) ,
2016-02-28 14:06:51 +00:00
definitions : vardefs ( no _in , "var" ) ,
2012-05-27 14:25:31 +00:00
end : prev ( )
2012-05-27 11:09:01 +00:00
} ) ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
2015-09-06 20:33:17 +00:00
var let _ = function ( no _in ) {
return new AST _Let ( {
start : prev ( ) ,
2016-02-28 14:06:51 +00:00
definitions : vardefs ( no _in , "let" ) ,
2015-09-06 20:33:17 +00:00
end : prev ( )
} ) ;
} ;
2017-05-10 03:36:03 +00:00
var const _ = function ( no _in ) {
2012-05-27 11:09:01 +00:00
return new AST _Const ( {
2012-05-27 14:25:31 +00:00
start : prev ( ) ,
2017-05-10 03:36:03 +00:00
definitions : vardefs ( no _in , "const" ) ,
2012-05-27 14:25:31 +00:00
end : prev ( )
2012-05-27 11:09:01 +00:00
} ) ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
2015-08-06 19:27:46 +00:00
var new _ = function ( allow _calls ) {
2012-05-27 14:25:31 +00:00
var start = S . token ;
expect _token ( "operator" , "new" ) ;
2015-11-21 14:48:23 +00:00
if ( is ( "punc" , "." ) ) {
next ( ) ;
2016-06-25 17:32:09 +00:00
expect _token ( "name" , "target" ) ;
2015-11-21 14:48:23 +00:00
return subscripts ( new AST _NewTarget ( {
start : start ,
end : prev ( )
} ) , allow _calls ) ;
}
2012-05-27 11:09:01 +00:00
var newexp = expr _atom ( false ) , args ;
if ( is ( "punc" , "(" ) ) {
next ( ) ;
2017-06-24 09:34:14 +00:00
args = expr _list ( ")" , options . ecma >= 8 ) ;
2012-05-27 11:09:01 +00:00
} else {
args = [ ] ;
}
return subscripts ( new AST _New ( {
2012-05-27 14:25:31 +00:00
start : start ,
2012-05-27 11:09:01 +00:00
expression : newexp ,
2012-05-27 14:25:31 +00:00
args : args ,
end : prev ( )
2015-08-06 19:27:46 +00:00
} ) , allow _calls ) ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
function as _atom _node ( ) {
var tok = S . token , ret ;
switch ( tok . type ) {
case "name" :
2013-10-30 09:50:22 +00:00
ret = _make _symbol ( AST _SymbolRef ) ;
break ;
2012-05-27 11:09:01 +00:00
case "num" :
2015-11-11 20:15:25 +00:00
ret = new AST _Number ( { start : tok , end : tok , value : tok . value } ) ;
2012-05-27 11:09:01 +00:00
break ;
case "string" :
2015-01-27 20:26:27 +00:00
ret = new AST _String ( {
start : tok ,
end : tok ,
value : tok . value ,
quote : tok . quote
} ) ;
2012-05-27 11:09:01 +00:00
break ;
case "regexp" :
2012-10-09 13:25:45 +00:00
ret = new AST _RegExp ( { start : tok , end : tok , value : tok . value } ) ;
2012-05-27 11:09:01 +00:00
break ;
case "atom" :
switch ( tok . value ) {
case "false" :
ret = new AST _False ( { start : tok , end : tok } ) ;
break ;
case "true" :
ret = new AST _True ( { start : tok , end : tok } ) ;
break ;
case "null" :
ret = new AST _Null ( { start : tok , end : tok } ) ;
break ;
}
break ;
}
next ( ) ;
return ret ;
} ;
2017-05-24 09:45:18 +00:00
function to _fun _args ( ex , _ , _ _ , default _seen _above ) {
var insert _default = function ( ex , default _value ) {
if ( default _value ) {
return new AST _DefaultAssign ( {
start : ex . start ,
left : ex ,
operator : "=" ,
right : default _value ,
end : default _value . end
} ) ;
}
return ex ;
}
if ( ex instanceof AST _Object ) {
return insert _default ( new AST _Destructuring ( {
start : ex . start ,
end : ex . end ,
is _array : false ,
names : ex . properties . map ( to _fun _args )
} ) , default _seen _above ) ;
} else if ( ex instanceof AST _ObjectKeyVal ) {
ex . value = to _fun _args ( ex . value , 0 , [ ex . key ] ) ;
return insert _default ( ex , default _seen _above ) ;
} else if ( ex instanceof AST _Hole ) {
return ex ;
} else if ( ex instanceof AST _Destructuring ) {
ex . names = ex . names . map ( to _fun _args ) ;
return insert _default ( ex , default _seen _above ) ;
} else if ( ex instanceof AST _SymbolRef ) {
return insert _default ( new AST _SymbolFunarg ( {
name : ex . name ,
start : ex . start ,
end : ex . end
} ) , default _seen _above ) ;
} else if ( ex instanceof AST _Expansion ) {
ex . expression = to _fun _args ( ex . expression ) ;
return insert _default ( ex , default _seen _above ) ;
} else if ( ex instanceof AST _Array ) {
return insert _default ( new AST _Destructuring ( {
start : ex . start ,
end : ex . end ,
is _array : true ,
names : ex . elements . map ( to _fun _args )
} ) , default _seen _above ) ;
} else if ( ex instanceof AST _Assign ) {
return insert _default ( to _fun _args ( ex . left , undefined , undefined , ex . right ) , default _seen _above ) ;
} else if ( ex instanceof AST _DefaultAssign ) {
ex . left = to _fun _args ( ex . left , 0 , [ ex . left ] ) ;
return ex ;
} else {
croak ( "Invalid function parameter" , ex . start . line , ex . start . col ) ;
}
}
2017-06-23 21:26:35 +00:00
var expr _atom = function ( allow _calls , allow _arrows ) {
2012-05-27 11:09:01 +00:00
if ( is ( "operator" , "new" ) ) {
2015-08-06 19:27:46 +00:00
return new _ ( allow _calls ) ;
2012-05-27 11:09:01 +00:00
}
2012-05-27 14:25:31 +00:00
var start = S . token ;
2017-06-23 21:26:35 +00:00
var async = is ( "name" , "async" ) && as _atom _node ( ) ;
2012-05-27 11:09:01 +00:00
if ( is ( "punc" ) ) {
2017-06-23 21:26:35 +00:00
switch ( S . token . value ) {
2012-05-27 11:09:01 +00:00
case "(" :
2017-06-23 21:26:35 +00:00
if ( async && ! allow _calls ) break ;
2017-06-24 09:34:14 +00:00
var exprs = params _or _seq _ ( allow _arrows , ! async ) ;
2017-06-23 21:26:35 +00:00
if ( allow _arrows && is ( "arrow" , "=>" ) ) {
return arrow _function ( start , exprs . map ( to _fun _args ) , ! ! async ) ;
2015-08-03 23:14:18 +00:00
}
2017-06-23 21:26:35 +00:00
var ex = async ? new AST _Call ( {
expression : async ,
args : exprs
} ) : exprs . length == 1 ? exprs [ 0 ] : new AST _Sequence ( {
2017-05-24 09:45:18 +00:00
expressions : exprs
} ) ;
2017-12-24 11:19:24 +00:00
if ( ex . start ) {
var len = start . comments _before . length ;
[ ] . unshift . apply ( ex . start . comments _before , start . comments _before ) ;
start . comments _before = ex . start . comments _before ;
start . comments _before _length = len ;
if ( len == 0 && start . comments _before . length > 0 ) {
var comment = start . comments _before [ 0 ] ;
if ( ! comment . nlb ) {
comment . nlb = start . nlb ;
start . nlb = false ;
}
2017-12-24 04:38:45 +00:00
}
2017-12-24 11:19:24 +00:00
start . comments _after = ex . start . comments _after ;
2017-12-24 04:38:45 +00:00
}
2017-02-27 06:54:47 +00:00
ex . start = start ;
2017-12-21 20:59:54 +00:00
var end = prev ( ) ;
2017-12-24 11:19:24 +00:00
if ( ex . end ) {
end . comments _before = ex . end . comments _before ;
[ ] . push . apply ( ex . end . comments _after , end . comments _after ) ;
end . comments _after = ex . end . comments _after ;
}
2017-12-21 20:59:54 +00:00
ex . end = end ;
2017-12-24 04:38:45 +00:00
if ( ex instanceof AST _Call ) mark _pure ( ex ) ;
2017-02-27 06:54:47 +00:00
return subscripts ( ex , allow _calls ) ;
2012-05-27 11:09:01 +00:00
case "[" :
return subscripts ( array _ ( ) , allow _calls ) ;
case "{" :
2017-06-16 04:18:18 +00:00
return subscripts ( object _or _destructuring _ ( ) , allow _calls ) ;
2012-05-27 11:09:01 +00:00
}
2017-06-23 21:26:35 +00:00
if ( ! async ) unexpected ( ) ;
2012-05-27 11:09:01 +00:00
}
2017-06-23 21:26:35 +00:00
if ( allow _arrows && is ( "name" ) && is _token ( peek ( ) , "arrow" ) ) {
var param = new AST _SymbolFunarg ( {
name : S . token . value ,
start : start ,
end : start ,
} ) ;
2017-06-14 22:15:48 +00:00
next ( ) ;
2017-06-23 21:26:35 +00:00
return arrow _function ( start , [ param ] , ! ! async ) ;
2017-06-14 22:15:48 +00:00
}
2012-05-27 11:09:01 +00:00
if ( is ( "keyword" , "function" ) ) {
next ( ) ;
2017-06-23 21:26:35 +00:00
var func = function _ ( AST _Function , false , ! ! async ) ;
2012-05-27 11:09:01 +00:00
func . start = start ;
func . end = prev ( ) ;
return subscripts ( func , allow _calls ) ;
}
2017-06-23 21:26:35 +00:00
if ( async ) return subscripts ( async , allow _calls ) ;
2015-10-27 00:40:46 +00:00
if ( is ( "keyword" , "class" ) ) {
next ( ) ;
2015-11-21 09:17:32 +00:00
var cls = class _ ( AST _ClassExpression ) ;
2015-10-27 00:40:46 +00:00
cls . start = start ;
cls . end = prev ( ) ;
return subscripts ( cls , allow _calls ) ;
}
2016-06-22 17:24:03 +00:00
if ( is ( "template_head" ) ) {
return subscripts ( template _string ( ) , allow _calls ) ;
}
2017-06-03 06:00:59 +00:00
if ( ATOMIC _START _TOKEN ( S . token . type ) ) {
2012-05-27 11:09:01 +00:00
return subscripts ( as _atom _node ( ) , allow _calls ) ;
}
unexpected ( ) ;
} ;
2015-09-05 21:32:57 +00:00
function template _string ( ) {
2016-06-22 17:24:03 +00:00
var segments = [ ] , start = S . token ;
2015-09-05 21:32:57 +00:00
2016-06-22 17:24:03 +00:00
segments . push ( new AST _TemplateSegment ( {
start : S . token ,
raw : S . token . raw ,
value : S . token . value ,
end : S . token
} ) ) ;
while ( S . token . end === false ) {
next ( ) ;
2017-11-16 17:34:57 +00:00
handle _regexp ( ) ;
segments . push ( expression ( true ) ) ;
2015-09-05 21:32:57 +00:00
2016-06-22 17:24:03 +00:00
if ( ! is _token ( "template_substitution" ) ) {
unexpected ( ) ;
}
2015-09-05 21:32:57 +00:00
2016-06-22 17:24:03 +00:00
segments . push ( new AST _TemplateSegment ( {
start : S . token ,
raw : S . token . raw ,
value : S . token . value ,
end : S . token
} ) ) ;
}
2015-09-05 21:32:57 +00:00
next ( ) ;
return new AST _TemplateString ( {
start : start ,
segments : segments ,
end : S . token
} ) ;
}
2012-05-27 11:09:01 +00:00
function expr _list ( closing , allow _trailing _comma , allow _empty ) {
var first = true , a = [ ] ;
while ( ! is ( "punc" , closing ) ) {
if ( first ) first = false ; else expect ( "," ) ;
if ( allow _trailing _comma && is ( "punc" , closing ) ) break ;
if ( is ( "punc" , "," ) && allow _empty ) {
2013-01-16 19:59:19 +00:00
a . push ( new AST _Hole ( { start : S . token , end : S . token } ) ) ;
2016-06-10 23:40:45 +00:00
} else if ( is ( "expand" , "..." ) ) {
next ( ) ;
2017-02-24 00:49:19 +00:00
a . push ( new AST _Expansion ( { start : prev ( ) , expression : expression ( ) , end : S . token } ) ) ;
2012-05-27 11:09:01 +00:00
} else {
a . push ( expression ( false ) ) ;
}
}
next ( ) ;
return a ;
} ;
2012-05-27 14:25:31 +00:00
var array _ = embed _tokens ( function ( ) {
expect ( "[" ) ;
2012-05-27 11:09:01 +00:00
return new AST _Array ( {
2012-09-21 11:19:05 +00:00
elements : expr _list ( "]" , ! options . strict , true )
2012-05-27 11:09:01 +00:00
} ) ;
2012-05-27 14:25:31 +00:00
} ) ;
2012-05-27 11:09:01 +00:00
2017-06-14 22:15:48 +00:00
var create _accessor = embed _tokens ( function ( is _generator , is _async ) {
return function _ ( AST _Accessor , is _generator , is _async ) ;
2017-02-20 09:14:53 +00:00
} ) ;
2017-06-16 04:18:18 +00:00
var object _or _destructuring _ = embed _tokens ( function object _or _destructuring _ ( ) {
2015-09-05 22:01:25 +00:00
var start = S . token , first = true , a = [ ] ;
2012-05-27 14:25:31 +00:00
expect ( "{" ) ;
2015-09-05 22:01:25 +00:00
while ( ! is ( "punc" , "}" ) ) {
if ( first ) first = false ; else expect ( "," ) ;
if ( ! options . strict && is ( "punc" , "}" ) )
// allow trailing comma
break ;
2017-08-02 05:47:58 +00:00
2016-07-05 22:40:28 +00:00
start = S . token ;
2017-08-02 05:47:58 +00:00
if ( start . type == "expand" ) {
next ( ) ;
a . push ( new AST _Expansion ( {
start : start ,
expression : expression ( false ) ,
end : prev ( ) ,
} ) ) ;
continue ;
}
2015-09-05 22:01:25 +00:00
var name = as _property _name ( ) ;
2017-02-24 00:49:19 +00:00
var value ;
// Check property and fetch value
2016-07-29 01:18:21 +00:00
if ( ! is ( "punc" , ":" ) ) {
2015-10-27 00:40:46 +00:00
var concise = concise _method _or _getset ( name , start ) ;
if ( concise ) {
a . push ( concise ) ;
2015-09-05 22:01:25 +00:00
continue ;
2012-05-27 11:09:01 +00:00
}
2015-09-07 21:46:07 +00:00
2017-02-24 00:49:19 +00:00
value = new AST _SymbolRef ( {
start : prev ( ) ,
name : name ,
2016-07-29 01:18:21 +00:00
end : prev ( )
2017-02-24 00:49:19 +00:00
} ) ;
} else if ( name === null ) {
unexpected ( prev ( ) ) ;
} else {
next ( ) ; // `:` - see first condition
value = expression ( false ) ;
2015-09-07 21:46:07 +00:00
}
2016-04-17 11:37:01 +00:00
2017-02-24 00:49:19 +00:00
// Check for default value and alter value accordingly if necessary
2015-11-22 19:04:42 +00:00
if ( is ( "operator" , "=" ) ) {
next ( ) ;
2017-02-24 00:49:19 +00:00
value = new AST _Assign ( {
2015-11-22 19:04:42 +00:00
start : start ,
2017-02-24 00:49:19 +00:00
left : value ,
2015-11-22 19:04:42 +00:00
operator : "=" ,
right : expression ( false ) ,
end : prev ( )
2017-02-24 00:49:19 +00:00
} ) ;
2015-09-05 22:01:25 +00:00
}
2017-02-24 00:49:19 +00:00
// Create property
a . push ( new AST _ObjectKeyVal ( {
start : start ,
quote : start . quote ,
key : name ,
value : value ,
end : prev ( )
} ) ) ;
2015-08-03 23:14:18 +00:00
}
2015-09-05 22:01:25 +00:00
next ( ) ;
return new AST _Object ( { properties : a } )
2012-05-27 11:09:01 +00:00
} ) ;
2015-11-21 09:17:32 +00:00
function class _ ( KindOfClass ) {
2016-07-05 22:40:28 +00:00
var start , method , class _name , extends _ , a = [ ] ;
2015-10-27 00:40:46 +00:00
2016-09-11 13:06:10 +00:00
S . input . push _directives _stack ( ) ; // Push directive stack, but not scope stack
S . input . add _directive ( "use strict" ) ;
2015-10-27 00:40:46 +00:00
if ( S . token . type == "name" && S . token . value != "extends" ) {
2015-11-21 09:17:32 +00:00
class _name = as _symbol ( KindOfClass === AST _DefClass ? AST _SymbolDefClass : AST _SymbolClass ) ;
}
if ( KindOfClass === AST _DefClass && ! class _name ) {
2016-05-26 15:00:37 +00:00
unexpected ( ) ;
2015-10-27 00:40:46 +00:00
}
if ( S . token . value == "extends" ) {
next ( ) ;
extends _ = expression ( true ) ;
}
expect ( "{" ) ;
if ( is ( "punc" , ";" ) ) { next ( ) ; } // Leading semicolons are okay in class bodies.
while ( ! is ( "punc" , "}" ) ) {
start = S . token ;
2016-07-05 22:40:28 +00:00
method = concise _method _or _getset ( as _property _name ( ) , start , true ) ;
2016-05-26 15:00:37 +00:00
if ( ! method ) { unexpected ( ) ; }
2015-10-27 00:40:46 +00:00
a . push ( method ) ;
if ( is ( "punc" , ";" ) ) { next ( ) ; }
}
2016-09-11 13:06:10 +00:00
S . input . pop _directives _stack ( ) ;
2015-10-27 00:40:46 +00:00
next ( ) ;
2015-11-21 09:17:32 +00:00
return new KindOfClass ( {
2015-10-27 00:40:46 +00:00
start : start ,
name : class _name ,
extends : extends _ ,
properties : a ,
end : prev ( ) ,
} ) ;
}
2016-05-26 15:00:37 +00:00
function concise _method _or _getset ( name , start , is _class ) {
2016-07-05 22:40:28 +00:00
var get _ast = function ( name , token ) {
if ( typeof name === "string" || typeof name === "number" ) {
return new AST _SymbolMethod ( {
start : token ,
name : name ,
end : prev ( )
} ) ;
2016-07-22 09:46:30 +00:00
} else if ( name === null ) {
unexpected ( ) ;
2016-07-05 22:40:28 +00:00
}
return name ;
}
2017-06-14 22:15:48 +00:00
var is _async = false ;
2015-10-27 00:51:47 +00:00
var is _static = false ;
2016-05-26 15:00:37 +00:00
var is _generator = false ;
2016-07-29 01:18:21 +00:00
var property _token = start ;
2016-05-26 15:00:37 +00:00
if ( is _class && name === "static" && ! is ( "punc" , "(" ) ) {
2015-10-27 00:51:47 +00:00
is _static = true ;
2016-07-29 01:18:21 +00:00
property _token = S . token ;
2016-07-05 22:40:28 +00:00
name = as _property _name ( ) ;
2015-10-27 00:51:47 +00:00
}
2017-06-16 04:18:18 +00:00
if ( name === "async" && ! is ( "punc" , "(" ) && ! is ( "punc" , "," ) && ! is ( "punc" , "}" ) ) {
2017-06-14 22:15:48 +00:00
is _async = true ;
property _token = S . token ;
name = as _property _name ( ) ;
}
2016-07-22 09:46:30 +00:00
if ( name === null ) {
2016-05-26 15:00:37 +00:00
is _generator = true ;
2016-07-29 01:18:21 +00:00
property _token = S . token ;
2016-07-05 22:40:28 +00:00
name = as _property _name ( ) ;
2016-07-22 09:46:30 +00:00
if ( name === null ) {
unexpected ( ) ;
}
2016-05-26 15:00:37 +00:00
}
2015-10-27 00:40:46 +00:00
if ( is ( "punc" , "(" ) ) {
2016-07-05 22:40:28 +00:00
name = get _ast ( name , start ) ;
2016-07-29 01:18:21 +00:00
var node = new AST _ConciseMethod ( {
2016-05-26 15:00:37 +00:00
start : start ,
static : is _static ,
2016-07-29 01:18:21 +00:00
is _generator : is _generator ,
2017-06-14 22:15:48 +00:00
async : is _async ,
2016-07-29 01:18:21 +00:00
key : name ,
quote : name instanceof AST _SymbolMethod ?
property _token . quote : undefined ,
2017-06-14 22:15:48 +00:00
value : create _accessor ( is _generator , is _async ) ,
2016-05-26 15:00:37 +00:00
end : prev ( )
2015-10-27 00:40:46 +00:00
} ) ;
2016-07-29 01:18:21 +00:00
return node ;
2015-10-27 00:40:46 +00:00
}
2016-07-29 01:18:21 +00:00
property _token = S . token ;
2015-10-27 00:40:46 +00:00
if ( name == "get" ) {
2016-07-05 22:40:28 +00:00
if ( ! is ( "punc" ) || is ( "punc" , "[" ) ) {
2016-07-29 01:18:21 +00:00
name = get _ast ( as _property _name ( ) , start ) ;
2016-07-05 22:40:28 +00:00
return new AST _ObjectGetter ( {
start : start ,
static : is _static ,
key : name ,
2016-07-29 01:18:21 +00:00
quote : name instanceof AST _SymbolMethod ?
property _token . quote : undefined ,
2017-02-26 20:37:48 +00:00
value : create _accessor ( ) ,
2016-07-05 22:40:28 +00:00
end : prev ( )
} ) ;
}
2015-10-27 00:40:46 +00:00
}
2016-07-05 22:40:28 +00:00
else if ( name == "set" ) {
if ( ! is ( "punc" ) || is ( "punc" , "[" ) ) {
2016-07-29 01:18:21 +00:00
name = get _ast ( as _property _name ( ) , start ) ;
2016-07-05 22:40:28 +00:00
return new AST _ObjectSetter ( {
start : start ,
static : is _static ,
key : name ,
2016-07-29 01:18:21 +00:00
quote : name instanceof AST _SymbolMethod ?
property _token . quote : undefined ,
2017-02-26 20:37:48 +00:00
value : create _accessor ( ) ,
2016-07-05 22:40:28 +00:00
end : prev ( )
} ) ;
}
2015-10-27 00:40:46 +00:00
}
}
2016-01-29 20:47:49 +00:00
function import _ ( ) {
2016-02-21 17:06:09 +00:00
var start = prev ( ) ;
var imported _name ;
2016-02-26 21:12:19 +00:00
var imported _names ;
2016-02-21 17:06:09 +00:00
if ( is ( "name" ) ) {
imported _name = as _symbol ( AST _SymbolImport ) ;
2016-02-26 21:12:19 +00:00
}
if ( is ( "punc" , "," ) ) {
next ( ) ;
}
2017-06-20 16:51:36 +00:00
imported _names = map _names ( true ) ;
2016-02-26 21:12:19 +00:00
if ( imported _names || imported _name ) {
2016-02-21 17:06:09 +00:00
expect _token ( "name" , "from" ) ;
}
var mod _str = S . token ;
if ( mod _str . type !== 'string' ) {
unexpected ( ) ;
}
next ( ) ;
2016-01-29 20:47:49 +00:00
return new AST _Import ( {
2016-02-21 17:06:09 +00:00
start : start ,
imported _name : imported _name ,
2016-02-26 21:12:19 +00:00
imported _names : imported _names ,
2016-01-29 20:47:49 +00:00
module _name : new AST _String ( {
2016-02-21 17:06:09 +00:00
start : mod _str ,
value : mod _str . value ,
quote : mod _str . quote ,
end : mod _str ,
2016-01-29 20:47:49 +00:00
} ) ,
2016-02-21 17:06:09 +00:00
end : S . token ,
2016-01-29 20:47:49 +00:00
} ) ;
}
2017-06-20 16:51:36 +00:00
function map _name ( is _import ) {
2017-06-22 19:49:30 +00:00
function make _symbol ( type ) {
return new type ( {
name : as _property _name ( ) ,
start : prev ( ) ,
end : prev ( )
} ) ;
}
2017-06-20 16:51:36 +00:00
var foreign _type = is _import ? AST _SymbolImportForeign : AST _SymbolExportForeign ;
var type = is _import ? AST _SymbolImport : AST _SymbolExport ;
2016-02-26 21:12:19 +00:00
var start = S . token ;
var foreign _name ;
var name ;
2017-06-20 16:51:36 +00:00
if ( is _import ) {
2017-06-22 19:49:30 +00:00
foreign _name = make _symbol ( foreign _type ) ;
2017-06-20 16:51:36 +00:00
} else {
2017-06-22 19:49:30 +00:00
name = make _symbol ( type ) ;
2016-02-26 21:12:19 +00:00
}
2017-06-20 16:51:36 +00:00
if ( is ( "name" , "as" ) ) {
next ( ) ; // The "as" word
if ( is _import ) {
2017-06-22 19:49:30 +00:00
name = make _symbol ( type ) ;
2017-06-20 16:51:36 +00:00
} else {
2017-06-22 19:49:30 +00:00
foreign _name = make _symbol ( foreign _type ) ;
2017-06-20 16:51:36 +00:00
}
} else if ( is _import ) {
name = new type ( foreign _name ) ;
} else {
foreign _name = new foreign _type ( name ) ;
2016-02-27 12:01:16 +00:00
}
2017-06-20 16:51:36 +00:00
return new AST _NameMapping ( {
2016-02-26 21:12:19 +00:00
start : start ,
foreign _name : foreign _name ,
name : name ,
end : prev ( ) ,
} )
}
2017-06-20 16:51:36 +00:00
function map _nameAsterisk ( is _import , name ) {
var foreign _type = is _import ? AST _SymbolImportForeign : AST _SymbolExportForeign ;
var type = is _import ? AST _SymbolImport : AST _SymbolExport ;
2017-03-30 09:07:50 +00:00
var start = S . token ;
var foreign _name ;
var end = prev ( ) ;
2017-06-20 16:51:36 +00:00
name = name || new type ( {
2017-03-30 09:07:50 +00:00
name : '*' ,
start : start ,
end : end ,
} ) ;
2017-06-20 16:51:36 +00:00
foreign _name = new foreign _type ( {
2017-03-30 09:07:50 +00:00
name : '*' ,
start : start ,
end : end ,
} ) ;
2017-06-20 16:51:36 +00:00
return new AST _NameMapping ( {
2017-03-30 09:07:50 +00:00
start : start ,
foreign _name : foreign _name ,
name : name ,
end : end ,
} )
}
2017-06-20 16:51:36 +00:00
function map _names ( is _import ) {
2017-03-31 09:52:56 +00:00
var names ;
if ( is ( "punc" , "{" ) ) {
next ( ) ;
names = [ ] ;
while ( ! is ( "punc" , "}" ) ) {
2017-06-20 16:51:36 +00:00
names . push ( map _name ( is _import ) ) ;
2017-03-31 09:52:56 +00:00
if ( is ( "punc" , "," ) ) {
next ( ) ;
}
}
next ( ) ;
} else if ( is ( "operator" , "*" ) ) {
var name ;
next ( ) ;
2017-06-20 16:51:36 +00:00
if ( is _import && is ( "name" , "as" ) ) {
2017-03-31 09:52:56 +00:00
next ( ) ; // The "as" word
name = as _symbol ( AST _SymbolImportForeign ) ;
}
2017-06-20 16:51:36 +00:00
names = [ map _nameAsterisk ( is _import , name ) ] ;
2017-03-31 09:52:56 +00:00
}
return names ;
}
2016-02-27 12:24:18 +00:00
function export _ ( ) {
var start = S . token ;
var is _default ;
2017-03-30 09:07:50 +00:00
var exported _names ;
2016-02-27 12:24:18 +00:00
if ( is ( "keyword" , "default" ) ) {
is _default = true ;
next ( ) ;
2017-06-21 15:15:39 +00:00
} else if ( exported _names = map _names ( false ) ) {
if ( is ( "name" , "from" ) ) {
next ( ) ;
2017-03-30 09:07:50 +00:00
2017-06-21 15:15:39 +00:00
var mod _str = S . token ;
if ( mod _str . type !== 'string' ) {
unexpected ( ) ;
2017-03-31 09:51:27 +00:00
}
2017-06-21 15:15:39 +00:00
next ( ) ;
2017-03-30 09:07:50 +00:00
2017-06-21 15:15:39 +00:00
return new AST _Export ( {
start : start ,
is _default : is _default ,
exported _names : exported _names ,
module _name : new AST _String ( {
start : mod _str ,
value : mod _str . value ,
quote : mod _str . quote ,
end : mod _str ,
} ) ,
end : prev ( ) ,
} ) ;
2017-05-26 05:35:40 +00:00
} else {
2017-06-21 15:15:39 +00:00
return new AST _Export ( {
start : start ,
is _default : is _default ,
exported _names : exported _names ,
end : prev ( ) ,
} ) ;
2017-05-26 05:35:40 +00:00
}
2017-06-21 15:15:39 +00:00
}
var node ;
var exported _value ;
var exported _definition ;
if ( is ( "punc" , "{" )
|| is _default
&& ( is ( "keyword" , "class" ) || is ( "keyword" , "function" ) )
&& is _token ( peek ( ) , "punc" ) ) {
2017-05-25 19:12:52 +00:00
exported _value = expression ( false ) ;
2016-07-26 13:50:35 +00:00
semicolon ( ) ;
2017-12-17 16:11:52 +00:00
} else if ( ( node = statement ( is _default ) ) instanceof AST _Definitions && is _default ) {
2017-06-21 15:15:39 +00:00
unexpected ( node . start ) ;
2017-12-17 16:11:52 +00:00
} else if ( node instanceof AST _Definitions || node instanceof AST _Lambda || node instanceof AST _DefClass ) {
2017-06-21 15:15:39 +00:00
exported _definition = node ;
} else if ( node instanceof AST _SimpleStatement ) {
exported _value = node . body ;
} else {
unexpected ( node . start ) ;
2016-02-27 12:24:18 +00:00
}
return new AST _Export ( {
start : start ,
is _default : is _default ,
exported _value : exported _value ,
exported _definition : exported _definition ,
end : prev ( ) ,
} ) ;
}
2012-05-27 11:09:01 +00:00
function as _property _name ( ) {
2012-10-13 09:42:01 +00:00
var tmp = S . token ;
switch ( tmp . type ) {
2015-09-07 21:46:07 +00:00
case "punc" :
if ( tmp . value === "[" ) {
2017-05-06 23:18:15 +00:00
next ( ) ;
2015-09-07 21:46:07 +00:00
var ex = expression ( false ) ;
expect ( "]" ) ;
return ex ;
2016-07-05 22:40:28 +00:00
} else unexpected ( tmp ) ;
case "operator" :
2016-07-22 09:46:30 +00:00
if ( tmp . value === "*" ) {
2017-05-06 23:18:15 +00:00
next ( ) ;
2016-07-22 09:46:30 +00:00
return null ;
}
if ( [ "delete" , "in" , "instanceof" , "new" , "typeof" , "void" ] . indexOf ( tmp . value ) === - 1 ) {
2016-07-05 22:40:28 +00:00
unexpected ( tmp ) ;
}
2012-05-27 14:25:31 +00:00
case "name" :
2017-10-21 06:22:39 +00:00
if ( tmp . value == "yield" && ! is _token ( peek ( ) , "punc" , ":" ) && ! is _token ( peek ( ) , "punc" , "(" )
2017-05-20 05:11:37 +00:00
&& S . input . has _directive ( "use strict" ) && ! is _in _generator ( ) ) {
2017-02-26 20:37:48 +00:00
token _error ( tmp , "Unexpected yield identifier inside strict mode" ) ;
2016-06-17 18:39:03 +00:00
}
case "string" :
case "num" :
2012-05-27 14:25:31 +00:00
case "keyword" :
case "atom" :
2017-04-18 20:27:13 +00:00
next ( ) ;
2012-10-13 09:42:01 +00:00
return tmp . value ;
2012-05-27 14:25:31 +00:00
default :
2016-07-05 22:40:28 +00:00
unexpected ( tmp ) ;
2012-05-27 11:09:01 +00:00
}
} ;
function as _name ( ) {
2012-10-13 09:42:01 +00:00
var tmp = S . token ;
2017-04-18 20:27:13 +00:00
if ( tmp . type != "name" ) unexpected ( ) ;
2012-10-13 09:42:01 +00:00
next ( ) ;
2017-04-18 20:27:13 +00:00
return tmp . value ;
2012-05-27 11:09:01 +00:00
} ;
2013-10-30 09:50:22 +00:00
function _make _symbol ( type ) {
var name = S . token . value ;
2015-08-07 01:44:53 +00:00
return new ( name == "this" ? AST _This :
name == "super" ? AST _Super :
type ) ( {
2013-10-30 09:50:22 +00:00
name : String ( name ) ,
start : S . token ,
end : S . token
} ) ;
} ;
2017-04-23 12:05:22 +00:00
function strict _verify _symbol ( sym ) {
if ( sym . name == "arguments" || sym . name == "eval" )
croak ( "Unexpected " + sym . name + " in strict mode" , sym . start . line , sym . start . col , sym . start . pos ) ;
}
2012-08-19 12:57:50 +00:00
function as _symbol ( type , noerror ) {
if ( ! is ( "name" ) ) {
2017-02-26 19:40:54 +00:00
if ( ! noerror ) croak ( "Name expected" ) ;
2012-08-19 12:57:50 +00:00
return null ;
}
2016-06-17 18:39:03 +00:00
if ( is ( "name" , "yield" ) && S . input . has _directive ( "use strict" ) ) {
2017-02-26 20:37:48 +00:00
token _error ( S . prev , "Unexpected yield identifier inside strict mode" ) ;
2016-06-17 18:39:03 +00:00
}
2013-10-30 09:50:22 +00:00
var sym = _make _symbol ( type ) ;
2017-04-23 12:05:22 +00:00
if ( S . input . has _directive ( "use strict" ) && sym instanceof AST _SymbolDeclaration ) {
strict _verify _symbol ( sym ) ;
}
2012-05-27 11:09:01 +00:00
next ( ) ;
return sym ;
} ;
2017-12-24 04:38:45 +00:00
function mark _pure ( call ) {
var start = call . start ;
var comments = start . comments _before ;
var i = HOP ( start , "comments_before_length" ) ? start . comments _before _length : comments . length ;
while ( -- i >= 0 ) {
var comment = comments [ i ] ;
if ( /[@#]__PURE__/ . test ( comment . value ) ) {
call . pure = comment ;
break ;
}
}
}
2012-05-27 14:25:31 +00:00
var subscripts = function ( expr , allow _calls ) {
var start = expr . start ;
2012-05-27 11:09:01 +00:00
if ( is ( "punc" , "." ) ) {
next ( ) ;
return subscripts ( new AST _Dot ( {
2012-05-27 14:25:31 +00:00
start : start ,
2012-05-27 11:09:01 +00:00
expression : expr ,
2012-05-27 14:25:31 +00:00
property : as _name ( ) ,
end : prev ( )
2012-05-27 11:09:01 +00:00
} ) , allow _calls ) ;
}
if ( is ( "punc" , "[" ) ) {
next ( ) ;
2012-10-11 10:00:58 +00:00
var prop = expression ( true ) ;
2012-05-27 14:25:31 +00:00
expect ( "]" ) ;
2012-05-27 11:09:01 +00:00
return subscripts ( new AST _Sub ( {
2012-05-27 14:25:31 +00:00
start : start ,
2012-05-27 11:09:01 +00:00
expression : expr ,
2012-05-27 14:25:31 +00:00
property : prop ,
end : prev ( )
2012-05-27 11:09:01 +00:00
} ) , allow _calls ) ;
}
if ( allow _calls && is ( "punc" , "(" ) ) {
next ( ) ;
2017-12-24 04:38:45 +00:00
var call = new AST _Call ( {
2012-05-27 14:25:31 +00:00
start : start ,
2012-05-27 11:09:01 +00:00
expression : expr ,
2015-04-13 00:26:26 +00:00
args : call _args ( ) ,
2012-05-27 14:25:31 +00:00
end : prev ( )
2017-12-24 04:38:45 +00:00
} ) ;
mark _pure ( call ) ;
return subscripts ( call , true ) ;
2012-05-27 11:09:01 +00:00
}
2016-06-22 17:24:03 +00:00
if ( is ( "template_head" ) ) {
return subscripts ( new AST _PrefixedTemplateString ( {
start : start ,
prefix : expr ,
template _string : template _string ( )
} ) , allow _calls ) ;
}
2012-05-27 11:09:01 +00:00
return expr ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
2017-06-24 09:34:14 +00:00
var call _args = embed _tokens ( function _call _args ( ) {
2015-04-13 00:26:26 +00:00
var args = [ ] ;
while ( ! is ( "punc" , ")" ) ) {
if ( is ( "expand" , "..." ) ) {
next ( ) ;
args . push ( new AST _Expansion ( {
start : prev ( ) ,
2016-09-29 17:25:17 +00:00
expression : expression ( false )
2015-04-13 00:26:26 +00:00
} ) ) ;
} else {
args . push ( expression ( false ) ) ;
}
2017-06-24 09:34:14 +00:00
if ( ! is ( "punc" , ")" ) ) {
expect ( "," ) ;
if ( is ( "punc" , ")" ) && options . ecma < 8 ) unexpected ( ) ;
}
2015-04-13 00:26:26 +00:00
}
next ( ) ;
return args ;
} ) ;
2017-06-23 21:26:35 +00:00
var maybe _unary = function ( allow _calls , allow _arrows ) {
2012-10-13 09:42:01 +00:00
var start = S . token ;
2017-06-14 22:15:48 +00:00
if ( start . type == "name" && start . value == "await" ) {
if ( is _in _async ( ) ) {
next ( ) ;
return _await _expression ( ) ;
} else if ( S . input . has _directive ( "use strict" ) ) {
token _error ( S . token , "Unexpected await identifier inside strict mode" )
}
}
2012-10-13 09:42:01 +00:00
if ( is ( "operator" ) && UNARY _PREFIX ( start . value ) ) {
next ( ) ;
2013-09-02 06:56:27 +00:00
handle _regexp ( ) ;
2017-04-18 20:27:13 +00:00
var ex = make _unary ( AST _UnaryPrefix , start , maybe _unary ( allow _calls ) ) ;
2012-05-27 14:25:31 +00:00
ex . start = start ;
ex . end = prev ( ) ;
return ex ;
2012-05-27 11:09:01 +00:00
}
2017-06-23 21:26:35 +00:00
var val = expr _atom ( allow _calls , allow _arrows ) ;
2017-12-25 17:38:01 +00:00
while ( is ( "operator" ) && UNARY _POSTFIX ( S . token . value ) && ! has _newline _before ( S . token ) ) {
2017-06-23 21:26:35 +00:00
if ( val instanceof AST _Arrow ) unexpected ( ) ;
2017-04-18 20:27:13 +00:00
val = make _unary ( AST _UnaryPostfix , S . token , val ) ;
2012-05-27 14:25:31 +00:00
val . start = start ;
val . end = S . token ;
2012-05-27 11:09:01 +00:00
next ( ) ;
}
return val ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
2017-04-18 20:27:13 +00:00
function make _unary ( ctor , token , expr ) {
var op = token . value ;
2017-04-23 12:05:22 +00:00
switch ( op ) {
case "++" :
case "--" :
if ( ! is _assignable ( expr ) )
croak ( "Invalid use of " + op + " operator" , token . line , token . col , token . pos ) ;
break ;
case "delete" :
if ( expr instanceof AST _SymbolRef && S . input . has _directive ( "use strict" ) )
croak ( "Calling delete on expression not allowed in strict mode" , expr . start . line , expr . start . col , expr . start . pos ) ;
break ;
}
2012-05-27 11:09:01 +00:00
return new ctor ( { operator : op , expression : expr } ) ;
} ;
2012-05-27 14:25:31 +00:00
var expr _op = function ( left , min _prec , no _in ) {
2012-05-27 11:09:01 +00:00
var op = is ( "operator" ) ? S . token . value : null ;
if ( op == "in" && no _in ) op = null ;
2016-06-17 22:25:18 +00:00
if ( op == "**" && left instanceof AST _UnaryPrefix
2017-12-24 11:19:24 +00:00
/* unary token in front not allowed - parenthesis required */
&& ! is _token ( left . start , "punc" , "(" )
2016-06-17 22:25:18 +00:00
&& left . operator !== "--" && left . operator !== "++" )
unexpected ( left . start ) ;
2012-05-27 11:09:01 +00:00
var prec = op != null ? PRECEDENCE [ op ] : null ;
2016-06-17 22:25:18 +00:00
if ( prec != null && ( prec > min _prec || ( op === "**" && min _prec === prec ) ) ) {
2012-05-27 11:09:01 +00:00
next ( ) ;
var right = expr _op ( maybe _unary ( true ) , prec , no _in ) ;
return expr _op ( new AST _Binary ( {
2012-05-27 14:25:31 +00:00
start : left . start ,
2012-05-27 11:09:01 +00:00
left : left ,
operator : op ,
2012-05-27 14:25:31 +00:00
right : right ,
end : right . end
2012-05-27 11:09:01 +00:00
} ) , min _prec , no _in ) ;
}
return left ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
function expr _ops ( no _in ) {
2017-06-23 21:26:35 +00:00
return expr _op ( maybe _unary ( true , true ) , 0 , no _in ) ;
2012-05-27 11:09:01 +00:00
} ;
2012-05-27 14:25:31 +00:00
var maybe _conditional = function ( no _in ) {
var start = S . token ;
2012-05-27 11:09:01 +00:00
var expr = expr _ops ( no _in ) ;
if ( is ( "operator" , "?" ) ) {
next ( ) ;
var yes = expression ( false ) ;
expect ( ":" ) ;
return new AST _Conditional ( {
2012-05-27 14:25:31 +00:00
start : start ,
condition : expr ,
consequent : yes ,
alternative : expression ( false , no _in ) ,
2014-01-21 08:38:59 +00:00
end : prev ( )
2012-05-27 11:09:01 +00:00
} ) ;
}
return expr ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
function is _assignable ( expr ) {
2017-03-21 06:11:32 +00:00
return expr instanceof AST _PropAccess || expr instanceof AST _SymbolRef ;
2012-05-27 11:09:01 +00:00
} ;
2017-03-23 07:11:16 +00:00
function to _destructuring ( node ) {
if ( node instanceof AST _Object ) {
node = new AST _Destructuring ( {
start : node . start ,
names : node . properties . map ( to _destructuring ) ,
is _array : false ,
end : node . end
} ) ;
} else if ( node instanceof AST _Array ) {
var names = [ ] ;
for ( var i = 0 ; i < node . elements . length ; i ++ ) {
// Only allow expansion as last element
if ( node . elements [ i ] instanceof AST _Expansion ) {
if ( i + 1 !== node . elements . length ) {
token _error ( node . elements [ i ] . start , "Spread must the be last element in destructuring array" ) ;
}
node . elements [ i ] . expression = to _destructuring ( node . elements [ i ] . expression ) ;
}
names . push ( to _destructuring ( node . elements [ i ] ) ) ;
}
node = new AST _Destructuring ( {
start : node . start ,
names : names ,
is _array : true ,
end : node . end
} ) ;
} else if ( node instanceof AST _ObjectProperty ) {
node . value = to _destructuring ( node . value ) ;
} else if ( node instanceof AST _Assign ) {
node = new AST _DefaultAssign ( {
start : node . start ,
left : node . left ,
operator : "=" ,
right : node . right ,
end : node . end
} ) ;
}
return node ;
}
2015-08-03 23:14:18 +00:00
// In ES6, AssignmentExpression can also be an ArrowFunction
2012-05-27 14:25:31 +00:00
var maybe _assign = function ( no _in ) {
var start = S . token ;
2015-01-11 20:07:19 +00:00
2016-06-17 18:39:03 +00:00
if ( start . type == "name" && start . value == "yield" ) {
if ( is _in _generator ( ) ) {
next ( ) ;
return _yield _expression ( ) ;
} else if ( S . input . has _directive ( "use strict" ) ) {
2017-02-26 20:37:48 +00:00
token _error ( S . token , "Unexpected yield identifier inside strict mode" )
2016-06-17 18:39:03 +00:00
}
2016-05-26 15:00:37 +00:00
}
2015-08-03 23:14:18 +00:00
var left = maybe _conditional ( no _in ) ;
var val = S . token . value ;
2015-01-11 20:07:19 +00:00
2012-10-11 10:00:58 +00:00
if ( is ( "operator" ) && ASSIGNMENT ( val ) ) {
2017-03-23 07:11:16 +00:00
if ( is _assignable ( left ) || ( left = to _destructuring ( left ) ) instanceof AST _Destructuring ) {
2012-05-27 11:09:01 +00:00
next ( ) ;
return new AST _Assign ( {
2012-05-27 14:25:31 +00:00
start : start ,
2012-05-27 11:09:01 +00:00
left : left ,
2012-10-11 10:00:58 +00:00
operator : val ,
2012-05-27 14:25:31 +00:00
right : maybe _assign ( no _in ) ,
2013-01-26 12:24:54 +00:00
end : prev ( )
2012-05-27 11:09:01 +00:00
} ) ;
}
2017-02-26 19:40:54 +00:00
croak ( "Invalid assignment" ) ;
2012-05-27 11:09:01 +00:00
}
return left ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
2012-05-27 14:25:31 +00:00
var expression = function ( commas , no _in ) {
var start = S . token ;
2017-04-12 13:56:27 +00:00
var exprs = [ ] ;
while ( true ) {
exprs . push ( maybe _assign ( no _in ) ) ;
if ( ! commas || ! is ( "punc" , "," ) ) break ;
2012-05-27 11:09:01 +00:00
next ( ) ;
2017-04-12 13:56:27 +00:00
commas = true ;
2012-05-27 11:09:01 +00:00
}
2017-05-24 09:45:18 +00:00
return exprs . length == 1 ? exprs [ 0 ] : new AST _Sequence ( {
2017-04-12 13:56:27 +00:00
start : start ,
expressions : exprs ,
end : peek ( )
} ) ;
2012-05-27 14:25:31 +00:00
} ;
2012-05-27 11:09:01 +00:00
function in _loop ( cont ) {
++ S . in _loop ;
var ret = cont ( ) ;
-- S . in _loop ;
return ret ;
} ;
2013-05-15 10:27:23 +00:00
if ( options . expression ) {
return expression ( true ) ;
}
2012-09-21 11:19:05 +00:00
return ( function ( ) {
var start = S . token ;
var body = [ ] ;
2016-05-20 08:25:35 +00:00
S . input . push _directives _stack ( ) ;
2012-09-21 11:19:05 +00:00
while ( ! is ( "eof" ) )
body . push ( statement ( ) ) ;
2016-05-20 08:25:35 +00:00
S . input . pop _directives _stack ( ) ;
2012-09-21 11:19:05 +00:00
var end = prev ( ) ;
var toplevel = options . toplevel ;
if ( toplevel ) {
toplevel . body = toplevel . body . concat ( body ) ;
toplevel . end = end ;
} else {
toplevel = new AST _Toplevel ( { start : start , body : body , end : end } ) ;
}
return toplevel ;
} ) ( ) ;
2012-05-27 11:09:01 +00:00
} ;