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" ;
2016-05-26 15:00:37 +00:00
var KEYWORDS = 'break case catch class const continue debugger default delete do else export extends finally for function if in instanceof new return switch throw try typeof var let void while with import' ;
2012-10-11 08:52:05 +00:00
var KEYWORDS _ATOM = 'false null true' ;
2016-08-20 20:32:29 +00:00
var RESERVED _WORDS = 'enum implements interface package private protected public static super this ' + KEYWORDS _ATOM + " " + KEYWORDS ;
2016-05-26 15:00:37 +00:00
var KEYWORDS _BEFORE _EXPRESSION = 'return new delete throw else case yield' ;
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
2012-10-11 08:52:05 +00:00
var REGEXP _MODIFIERS = makePredicate ( characters ( "gmsiy" ) ) ;
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 ;
S . comments _before = [ ] ;
// make note of any newlines in the comments that came before
for ( var i = 0 , len = ret . comments _before . length ; i < len ; i ++ ) {
ret . nlb = ret . nlb || ret . comments _before [ i ] . nlb ;
}
}
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 ) ;
while ( ( ch = next ( true , true ) ) !== "`" ) {
2016-06-22 17:24:03 +00:00
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 ;
if ( ch === "\\" ) {
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
] ,
{ }
) ;
var STATEMENTS _WITH _LABELS = array _to _hash ( [ "for" , "do" , "while" , "switch" ] ) ;
var ATOMIC _START _TOKEN = array _to _hash ( [ "atom" , "num" , "string" , "regexp" , "name" ] ) ;
/* -----[ 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 ,
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 ,
2012-09-21 11:19:05 +00:00
} ) ;
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 ,
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 ) ; } ;
function can _insert _semicolon ( ) {
2012-09-21 11:19:05 +00:00
return ! options . strict && (
2012-05-27 11:09:01 +00:00
S . token . nlb || is ( "eof" ) || is ( "punc" , "}" )
) ;
} ;
2016-05-26 15:00:37 +00:00
function is _in _generator ( ) {
return S . in _generator === 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
} ;
var statement = embed _tokens ( function ( ) {
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-05-15 15:02:55 +00:00
&& ( token . nlb
|| is _token ( token , "eof" )
|| is _token ( token , "punc" , ";" )
|| is _token ( token , "punc" , "}" ) ) ) {
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" :
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 ( ) ;
2013-10-30 09:50:22 +00:00
return function _ ( AST _Defun ) ;
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 ( ) ;
2012-05-27 11:09:01 +00:00
if ( S . token . nlb )
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-01-29 20:47:49 +00:00
case "import" :
2017-05-15 22:48:23 +00:00
next ( ) ;
var node = import _ ( ) ;
semicolon ( ) ;
return node ;
2016-01-29 20:47:49 +00:00
2016-02-27 12:24:18 +00:00
case "export" :
2017-05-15 22:48:23 +00:00
next ( ) ;
2016-07-26 13:50:35 +00:00
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
}
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 ) {
2016-03-27 11:21:39 +00:00
if ( ( init instanceof AST _Definitions ) &&
2015-09-06 20:33:17 +00:00
init . definitions . length > 1 )
2017-02-26 19:40:54 +00:00
croak ( "Only one variable declaration allowed in for..in loop" ) ;
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-05-24 09:45:18 +00:00
var arrow _function = function ( start , argnames ) {
2016-09-06 23:00:07 +00:00
if ( S . token . nlb ) {
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-05-24 09:45:18 +00:00
var body = _function _body ( is ( "punc" , "{" ) ) ;
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 ,
argnames : argnames ,
body : body
2015-01-11 20:07:19 +00:00
} ) ;
} ;
2016-07-29 01:18:21 +00:00
var function _ = function ( ctor , is _generator _property ) {
2015-01-15 03:03:38 +00:00
var start = S . token
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 ) {
next ( ) ;
}
2013-10-30 09:50:22 +00:00
var name = is ( "name" ) ? as _symbol ( in _statement ? AST _SymbolDefun : AST _SymbolLambda ) : null ;
2012-05-27 11:09:01 +00:00
if ( in _statement && ! name )
unexpected ( ) ;
2015-01-15 03:03:38 +00:00
2016-08-20 20:32:29 +00:00
var args = parameters ( ) ;
2017-05-06 23:18:15 +00:00
var body = _function _body ( true , is _generator || is _generator _property , 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 ,
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 first = true ;
var params = [ ] ;
var used _parameters = track _used _binding _identifiers ( true , S . input . has _directive ( "use strict" ) ) ;
expect ( "(" ) ;
while ( ! is ( "punc" , ")" ) ) {
if ( first ) {
first = false ;
} else {
expect ( "," ) ;
}
var param = parameter ( used _parameters ) ;
params . push ( param ) ;
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" , "]" ) ) {
unexpected ( ) ; // Must be last element
}
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 ( "," ) ;
}
if ( is ( "name" ) && ( is _token ( peek ( ) , "punc" ) || is _token ( peek ( ) , "operator" ) ) && [ "," , "}" , "=" ] . indexOf ( peek ( ) . value ) !== - 1 ) {
used _parameters . add _parameter ( S . token ) ;
2017-02-24 00:49:19 +00:00
elements . push ( new AST _ObjectKeyVal ( {
start : prev ( ) ,
key : S . token . value ,
value : new symbol _type ( {
start : S . token ,
name : S . token . value ,
end : S . token
} ) ,
end : prev ( )
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
} ) ) ;
}
}
if ( is ( "operator" , "=" ) ) {
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
}
}
2015-01-15 03:03:38 +00:00
function params _or _seq _ ( ) {
var first = true ;
var a = [ ] ;
while ( ! is ( "punc" , ")" ) ) {
if ( first ) first = false ; else expect ( "," ) ;
2015-04-13 00:26:26 +00:00
if ( is ( "expand" , "..." ) ) {
2016-06-12 20:40:07 +00:00
var spread _token = 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 ,
} ) ) ;
2016-06-12 20:40:07 +00:00
if ( ! is ( "punc" , ")" ) ) {
unexpected ( spread _token ) ;
}
2015-04-13 00:26:26 +00:00
} else {
2017-05-24 09:45:18 +00:00
a . push ( expression ( ) ) ;
2015-04-13 00:26:26 +00:00
}
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-05-06 23:18:15 +00:00
function _function _body ( block , generator , 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 ;
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 ;
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 ;
2015-01-15 03:03:38 +00:00
return a ;
}
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 ;
var tmp ;
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 ( )
} )
}
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 ( ) ;
args = expr _list ( ")" ) ;
} 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
case "keyword" :
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 ;
2016-01-15 14:58:15 +00:00
case "operator" :
if ( ! is _identifier _string ( tok . value ) ) {
2017-02-26 19:40:54 +00:00
croak ( "Invalid getter/setter name: " + tok . value ,
2016-06-18 15:28:22 +00:00
tok . line , tok . col , tok . pos ) ;
2016-01-15 14:58:15 +00:00
}
ret = _make _symbol ( AST _SymbolRef ) ;
break ;
2012-05-27 11:09:01 +00:00
}
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 ) {
if ( ex . key instanceof AST _SymbolRef ) {
ex . key = to _fun _args ( ex . key , 0 , [ ex . key ] ) ;
}
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 ) ;
}
}
2012-05-27 11:09:01 +00:00
var expr _atom = function ( allow _calls ) {
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 ;
2012-05-27 11:09:01 +00:00
if ( is ( "punc" ) ) {
2012-05-27 14:25:31 +00:00
switch ( start . value ) {
2012-05-27 11:09:01 +00:00
case "(" :
2017-05-24 09:45:18 +00:00
next ( ) ;
var exprs = params _or _seq _ ( ) ;
expect ( ")" ) ;
2015-08-03 23:14:18 +00:00
if ( is ( "arrow" , "=>" ) ) {
2017-05-24 09:45:18 +00:00
return arrow _function ( start , exprs . map ( to _fun _args ) ) ;
2015-08-03 23:14:18 +00:00
}
2017-05-24 09:45:18 +00:00
var ex = exprs . length == 1 ? exprs [ 0 ] : new AST _Sequence ( {
expressions : exprs
} ) ;
2017-02-27 06:54:47 +00:00
ex . start = start ;
ex . end = S . token ;
return subscripts ( ex , allow _calls ) ;
2012-05-27 11:09:01 +00:00
case "[" :
return subscripts ( array _ ( ) , allow _calls ) ;
case "{" :
2015-08-03 23:14:18 +00:00
return subscripts ( object _or _object _destructuring _ ( ) , allow _calls ) ;
2012-05-27 11:09:01 +00:00
}
unexpected ( ) ;
}
if ( is ( "keyword" , "function" ) ) {
next ( ) ;
2013-10-30 09:50:22 +00:00
var func = function _ ( AST _Function ) ;
2012-05-27 11:09:01 +00:00
func . start = start ;
func . end = prev ( ) ;
return subscripts ( func , 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 ) ;
}
2012-10-11 08:07:42 +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 ( ) ;
segments . push ( expression ( ) ) ;
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-02-28 06:08:31 +00:00
var create _accessor = embed _tokens ( function ( is _generator ) {
return function _ ( AST _Accessor , is _generator ) ;
2017-02-20 09:14:53 +00:00
} ) ;
2015-08-03 23:14:18 +00:00
var object _or _object _destructuring _ = embed _tokens ( function ( ) {
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 ;
2016-07-05 22:40:28 +00:00
start = S . token ;
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 ;
}
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
}
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 ,
key : name ,
quote : name instanceof AST _SymbolMethod ?
property _token . quote : undefined ,
2017-02-28 06:08:31 +00:00
value : create _accessor ( is _generator ) ,
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-03-31 09:52:56 +00:00
imported _names = import _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
} ) ;
}
2016-02-26 21:12:19 +00:00
function import _name ( ) {
var start = S . token ;
var foreign _name ;
var name ;
if ( peek ( ) . value === "as" && peek ( ) . type === "name" ) {
foreign _name = as _symbol ( AST _SymbolImportForeign ) ;
next ( ) ; // The "as" word
}
name = as _symbol ( AST _SymbolImport ) ;
2016-02-27 12:01:16 +00:00
if ( foreign _name === undefined ) {
foreign _name = new AST _SymbolImportForeign ( {
name : name . name ,
start : name . start ,
end : name . end ,
} ) ;
}
2016-02-26 21:12:19 +00:00
return new AST _NameImport ( {
start : start ,
foreign _name : foreign _name ,
name : name ,
end : prev ( ) ,
} )
}
2017-03-31 09:52:56 +00:00
function import _nameAsterisk ( name ) {
2017-03-30 09:07:50 +00:00
var start = S . token ;
var foreign _name ;
var end = prev ( ) ;
2017-03-31 09:52:56 +00:00
name = name || new AST _SymbolImport ( {
2017-03-30 09:07:50 +00:00
name : '*' ,
start : start ,
end : end ,
} ) ;
foreign _name = new AST _SymbolImportForeign ( {
name : '*' ,
start : start ,
end : end ,
} ) ;
return new AST _NameImport ( {
start : start ,
foreign _name : foreign _name ,
name : name ,
end : end ,
} )
}
2017-03-31 09:52:56 +00:00
function import _names ( allow _as ) {
var names ;
if ( is ( "punc" , "{" ) ) {
next ( ) ;
names = [ ] ;
while ( ! is ( "punc" , "}" ) ) {
names . push ( import _name ( ) ) ;
if ( is ( "punc" , "," ) ) {
next ( ) ;
}
}
next ( ) ;
} else if ( is ( "operator" , "*" ) ) {
var name ;
next ( ) ;
if ( allow _as && is ( "name" , "as" ) ) {
next ( ) ; // The "as" word
name = as _symbol ( AST _SymbolImportForeign ) ;
}
names = [ import _nameAsterisk ( name ) ] ;
}
return names ;
}
2016-02-27 12:24:18 +00:00
function export _ ( ) {
var start = S . token ;
var is _default ;
var exported _value ;
var exported _definition ;
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-05-13 04:56:46 +00:00
} else {
exported _names = import _names ( false ) ;
2016-02-27 12:24:18 +00:00
2017-05-13 04:56:46 +00:00
if ( exported _names ) {
if ( is ( "name" , "from" ) ) {
next ( ) ;
2017-03-30 09:07:50 +00:00
2017-05-13 04:56:46 +00:00
var mod _str = S . token ;
if ( mod _str . type !== 'string' ) {
unexpected ( ) ;
}
next ( ) ;
2017-03-30 09:07:50 +00:00
2017-05-13 04:56:46 +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 ( ) ,
} ) ;
} else {
return new AST _Export ( {
start : start ,
is _default : is _default ,
exported _names : exported _names ,
end : prev ( ) ,
} ) ;
2017-03-31 09:51:27 +00:00
}
}
2017-03-30 09:07:50 +00:00
}
2017-05-25 19:12:52 +00:00
var is _definition = is ( "keyword" , "var" )
|| is ( "keyword" , "let" )
|| is ( "keyword" , "const" )
|| is ( "keyword" , "function" ) && ! is _default ;
2016-02-27 12:24:18 +00:00
if ( is _definition ) {
exported _definition = statement ( ) ;
2017-05-25 19:12:52 +00:00
} else if ( is ( "keyword" , "function" ) ) {
exported _value = expr _atom ( false ) ;
2016-02-27 12:24:18 +00:00
} else {
2017-05-25 19:12:52 +00:00
exported _value = expression ( false ) ;
2016-07-26 13:50:35 +00:00
semicolon ( ) ;
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-05-20 05:11:37 +00:00
if ( tmp . value == "yield" && ! is _token ( peek ( ) , "punc" , ":" )
&& 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 ;
} ;
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 ( ) ;
return subscripts ( 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 ( )
2012-05-27 11:09:01 +00:00
} ) , true ) ;
}
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
2015-04-13 00:26:26 +00:00
var call _args = embed _tokens ( function call _args ( ) {
var first = true ;
var args = [ ] ;
while ( ! is ( "punc" , ")" ) ) {
if ( first ) first = false ; else expect ( "," ) ;
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 ) ) ;
}
}
next ( ) ;
return args ;
} ) ;
2012-05-27 14:25:31 +00:00
var maybe _unary = function ( allow _calls ) {
2012-10-13 09:42:01 +00:00
var start = S . token ;
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
}
var val = expr _atom ( allow _calls ) ;
2012-10-11 10:00:58 +00:00
while ( is ( "operator" ) && UNARY _POSTFIX ( S . token . value ) && ! S . token . nlb ) {
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
&& left . end === S . prev /* unary token in front not allowed, but allowed if prev is for example `)` */
&& 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 ) {
return expr _op ( maybe _unary ( true ) , 0 , no _in ) ;
} ;
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
}
2016-03-08 07:43:01 +00:00
if ( start . type == "punc" && start . value == "(" && peek ( ) . value == ")" ) {
2016-02-09 00:02:23 +00:00
next ( ) ;
next ( ) ;
2017-05-24 09:45:18 +00:00
return arrow _function ( start , [ ] ) ;
2016-02-09 00:02:23 +00:00
}
2016-10-28 18:42:28 +00:00
if ( is ( "name" ) && is _token ( peek ( ) , "arrow" ) ) {
var param = new AST _SymbolFunarg ( {
name : start . value ,
start : start ,
end : start ,
} ) ;
next ( ) ;
2017-05-24 09:45:18 +00:00
return arrow _function ( start , [ param ] ) ;
2016-10-28 18:42:28 +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
} ;