toolkit/devtools/acorn/acorn.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/devtools/acorn/acorn.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1768 @@
     1.4 +// Acorn is a tiny, fast JavaScript parser written in JavaScript.
     1.5 +//
     1.6 +// Acorn was written by Marijn Haverbeke and released under an MIT
     1.7 +// license. The Unicode regexps (for identifiers and whitespace) were
     1.8 +// taken from [Esprima](http://esprima.org) by Ariya Hidayat.
     1.9 +//
    1.10 +// Git repositories for Acorn are available at
    1.11 +//
    1.12 +//     http://marijnhaverbeke.nl/git/acorn
    1.13 +//     https://github.com/marijnh/acorn.git
    1.14 +//
    1.15 +// Please use the [github bug tracker][ghbt] to report issues.
    1.16 +//
    1.17 +// [ghbt]: https://github.com/marijnh/acorn/issues
    1.18 +//
    1.19 +// This file defines the main parser interface. The library also comes
    1.20 +// with a [error-tolerant parser][dammit] and an
    1.21 +// [abstract syntax tree walker][walk], defined in other files.
    1.22 +//
    1.23 +// [dammit]: acorn_loose.js
    1.24 +// [walk]: util/walk.js
    1.25 +
    1.26 +(function(root, mod) {
    1.27 +  if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS
    1.28 +  if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD
    1.29 +  mod(root.acorn || (root.acorn = {})); // Plain browser env
    1.30 +})(this, function(exports) {
    1.31 +  "use strict";
    1.32 +
    1.33 +  exports.version = "0.4.1";
    1.34 +
    1.35 +  // The main exported interface (under `self.acorn` when in the
    1.36 +  // browser) is a `parse` function that takes a code string and
    1.37 +  // returns an abstract syntax tree as specified by [Mozilla parser
    1.38 +  // API][api], with the caveat that the SpiderMonkey-specific syntax
    1.39 +  // (`let`, `yield`, inline XML, etc) is not recognized.
    1.40 +  //
    1.41 +  // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
    1.42 +
    1.43 +  var options, input, inputLen, sourceFile;
    1.44 +
    1.45 +  exports.parse = function(inpt, opts) {
    1.46 +    input = String(inpt); inputLen = input.length;
    1.47 +    setOptions(opts);
    1.48 +    initTokenState();
    1.49 +    return parseTopLevel(options.program);
    1.50 +  };
    1.51 +
    1.52 +  // A second optional argument can be given to further configure
    1.53 +  // the parser process. These options are recognized:
    1.54 +
    1.55 +  var defaultOptions = exports.defaultOptions = {
    1.56 +    // `ecmaVersion` indicates the ECMAScript version to parse. Must
    1.57 +    // be either 3 or 5. This
    1.58 +    // influences support for strict mode, the set of reserved words, and
    1.59 +    // support for getters and setter.
    1.60 +    ecmaVersion: 5,
    1.61 +    // Turn on `strictSemicolons` to prevent the parser from doing
    1.62 +    // automatic semicolon insertion.
    1.63 +    strictSemicolons: false,
    1.64 +    // When `allowTrailingCommas` is false, the parser will not allow
    1.65 +    // trailing commas in array and object literals.
    1.66 +    allowTrailingCommas: true,
    1.67 +    // By default, reserved words are not enforced. Enable
    1.68 +    // `forbidReserved` to enforce them.
    1.69 +    forbidReserved: false,
    1.70 +    // When `locations` is on, `loc` properties holding objects with
    1.71 +    // `start` and `end` properties in `{line, column}` form (with
    1.72 +    // line being 1-based and column 0-based) will be attached to the
    1.73 +    // nodes.
    1.74 +    locations: false,
    1.75 +    // A function can be passed as `onComment` option, which will
    1.76 +    // cause Acorn to call that function with `(block, text, start,
    1.77 +    // end)` parameters whenever a comment is skipped. `block` is a
    1.78 +    // boolean indicating whether this is a block (`/* */`) comment,
    1.79 +    // `text` is the content of the comment, and `start` and `end` are
    1.80 +    // character offsets that denote the start and end of the comment.
    1.81 +    // When the `locations` option is on, two more parameters are
    1.82 +    // passed, the full `{line, column}` locations of the start and
    1.83 +    // end of the comments. Note that you are not allowed to call the
    1.84 +    // parser from the callback—that will corrupt its internal state.
    1.85 +    onComment: null,
    1.86 +    // Nodes have their start and end characters offsets recorded in
    1.87 +    // `start` and `end` properties (directly on the node, rather than
    1.88 +    // the `loc` object, which holds line/column data. To also add a
    1.89 +    // [semi-standardized][range] `range` property holding a `[start,
    1.90 +    // end]` array with the same numbers, set the `ranges` option to
    1.91 +    // `true`.
    1.92 +    //
    1.93 +    // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
    1.94 +    ranges: false,
    1.95 +    // It is possible to parse multiple files into a single AST by
    1.96 +    // passing the tree produced by parsing the first file as
    1.97 +    // `program` option in subsequent parses. This will add the
    1.98 +    // toplevel forms of the parsed file to the `Program` (top) node
    1.99 +    // of an existing parse tree.
   1.100 +    program: null,
   1.101 +    // When `locations` is on, you can pass this to record the source
   1.102 +    // file in every node's `loc` object.
   1.103 +    sourceFile: null,
   1.104 +    // This value, if given, is stored in every node, whether
   1.105 +    // `locations` is on or off.
   1.106 +    directSourceFile: null
   1.107 +  };
   1.108 +
   1.109 +  function setOptions(opts) {
   1.110 +    options = opts || {};
   1.111 +    for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt))
   1.112 +      options[opt] = defaultOptions[opt];
   1.113 +    sourceFile = options.sourceFile || null;
   1.114 +  }
   1.115 +
   1.116 +  // The `getLineInfo` function is mostly useful when the
   1.117 +  // `locations` option is off (for performance reasons) and you
   1.118 +  // want to find the line/column position for a given character
   1.119 +  // offset. `input` should be the code string that the offset refers
   1.120 +  // into.
   1.121 +
   1.122 +  var getLineInfo = exports.getLineInfo = function(input, offset) {
   1.123 +    for (var line = 1, cur = 0;;) {
   1.124 +      lineBreak.lastIndex = cur;
   1.125 +      var match = lineBreak.exec(input);
   1.126 +      if (match && match.index < offset) {
   1.127 +        ++line;
   1.128 +        cur = match.index + match[0].length;
   1.129 +      } else break;
   1.130 +    }
   1.131 +    return {line: line, column: offset - cur};
   1.132 +  };
   1.133 +
   1.134 +  // Acorn is organized as a tokenizer and a recursive-descent parser.
   1.135 +  // The `tokenize` export provides an interface to the tokenizer.
   1.136 +  // Because the tokenizer is optimized for being efficiently used by
   1.137 +  // the Acorn parser itself, this interface is somewhat crude and not
   1.138 +  // very modular. Performing another parse or call to `tokenize` will
   1.139 +  // reset the internal state, and invalidate existing tokenizers.
   1.140 +
   1.141 +  exports.tokenize = function(inpt, opts) {
   1.142 +    input = String(inpt); inputLen = input.length;
   1.143 +    setOptions(opts);
   1.144 +    initTokenState();
   1.145 +
   1.146 +    var t = {};
   1.147 +    function getToken(forceRegexp) {
   1.148 +      lastEnd = tokEnd;
   1.149 +      readToken(forceRegexp);
   1.150 +      t.start = tokStart; t.end = tokEnd;
   1.151 +      t.startLoc = tokStartLoc; t.endLoc = tokEndLoc;
   1.152 +      t.type = tokType; t.value = tokVal;
   1.153 +      return t;
   1.154 +    }
   1.155 +    getToken.jumpTo = function(pos, reAllowed) {
   1.156 +      tokPos = pos;
   1.157 +      if (options.locations) {
   1.158 +        tokCurLine = 1;
   1.159 +        tokLineStart = lineBreak.lastIndex = 0;
   1.160 +        var match;
   1.161 +        while ((match = lineBreak.exec(input)) && match.index < pos) {
   1.162 +          ++tokCurLine;
   1.163 +          tokLineStart = match.index + match[0].length;
   1.164 +        }
   1.165 +      }
   1.166 +      tokRegexpAllowed = reAllowed;
   1.167 +      skipSpace();
   1.168 +    };
   1.169 +    return getToken;
   1.170 +  };
   1.171 +
   1.172 +  // State is kept in (closure-)global variables. We already saw the
   1.173 +  // `options`, `input`, and `inputLen` variables above.
   1.174 +
   1.175 +  // The current position of the tokenizer in the input.
   1.176 +
   1.177 +  var tokPos;
   1.178 +
   1.179 +  // The start and end offsets of the current token.
   1.180 +
   1.181 +  var tokStart, tokEnd;
   1.182 +
   1.183 +  // When `options.locations` is true, these hold objects
   1.184 +  // containing the tokens start and end line/column pairs.
   1.185 +
   1.186 +  var tokStartLoc, tokEndLoc;
   1.187 +
   1.188 +  // The type and value of the current token. Token types are objects,
   1.189 +  // named by variables against which they can be compared, and
   1.190 +  // holding properties that describe them (indicating, for example,
   1.191 +  // the precedence of an infix operator, and the original name of a
   1.192 +  // keyword token). The kind of value that's held in `tokVal` depends
   1.193 +  // on the type of the token. For literals, it is the literal value,
   1.194 +  // for operators, the operator name, and so on.
   1.195 +
   1.196 +  var tokType, tokVal;
   1.197 +
   1.198 +  // Interal state for the tokenizer. To distinguish between division
   1.199 +  // operators and regular expressions, it remembers whether the last
   1.200 +  // token was one that is allowed to be followed by an expression.
   1.201 +  // (If it is, a slash is probably a regexp, if it isn't it's a
   1.202 +  // division operator. See the `parseStatement` function for a
   1.203 +  // caveat.)
   1.204 +
   1.205 +  var tokRegexpAllowed;
   1.206 +
   1.207 +  // When `options.locations` is true, these are used to keep
   1.208 +  // track of the current line, and know when a new line has been
   1.209 +  // entered.
   1.210 +
   1.211 +  var tokCurLine, tokLineStart;
   1.212 +
   1.213 +  // These store the position of the previous token, which is useful
   1.214 +  // when finishing a node and assigning its `end` position.
   1.215 +
   1.216 +  var lastStart, lastEnd, lastEndLoc;
   1.217 +
   1.218 +  // This is the parser's state. `inFunction` is used to reject
   1.219 +  // `return` statements outside of functions, `labels` to verify that
   1.220 +  // `break` and `continue` have somewhere to jump to, and `strict`
   1.221 +  // indicates whether strict mode is on.
   1.222 +
   1.223 +  var inFunction, labels, strict;
   1.224 +
   1.225 +  // This function is used to raise exceptions on parse errors. It
   1.226 +  // takes an offset integer (into the current `input`) to indicate
   1.227 +  // the location of the error, attaches the position to the end
   1.228 +  // of the error message, and then raises a `SyntaxError` with that
   1.229 +  // message.
   1.230 +
   1.231 +  function raise(pos, message) {
   1.232 +    var loc = getLineInfo(input, pos);
   1.233 +    message += " (" + loc.line + ":" + loc.column + ")";
   1.234 +    var err = new SyntaxError(message);
   1.235 +    err.pos = pos; err.loc = loc; err.raisedAt = tokPos;
   1.236 +    throw err;
   1.237 +  }
   1.238 +
   1.239 +  // Reused empty array added for node fields that are always empty.
   1.240 +
   1.241 +  var empty = [];
   1.242 +
   1.243 +  // ## Token types
   1.244 +
   1.245 +  // The assignment of fine-grained, information-carrying type objects
   1.246 +  // allows the tokenizer to store the information it has about a
   1.247 +  // token in a way that is very cheap for the parser to look up.
   1.248 +
   1.249 +  // All token type variables start with an underscore, to make them
   1.250 +  // easy to recognize.
   1.251 +
   1.252 +  // These are the general types. The `type` property is only used to
   1.253 +  // make them recognizeable when debugging.
   1.254 +
   1.255 +  var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"};
   1.256 +  var _name = {type: "name"}, _eof = {type: "eof"};
   1.257 +
   1.258 +  // Keyword tokens. The `keyword` property (also used in keyword-like
   1.259 +  // operators) indicates that the token originated from an
   1.260 +  // identifier-like word, which is used when parsing property names.
   1.261 +  //
   1.262 +  // The `beforeExpr` property is used to disambiguate between regular
   1.263 +  // expressions and divisions. It is set on all token types that can
   1.264 +  // be followed by an expression (thus, a slash after them would be a
   1.265 +  // regular expression).
   1.266 +  //
   1.267 +  // `isLoop` marks a keyword as starting a loop, which is important
   1.268 +  // to know when parsing a label, in order to allow or disallow
   1.269 +  // continue jumps to that label.
   1.270 +
   1.271 +  var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"};
   1.272 +  var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"};
   1.273 +  var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true};
   1.274 +  var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"};
   1.275 +  var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"};
   1.276 +  var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"};
   1.277 +  var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true};
   1.278 +  var _this = {keyword: "this"};
   1.279 +
   1.280 +  // The keywords that denote values.
   1.281 +
   1.282 +  var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true};
   1.283 +  var _false = {keyword: "false", atomValue: false};
   1.284 +
   1.285 +  // Some keywords are treated as regular operators. `in` sometimes
   1.286 +  // (when parsing `for`) needs to be tested against specifically, so
   1.287 +  // we assign a variable name to it for quick comparing.
   1.288 +
   1.289 +  var _in = {keyword: "in", binop: 7, beforeExpr: true};
   1.290 +
   1.291 +  // Map keyword names to token types.
   1.292 +
   1.293 +  var keywordTypes = {"break": _break, "case": _case, "catch": _catch,
   1.294 +                      "continue": _continue, "debugger": _debugger, "default": _default,
   1.295 +                      "do": _do, "else": _else, "finally": _finally, "for": _for,
   1.296 +                      "function": _function, "if": _if, "return": _return, "switch": _switch,
   1.297 +                      "throw": _throw, "try": _try, "var": _var, "while": _while, "with": _with,
   1.298 +                      "null": _null, "true": _true, "false": _false, "new": _new, "in": _in,
   1.299 +                      "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this,
   1.300 +                      "typeof": {keyword: "typeof", prefix: true, beforeExpr: true},
   1.301 +                      "void": {keyword: "void", prefix: true, beforeExpr: true},
   1.302 +                      "delete": {keyword: "delete", prefix: true, beforeExpr: true}};
   1.303 +
   1.304 +  // Punctuation token types. Again, the `type` property is purely for debugging.
   1.305 +
   1.306 +  var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true};
   1.307 +  var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"};
   1.308 +  var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true};
   1.309 +  var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _question = {type: "?", beforeExpr: true};
   1.310 +
   1.311 +  // Operators. These carry several kinds of properties to help the
   1.312 +  // parser use them properly (the presence of these properties is
   1.313 +  // what categorizes them as operators).
   1.314 +  //
   1.315 +  // `binop`, when present, specifies that this operator is a binary
   1.316 +  // operator, and will refer to its precedence.
   1.317 +  //
   1.318 +  // `prefix` and `postfix` mark the operator as a prefix or postfix
   1.319 +  // unary operator. `isUpdate` specifies that the node produced by
   1.320 +  // the operator should be of type UpdateExpression rather than
   1.321 +  // simply UnaryExpression (`++` and `--`).
   1.322 +  //
   1.323 +  // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
   1.324 +  // binary operators with a very low precedence, that should result
   1.325 +  // in AssignmentExpression nodes.
   1.326 +
   1.327 +  var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true};
   1.328 +  var _assign = {isAssign: true, beforeExpr: true};
   1.329 +  var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true};
   1.330 +  var _logicalOR = {binop: 1, beforeExpr: true};
   1.331 +  var _logicalAND = {binop: 2, beforeExpr: true};
   1.332 +  var _bitwiseOR = {binop: 3, beforeExpr: true};
   1.333 +  var _bitwiseXOR = {binop: 4, beforeExpr: true};
   1.334 +  var _bitwiseAND = {binop: 5, beforeExpr: true};
   1.335 +  var _equality = {binop: 6, beforeExpr: true};
   1.336 +  var _relational = {binop: 7, beforeExpr: true};
   1.337 +  var _bitShift = {binop: 8, beforeExpr: true};
   1.338 +  var _plusMin = {binop: 9, prefix: true, beforeExpr: true};
   1.339 +  var _multiplyModulo = {binop: 10, beforeExpr: true};
   1.340 +
   1.341 +  // Provide access to the token types for external users of the
   1.342 +  // tokenizer.
   1.343 +
   1.344 +  exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,
   1.345 +                      parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,
   1.346 +                      dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof,
   1.347 +                      num: _num, regexp: _regexp, string: _string};
   1.348 +  for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw];
   1.349 +
   1.350 +  // This is a trick taken from Esprima. It turns out that, on
   1.351 +  // non-Chrome browsers, to check whether a string is in a set, a
   1.352 +  // predicate containing a big ugly `switch` statement is faster than
   1.353 +  // a regular expression, and on Chrome the two are about on par.
   1.354 +  // This function uses `eval` (non-lexical) to produce such a
   1.355 +  // predicate from a space-separated string of words.
   1.356 +  //
   1.357 +  // It starts by sorting the words by length.
   1.358 +
   1.359 +  function makePredicate(words) {
   1.360 +    words = words.split(" ");
   1.361 +    var f = "", cats = [];
   1.362 +    out: for (var i = 0; i < words.length; ++i) {
   1.363 +      for (var j = 0; j < cats.length; ++j)
   1.364 +        if (cats[j][0].length == words[i].length) {
   1.365 +          cats[j].push(words[i]);
   1.366 +          continue out;
   1.367 +        }
   1.368 +      cats.push([words[i]]);
   1.369 +    }
   1.370 +    function compareTo(arr) {
   1.371 +      if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
   1.372 +      f += "switch(str){";
   1.373 +      for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
   1.374 +      f += "return true}return false;";
   1.375 +    }
   1.376 +
   1.377 +    // When there are more than three length categories, an outer
   1.378 +    // switch first dispatches on the lengths, to save on comparisons.
   1.379 +
   1.380 +    if (cats.length > 3) {
   1.381 +      cats.sort(function(a, b) {return b.length - a.length;});
   1.382 +      f += "switch(str.length){";
   1.383 +      for (var i = 0; i < cats.length; ++i) {
   1.384 +        var cat = cats[i];
   1.385 +        f += "case " + cat[0].length + ":";
   1.386 +        compareTo(cat);
   1.387 +      }
   1.388 +      f += "}";
   1.389 +
   1.390 +    // Otherwise, simply generate a flat `switch` statement.
   1.391 +
   1.392 +    } else {
   1.393 +      compareTo(words);
   1.394 +    }
   1.395 +    return new Function("str", f);
   1.396 +  }
   1.397 +
   1.398 +  // The ECMAScript 3 reserved word list.
   1.399 +
   1.400 +  var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile");
   1.401 +
   1.402 +  // ECMAScript 5 reserved words.
   1.403 +
   1.404 +  var isReservedWord5 = makePredicate("class enum extends super const export import");
   1.405 +
   1.406 +  // The additional reserved words in strict mode.
   1.407 +
   1.408 +  var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield");
   1.409 +
   1.410 +  // The forbidden variable names in strict mode.
   1.411 +
   1.412 +  var isStrictBadIdWord = makePredicate("eval arguments");
   1.413 +
   1.414 +  // And the keywords.
   1.415 +
   1.416 +  var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this");
   1.417 +
   1.418 +  // ## Character categories
   1.419 +
   1.420 +  // Big ugly regular expressions that match characters in the
   1.421 +  // whitespace, identifier, and identifier-start categories. These
   1.422 +  // are only applied when a character is found to actually have a
   1.423 +  // code point above 128.
   1.424 +
   1.425 +  var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
   1.426 +  var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
   1.427 +  var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
   1.428 +  var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
   1.429 +  var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
   1.430 +
   1.431 +  // Whether a single character denotes a newline.
   1.432 +
   1.433 +  var newline = /[\n\r\u2028\u2029]/;
   1.434 +
   1.435 +  // Matches a whole line break (where CRLF is considered a single
   1.436 +  // line break). Used to count lines.
   1.437 +
   1.438 +  var lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
   1.439 +
   1.440 +  // Test whether a given character code starts an identifier.
   1.441 +
   1.442 +  var isIdentifierStart = exports.isIdentifierStart = function(code) {
   1.443 +    if (code < 65) return code === 36;
   1.444 +    if (code < 91) return true;
   1.445 +    if (code < 97) return code === 95;
   1.446 +    if (code < 123)return true;
   1.447 +    return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
   1.448 +  };
   1.449 +
   1.450 +  // Test whether a given character is part of an identifier.
   1.451 +
   1.452 +  var isIdentifierChar = exports.isIdentifierChar = function(code) {
   1.453 +    if (code < 48) return code === 36;
   1.454 +    if (code < 58) return true;
   1.455 +    if (code < 65) return false;
   1.456 +    if (code < 91) return true;
   1.457 +    if (code < 97) return code === 95;
   1.458 +    if (code < 123)return true;
   1.459 +    return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
   1.460 +  };
   1.461 +
   1.462 +  // ## Tokenizer
   1.463 +
   1.464 +  // These are used when `options.locations` is on, for the
   1.465 +  // `tokStartLoc` and `tokEndLoc` properties.
   1.466 +
   1.467 +  function line_loc_t() {
   1.468 +    this.line = tokCurLine;
   1.469 +    this.column = tokPos - tokLineStart;
   1.470 +  }
   1.471 +
   1.472 +  // Reset the token state. Used at the start of a parse.
   1.473 +
   1.474 +  function initTokenState() {
   1.475 +    tokCurLine = 1;
   1.476 +    tokPos = tokLineStart = 0;
   1.477 +    tokRegexpAllowed = true;
   1.478 +    skipSpace();
   1.479 +  }
   1.480 +
   1.481 +  // Called at the end of every token. Sets `tokEnd`, `tokVal`, and
   1.482 +  // `tokRegexpAllowed`, and skips the space after the token, so that
   1.483 +  // the next one's `tokStart` will point at the right position.
   1.484 +
   1.485 +  function finishToken(type, val) {
   1.486 +    tokEnd = tokPos;
   1.487 +    if (options.locations) tokEndLoc = new line_loc_t;
   1.488 +    tokType = type;
   1.489 +    skipSpace();
   1.490 +    tokVal = val;
   1.491 +    tokRegexpAllowed = type.beforeExpr;
   1.492 +  }
   1.493 +
   1.494 +  function skipBlockComment() {
   1.495 +    var startLoc = options.onComment && options.locations && new line_loc_t;
   1.496 +    var start = tokPos, end = input.indexOf("*/", tokPos += 2);
   1.497 +    if (end === -1) raise(tokPos - 2, "Unterminated comment");
   1.498 +    tokPos = end + 2;
   1.499 +    if (options.locations) {
   1.500 +      lineBreak.lastIndex = start;
   1.501 +      var match;
   1.502 +      while ((match = lineBreak.exec(input)) && match.index < tokPos) {
   1.503 +        ++tokCurLine;
   1.504 +        tokLineStart = match.index + match[0].length;
   1.505 +      }
   1.506 +    }
   1.507 +    if (options.onComment)
   1.508 +      options.onComment(true, input.slice(start + 2, end), start, tokPos,
   1.509 +                        startLoc, options.locations && new line_loc_t);
   1.510 +  }
   1.511 +
   1.512 +  function skipLineComment() {
   1.513 +    var start = tokPos;
   1.514 +    var startLoc = options.onComment && options.locations && new line_loc_t;
   1.515 +    var ch = input.charCodeAt(tokPos+=2);
   1.516 +    while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
   1.517 +      ++tokPos;
   1.518 +      ch = input.charCodeAt(tokPos);
   1.519 +    }
   1.520 +    if (options.onComment)
   1.521 +      options.onComment(false, input.slice(start + 2, tokPos), start, tokPos,
   1.522 +                        startLoc, options.locations && new line_loc_t);
   1.523 +  }
   1.524 +
   1.525 +  // Called at the start of the parse and after every token. Skips
   1.526 +  // whitespace and comments, and.
   1.527 +
   1.528 +  function skipSpace() {
   1.529 +    while (tokPos < inputLen) {
   1.530 +      var ch = input.charCodeAt(tokPos);
   1.531 +      if (ch === 32) { // ' '
   1.532 +        ++tokPos;
   1.533 +      } else if (ch === 13) {
   1.534 +        ++tokPos;
   1.535 +        var next = input.charCodeAt(tokPos);
   1.536 +        if (next === 10) {
   1.537 +          ++tokPos;
   1.538 +        }
   1.539 +        if (options.locations) {
   1.540 +          ++tokCurLine;
   1.541 +          tokLineStart = tokPos;
   1.542 +        }
   1.543 +      } else if (ch === 10 || ch === 8232 || ch === 8233) {
   1.544 +        ++tokPos;
   1.545 +        if (options.locations) {
   1.546 +          ++tokCurLine;
   1.547 +          tokLineStart = tokPos;
   1.548 +        }
   1.549 +      } else if (ch > 8 && ch < 14) {
   1.550 +        ++tokPos;
   1.551 +      } else if (ch === 47) { // '/'
   1.552 +        var next = input.charCodeAt(tokPos + 1);
   1.553 +        if (next === 42) { // '*'
   1.554 +          skipBlockComment();
   1.555 +        } else if (next === 47) { // '/'
   1.556 +          skipLineComment();
   1.557 +        } else break;
   1.558 +      } else if (ch === 160) { // '\xa0'
   1.559 +        ++tokPos;
   1.560 +      } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
   1.561 +        ++tokPos;
   1.562 +      } else {
   1.563 +        break;
   1.564 +      }
   1.565 +    }
   1.566 +  }
   1.567 +
   1.568 +  // ### Token reading
   1.569 +
   1.570 +  // This is the function that is called to fetch the next token. It
   1.571 +  // is somewhat obscure, because it works in character codes rather
   1.572 +  // than characters, and because operator parsing has been inlined
   1.573 +  // into it.
   1.574 +  //
   1.575 +  // All in the name of speed.
   1.576 +  //
   1.577 +  // The `forceRegexp` parameter is used in the one case where the
   1.578 +  // `tokRegexpAllowed` trick does not work. See `parseStatement`.
   1.579 +
   1.580 +  function readToken_dot() {
   1.581 +    var next = input.charCodeAt(tokPos + 1);
   1.582 +    if (next >= 48 && next <= 57) return readNumber(true);
   1.583 +    ++tokPos;
   1.584 +    return finishToken(_dot);
   1.585 +  }
   1.586 +
   1.587 +  function readToken_slash() { // '/'
   1.588 +    var next = input.charCodeAt(tokPos + 1);
   1.589 +    if (tokRegexpAllowed) {++tokPos; return readRegexp();}
   1.590 +    if (next === 61) return finishOp(_assign, 2);
   1.591 +    return finishOp(_slash, 1);
   1.592 +  }
   1.593 +
   1.594 +  function readToken_mult_modulo() { // '%*'
   1.595 +    var next = input.charCodeAt(tokPos + 1);
   1.596 +    if (next === 61) return finishOp(_assign, 2);
   1.597 +    return finishOp(_multiplyModulo, 1);
   1.598 +  }
   1.599 +
   1.600 +  function readToken_pipe_amp(code) { // '|&'
   1.601 +    var next = input.charCodeAt(tokPos + 1);
   1.602 +    if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2);
   1.603 +    if (next === 61) return finishOp(_assign, 2);
   1.604 +    return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);
   1.605 +  }
   1.606 +
   1.607 +  function readToken_caret() { // '^'
   1.608 +    var next = input.charCodeAt(tokPos + 1);
   1.609 +    if (next === 61) return finishOp(_assign, 2);
   1.610 +    return finishOp(_bitwiseXOR, 1);
   1.611 +  }
   1.612 +
   1.613 +  function readToken_plus_min(code) { // '+-'
   1.614 +    var next = input.charCodeAt(tokPos + 1);
   1.615 +    if (next === code) {
   1.616 +      if (next == 45 && input.charCodeAt(tokPos + 2) == 62 &&
   1.617 +          newline.test(input.slice(lastEnd, tokPos))) {
   1.618 +        // A `-->` line comment
   1.619 +        tokPos += 3;
   1.620 +        skipLineComment();
   1.621 +        skipSpace();
   1.622 +        return readToken();
   1.623 +      }
   1.624 +      return finishOp(_incDec, 2);
   1.625 +    }
   1.626 +    if (next === 61) return finishOp(_assign, 2);
   1.627 +    return finishOp(_plusMin, 1);
   1.628 +  }
   1.629 +
   1.630 +  function readToken_lt_gt(code) { // '<>'
   1.631 +    var next = input.charCodeAt(tokPos + 1);
   1.632 +    var size = 1;
   1.633 +    if (next === code) {
   1.634 +      size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2;
   1.635 +      if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);
   1.636 +      return finishOp(_bitShift, size);
   1.637 +    }
   1.638 +    if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 &&
   1.639 +        input.charCodeAt(tokPos + 3) == 45) {
   1.640 +      // `<!--`, an XML-style comment that should be interpreted as a line comment
   1.641 +      tokPos += 4;
   1.642 +      skipLineComment();
   1.643 +      skipSpace();
   1.644 +      return readToken();
   1.645 +    }
   1.646 +    if (next === 61)
   1.647 +      size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;
   1.648 +    return finishOp(_relational, size);
   1.649 +  }
   1.650 +
   1.651 +  function readToken_eq_excl(code) { // '=!'
   1.652 +    var next = input.charCodeAt(tokPos + 1);
   1.653 +    if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);
   1.654 +    return finishOp(code === 61 ? _eq : _prefix, 1);
   1.655 +  }
   1.656 +
   1.657 +  function getTokenFromCode(code) {
   1.658 +    switch(code) {
   1.659 +      // The interpretation of a dot depends on whether it is followed
   1.660 +      // by a digit.
   1.661 +    case 46: // '.'
   1.662 +      return readToken_dot();
   1.663 +
   1.664 +      // Punctuation tokens.
   1.665 +    case 40: ++tokPos; return finishToken(_parenL);
   1.666 +    case 41: ++tokPos; return finishToken(_parenR);
   1.667 +    case 59: ++tokPos; return finishToken(_semi);
   1.668 +    case 44: ++tokPos; return finishToken(_comma);
   1.669 +    case 91: ++tokPos; return finishToken(_bracketL);
   1.670 +    case 93: ++tokPos; return finishToken(_bracketR);
   1.671 +    case 123: ++tokPos; return finishToken(_braceL);
   1.672 +    case 125: ++tokPos; return finishToken(_braceR);
   1.673 +    case 58: ++tokPos; return finishToken(_colon);
   1.674 +    case 63: ++tokPos; return finishToken(_question);
   1.675 +
   1.676 +      // '0x' is a hexadecimal number.
   1.677 +    case 48: // '0'
   1.678 +      var next = input.charCodeAt(tokPos + 1);
   1.679 +      if (next === 120 || next === 88) return readHexNumber();
   1.680 +      // Anything else beginning with a digit is an integer, octal
   1.681 +      // number, or float.
   1.682 +    case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
   1.683 +      return readNumber(false);
   1.684 +
   1.685 +      // Quotes produce strings.
   1.686 +    case 34: case 39: // '"', "'"
   1.687 +      return readString(code);
   1.688 +
   1.689 +    // Operators are parsed inline in tiny state machines. '=' (61) is
   1.690 +    // often referred to. `finishOp` simply skips the amount of
   1.691 +    // characters it is given as second argument, and returns a token
   1.692 +    // of the type given by its first argument.
   1.693 +
   1.694 +    case 47: // '/'
   1.695 +      return readToken_slash(code);
   1.696 +
   1.697 +    case 37: case 42: // '%*'
   1.698 +      return readToken_mult_modulo();
   1.699 +
   1.700 +    case 124: case 38: // '|&'
   1.701 +      return readToken_pipe_amp(code);
   1.702 +
   1.703 +    case 94: // '^'
   1.704 +      return readToken_caret();
   1.705 +
   1.706 +    case 43: case 45: // '+-'
   1.707 +      return readToken_plus_min(code);
   1.708 +
   1.709 +    case 60: case 62: // '<>'
   1.710 +      return readToken_lt_gt(code);
   1.711 +
   1.712 +    case 61: case 33: // '=!'
   1.713 +      return readToken_eq_excl(code);
   1.714 +
   1.715 +    case 126: // '~'
   1.716 +      return finishOp(_prefix, 1);
   1.717 +    }
   1.718 +
   1.719 +    return false;
   1.720 +  }
   1.721 +
   1.722 +  function readToken(forceRegexp) {
   1.723 +    if (!forceRegexp) tokStart = tokPos;
   1.724 +    else tokPos = tokStart + 1;
   1.725 +    if (options.locations) tokStartLoc = new line_loc_t;
   1.726 +    if (forceRegexp) return readRegexp();
   1.727 +    if (tokPos >= inputLen) return finishToken(_eof);
   1.728 +
   1.729 +    var code = input.charCodeAt(tokPos);
   1.730 +    // Identifier or keyword. '\uXXXX' sequences are allowed in
   1.731 +    // identifiers, so '\' also dispatches to that.
   1.732 +    if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord();
   1.733 +
   1.734 +    var tok = getTokenFromCode(code);
   1.735 +
   1.736 +    if (tok === false) {
   1.737 +      // If we are here, we either found a non-ASCII identifier
   1.738 +      // character, or something that's entirely disallowed.
   1.739 +      var ch = String.fromCharCode(code);
   1.740 +      if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return readWord();
   1.741 +      raise(tokPos, "Unexpected character '" + ch + "'");
   1.742 +    }
   1.743 +    return tok;
   1.744 +  }
   1.745 +
   1.746 +  function finishOp(type, size) {
   1.747 +    var str = input.slice(tokPos, tokPos + size);
   1.748 +    tokPos += size;
   1.749 +    finishToken(type, str);
   1.750 +  }
   1.751 +
   1.752 +  // Parse a regular expression. Some context-awareness is necessary,
   1.753 +  // since a '/' inside a '[]' set does not end the expression.
   1.754 +
   1.755 +  function readRegexp() {
   1.756 +    var content = "", escaped, inClass, start = tokPos;
   1.757 +    for (;;) {
   1.758 +      if (tokPos >= inputLen) raise(start, "Unterminated regular expression");
   1.759 +      var ch = input.charAt(tokPos);
   1.760 +      if (newline.test(ch)) raise(start, "Unterminated regular expression");
   1.761 +      if (!escaped) {
   1.762 +        if (ch === "[") inClass = true;
   1.763 +        else if (ch === "]" && inClass) inClass = false;
   1.764 +        else if (ch === "/" && !inClass) break;
   1.765 +        escaped = ch === "\\";
   1.766 +      } else escaped = false;
   1.767 +      ++tokPos;
   1.768 +    }
   1.769 +    var content = input.slice(start, tokPos);
   1.770 +    ++tokPos;
   1.771 +    // Need to use `readWord1` because '\uXXXX' sequences are allowed
   1.772 +    // here (don't ask).
   1.773 +    var mods = readWord1();
   1.774 +    if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regexp flag");
   1.775 +    try {
   1.776 +      var value = new RegExp(content, mods);
   1.777 +    } catch (e) {
   1.778 +      if (e instanceof SyntaxError) raise(start, e.message);
   1.779 +      raise(e);
   1.780 +    }
   1.781 +    return finishToken(_regexp, value);
   1.782 +  }
   1.783 +
   1.784 +  // Read an integer in the given radix. Return null if zero digits
   1.785 +  // were read, the integer value otherwise. When `len` is given, this
   1.786 +  // will return `null` unless the integer has exactly `len` digits.
   1.787 +
   1.788 +  function readInt(radix, len) {
   1.789 +    var start = tokPos, total = 0;
   1.790 +    for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
   1.791 +      var code = input.charCodeAt(tokPos), val;
   1.792 +      if (code >= 97) val = code - 97 + 10; // a
   1.793 +      else if (code >= 65) val = code - 65 + 10; // A
   1.794 +      else if (code >= 48 && code <= 57) val = code - 48; // 0-9
   1.795 +      else val = Infinity;
   1.796 +      if (val >= radix) break;
   1.797 +      ++tokPos;
   1.798 +      total = total * radix + val;
   1.799 +    }
   1.800 +    if (tokPos === start || len != null && tokPos - start !== len) return null;
   1.801 +
   1.802 +    return total;
   1.803 +  }
   1.804 +
   1.805 +  function readHexNumber() {
   1.806 +    tokPos += 2; // 0x
   1.807 +    var val = readInt(16);
   1.808 +    if (val == null) raise(tokStart + 2, "Expected hexadecimal number");
   1.809 +    if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");
   1.810 +    return finishToken(_num, val);
   1.811 +  }
   1.812 +
   1.813 +  // Read an integer, octal integer, or floating-point number.
   1.814 +
   1.815 +  function readNumber(startsWithDot) {
   1.816 +    var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48;
   1.817 +    if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number");
   1.818 +    if (input.charCodeAt(tokPos) === 46) {
   1.819 +      ++tokPos;
   1.820 +      readInt(10);
   1.821 +      isFloat = true;
   1.822 +    }
   1.823 +    var next = input.charCodeAt(tokPos);
   1.824 +    if (next === 69 || next === 101) { // 'eE'
   1.825 +      next = input.charCodeAt(++tokPos);
   1.826 +      if (next === 43 || next === 45) ++tokPos; // '+-'
   1.827 +      if (readInt(10) === null) raise(start, "Invalid number");
   1.828 +      isFloat = true;
   1.829 +    }
   1.830 +    if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");
   1.831 +
   1.832 +    var str = input.slice(start, tokPos), val;
   1.833 +    if (isFloat) val = parseFloat(str);
   1.834 +    else if (!octal || str.length === 1) val = parseInt(str, 10);
   1.835 +    else if (/[89]/.test(str) || strict) raise(start, "Invalid number");
   1.836 +    else val = parseInt(str, 8);
   1.837 +    return finishToken(_num, val);
   1.838 +  }
   1.839 +
   1.840 +  // Read a string value, interpreting backslash-escapes.
   1.841 +
   1.842 +  function readString(quote) {
   1.843 +    tokPos++;
   1.844 +    var out = "";
   1.845 +    for (;;) {
   1.846 +      if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
   1.847 +      var ch = input.charCodeAt(tokPos);
   1.848 +      if (ch === quote) {
   1.849 +        ++tokPos;
   1.850 +        return finishToken(_string, out);
   1.851 +      }
   1.852 +      if (ch === 92) { // '\'
   1.853 +        ch = input.charCodeAt(++tokPos);
   1.854 +        var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));
   1.855 +        if (octal) octal = octal[0];
   1.856 +        while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);
   1.857 +        if (octal === "0") octal = null;
   1.858 +        ++tokPos;
   1.859 +        if (octal) {
   1.860 +          if (strict) raise(tokPos - 2, "Octal literal in strict mode");
   1.861 +          out += String.fromCharCode(parseInt(octal, 8));
   1.862 +          tokPos += octal.length - 1;
   1.863 +        } else {
   1.864 +          switch (ch) {
   1.865 +          case 110: out += "\n"; break; // 'n' -> '\n'
   1.866 +          case 114: out += "\r"; break; // 'r' -> '\r'
   1.867 +          case 120: out += String.fromCharCode(readHexChar(2)); break; // 'x'
   1.868 +          case 117: out += String.fromCharCode(readHexChar(4)); break; // 'u'
   1.869 +          case 85: out += String.fromCharCode(readHexChar(8)); break; // 'U'
   1.870 +          case 116: out += "\t"; break; // 't' -> '\t'
   1.871 +          case 98: out += "\b"; break; // 'b' -> '\b'
   1.872 +          case 118: out += "\u000b"; break; // 'v' -> '\u000b'
   1.873 +          case 102: out += "\f"; break; // 'f' -> '\f'
   1.874 +          case 48: out += "\0"; break; // 0 -> '\0'
   1.875 +          case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n'
   1.876 +          case 10: // ' \n'
   1.877 +            if (options.locations) { tokLineStart = tokPos; ++tokCurLine; }
   1.878 +            break;
   1.879 +          default: out += String.fromCharCode(ch); break;
   1.880 +          }
   1.881 +        }
   1.882 +      } else {
   1.883 +        if (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) raise(tokStart, "Unterminated string constant");
   1.884 +        out += String.fromCharCode(ch); // '\'
   1.885 +        ++tokPos;
   1.886 +      }
   1.887 +    }
   1.888 +  }
   1.889 +
   1.890 +  // Used to read character escape sequences ('\x', '\u', '\U').
   1.891 +
   1.892 +  function readHexChar(len) {
   1.893 +    var n = readInt(16, len);
   1.894 +    if (n === null) raise(tokStart, "Bad character escape sequence");
   1.895 +    return n;
   1.896 +  }
   1.897 +
   1.898 +  // Used to signal to callers of `readWord1` whether the word
   1.899 +  // contained any escape sequences. This is needed because words with
   1.900 +  // escape sequences must not be interpreted as keywords.
   1.901 +
   1.902 +  var containsEsc;
   1.903 +
   1.904 +  // Read an identifier, and return it as a string. Sets `containsEsc`
   1.905 +  // to whether the word contained a '\u' escape.
   1.906 +  //
   1.907 +  // Only builds up the word character-by-character when it actually
   1.908 +  // containeds an escape, as a micro-optimization.
   1.909 +
   1.910 +  function readWord1() {
   1.911 +    containsEsc = false;
   1.912 +    var word, first = true, start = tokPos;
   1.913 +    for (;;) {
   1.914 +      var ch = input.charCodeAt(tokPos);
   1.915 +      if (isIdentifierChar(ch)) {
   1.916 +        if (containsEsc) word += input.charAt(tokPos);
   1.917 +        ++tokPos;
   1.918 +      } else if (ch === 92) { // "\"
   1.919 +        if (!containsEsc) word = input.slice(start, tokPos);
   1.920 +        containsEsc = true;
   1.921 +        if (input.charCodeAt(++tokPos) != 117) // "u"
   1.922 +          raise(tokPos, "Expecting Unicode escape sequence \\uXXXX");
   1.923 +        ++tokPos;
   1.924 +        var esc = readHexChar(4);
   1.925 +        var escStr = String.fromCharCode(esc);
   1.926 +        if (!escStr) raise(tokPos - 1, "Invalid Unicode escape");
   1.927 +        if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))
   1.928 +          raise(tokPos - 4, "Invalid Unicode escape");
   1.929 +        word += escStr;
   1.930 +      } else {
   1.931 +        break;
   1.932 +      }
   1.933 +      first = false;
   1.934 +    }
   1.935 +    return containsEsc ? word : input.slice(start, tokPos);
   1.936 +  }
   1.937 +
   1.938 +  // Read an identifier or keyword token. Will check for reserved
   1.939 +  // words when necessary.
   1.940 +
   1.941 +  function readWord() {
   1.942 +    var word = readWord1();
   1.943 +    var type = _name;
   1.944 +    if (!containsEsc) {
   1.945 +      if (isKeyword(word)) type = keywordTypes[word];
   1.946 +      else if (options.forbidReserved &&
   1.947 +               (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(word) ||
   1.948 +               strict && isStrictReservedWord(word))
   1.949 +        raise(tokStart, "The keyword '" + word + "' is reserved");
   1.950 +    }
   1.951 +    return finishToken(type, word);
   1.952 +  }
   1.953 +
   1.954 +  // ## Parser
   1.955 +
   1.956 +  // A recursive descent parser operates by defining functions for all
   1.957 +  // syntactic elements, and recursively calling those, each function
   1.958 +  // advancing the input stream and returning an AST node. Precedence
   1.959 +  // of constructs (for example, the fact that `!x[1]` means `!(x[1])`
   1.960 +  // instead of `(!x)[1]` is handled by the fact that the parser
   1.961 +  // function that parses unary prefix operators is called first, and
   1.962 +  // in turn calls the function that parses `[]` subscripts — that
   1.963 +  // way, it'll receive the node for `x[1]` already parsed, and wraps
   1.964 +  // *that* in the unary operator node.
   1.965 +  //
   1.966 +  // Acorn uses an [operator precedence parser][opp] to handle binary
   1.967 +  // operator precedence, because it is much more compact than using
   1.968 +  // the technique outlined above, which uses different, nesting
   1.969 +  // functions to specify precedence, for all of the ten binary
   1.970 +  // precedence levels that JavaScript defines.
   1.971 +  //
   1.972 +  // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
   1.973 +
   1.974 +  // ### Parser utilities
   1.975 +
   1.976 +  // Continue to the next token.
   1.977 +
   1.978 +  function next() {
   1.979 +    lastStart = tokStart;
   1.980 +    lastEnd = tokEnd;
   1.981 +    lastEndLoc = tokEndLoc;
   1.982 +    readToken();
   1.983 +  }
   1.984 +
   1.985 +  // Enter strict mode. Re-reads the next token to please pedantic
   1.986 +  // tests ("use strict"; 010; -- should fail).
   1.987 +
   1.988 +  function setStrict(strct) {
   1.989 +    strict = strct;
   1.990 +    tokPos = tokStart;
   1.991 +    if (options.locations) {
   1.992 +      while (tokPos < tokLineStart) {
   1.993 +        tokLineStart = input.lastIndexOf("\n", tokLineStart - 2) + 1;
   1.994 +        --tokCurLine;
   1.995 +      }
   1.996 +    }
   1.997 +    skipSpace();
   1.998 +    readToken();
   1.999 +  }
  1.1000 +
  1.1001 +  // Start an AST node, attaching a start offset.
  1.1002 +
  1.1003 +  function node_t() {
  1.1004 +    this.type = null;
  1.1005 +    this.start = tokStart;
  1.1006 +    this.end = null;
  1.1007 +  }
  1.1008 +
  1.1009 +  function node_loc_t() {
  1.1010 +    this.start = tokStartLoc;
  1.1011 +    this.end = null;
  1.1012 +    if (sourceFile !== null) this.source = sourceFile;
  1.1013 +  }
  1.1014 +
  1.1015 +  function startNode() {
  1.1016 +    var node = new node_t();
  1.1017 +    if (options.locations)
  1.1018 +      node.loc = new node_loc_t();
  1.1019 +    if (options.directSourceFile)
  1.1020 +      node.sourceFile = options.directSourceFile;
  1.1021 +    if (options.ranges)
  1.1022 +      node.range = [tokStart, 0];
  1.1023 +    return node;
  1.1024 +  }
  1.1025 +
  1.1026 +  // Start a node whose start offset information should be based on
  1.1027 +  // the start of another node. For example, a binary operator node is
  1.1028 +  // only started after its left-hand side has already been parsed.
  1.1029 +
  1.1030 +  function startNodeFrom(other) {
  1.1031 +    var node = new node_t();
  1.1032 +    node.start = other.start;
  1.1033 +    if (options.locations) {
  1.1034 +      node.loc = new node_loc_t();
  1.1035 +      node.loc.start = other.loc.start;
  1.1036 +    }
  1.1037 +    if (options.ranges)
  1.1038 +      node.range = [other.range[0], 0];
  1.1039 +
  1.1040 +    return node;
  1.1041 +  }
  1.1042 +
  1.1043 +  // Finish an AST node, adding `type` and `end` properties.
  1.1044 +
  1.1045 +  function finishNode(node, type) {
  1.1046 +    node.type = type;
  1.1047 +    node.end = lastEnd;
  1.1048 +    if (options.locations)
  1.1049 +      node.loc.end = lastEndLoc;
  1.1050 +    if (options.ranges)
  1.1051 +      node.range[1] = lastEnd;
  1.1052 +    return node;
  1.1053 +  }
  1.1054 +
  1.1055 +  // Test whether a statement node is the string literal `"use strict"`.
  1.1056 +
  1.1057 +  function isUseStrict(stmt) {
  1.1058 +    return options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" &&
  1.1059 +      stmt.expression.type === "Literal" && stmt.expression.value === "use strict";
  1.1060 +  }
  1.1061 +
  1.1062 +  // Predicate that tests whether the next token is of the given
  1.1063 +  // type, and if yes, consumes it as a side effect.
  1.1064 +
  1.1065 +  function eat(type) {
  1.1066 +    if (tokType === type) {
  1.1067 +      next();
  1.1068 +      return true;
  1.1069 +    }
  1.1070 +  }
  1.1071 +
  1.1072 +  // Test whether a semicolon can be inserted at the current position.
  1.1073 +
  1.1074 +  function canInsertSemicolon() {
  1.1075 +    return !options.strictSemicolons &&
  1.1076 +      (tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));
  1.1077 +  }
  1.1078 +
  1.1079 +  // Consume a semicolon, or, failing that, see if we are allowed to
  1.1080 +  // pretend that there is a semicolon at this position.
  1.1081 +
  1.1082 +  function semicolon() {
  1.1083 +    if (!eat(_semi) && !canInsertSemicolon()) unexpected();
  1.1084 +  }
  1.1085 +
  1.1086 +  // Expect a token of a given type. If found, consume it, otherwise,
  1.1087 +  // raise an unexpected token error.
  1.1088 +
  1.1089 +  function expect(type) {
  1.1090 +    if (tokType === type) next();
  1.1091 +    else unexpected();
  1.1092 +  }
  1.1093 +
  1.1094 +  // Raise an unexpected token error.
  1.1095 +
  1.1096 +  function unexpected() {
  1.1097 +    raise(tokStart, "Unexpected token");
  1.1098 +  }
  1.1099 +
  1.1100 +  // Verify that a node is an lval — something that can be assigned
  1.1101 +  // to.
  1.1102 +
  1.1103 +  function checkLVal(expr) {
  1.1104 +    if (expr.type !== "Identifier" && expr.type !== "MemberExpression")
  1.1105 +      raise(expr.start, "Assigning to rvalue");
  1.1106 +    if (strict && expr.type === "Identifier" && isStrictBadIdWord(expr.name))
  1.1107 +      raise(expr.start, "Assigning to " + expr.name + " in strict mode");
  1.1108 +  }
  1.1109 +
  1.1110 +  // ### Statement parsing
  1.1111 +
  1.1112 +  // Parse a program. Initializes the parser, reads any number of
  1.1113 +  // statements, and wraps them in a Program node.  Optionally takes a
  1.1114 +  // `program` argument.  If present, the statements will be appended
  1.1115 +  // to its body instead of creating a new node.
  1.1116 +
  1.1117 +  function parseTopLevel(program) {
  1.1118 +    lastStart = lastEnd = tokPos;
  1.1119 +    if (options.locations) lastEndLoc = new line_loc_t;
  1.1120 +    inFunction = strict = null;
  1.1121 +    labels = [];
  1.1122 +    readToken();
  1.1123 +
  1.1124 +    var node = program || startNode(), first = true;
  1.1125 +    if (!program) node.body = [];
  1.1126 +    while (tokType !== _eof) {
  1.1127 +      var stmt = parseStatement();
  1.1128 +      node.body.push(stmt);
  1.1129 +      if (first && isUseStrict(stmt)) setStrict(true);
  1.1130 +      first = false;
  1.1131 +    }
  1.1132 +    return finishNode(node, "Program");
  1.1133 +  }
  1.1134 +
  1.1135 +  var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
  1.1136 +
  1.1137 +  // Parse a single statement.
  1.1138 +  //
  1.1139 +  // If expecting a statement and finding a slash operator, parse a
  1.1140 +  // regular expression literal. This is to handle cases like
  1.1141 +  // `if (foo) /blah/.exec(foo);`, where looking at the previous token
  1.1142 +  // does not help.
  1.1143 +
  1.1144 +  function parseStatement() {
  1.1145 +    if (tokType === _slash || tokType === _assign && tokVal == "/=")
  1.1146 +      readToken(true);
  1.1147 +
  1.1148 +    var starttype = tokType, node = startNode();
  1.1149 +
  1.1150 +    // Most types of statements are recognized by the keyword they
  1.1151 +    // start with. Many are trivial to parse, some require a bit of
  1.1152 +    // complexity.
  1.1153 +
  1.1154 +    switch (starttype) {
  1.1155 +    case _break: case _continue:
  1.1156 +      next();
  1.1157 +      var isBreak = starttype === _break;
  1.1158 +      if (eat(_semi) || canInsertSemicolon()) node.label = null;
  1.1159 +      else if (tokType !== _name) unexpected();
  1.1160 +      else {
  1.1161 +        node.label = parseIdent();
  1.1162 +        semicolon();
  1.1163 +      }
  1.1164 +
  1.1165 +      // Verify that there is an actual destination to break or
  1.1166 +      // continue to.
  1.1167 +      for (var i = 0; i < labels.length; ++i) {
  1.1168 +        var lab = labels[i];
  1.1169 +        if (node.label == null || lab.name === node.label.name) {
  1.1170 +          if (lab.kind != null && (isBreak || lab.kind === "loop")) break;
  1.1171 +          if (node.label && isBreak) break;
  1.1172 +        }
  1.1173 +      }
  1.1174 +      if (i === labels.length) raise(node.start, "Unsyntactic " + starttype.keyword);
  1.1175 +      return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
  1.1176 +
  1.1177 +    case _debugger:
  1.1178 +      next();
  1.1179 +      semicolon();
  1.1180 +      return finishNode(node, "DebuggerStatement");
  1.1181 +
  1.1182 +    case _do:
  1.1183 +      next();
  1.1184 +      labels.push(loopLabel);
  1.1185 +      node.body = parseStatement();
  1.1186 +      labels.pop();
  1.1187 +      expect(_while);
  1.1188 +      node.test = parseParenExpression();
  1.1189 +      semicolon();
  1.1190 +      return finishNode(node, "DoWhileStatement");
  1.1191 +
  1.1192 +      // Disambiguating between a `for` and a `for`/`in` loop is
  1.1193 +      // non-trivial. Basically, we have to parse the init `var`
  1.1194 +      // statement or expression, disallowing the `in` operator (see
  1.1195 +      // the second parameter to `parseExpression`), and then check
  1.1196 +      // whether the next token is `in`. When there is no init part
  1.1197 +      // (semicolon immediately after the opening parenthesis), it is
  1.1198 +      // a regular `for` loop.
  1.1199 +
  1.1200 +    case _for:
  1.1201 +      next();
  1.1202 +      labels.push(loopLabel);
  1.1203 +      expect(_parenL);
  1.1204 +      if (tokType === _semi) return parseFor(node, null);
  1.1205 +      if (tokType === _var) {
  1.1206 +        var init = startNode();
  1.1207 +        next();
  1.1208 +        parseVar(init, true);
  1.1209 +        finishNode(init, "VariableDeclaration");
  1.1210 +        if (init.declarations.length === 1 && eat(_in))
  1.1211 +          return parseForIn(node, init);
  1.1212 +        return parseFor(node, init);
  1.1213 +      }
  1.1214 +      var init = parseExpression(false, true);
  1.1215 +      if (eat(_in)) {checkLVal(init); return parseForIn(node, init);}
  1.1216 +      return parseFor(node, init);
  1.1217 +
  1.1218 +    case _function:
  1.1219 +      next();
  1.1220 +      return parseFunction(node, true);
  1.1221 +
  1.1222 +    case _if:
  1.1223 +      next();
  1.1224 +      node.test = parseParenExpression();
  1.1225 +      node.consequent = parseStatement();
  1.1226 +      node.alternate = eat(_else) ? parseStatement() : null;
  1.1227 +      return finishNode(node, "IfStatement");
  1.1228 +
  1.1229 +    case _return:
  1.1230 +      if (!inFunction) raise(tokStart, "'return' outside of function");
  1.1231 +      next();
  1.1232 +
  1.1233 +      // In `return` (and `break`/`continue`), the keywords with
  1.1234 +      // optional arguments, we eagerly look for a semicolon or the
  1.1235 +      // possibility to insert one.
  1.1236 +
  1.1237 +      if (eat(_semi) || canInsertSemicolon()) node.argument = null;
  1.1238 +      else { node.argument = parseExpression(); semicolon(); }
  1.1239 +      return finishNode(node, "ReturnStatement");
  1.1240 +
  1.1241 +    case _switch:
  1.1242 +      next();
  1.1243 +      node.discriminant = parseParenExpression();
  1.1244 +      node.cases = [];
  1.1245 +      expect(_braceL);
  1.1246 +      labels.push(switchLabel);
  1.1247 +
  1.1248 +      // Statements under must be grouped (by label) in SwitchCase
  1.1249 +      // nodes. `cur` is used to keep the node that we are currently
  1.1250 +      // adding statements to.
  1.1251 +
  1.1252 +      for (var cur, sawDefault; tokType != _braceR;) {
  1.1253 +        if (tokType === _case || tokType === _default) {
  1.1254 +          var isCase = tokType === _case;
  1.1255 +          if (cur) finishNode(cur, "SwitchCase");
  1.1256 +          node.cases.push(cur = startNode());
  1.1257 +          cur.consequent = [];
  1.1258 +          next();
  1.1259 +          if (isCase) cur.test = parseExpression();
  1.1260 +          else {
  1.1261 +            if (sawDefault) raise(lastStart, "Multiple default clauses"); sawDefault = true;
  1.1262 +            cur.test = null;
  1.1263 +          }
  1.1264 +          expect(_colon);
  1.1265 +        } else {
  1.1266 +          if (!cur) unexpected();
  1.1267 +          cur.consequent.push(parseStatement());
  1.1268 +        }
  1.1269 +      }
  1.1270 +      if (cur) finishNode(cur, "SwitchCase");
  1.1271 +      next(); // Closing brace
  1.1272 +      labels.pop();
  1.1273 +      return finishNode(node, "SwitchStatement");
  1.1274 +
  1.1275 +    case _throw:
  1.1276 +      next();
  1.1277 +      if (newline.test(input.slice(lastEnd, tokStart)))
  1.1278 +        raise(lastEnd, "Illegal newline after throw");
  1.1279 +      node.argument = parseExpression();
  1.1280 +      semicolon();
  1.1281 +      return finishNode(node, "ThrowStatement");
  1.1282 +
  1.1283 +    case _try:
  1.1284 +      next();
  1.1285 +      node.block = parseBlock();
  1.1286 +      node.handler = null;
  1.1287 +      if (tokType === _catch) {
  1.1288 +        var clause = startNode();
  1.1289 +        next();
  1.1290 +        expect(_parenL);
  1.1291 +        clause.param = parseIdent();
  1.1292 +        if (strict && isStrictBadIdWord(clause.param.name))
  1.1293 +          raise(clause.param.start, "Binding " + clause.param.name + " in strict mode");
  1.1294 +        expect(_parenR);
  1.1295 +        clause.guard = null;
  1.1296 +        clause.body = parseBlock();
  1.1297 +        node.handler = finishNode(clause, "CatchClause");
  1.1298 +      }
  1.1299 +      node.guardedHandlers = empty;
  1.1300 +      node.finalizer = eat(_finally) ? parseBlock() : null;
  1.1301 +      if (!node.handler && !node.finalizer)
  1.1302 +        raise(node.start, "Missing catch or finally clause");
  1.1303 +      return finishNode(node, "TryStatement");
  1.1304 +
  1.1305 +    case _var:
  1.1306 +      next();
  1.1307 +      parseVar(node);
  1.1308 +      semicolon();
  1.1309 +      return finishNode(node, "VariableDeclaration");
  1.1310 +
  1.1311 +    case _while:
  1.1312 +      next();
  1.1313 +      node.test = parseParenExpression();
  1.1314 +      labels.push(loopLabel);
  1.1315 +      node.body = parseStatement();
  1.1316 +      labels.pop();
  1.1317 +      return finishNode(node, "WhileStatement");
  1.1318 +
  1.1319 +    case _with:
  1.1320 +      if (strict) raise(tokStart, "'with' in strict mode");
  1.1321 +      next();
  1.1322 +      node.object = parseParenExpression();
  1.1323 +      node.body = parseStatement();
  1.1324 +      return finishNode(node, "WithStatement");
  1.1325 +
  1.1326 +    case _braceL:
  1.1327 +      return parseBlock();
  1.1328 +
  1.1329 +    case _semi:
  1.1330 +      next();
  1.1331 +      return finishNode(node, "EmptyStatement");
  1.1332 +
  1.1333 +      // If the statement does not start with a statement keyword or a
  1.1334 +      // brace, it's an ExpressionStatement or LabeledStatement. We
  1.1335 +      // simply start parsing an expression, and afterwards, if the
  1.1336 +      // next token is a colon and the expression was a simple
  1.1337 +      // Identifier node, we switch to interpreting it as a label.
  1.1338 +
  1.1339 +    default:
  1.1340 +      var maybeName = tokVal, expr = parseExpression();
  1.1341 +      if (starttype === _name && expr.type === "Identifier" && eat(_colon)) {
  1.1342 +        for (var i = 0; i < labels.length; ++i)
  1.1343 +          if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared");
  1.1344 +        var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null;
  1.1345 +        labels.push({name: maybeName, kind: kind});
  1.1346 +        node.body = parseStatement();
  1.1347 +        labels.pop();
  1.1348 +        node.label = expr;
  1.1349 +        return finishNode(node, "LabeledStatement");
  1.1350 +      } else {
  1.1351 +        node.expression = expr;
  1.1352 +        semicolon();
  1.1353 +        return finishNode(node, "ExpressionStatement");
  1.1354 +      }
  1.1355 +    }
  1.1356 +  }
  1.1357 +
  1.1358 +  // Used for constructs like `switch` and `if` that insist on
  1.1359 +  // parentheses around their expression.
  1.1360 +
  1.1361 +  function parseParenExpression() {
  1.1362 +    expect(_parenL);
  1.1363 +    var val = parseExpression();
  1.1364 +    expect(_parenR);
  1.1365 +    return val;
  1.1366 +  }
  1.1367 +
  1.1368 +  // Parse a semicolon-enclosed block of statements, handling `"use
  1.1369 +  // strict"` declarations when `allowStrict` is true (used for
  1.1370 +  // function bodies).
  1.1371 +
  1.1372 +  function parseBlock(allowStrict) {
  1.1373 +    var node = startNode(), first = true, strict = false, oldStrict;
  1.1374 +    node.body = [];
  1.1375 +    expect(_braceL);
  1.1376 +    while (!eat(_braceR)) {
  1.1377 +      var stmt = parseStatement();
  1.1378 +      node.body.push(stmt);
  1.1379 +      if (first && allowStrict && isUseStrict(stmt)) {
  1.1380 +        oldStrict = strict;
  1.1381 +        setStrict(strict = true);
  1.1382 +      }
  1.1383 +      first = false;
  1.1384 +    }
  1.1385 +    if (strict && !oldStrict) setStrict(false);
  1.1386 +    return finishNode(node, "BlockStatement");
  1.1387 +  }
  1.1388 +
  1.1389 +  // Parse a regular `for` loop. The disambiguation code in
  1.1390 +  // `parseStatement` will already have parsed the init statement or
  1.1391 +  // expression.
  1.1392 +
  1.1393 +  function parseFor(node, init) {
  1.1394 +    node.init = init;
  1.1395 +    expect(_semi);
  1.1396 +    node.test = tokType === _semi ? null : parseExpression();
  1.1397 +    expect(_semi);
  1.1398 +    node.update = tokType === _parenR ? null : parseExpression();
  1.1399 +    expect(_parenR);
  1.1400 +    node.body = parseStatement();
  1.1401 +    labels.pop();
  1.1402 +    return finishNode(node, "ForStatement");
  1.1403 +  }
  1.1404 +
  1.1405 +  // Parse a `for`/`in` loop.
  1.1406 +
  1.1407 +  function parseForIn(node, init) {
  1.1408 +    node.left = init;
  1.1409 +    node.right = parseExpression();
  1.1410 +    expect(_parenR);
  1.1411 +    node.body = parseStatement();
  1.1412 +    labels.pop();
  1.1413 +    return finishNode(node, "ForInStatement");
  1.1414 +  }
  1.1415 +
  1.1416 +  // Parse a list of variable declarations.
  1.1417 +
  1.1418 +  function parseVar(node, noIn) {
  1.1419 +    node.declarations = [];
  1.1420 +    node.kind = "var";
  1.1421 +    for (;;) {
  1.1422 +      var decl = startNode();
  1.1423 +      decl.id = parseIdent();
  1.1424 +      if (strict && isStrictBadIdWord(decl.id.name))
  1.1425 +        raise(decl.id.start, "Binding " + decl.id.name + " in strict mode");
  1.1426 +      decl.init = eat(_eq) ? parseExpression(true, noIn) : null;
  1.1427 +      node.declarations.push(finishNode(decl, "VariableDeclarator"));
  1.1428 +      if (!eat(_comma)) break;
  1.1429 +    }
  1.1430 +    return node;
  1.1431 +  }
  1.1432 +
  1.1433 +  // ### Expression parsing
  1.1434 +
  1.1435 +  // These nest, from the most general expression type at the top to
  1.1436 +  // 'atomic', nondivisible expression types at the bottom. Most of
  1.1437 +  // the functions will simply let the function(s) below them parse,
  1.1438 +  // and, *if* the syntactic construct they handle is present, wrap
  1.1439 +  // the AST node that the inner parser gave them in another node.
  1.1440 +
  1.1441 +  // Parse a full expression. The arguments are used to forbid comma
  1.1442 +  // sequences (in argument lists, array literals, or object literals)
  1.1443 +  // or the `in` operator (in for loops initalization expressions).
  1.1444 +
  1.1445 +  function parseExpression(noComma, noIn) {
  1.1446 +    var expr = parseMaybeAssign(noIn);
  1.1447 +    if (!noComma && tokType === _comma) {
  1.1448 +      var node = startNodeFrom(expr);
  1.1449 +      node.expressions = [expr];
  1.1450 +      while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
  1.1451 +      return finishNode(node, "SequenceExpression");
  1.1452 +    }
  1.1453 +    return expr;
  1.1454 +  }
  1.1455 +
  1.1456 +  // Parse an assignment expression. This includes applications of
  1.1457 +  // operators like `+=`.
  1.1458 +
  1.1459 +  function parseMaybeAssign(noIn) {
  1.1460 +    var left = parseMaybeConditional(noIn);
  1.1461 +    if (tokType.isAssign) {
  1.1462 +      var node = startNodeFrom(left);
  1.1463 +      node.operator = tokVal;
  1.1464 +      node.left = left;
  1.1465 +      next();
  1.1466 +      node.right = parseMaybeAssign(noIn);
  1.1467 +      checkLVal(left);
  1.1468 +      return finishNode(node, "AssignmentExpression");
  1.1469 +    }
  1.1470 +    return left;
  1.1471 +  }
  1.1472 +
  1.1473 +  // Parse a ternary conditional (`?:`) operator.
  1.1474 +
  1.1475 +  function parseMaybeConditional(noIn) {
  1.1476 +    var expr = parseExprOps(noIn);
  1.1477 +    if (eat(_question)) {
  1.1478 +      var node = startNodeFrom(expr);
  1.1479 +      node.test = expr;
  1.1480 +      node.consequent = parseExpression(true);
  1.1481 +      expect(_colon);
  1.1482 +      node.alternate = parseExpression(true, noIn);
  1.1483 +      return finishNode(node, "ConditionalExpression");
  1.1484 +    }
  1.1485 +    return expr;
  1.1486 +  }
  1.1487 +
  1.1488 +  // Start the precedence parser.
  1.1489 +
  1.1490 +  function parseExprOps(noIn) {
  1.1491 +    return parseExprOp(parseMaybeUnary(), -1, noIn);
  1.1492 +  }
  1.1493 +
  1.1494 +  // Parse binary operators with the operator precedence parsing
  1.1495 +  // algorithm. `left` is the left-hand side of the operator.
  1.1496 +  // `minPrec` provides context that allows the function to stop and
  1.1497 +  // defer further parser to one of its callers when it encounters an
  1.1498 +  // operator that has a lower precedence than the set it is parsing.
  1.1499 +
  1.1500 +  function parseExprOp(left, minPrec, noIn) {
  1.1501 +    var prec = tokType.binop;
  1.1502 +    if (prec != null && (!noIn || tokType !== _in)) {
  1.1503 +      if (prec > minPrec) {
  1.1504 +        var node = startNodeFrom(left);
  1.1505 +        node.left = left;
  1.1506 +        node.operator = tokVal;
  1.1507 +        var op = tokType;
  1.1508 +        next();
  1.1509 +        node.right = parseExprOp(parseMaybeUnary(), prec, noIn);
  1.1510 +        var exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? "LogicalExpression" : "BinaryExpression");
  1.1511 +        return parseExprOp(exprNode, minPrec, noIn);
  1.1512 +      }
  1.1513 +    }
  1.1514 +    return left;
  1.1515 +  }
  1.1516 +
  1.1517 +  // Parse unary operators, both prefix and postfix.
  1.1518 +
  1.1519 +  function parseMaybeUnary() {
  1.1520 +    if (tokType.prefix) {
  1.1521 +      var node = startNode(), update = tokType.isUpdate;
  1.1522 +      node.operator = tokVal;
  1.1523 +      node.prefix = true;
  1.1524 +      tokRegexpAllowed = true;
  1.1525 +      next();
  1.1526 +      node.argument = parseMaybeUnary();
  1.1527 +      if (update) checkLVal(node.argument);
  1.1528 +      else if (strict && node.operator === "delete" &&
  1.1529 +               node.argument.type === "Identifier")
  1.1530 +        raise(node.start, "Deleting local variable in strict mode");
  1.1531 +      return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
  1.1532 +    }
  1.1533 +    var expr = parseExprSubscripts();
  1.1534 +    while (tokType.postfix && !canInsertSemicolon()) {
  1.1535 +      var node = startNodeFrom(expr);
  1.1536 +      node.operator = tokVal;
  1.1537 +      node.prefix = false;
  1.1538 +      node.argument = expr;
  1.1539 +      checkLVal(expr);
  1.1540 +      next();
  1.1541 +      expr = finishNode(node, "UpdateExpression");
  1.1542 +    }
  1.1543 +    return expr;
  1.1544 +  }
  1.1545 +
  1.1546 +  // Parse call, dot, and `[]`-subscript expressions.
  1.1547 +
  1.1548 +  function parseExprSubscripts() {
  1.1549 +    return parseSubscripts(parseExprAtom());
  1.1550 +  }
  1.1551 +
  1.1552 +  function parseSubscripts(base, noCalls) {
  1.1553 +    if (eat(_dot)) {
  1.1554 +      var node = startNodeFrom(base);
  1.1555 +      node.object = base;
  1.1556 +      node.property = parseIdent(true);
  1.1557 +      node.computed = false;
  1.1558 +      return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
  1.1559 +    } else if (eat(_bracketL)) {
  1.1560 +      var node = startNodeFrom(base);
  1.1561 +      node.object = base;
  1.1562 +      node.property = parseExpression();
  1.1563 +      node.computed = true;
  1.1564 +      expect(_bracketR);
  1.1565 +      return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
  1.1566 +    } else if (!noCalls && eat(_parenL)) {
  1.1567 +      var node = startNodeFrom(base);
  1.1568 +      node.callee = base;
  1.1569 +      node.arguments = parseExprList(_parenR, false);
  1.1570 +      return parseSubscripts(finishNode(node, "CallExpression"), noCalls);
  1.1571 +    } else return base;
  1.1572 +  }
  1.1573 +
  1.1574 +  // Parse an atomic expression — either a single token that is an
  1.1575 +  // expression, an expression started by a keyword like `function` or
  1.1576 +  // `new`, or an expression wrapped in punctuation like `()`, `[]`,
  1.1577 +  // or `{}`.
  1.1578 +
  1.1579 +  function parseExprAtom() {
  1.1580 +    switch (tokType) {
  1.1581 +    case _this:
  1.1582 +      var node = startNode();
  1.1583 +      next();
  1.1584 +      return finishNode(node, "ThisExpression");
  1.1585 +    case _name:
  1.1586 +      return parseIdent();
  1.1587 +    case _num: case _string: case _regexp:
  1.1588 +      var node = startNode();
  1.1589 +      node.value = tokVal;
  1.1590 +      node.raw = input.slice(tokStart, tokEnd);
  1.1591 +      next();
  1.1592 +      return finishNode(node, "Literal");
  1.1593 +
  1.1594 +    case _null: case _true: case _false:
  1.1595 +      var node = startNode();
  1.1596 +      node.value = tokType.atomValue;
  1.1597 +      node.raw = tokType.keyword;
  1.1598 +      next();
  1.1599 +      return finishNode(node, "Literal");
  1.1600 +
  1.1601 +    case _parenL:
  1.1602 +      var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart;
  1.1603 +      next();
  1.1604 +      var val = parseExpression();
  1.1605 +      val.start = tokStart1;
  1.1606 +      val.end = tokEnd;
  1.1607 +      if (options.locations) {
  1.1608 +        val.loc.start = tokStartLoc1;
  1.1609 +        val.loc.end = tokEndLoc;
  1.1610 +      }
  1.1611 +      if (options.ranges)
  1.1612 +        val.range = [tokStart1, tokEnd];
  1.1613 +      expect(_parenR);
  1.1614 +      return val;
  1.1615 +
  1.1616 +    case _bracketL:
  1.1617 +      var node = startNode();
  1.1618 +      next();
  1.1619 +      node.elements = parseExprList(_bracketR, true, true);
  1.1620 +      return finishNode(node, "ArrayExpression");
  1.1621 +
  1.1622 +    case _braceL:
  1.1623 +      return parseObj();
  1.1624 +
  1.1625 +    case _function:
  1.1626 +      var node = startNode();
  1.1627 +      next();
  1.1628 +      return parseFunction(node, false);
  1.1629 +
  1.1630 +    case _new:
  1.1631 +      return parseNew();
  1.1632 +
  1.1633 +    default:
  1.1634 +      unexpected();
  1.1635 +    }
  1.1636 +  }
  1.1637 +
  1.1638 +  // New's precedence is slightly tricky. It must allow its argument
  1.1639 +  // to be a `[]` or dot subscript expression, but not a call — at
  1.1640 +  // least, not without wrapping it in parentheses. Thus, it uses the
  1.1641 +
  1.1642 +  function parseNew() {
  1.1643 +    var node = startNode();
  1.1644 +    next();
  1.1645 +    node.callee = parseSubscripts(parseExprAtom(), true);
  1.1646 +    if (eat(_parenL)) node.arguments = parseExprList(_parenR, false);
  1.1647 +    else node.arguments = empty;
  1.1648 +    return finishNode(node, "NewExpression");
  1.1649 +  }
  1.1650 +
  1.1651 +  // Parse an object literal.
  1.1652 +
  1.1653 +  function parseObj() {
  1.1654 +    var node = startNode(), first = true, sawGetSet = false;
  1.1655 +    node.properties = [];
  1.1656 +    next();
  1.1657 +    while (!eat(_braceR)) {
  1.1658 +      if (!first) {
  1.1659 +        expect(_comma);
  1.1660 +        if (options.allowTrailingCommas && eat(_braceR)) break;
  1.1661 +      } else first = false;
  1.1662 +
  1.1663 +      var prop = {key: parsePropertyName()}, isGetSet = false, kind;
  1.1664 +      if (eat(_colon)) {
  1.1665 +        prop.value = parseExpression(true);
  1.1666 +        kind = prop.kind = "init";
  1.1667 +      } else if (options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&
  1.1668 +                 (prop.key.name === "get" || prop.key.name === "set")) {
  1.1669 +        isGetSet = sawGetSet = true;
  1.1670 +        kind = prop.kind = prop.key.name;
  1.1671 +        prop.key = parsePropertyName();
  1.1672 +        if (tokType !== _parenL) unexpected();
  1.1673 +        prop.value = parseFunction(startNode(), false);
  1.1674 +      } else unexpected();
  1.1675 +
  1.1676 +      // getters and setters are not allowed to clash — either with
  1.1677 +      // each other or with an init property — and in strict mode,
  1.1678 +      // init properties are also not allowed to be repeated.
  1.1679 +
  1.1680 +      if (prop.key.type === "Identifier" && (strict || sawGetSet)) {
  1.1681 +        for (var i = 0; i < node.properties.length; ++i) {
  1.1682 +          var other = node.properties[i];
  1.1683 +          if (other.key.name === prop.key.name) {
  1.1684 +            var conflict = kind == other.kind || isGetSet && other.kind === "init" ||
  1.1685 +              kind === "init" && (other.kind === "get" || other.kind === "set");
  1.1686 +            if (conflict && !strict && kind === "init" && other.kind === "init") conflict = false;
  1.1687 +            if (conflict) raise(prop.key.start, "Redefinition of property");
  1.1688 +          }
  1.1689 +        }
  1.1690 +      }
  1.1691 +      node.properties.push(prop);
  1.1692 +    }
  1.1693 +    return finishNode(node, "ObjectExpression");
  1.1694 +  }
  1.1695 +
  1.1696 +  function parsePropertyName() {
  1.1697 +    if (tokType === _num || tokType === _string) return parseExprAtom();
  1.1698 +    return parseIdent(true);
  1.1699 +  }
  1.1700 +
  1.1701 +  // Parse a function declaration or literal (depending on the
  1.1702 +  // `isStatement` parameter).
  1.1703 +
  1.1704 +  function parseFunction(node, isStatement) {
  1.1705 +    if (tokType === _name) node.id = parseIdent();
  1.1706 +    else if (isStatement) unexpected();
  1.1707 +    else node.id = null;
  1.1708 +    node.params = [];
  1.1709 +    var first = true;
  1.1710 +    expect(_parenL);
  1.1711 +    while (!eat(_parenR)) {
  1.1712 +      if (!first) expect(_comma); else first = false;
  1.1713 +      node.params.push(parseIdent());
  1.1714 +    }
  1.1715 +
  1.1716 +    // Start a new scope with regard to labels and the `inFunction`
  1.1717 +    // flag (restore them to their old value afterwards).
  1.1718 +    var oldInFunc = inFunction, oldLabels = labels;
  1.1719 +    inFunction = true; labels = [];
  1.1720 +    node.body = parseBlock(true);
  1.1721 +    inFunction = oldInFunc; labels = oldLabels;
  1.1722 +
  1.1723 +    // If this is a strict mode function, verify that argument names
  1.1724 +    // are not repeated, and it does not try to bind the words `eval`
  1.1725 +    // or `arguments`.
  1.1726 +    if (strict || node.body.body.length && isUseStrict(node.body.body[0])) {
  1.1727 +      for (var i = node.id ? -1 : 0; i < node.params.length; ++i) {
  1.1728 +        var id = i < 0 ? node.id : node.params[i];
  1.1729 +        if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
  1.1730 +          raise(id.start, "Defining '" + id.name + "' in strict mode");
  1.1731 +        if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)
  1.1732 +          raise(id.start, "Argument name clash in strict mode");
  1.1733 +      }
  1.1734 +    }
  1.1735 +
  1.1736 +    return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
  1.1737 +  }
  1.1738 +
  1.1739 +  // Parses a comma-separated list of expressions, and returns them as
  1.1740 +  // an array. `close` is the token type that ends the list, and
  1.1741 +  // `allowEmpty` can be turned on to allow subsequent commas with
  1.1742 +  // nothing in between them to be parsed as `null` (which is needed
  1.1743 +  // for array literals).
  1.1744 +
  1.1745 +  function parseExprList(close, allowTrailingComma, allowEmpty) {
  1.1746 +    var elts = [], first = true;
  1.1747 +    while (!eat(close)) {
  1.1748 +      if (!first) {
  1.1749 +        expect(_comma);
  1.1750 +        if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break;
  1.1751 +      } else first = false;
  1.1752 +
  1.1753 +      if (allowEmpty && tokType === _comma) elts.push(null);
  1.1754 +      else elts.push(parseExpression(true));
  1.1755 +    }
  1.1756 +    return elts;
  1.1757 +  }
  1.1758 +
  1.1759 +  // Parse the next token as an identifier. If `liberal` is true (used
  1.1760 +  // when parsing properties), it will also convert keywords into
  1.1761 +  // identifiers.
  1.1762 +
  1.1763 +  function parseIdent(liberal) {
  1.1764 +    var node = startNode();
  1.1765 +    node.name = tokType === _name ? tokVal : (liberal && !options.forbidReserved && tokType.keyword) || unexpected();
  1.1766 +    tokRegexpAllowed = false;
  1.1767 +    next();
  1.1768 +    return finishNode(node, "Identifier");
  1.1769 +  }
  1.1770 +
  1.1771 +});

mercurial