# JUST FOR NOW, later I will write my own - much faster and better.

#  Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
#  Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
#  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
#  Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
#  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
#  Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
#  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
#  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
#  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
#
#  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 HOLDERS AND CONTRIBUTORS "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 <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.

# -*- coding: latin-1 -*-
from __future__ import print_function
import re
def typeof(t):
    if t is None: return 'undefined'
    elif isinstance(t, bool): return 'boolean'
    elif isinstance(t, str): return 'string'
    elif isinstance(t, int) or isinstance(t, float): return 'number'
    elif hasattr(t, '__call__'): return 'function'
    else: return 'object'

def list_indexOf(l, v):
    try:
        return l.index(v)
    except:
        return -1

parseFloat = float
parseInt = int

class jsdict(object):
    def __init__(self, d):
        self.__dict__.update(d)
    def __getitem__(self, name):
        if name in self.__dict__:
          return self.__dict__[name]
        else:
          return None
    def __setitem__(self, name, value):
        self.__dict__[name] = value
        return value
    def __getattr__(self, name):
        try:
            return getattr(self, name)
        except:
            return None
    def __setattr__(self, name, value):
        self[name] = value
        return value
    def __contains__(self, name):
        return name in self.__dict__
    def __repr__(self):
        return str(self.__dict__)

class RegExp(object):
    def __init__(self, pattern, flags=''):
        self.flags = flags
        pyflags = 0 | re.M if 'm' in flags else 0 | re.I if 'i' in flags else 0
        self.source = pattern
        self.pattern = re.compile(pattern, pyflags)
    def test(self, s):
        return self.pattern.search(s) is not None

console = jsdict({"log":print})

def __temp__42(object=None, body=None):
    return jsdict({
"type": Syntax.WithStatement,
"object": object,
"body": body,
})

def __temp__41(test=None, body=None):
    return jsdict({
"type": Syntax.WhileStatement,
"test": test,
"body": body,
})

def __temp__40(id=None, init=None):
    return jsdict({
"type": Syntax.VariableDeclarator,
"id": id,
"init": init,
})

def __temp__39(declarations=None, kind=None):
    return jsdict({
"type": Syntax.VariableDeclaration,
"declarations": declarations,
"kind": kind,
})

def __temp__38(operator=None, argument=None):
    if (operator == "++") or (operator == "--"):
        return jsdict({
"type": Syntax.UpdateExpression,
"operator": operator,
"argument": argument,
"prefix": True,
})
    return jsdict({
"type": Syntax.UnaryExpression,
"operator": operator,
"argument": argument,
"prefix": True,
})

def __temp__37(block=None, guardedHandlers=None, handlers=None, finalizer=None):
    return jsdict({
"type": Syntax.TryStatement,
"block": block,
"guardedHandlers": guardedHandlers,
"handlers": handlers,
"finalizer": finalizer,
})

def __temp__36(argument=None):
    return jsdict({
"type": Syntax.ThrowStatement,
"argument": argument,
})

def __temp__35():
    return jsdict({
"type": Syntax.ThisExpression,
})

def __temp__34(discriminant=None, cases=None):
    return jsdict({
"type": Syntax.SwitchStatement,
"discriminant": discriminant,
"cases": cases,
})

def __temp__33(test=None, consequent=None):
    return jsdict({
"type": Syntax.SwitchCase,
"test": test,
"consequent": consequent,
})

def __temp__32(expressions=None):
    return jsdict({
"type": Syntax.SequenceExpression,
"expressions": expressions,
})

def __temp__31(argument=None):
    return jsdict({
"type": Syntax.ReturnStatement,
"argument": argument,
})

def __temp__30(kind=None, key=None, value=None):
    return jsdict({
"type": Syntax.Property,
"key": key,
"value": value,
"kind": kind,
})

def __temp__29(body=None):
    return jsdict({
"type": Syntax.Program,
"body": body,
})

def __temp__28(operator=None, argument=None):
    return jsdict({
"type": Syntax.UpdateExpression,
"operator": operator,
"argument": argument,
"prefix": False,
})

def __temp__27(properties=None):
    return jsdict({
"type": Syntax.ObjectExpression,
"properties": properties,
})

def __temp__26(callee=None, args=None):
    return jsdict({
"type": Syntax.NewExpression,
"callee": callee,
"arguments": args,
})

def __temp__25(accessor=None, object=None, property=None):
    return jsdict({
"type": Syntax.MemberExpression,
"computed": accessor == "[",
"object": object,
"property": property,
})

def __temp__24(token=None):
    return jsdict({
"type": Syntax.Literal,
"value": token.value,
"raw": source[token.range[0]:token.range[1]],
})

def __temp__23(label=None, body=None):
    return jsdict({
"type": Syntax.LabeledStatement,
"label": label,
"body": body,
})

def __temp__22(test=None, consequent=None, alternate=None):
    return jsdict({
"type": Syntax.IfStatement,
"test": test,
"consequent": consequent,
"alternate": alternate,
})

def __temp__21(name=None):
    return jsdict({
"type": Syntax.Identifier,
"name": name,
})

def __temp__20(id=None, params=None, defaults=None, body=None):
    return jsdict({
"type": Syntax.FunctionExpression,
"id": id,
"params": params,
"defaults": defaults,
"body": body,
"rest": None,
"generator": False,
"expression": False,
})

def __temp__19(id=None, params=None, defaults=None, body=None):
    return jsdict({
"type": Syntax.FunctionDeclaration,
"id": id,
"params": params,
"defaults": defaults,
"body": body,
"rest": None,
"generator": False,
"expression": False,
})

def __temp__18(left=None, right=None, body=None):
    return jsdict({
"type": Syntax.ForInStatement,
"left": left,
"right": right,
"body": body,
"each": False,
})

def __temp__17(init=None, test=None, update=None, body=None):
    return jsdict({
"type": Syntax.ForStatement,
"init": init,
"test": test,
"update": update,
"body": body,
})

def __temp__16(expression=None):
    return jsdict({
"type": Syntax.ExpressionStatement,
"expression": expression,
})

def __temp__15():
    return jsdict({
"type": Syntax.EmptyStatement,
})

def __temp__14(body=None, test=None):
    return jsdict({
"type": Syntax.DoWhileStatement,
"body": body,
"test": test,
})

def __temp__13():
    return jsdict({
"type": Syntax.DebuggerStatement,
})

def __temp__12(label=None):
    return jsdict({
"type": Syntax.ContinueStatement,
"label": label,
})

def __temp__11(test=None, consequent=None, alternate=None):
    return jsdict({
"type": Syntax.ConditionalExpression,
"test": test,
"consequent": consequent,
"alternate": alternate,
})

def __temp__10(param=None, body=None):
    return jsdict({
"type": Syntax.CatchClause,
"param": param,
"body": body,
})

def __temp__9(callee=None, args=None):
    return jsdict({
"type": Syntax.CallExpression,
"callee": callee,
"arguments": args,
})

def __temp__8(label=None):
    return jsdict({
"type": Syntax.BreakStatement,
"label": label,
})

def __temp__7(body=None):
    return jsdict({
"type": Syntax.BlockStatement,
"body": body,
})

def __temp__6(operator=None, left=None, right=None):
    type = (Syntax.LogicalExpression if (operator == "||") or (operator == "&&") else Syntax.BinaryExpression)
    return jsdict({
"type": type,
"operator": operator,
"left": left,
"right": right,
})

def __temp__5(operator=None, left=None, right=None):
    return jsdict({
"type": Syntax.AssignmentExpression,
"operator": operator,
"left": left,
"right": right,
})

def __temp__4(elements=None):
    return jsdict({
"type": Syntax.ArrayExpression,
"elements": elements,
})

def __temp__3(node=None):
    if extra.source:
        node.loc.source = extra.source
    return node

def __temp__2(node=None):
    if node.range or node.loc:
        if extra.loc:
            state.markerStack.pop()
            state.markerStack.pop()
        if extra.range:
            state.markerStack.pop()
    else:
        SyntaxTreeDelegate.markEnd(node)
    return node

def __temp__1(node=None):
    if extra.range:
        node.range = [state.markerStack.pop(), index]
    if extra.loc:
        node.loc = jsdict({
"start": jsdict({
"line": state.markerStack.pop(),
"column": state.markerStack.pop(),
}),
"end": jsdict({
"line": lineNumber,
"column": index - lineStart,
}),
})
        SyntaxTreeDelegate.postProcess(node)
    return node

def __temp__0():
    if extra.loc:
        state.markerStack.append(index - lineStart)
        state.markerStack.append(lineNumber)
    if extra.range:
        state.markerStack.append(index)

Token = None
TokenName = None
FnExprTokens = None
Syntax = None
PropertyKind = None
Messages = None
Regex = None
SyntaxTreeDelegate = None
source = None
strict = None
index = None
lineNumber = None
lineStart = None
length = None
delegate = None
lookahead = None
state = None
extra = None
Token = jsdict({
"BooleanLiteral": 1,
"EOF": 2,
"Identifier": 3,
"Keyword": 4,
"NullLiteral": 5,
"NumericLiteral": 6,
"Punctuator": 7,
"StringLiteral": 8,
"RegularExpression": 9,
})
TokenName = jsdict({
})
TokenName[Token.BooleanLiteral] = "Boolean"
TokenName[Token.EOF] = "<end>"
TokenName[Token.Identifier] = "Identifier"
TokenName[Token.Keyword] = "Keyword"
TokenName[Token.NullLiteral] = "Null"
TokenName[Token.NumericLiteral] = "Numeric"
TokenName[Token.Punctuator] = "Punctuator"
TokenName[Token.StringLiteral] = "String"
TokenName[Token.RegularExpression] = "RegularExpression"
FnExprTokens = ["(", "{", "[", "in", "typeof", "instanceof", "new", "return", "case", "delete", "throw", "void", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "|=", "^=", ",", "+", "-", "*", "/", "%", "++", "--", "<<", ">>", ">>>", "&", "|", "^", "!", "~", "&&", "||", "?", ":", "===", "==", ">=", "<=", "<", ">", "!=", "!=="]
Syntax = jsdict({
"AssignmentExpression": "AssignmentExpression",
"ArrayExpression": "ArrayExpression",
"BlockStatement": "BlockStatement",
"BinaryExpression": "BinaryExpression",
"BreakStatement": "BreakStatement",
"CallExpression": "CallExpression",
"CatchClause": "CatchClause",
"ConditionalExpression": "ConditionalExpression",
"ContinueStatement": "ContinueStatement",
"DoWhileStatement": "DoWhileStatement",
"DebuggerStatement": "DebuggerStatement",
"EmptyStatement": "EmptyStatement",
"ExpressionStatement": "ExpressionStatement",
"ForStatement": "ForStatement",
"ForInStatement": "ForInStatement",
"FunctionDeclaration": "FunctionDeclaration",
"FunctionExpression": "FunctionExpression",
"Identifier": "Identifier",
"IfStatement": "IfStatement",
"Literal": "Literal",
"LabeledStatement": "LabeledStatement",
"LogicalExpression": "LogicalExpression",
"MemberExpression": "MemberExpression",
"NewExpression": "NewExpression",
"ObjectExpression": "ObjectExpression",
"Program": "Program",
"Property": "Property",
"ReturnStatement": "ReturnStatement",
"SequenceExpression": "SequenceExpression",
"SwitchStatement": "SwitchStatement",
"SwitchCase": "SwitchCase",
"ThisExpression": "ThisExpression",
"ThrowStatement": "ThrowStatement",
"TryStatement": "TryStatement",
"UnaryExpression": "UnaryExpression",
"UpdateExpression": "UpdateExpression",
"VariableDeclaration": "VariableDeclaration",
"VariableDeclarator": "VariableDeclarator",
"WhileStatement": "WhileStatement",
"WithStatement": "WithStatement",
})
PropertyKind = jsdict({
"Data": 1,
"Get": 2,
"Set": 4,
})
Messages = jsdict({
"UnexpectedToken": "Unexpected token %0",
"UnexpectedNumber": "Unexpected number",
"UnexpectedString": "Unexpected string",
"UnexpectedIdentifier": "Unexpected identifier",
"UnexpectedReserved": "Unexpected reserved word",
"UnexpectedEOS": "Unexpected end of input",
"NewlineAfterThrow": "Illegal newline after throw",
"InvalidRegExp": "Invalid regular expression",
"UnterminatedRegExp": "Invalid regular expression: missing /",
"InvalidLHSInAssignment": "Invalid left-hand side in assignment",
"InvalidLHSInForIn": "Invalid left-hand side in for-in",
"MultipleDefaultsInSwitch": "More than one default clause in switch statement",
"NoCatchOrFinally": "Missing catch or finally after try",
"UnknownLabel": "Undefined label '%0'",
"Redeclaration": "%0 '%1' has already been declared",
"IllegalContinue": "Illegal continue statement",
"IllegalBreak": "Illegal break statement",
"IllegalReturn": "Illegal return statement",
"StrictModeWith": "Strict mode code may not include a with statement",
"StrictCatchVariable": "Catch variable may not be eval or arguments in strict mode",
"StrictVarName": "Variable name may not be eval or arguments in strict mode",
"StrictParamName": "Parameter name eval or arguments is not allowed in strict mode",
"StrictParamDupe": "Strict mode function may not have duplicate parameter names",
"StrictFunctionName": "Function name may not be eval or arguments in strict mode",
"StrictOctalLiteral": "Octal literals are not allowed in strict mode.",
"StrictDelete": "Delete of an unqualified identifier in strict mode.",
"StrictDuplicateProperty": "Duplicate data property in object literal not allowed in strict mode",
"AccessorDataProperty": "Object literal may not have data and accessor property with the same name",
"AccessorGetSet": "Object literal may not have multiple get/set accessors with the same name",
"StrictLHSAssignment": "Assignment to eval or arguments is not allowed in strict mode",
"StrictLHSPostfix": "Postfix increment/decrement may not have eval or arguments operand in strict mode",
"StrictLHSPrefix": "Prefix increment/decrement may not have eval or arguments operand in strict mode",
"StrictReservedWord": "Use of future reserved word in strict mode",
})
Regex = jsdict({
"NonAsciiIdentifierStart": RegExp(u"[\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]"),
"NonAsciiIdentifierPart": RegExp(u"[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]"),
})
def assert__py__(condition=None, message=None):
    if not condition:
        raise RuntimeError("ASSERT: " + message)

def isDecimalDigit(ch=None):
    return (ch >= 48) and (ch <= 57)

def isHexDigit(ch=None):
    return "0123456789abcdefABCDEF".find(ch) >= 0

def isOctalDigit(ch=None):
    return "01234567".find(ch) >= 0

def isWhiteSpace(ch=None):
    return (((((ch == 32) or (ch == 9)) or (ch == 11)) or (ch == 12)) or (ch == 160)) or ((ch >= 5760) and (u"\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff".find(unichr(ch)) > 0))

def isLineTerminator(ch=None):
    return (((ch == 10) or (ch == 13)) or (ch == 8232)) or (ch == 8233)

def isIdentifierStart(ch=None):
    return (((((ch == 36) or (ch == 95)) or ((ch >= 65) and (ch <= 90))) or ((ch >= 97) and (ch <= 122))) or (ch == 92)) or ((ch >= 128) and Regex.NonAsciiIdentifierStart.test(unichr(ch)))

def isIdentifierPart(ch=None):
    return ((((((ch == 36) or (ch == 95)) or ((ch >= 65) and (ch <= 90))) or ((ch >= 97) and (ch <= 122))) or ((ch >= 48) and (ch <= 57))) or (ch == 92)) or ((ch >= 128) and Regex.NonAsciiIdentifierPart.test(unichr(ch)))

def isFutureReservedWord(id=None):
    while 1:
        if (id == "super") or ((id == "import") or ((id == "extends") or ((id == "export") or ((id == "enum") or (id == "class"))))):
            return True
        else:
            return False
        break

def isStrictModeReservedWord(id=None):
    while 1:
        if (id == "let") or ((id == "yield") or ((id == "static") or ((id == "public") or ((id == "protected") or ((id == "private") or ((id == "package") or ((id == "interface") or (id == "implements")))))))):
            return True
        else:
            return False
        break

def isRestrictedWord(id=None):
    return (id == "eval") or (id == "arguments")

def isKeyword(id=None):
    if strict and isStrictModeReservedWord(id):
        return True
    while 1:
        if len(id) == 2:
            return ((id == "if") or (id == "in")) or (id == "do")
        elif len(id) == 3:
            return ((((id == "var") or (id == "for")) or (id == "new")) or (id == "try")) or (id == "let")
        elif len(id) == 4:
            return (((((id == "this") or (id == "else")) or (id == "case")) or (id == "void")) or (id == "with")) or (id == "enum")
        elif len(id) == 5:
            return (((((((id == "while") or (id == "break")) or (id == "catch")) or (id == "throw")) or (id == "const")) or (id == "yield")) or (id == "class")) or (id == "super")
        elif len(id) == 6:
            return (((((id == "return") or (id == "typeof")) or (id == "delete")) or (id == "switch")) or (id == "export")) or (id == "import")
        elif len(id) == 7:
            return ((id == "default") or (id == "finally")) or (id == "extends")
        elif len(id) == 8:
            return ((id == "function") or (id == "continue")) or (id == "debugger")
        elif len(id) == 10:
            return id == "instanceof"
        else:
            return False
        break

def addComment(type=None, value=None, start=None, end=None, loc=None):
    comment = None
    assert__py__(('undefined' if not 'start' in locals() else typeof(start)) == "number", "Comment must have valid position")
    if state.lastCommentStart >= start:
        return 
    state.lastCommentStart = start
    comment = jsdict({
"type": type,
"value": value,
})
    if extra.range:
        comment.range = [start, end]
    if extra.loc:
        comment.loc = loc
    extra.comments.append(comment)

def skipSingleLineComment():
    global index, lineNumber, lineStart
    start = None
    loc = None
    ch = None
    comment = None
    start = index - 2
    loc = jsdict({
"start": jsdict({
"line": lineNumber,
"column": (index - lineStart) - 2,
}),
})
    while index < length:
        ch = (ord(source[index]) if index < len(source) else None)
        index += 1
        index
        if isLineTerminator(ch):
            if extra.comments:
                comment = source[(start + 2):(index - 1)]
                loc.end = jsdict({
"line": lineNumber,
"column": (index - lineStart) - 1,
})
                addComment("Line", comment, start, index - 1, loc)
            if (ch == 13) and ((ord(source[index]) if index < len(source) else None) == 10):
                index += 1
                index
            lineNumber += 1
            lineNumber
            lineStart = index
            return 
    if extra.comments:
        comment = source[(start + 2):index]
        loc.end = jsdict({
"line": lineNumber,
"column": index - lineStart,
})
        addComment("Line", comment, start, index, loc)

def skipMultiLineComment():
    global index, lineNumber, lineStart
    start = None
    loc = None
    ch = None
    comment = None
    if extra.comments:
        start = index - 2
        loc = jsdict({
"start": jsdict({
"line": lineNumber,
"column": (index - lineStart) - 2,
}),
})
    while index < length:
        ch = (ord(source[index]) if index < len(source) else None)
        if isLineTerminator(ch):
            if (ch == 13) and ((ord(source[index + 1]) if (index + 1) < len(source) else None) == 10):
                index += 1
                index
            lineNumber += 1
            lineNumber
            index += 1
            index
            lineStart = index
            if index >= length:
                throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
        elif ch == 42:
            if (ord(source[index + 1]) if (index + 1) < len(source) else None) == 47:
                index += 1
                index
                index += 1
                index
                if extra.comments:
                    comment = source[(start + 2):(index - 2)]
                    loc.end = jsdict({
"line": lineNumber,
"column": index - lineStart,
})
                    addComment("Block", comment, start, index, loc)
                return 
            index += 1
            index
        else:
            index += 1
            index
    throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")

def skipComment():
    global index, lineNumber, lineStart
    ch = None
    while index < length:
        ch = (ord(source[index]) if index < len(source) else None)
        if isWhiteSpace(ch):
            index += 1
            index
        elif isLineTerminator(ch):
            index += 1
            index
            if (ch == 13) and ((ord(source[index]) if index < len(source) else None) == 10):
                index += 1
                index
            lineNumber += 1
            lineNumber
            lineStart = index
        elif ch == 47:
            ch = (ord(source[index + 1]) if (index + 1) < len(source) else None)
            if ch == 47:
                index += 1
                index
                index += 1
                index
                skipSingleLineComment()
            elif ch == 42:
                index += 1
                index
                index += 1
                index
                skipMultiLineComment()
            else:
                break
        else:
            break

def scanHexEscape(prefix=None):
    global len__py__, index
    i = None
    len__py__ = None
    ch = None
    code = 0
    len__py__ = (4 if prefix == "u" else 2)
    i = 0
    while 1:
        if not (i < len__py__):
            break
        if (index < length) and isHexDigit(source[index]):
            index += 1
            ch = source[index - 1]
            code = (code * 16) + "0123456789abcdef".find(ch.lower())
        else:
            return ""
        i += 1
    return unichr(code)

def getEscapedIdentifier():
    global index
    ch = None
    id = None
    index += 1
    index += 1
    ch = (ord(source[index - 1]) if index - 1 < len(source) else None)
    id = unichr(ch)
    if ch == 92:
        if (ord(source[index]) if index < len(source) else None) != 117:
            throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
        index += 1
        index
        ch = scanHexEscape("u")
        if ((not ch) or (ch == "\\")) or (not isIdentifierStart((ord(ch[0]) if 0 < len(ch) else None))):
            throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
        id = ch
    while index < length:
        ch = (ord(source[index]) if index < len(source) else None)
        if not isIdentifierPart(ch):
            break
        index += 1
        index
        id += unichr(ch)
        if ch == 92:
            id = id[0:(0 + (len(id) - 1))]
            if (ord(source[index]) if index < len(source) else None) != 117:
                throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
            index += 1
            index
            ch = scanHexEscape("u")
            if ((not ch) or (ch == "\\")) or (not isIdentifierPart((ord(ch[0]) if 0 < len(ch) else None))):
                throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
            id += ch
    return id

def getIdentifier():
    global index
    start = None
    ch = None
    index += 1
    start = index - 1
    while index < length:
        ch = (ord(source[index]) if index < len(source) else None)
        if ch == 92:
            index = start
            return getEscapedIdentifier()
        if isIdentifierPart(ch):
            index += 1
            index
        else:
            break
    return source[start:index]

def scanIdentifier():
    start = None
    id = None
    type = None
    start = index
    id = (getEscapedIdentifier() if (ord(source[index]) if index < len(source) else None) == 92 else getIdentifier())
    if len(id) == 1:
        type = Token.Identifier
    elif isKeyword(id):
        type = Token.Keyword
    elif id == "null":
        type = Token.NullLiteral
    elif (id == "true") or (id == "false"):
        type = Token.BooleanLiteral
    else:
        type = Token.Identifier
    return jsdict({
"type": type,
"value": id,
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})

def scanPunctuator():
    global index
    start = index
    code = (ord(source[index]) if index < len(source) else None)
    code2 = None
    ch1 = source[index]
    ch2 = None
    ch3 = None
    ch4 = None
    while 1:
        if (code == 126) or ((code == 63) or ((code == 58) or ((code == 93) or ((code == 91) or ((code == 125) or ((code == 123) or ((code == 44) or ((code == 59) or ((code == 41) or ((code == 40) or (code == 46))))))))))):
            index += 1
            index
            if extra.tokenize:
                if code == 40:
                    extra.openParenToken = len(extra.tokens)
                elif code == 123:
                    extra.openCurlyToken = len(extra.tokens)
            return jsdict({
"type": Token.Punctuator,
"value": unichr(code),
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
        else:
            code2 = (ord(source[index + 1]) if (index + 1) < len(source) else None)
            if code2 == 61:
                while 1:
                    if (code == 124) or ((code == 94) or ((code == 62) or ((code == 60) or ((code == 47) or ((code == 45) or ((code == 43) or ((code == 42) or ((code == 38) or (code == 37))))))))):
                        index += 2
                        return jsdict({
"type": Token.Punctuator,
"value": unichr(code) + unichr(code2),
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
                    elif (code == 61) or (code == 33):
                        index += 2
                        if (ord(source[index]) if index < len(source) else None) == 61:
                            index += 1
                            index
                        return jsdict({
"type": Token.Punctuator,
"value": source[start:index],
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
                    else:
                        break
                    break
            break
        break
    ch2 = source[index + 1] if index + 1 < len(source) else None
    ch3 = source[index + 2] if index + 2 < len(source) else None
    ch4 = source[index + 3] if index + 3 < len(source) else None
    if ((ch1 == ">") and (ch2 == ">")) and (ch3 == ">"):
        if ch4 == "=":
            index += 4
            return jsdict({
"type": Token.Punctuator,
"value": ">>>=",
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
    if ((ch1 == ">") and (ch2 == ">")) and (ch3 == ">"):
        index += 3
        return jsdict({
"type": Token.Punctuator,
"value": ">>>",
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
    if ((ch1 == "<") and (ch2 == "<")) and (ch3 == "="):
        index += 3
        return jsdict({
"type": Token.Punctuator,
"value": "<<=",
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
    if ((ch1 == ">") and (ch2 == ">")) and (ch3 == "="):
        index += 3
        return jsdict({
"type": Token.Punctuator,
"value": ">>=",
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
    if (ch1 == ch2) and ("+-<>&|".find(ch1) >= 0):
        index += 2
        return jsdict({
"type": Token.Punctuator,
"value": ch1 + ch2,
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
    if "<>=!+-*%&|^/".find(ch1) >= 0:
        index += 1
        index
        return jsdict({
"type": Token.Punctuator,
"value": ch1,
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
    throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")

def scanHexLiteral(start=None):
    global index
    number = ""
    while index < length:
        if not isHexDigit(source[index]):
            break
        index += 1
        number += source[index - 1]
    if len(number) == 0:
        throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
    if isIdentifierStart((ord(source[index]) if index < len(source) else None)):
        throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
    return jsdict({
"type": Token.NumericLiteral,
"value": parseInt("0x" + number, 16),
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})

def scanOctalLiteral(start=None):
    global index
    index += 1
    number = "0" + source[index - 1]
    while index < length:
        if not isOctalDigit(source[index]):
            break
        index += 1
        number += source[index - 1]
    if isIdentifierStart((ord(source[index]) if index < len(source) else None)) or isDecimalDigit((ord(source[index]) if index < len(source) else None)):
        throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
    return jsdict({
"type": Token.NumericLiteral,
"value": parseInt(number, 8),
"octal": True,
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})

def scanNumericLiteral():
    global index
    number = None
    start = None
    ch = None
    ch = source[index]
    assert__py__(isDecimalDigit((ord(ch[0]) if 0 < len(ch) else None)) or (ch == "."), "Numeric literal must start with a decimal digit or a decimal point")
    start = index
    number = ""
    if ch != ".":
        index += 1
        number = source[index - 1]
        ch = source[index] if index < len(source) else None
        if number == "0":
            if (ch == "x") or (ch == "X"):
                index += 1
                index
                return scanHexLiteral(start)
            if isOctalDigit(ch):
                return scanOctalLiteral(start)
            if ch and isDecimalDigit((ord(ch[0]) if 0 < len(ch) else None)):
                throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
        while isDecimalDigit((ord(source[index]) if index < len(source) else None)):
            index += 1
            number += source[index - 1]
        ch = source[index] if index < len(source) else None
    if ch == ".":
        index += 1
        number += source[index - 1]
        while isDecimalDigit((ord(source[index]) if index < len(source) else None)):
            index += 1
            number += source[index - 1]
        ch = source[index]
    if (ch == "e") or (ch == "E"):
        index += 1
        number += source[index - 1]
        ch = source[index]
        if (ch == "+") or (ch == "-"):
            index += 1
            number += source[index - 1]
        if isDecimalDigit((ord(source[index]) if index < len(source) else None)):
            while isDecimalDigit((ord(source[index]) if index < len(source) else None)):
                index += 1
                number += source[index - 1]
        else:
            throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
    if isIdentifierStart((ord(source[index]) if index < len(source) else None)):
        throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
    return jsdict({
"type": Token.NumericLiteral,
"value": parseFloat(number),
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})

def scanStringLiteral():
    global index, lineNumber
    str = ""
    quote = None
    start = None
    ch = None
    code = None
    unescaped = None
    restore = None
    octal = False
    quote = source[index]
    assert__py__((quote == "'") or (quote == "\""), "String literal must starts with a quote")
    start = index
    index += 1
    index
    while index < length:
        index += 1
        ch = source[index - 1]
        if ch == quote:
            quote = ""
            break
        elif ch == "\\":
            index += 1
            ch = source[index - 1]
            if (not ch) or (not isLineTerminator((ord(ch[0]) if 0 < len(ch) else None))):
                while 1:
                    if ch == "n":
                        str += u"\x0a"
                        break
                    elif ch == "r":
                        str += u"\x0d"
                        break
                    elif ch == "t":
                        str += u"\x09"
                        break
                    elif (ch == "x") or (ch == "u"):
                        restore = index
                        unescaped = scanHexEscape(ch)
                        if unescaped:
                            str += unescaped
                        else:
                            index = restore
                            str += ch
                        break
                    elif ch == "b":
                        str += u"\x08"
                        break
                    elif ch == "f":
                        str += u"\x0c"
                        break
                    elif ch == "v":
                        str += u"\x0b"
                        break
                    else:
                        if isOctalDigit(ch):
                            code = "01234567".find(ch)
                            if code != 0:
                                octal = True
                            if (index < length) and isOctalDigit(source[index]):
                                octal = True
                                index += 1
                                code = (code * 8) + "01234567".find(source[index - 1])
                                if (("0123".find(ch) >= 0) and (index < length)) and isOctalDigit(source[index]):
                                    index += 1
                                    code = (code * 8) + "01234567".find(source[index - 1])
                            str += unichr(code)
                        else:
                            str += ch
                        break
                    break
            else:
                lineNumber += 1
                lineNumber
                if (ch == u"\x0d") and (source[index] == u"\x0a"):
                    index += 1
                    index
        elif isLineTerminator((ord(ch[0]) if 0 < len(ch) else None)):
            break
        else:
            str += ch
    if quote != "":
        throwError(jsdict({
}), Messages.UnexpectedToken, "ILLEGAL")
    return jsdict({
"type": Token.StringLiteral,
"value": str,
"octal": octal,
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})

def scanRegExp():
    global lookahead, index
    str = None
    ch = None
    start = None
    pattern = None
    flags = None
    value = None
    classMarker = False
    restore = None
    terminated = False
    lookahead = None
    skipComment()
    start = index
    ch = source[index]
    assert__py__(ch == "/", "Regular expression literal must start with a slash")
    index += 1
    str = source[index - 1]
    while index < length:
        index += 1
        ch = source[index - 1]
        str += ch
        if classMarker:
            if ch == "]":
                classMarker = False
        else:
            if ch == "\\":
                index += 1
                ch = source[index - 1]
                if isLineTerminator((ord(ch[0]) if 0 < len(ch) else None)):
                    throwError(jsdict({
}), Messages.UnterminatedRegExp)
                str += ch
            elif ch == "/":
                terminated = True
                break
            elif ch == "[":
                classMarker = True
            elif isLineTerminator((ord(ch[0]) if 0 < len(ch) else None)):
                throwError(jsdict({
}), Messages.UnterminatedRegExp)
    if not terminated:
        throwError(jsdict({
}), Messages.UnterminatedRegExp)
    pattern = str[1:(1 + (len(str) - 2))]
    flags = ""
    while index < length:
        ch = source[index]
        if not isIdentifierPart((ord(ch[0]) if 0 < len(ch) else None)):
            break
        index += 1
        index
        if (ch == "\\") and (index < length):
            ch = source[index]
            if ch == "u":
                index += 1
                index
                restore = index
                ch = scanHexEscape("u")
                if ch:
                    flags += ch
                    str += "\\u"
                    while 1:
                        if not (restore < index):
                            break
                        str += source[restore]
                        restore += 1
                else:
                    index = restore
                    flags += "u"
                    str += "\\u"
            else:
                str += "\\"
        else:
            flags += ch
            str += ch
    try:
        value = RegExp(pattern, flags)
    except Exception as e:
        throwError(jsdict({
}), Messages.InvalidRegExp)
    peek()
    if extra.tokenize:
        return jsdict({
"type": Token.RegularExpression,
"value": value,
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [start, index],
})
    return jsdict({
"literal": str,
"value": value,
"range": [start, index],
})

def isIdentifierName(token=None):
    return (((token.type == Token.Identifier) or (token.type == Token.Keyword)) or (token.type == Token.BooleanLiteral)) or (token.type == Token.NullLiteral)

def advanceSlash():
    prevToken = None
    checkToken = None
    prevToken = extra.tokens[len(extra.tokens) - 1]
    if not prevToken:
        return scanRegExp()
    if prevToken.type == "Punctuator":
        if prevToken.value == ")":
            checkToken = extra.tokens[extra.openParenToken - 1]
            if (checkToken and (checkToken.type == "Keyword")) and ((((checkToken.value == "if") or (checkToken.value == "while")) or (checkToken.value == "for")) or (checkToken.value == "with")):
                return scanRegExp()
            return scanPunctuator()
        if prevToken.value == "}":
            if extra.tokens[extra.openCurlyToken - 3] and (extra.tokens[extra.openCurlyToken - 3].type == "Keyword"):
                checkToken = extra.tokens[extra.openCurlyToken - 4]
                if not checkToken:
                    return scanPunctuator()
            elif extra.tokens[extra.openCurlyToken - 4] and (extra.tokens[extra.openCurlyToken - 4].type == "Keyword"):
                checkToken = extra.tokens[extra.openCurlyToken - 5]
                if not checkToken:
                    return scanRegExp()
            else:
                return scanPunctuator()
            if FnExprTokens.indexOf(checkToken.value) >= 0:
                return scanPunctuator()
            return scanRegExp()
        return scanRegExp()
    if prevToken.type == "Keyword":
        return scanRegExp()
    return scanPunctuator()

def advance():
    ch = None
    skipComment()
    if index >= length:
        return jsdict({
"type": Token.EOF,
"lineNumber": lineNumber,
"lineStart": lineStart,
"range": [index, index],
})
    ch = (ord(source[index]) if index < len(source) else None)
    if ((ch == 40) or (ch == 41)) or (ch == 58):
        return scanPunctuator()
    if (ch == 39) or (ch == 34):
        return scanStringLiteral()
    if isIdentifierStart(ch):
        return scanIdentifier()
    if ch == 46:
        if isDecimalDigit((ord(source[index + 1]) if (index + 1) < len(source) else None)):
            return scanNumericLiteral()
        return scanPunctuator()
    if isDecimalDigit(ch):
        return scanNumericLiteral()
    if extra.tokenize and (ch == 47):
        return advanceSlash()
    return scanPunctuator()

def lex():
    global index, lineNumber, lineStart, lookahead
    token = None
    token = lookahead
    index = token.range[1]
    lineNumber = token.lineNumber
    lineStart = token.lineStart
    lookahead = advance()
    index = token.range[1]
    lineNumber = token.lineNumber
    lineStart = token.lineStart
    return token

def peek():
    global lookahead, index, lineNumber, lineStart
    pos = None
    line = None
    start = None
    pos = index
    line = lineNumber
    start = lineStart
    lookahead = advance()
    index = pos
    lineNumber = line
    lineStart = start

SyntaxTreeDelegate = jsdict({
"name": "SyntaxTree",
"markStart": __temp__0,
"markEnd": __temp__1,
"markEndIf": __temp__2,
"postProcess": __temp__3,
"createArrayExpression": __temp__4,
"createAssignmentExpression": __temp__5,
"createBinaryExpression": __temp__6,
"createBlockStatement": __temp__7,
"createBreakStatement": __temp__8,
"createCallExpression": __temp__9,
"createCatchClause": __temp__10,
"createConditionalExpression": __temp__11,
"createContinueStatement": __temp__12,
"createDebuggerStatement": __temp__13,
"createDoWhileStatement": __temp__14,
"createEmptyStatement": __temp__15,
"createExpressionStatement": __temp__16,
"createForStatement": __temp__17,
"createForInStatement": __temp__18,
"createFunctionDeclaration": __temp__19,
"createFunctionExpression": __temp__20,
"createIdentifier": __temp__21,
"createIfStatement": __temp__22,
"createLabeledStatement": __temp__23,
"createLiteral": __temp__24,
"createMemberExpression": __temp__25,
"createNewExpression": __temp__26,
"createObjectExpression": __temp__27,
"createPostfixExpression": __temp__28,
"createProgram": __temp__29,
"createProperty": __temp__30,
"createReturnStatement": __temp__31,
"createSequenceExpression": __temp__32,
"createSwitchCase": __temp__33,
"createSwitchStatement": __temp__34,
"createThisExpression": __temp__35,
"createThrowStatement": __temp__36,
"createTryStatement": __temp__37,
"createUnaryExpression": __temp__38,
"createVariableDeclaration": __temp__39,
"createVariableDeclarator": __temp__40,
"createWhileStatement": __temp__41,
"createWithStatement": __temp__42,
})
def peekLineTerminator():
    global index, lineNumber, lineStart
    pos = None
    line = None
    start = None
    found = None
    pos = index
    line = lineNumber
    start = lineStart
    skipComment()
    found = lineNumber != line
    index = pos
    lineNumber = line
    lineStart = start
    return found

def throwError(token=None, messageFormat=None, a=None):
    def __temp__43(whole=None, index=None):
        assert__py__(index < len(args), "Message reference must be in range")
        return args[index]
    
    error = None
    args = Array.prototype.slice.call(arguments, 2)
    msg = messageFormat.replace(RegExp(r'%(\d)'), __temp__43)
    if ('undefined' if not ('lineNumber' in token) else typeof(token.lineNumber)) == "number":
        error = RuntimeError((("Line " + token.lineNumber) + ": ") + msg)
        error.index = token.range[0]
        error.lineNumber = token.lineNumber
        error.column = (token.range[0] - lineStart) + 1
    else:
        error = RuntimeError((("Line " + lineNumber) + ": ") + msg)
        error.index = index
        error.lineNumber = lineNumber
        error.column = (index - lineStart) + 1
    error.description = msg
    raise error

def throwErrorTolerant():
    try:
        throwError.apply(None, arguments)
    except Exception as e:
        if extra.errors:
            extra.errors.append(e)
        else:
            raise 

def throwUnexpected(token=None):
    if token.type == Token.EOF:
        throwError(token, Messages.UnexpectedEOS)
    if token.type == Token.NumericLiteral:
        throwError(token, Messages.UnexpectedNumber)
    if token.type == Token.StringLiteral:
        throwError(token, Messages.UnexpectedString)
    if token.type == Token.Identifier:
        throwError(token, Messages.UnexpectedIdentifier)
    if token.type == Token.Keyword:
        if isFutureReservedWord(token.value):
            throwError(token, Messages.UnexpectedReserved)
        elif strict and isStrictModeReservedWord(token.value):
            throwErrorTolerant(token, Messages.StrictReservedWord)
            return 
        throwError(token, Messages.UnexpectedToken, token.value)
    throwError(token, Messages.UnexpectedToken, token.value)

def expect(value=None):
    token = lex()
    if (token.type != Token.Punctuator) or (token.value != value):
        throwUnexpected(token)

def expectKeyword(keyword=None):
    token = lex()
    if (token.type != Token.Keyword) or (token.value != keyword):
        throwUnexpected(token)

def match(value=None):
    return (lookahead.type == Token.Punctuator) and (lookahead.value == value)

def matchKeyword(keyword=None):
    return (lookahead.type == Token.Keyword) and (lookahead.value == keyword)

def matchAssign():
    op = None
    if lookahead.type != Token.Punctuator:
        return False
    op = lookahead.value
    return (((((((((((op == "=") or (op == "*=")) or (op == "/=")) or (op == "%=")) or (op == "+=")) or (op == "-=")) or (op == "<<=")) or (op == ">>=")) or (op == ">>>=")) or (op == "&=")) or (op == "^=")) or (op == "|=")

def consumeSemicolon():
    line = None
    if (ord(source[index]) if index < len(source) else None) == 59:
        lex()
        return 
    line = lineNumber
    skipComment()
    if lineNumber != line:
        return 
    if match(";"):
        lex()
        return 
    if (lookahead.type != Token.EOF) and (not match("}")):
        throwUnexpected(lookahead)

def isLeftHandSide(expr=None):
    return (expr.type == Syntax.Identifier) or (expr.type == Syntax.MemberExpression)

def parseArrayInitialiser():
    elements = []
    expect("[")
    while not match("]"):
        if match(","):
            lex()
            elements.append(None)
        else:
            elements.append(parseAssignmentExpression())
            if not match("]"):
                expect(",")
    expect("]")
    return delegate.createArrayExpression(elements)

def parsePropertyFunction(param=None, first=None):
    global strict
    previousStrict = None
    body = None
    previousStrict = strict
    skipComment()
    delegate.markStart()
    body = parseFunctionSourceElements()
    if (first and strict) and isRestrictedWord(param[0].name):
        throwErrorTolerant(first, Messages.StrictParamName)
    strict = previousStrict
    return delegate.markEnd(delegate.createFunctionExpression(None, param, [], body))

def parseObjectPropertyKey():
    token = None
    skipComment()
    delegate.markStart()
    token = lex()
    if (token.type == Token.StringLiteral) or (token.type == Token.NumericLiteral):
        if strict and token.octal:
            throwErrorTolerant(token, Messages.StrictOctalLiteral)
        return delegate.markEnd(delegate.createLiteral(token))
    return delegate.markEnd(delegate.createIdentifier(token.value))

def parseObjectProperty():
    token = None
    key = None
    id = None
    value = None
    param = None
    token = lookahead
    skipComment()
    delegate.markStart()
    if token.type == Token.Identifier:
        id = parseObjectPropertyKey()
        if (token.value == "get") and (not match(":")):
            key = parseObjectPropertyKey()
            expect("(")
            expect(")")
            value = parsePropertyFunction([])
            return delegate.markEnd(delegate.createProperty("get", key, value))
        if (token.value == "set") and (not match(":")):
            key = parseObjectPropertyKey()
            expect("(")
            token = lookahead
            if token.type != Token.Identifier:
                expect(")")
                throwErrorTolerant(token, Messages.UnexpectedToken, token.value)
                value = parsePropertyFunction([])
            else:
                param = [parseVariableIdentifier()]
                expect(")")
                value = parsePropertyFunction(param, token)
            return delegate.markEnd(delegate.createProperty("set", key, value))
        expect(":")
        value = parseAssignmentExpression()
        return delegate.markEnd(delegate.createProperty("init", id, value))
    if (token.type == Token.EOF) or (token.type == Token.Punctuator):
        throwUnexpected(token)
    else:
        key = parseObjectPropertyKey()
        expect(":")
        value = parseAssignmentExpression()
        return delegate.markEnd(delegate.createProperty("init", key, value))

def parseObjectInitialiser():
    properties = []
    property = None
    name = None
    key = None
    kind = None
    map = jsdict({
})
    toString = str
    expect("{")
    while not match("}"):
        property = parseObjectProperty()
        if property.key.type == Syntax.Identifier:
            name = property.key.name
        else:
            name = toString(property.key.value)
        kind = (PropertyKind.Data if property.kind == "init" else (PropertyKind.Get if property.kind == "get" else PropertyKind.Set))
        key = "$" + name
        if key in map:
            if map[key] == PropertyKind.Data:
                if strict and (kind == PropertyKind.Data):
                    throwErrorTolerant(jsdict({
}), Messages.StrictDuplicateProperty)
                elif kind != PropertyKind.Data:
                    throwErrorTolerant(jsdict({
}), Messages.AccessorDataProperty)
            else:
                if kind == PropertyKind.Data:
                    throwErrorTolerant(jsdict({
}), Messages.AccessorDataProperty)
                elif map[key] & kind:
                    throwErrorTolerant(jsdict({
}), Messages.AccessorGetSet)
            map[key] |= kind
        else:
            map[key] = kind
        properties.append(property)
        if not match("}"):
            expect(",")
    expect("}")
    return delegate.createObjectExpression(properties)

def parseGroupExpression():
    expr = None
    expect("(")
    expr = parseExpression()
    expect(")")
    return expr

def parsePrimaryExpression():
    type = None
    token = None
    expr = None
    if match("("):
        return parseGroupExpression()
    type = lookahead.type
    delegate.markStart()
    if type == Token.Identifier:
        expr = delegate.createIdentifier(lex().value)
    elif (type == Token.StringLiteral) or (type == Token.NumericLiteral):
        if strict and lookahead.octal:
            throwErrorTolerant(lookahead, Messages.StrictOctalLiteral)
        expr = delegate.createLiteral(lex())
    elif type == Token.Keyword:
        if matchKeyword("this"):
            lex()
            expr = delegate.createThisExpression()
        elif matchKeyword("function"):
            expr = parseFunctionExpression()
    elif type == Token.BooleanLiteral:
        token = lex()
        token.value = token.value == "true"
        expr = delegate.createLiteral(token)
    elif type == Token.NullLiteral:
        token = lex()
        token.value = None
        expr = delegate.createLiteral(token)
    elif match("["):
        expr = parseArrayInitialiser()
    elif match("{"):
        expr = parseObjectInitialiser()
    elif match("/") or match("/="):
        expr = delegate.createLiteral(scanRegExp())
    if expr:
        return delegate.markEnd(expr)
    throwUnexpected(lex())

def parseArguments():
    args = []
    expect("(")
    if not match(")"):
        while index < length:
            args.append(parseAssignmentExpression())
            if match(")"):
                break
            expect(",")
    expect(")")
    return args

def parseNonComputedProperty():
    token = None
    delegate.markStart()
    token = lex()
    if not isIdentifierName(token):
        throwUnexpected(token)
    return delegate.markEnd(delegate.createIdentifier(token.value))

def parseNonComputedMember():
    expect(".")
    return parseNonComputedProperty()

def parseComputedMember():
    expr = None
    expect("[")
    expr = parseExpression()
    expect("]")
    return expr

def parseNewExpression():
    callee = None
    args = None
    delegate.markStart()
    expectKeyword("new")
    callee = parseLeftHandSideExpression()
    args = (parseArguments() if match("(") else [])
    return delegate.markEnd(delegate.createNewExpression(callee, args))

def parseLeftHandSideExpressionAllowCall():
    marker = None
    expr = None
    args = None
    property = None
    marker = createLocationMarker()
    expr = (parseNewExpression() if matchKeyword("new") else parsePrimaryExpression())
    while (match(".") or match("[")) or match("("):
        if match("("):
            args = parseArguments()
            expr = delegate.createCallExpression(expr, args)
        elif match("["):
            property = parseComputedMember()
            expr = delegate.createMemberExpression("[", expr, property)
        else:
            property = parseNonComputedMember()
            expr = delegate.createMemberExpression(".", expr, property)
        if marker:
            marker.end()
            marker.apply(expr)
    return expr

def parseLeftHandSideExpression():
    marker = None
    expr = None
    property = None
    marker = createLocationMarker()
    expr = (parseNewExpression() if matchKeyword("new") else parsePrimaryExpression())
    while match(".") or match("["):
        if match("["):
            property = parseComputedMember()
            expr = delegate.createMemberExpression("[", expr, property)
        else:
            property = parseNonComputedMember()
            expr = delegate.createMemberExpression(".", expr, property)
        if marker:
            marker.end()
            marker.apply(expr)
    return expr

def parsePostfixExpression():
    expr = None
    token = None
    delegate.markStart()
    expr = parseLeftHandSideExpressionAllowCall()
    if lookahead.type == Token.Punctuator:
        if (match("++") or match("--")) and (not peekLineTerminator()):
            if (strict and (expr.type == Syntax.Identifier)) and isRestrictedWord(expr.name):
                throwErrorTolerant(jsdict({
}), Messages.StrictLHSPostfix)
            if not isLeftHandSide(expr):
                throwError(jsdict({
}), Messages.InvalidLHSInAssignment)
            token = lex()
            expr = delegate.createPostfixExpression(token.value, expr)
    return delegate.markEndIf(expr)

def parseUnaryExpression():
    token = None
    expr = None
    delegate.markStart()
    if (lookahead.type != Token.Punctuator) and (lookahead.type != Token.Keyword):
        expr = parsePostfixExpression()
    elif match("++") or match("--"):
        token = lex()
        expr = parseUnaryExpression()
        if (strict and (expr.type == Syntax.Identifier)) and isRestrictedWord(expr.name):
            throwErrorTolerant(jsdict({
}), Messages.StrictLHSPrefix)
        if not isLeftHandSide(expr):
            throwError(jsdict({
}), Messages.InvalidLHSInAssignment)
        expr = delegate.createUnaryExpression(token.value, expr)
    elif ((match("+") or match("-")) or match("~")) or match("!"):
        token = lex()
        expr = parseUnaryExpression()
        expr = delegate.createUnaryExpression(token.value, expr)
    elif (matchKeyword("delete") or matchKeyword("void")) or matchKeyword("typeof"):
        token = lex()
        expr = parseUnaryExpression()
        expr = delegate.createUnaryExpression(token.value, expr)
        if (strict and (expr.operator == "delete")) and (expr.argument.type == Syntax.Identifier):
            throwErrorTolerant(jsdict({
}), Messages.StrictDelete)
    else:
        expr = parsePostfixExpression()
    return delegate.markEndIf(expr)

def binaryPrecedence(token=None, allowIn=None):
    prec = 0
    if (token.type != Token.Punctuator) and (token.type != Token.Keyword):
        return 0
    while 1:
        if token.value == "||":
            prec = 1
            break
        elif token.value == "&&":
            prec = 2
            break
        elif token.value == "|":
            prec = 3
            break
        elif token.value == "^":
            prec = 4
            break
        elif token.value == "&":
            prec = 5
            break
        elif (token.value == "!==") or ((token.value == "===") or ((token.value == "!=") or (token.value == "=="))):
            prec = 6
            break
        elif (token.value == "instanceof") or ((token.value == ">=") or ((token.value == "<=") or ((token.value == ">") or (token.value == "<")))):
            prec = 7
            break
        elif token.value == "in":
            prec = (7 if allowIn else 0)
            break
        elif (token.value == ">>>") or ((token.value == ">>") or (token.value == "<<")):
            prec = 8
            break
        elif (token.value == "-") or (token.value == "+"):
            prec = 9
            break
        elif (token.value == "%") or ((token.value == "/") or (token.value == "*")):
            prec = 11
            break
        else:
            break
        break
    return prec

def parseBinaryExpression():
    marker = None
    markers = None
    expr = None
    token = None
    prec = None
    previousAllowIn = None
    stack = None
    right = None
    operator = None
    left = None
    i = None
    previousAllowIn = state.allowIn
    state.allowIn = True
    marker = createLocationMarker()
    left = parseUnaryExpression()
    token = lookahead
    prec = binaryPrecedence(token, previousAllowIn)
    if prec == 0:
        return left
    token.prec = prec
    lex()
    markers = [marker, createLocationMarker()]
    right = parseUnaryExpression()
    stack = [left, token, right]
    prec = binaryPrecedence(lookahead, previousAllowIn)
    while prec > 0:
        while (len(stack) > 2) and (prec <= stack[len(stack) - 2].prec):
            right = stack.pop()
            operator = stack.pop().value
            left = stack.pop()
            expr = delegate.createBinaryExpression(operator, left, right)
            markers.pop()
            marker = markers.pop()
            if marker:
                marker.end()
                marker.apply(expr)
            stack.append(expr)
            markers.append(marker)
        token = lex()
        token.prec = prec
        stack.append(token)
        markers.append(createLocationMarker())
        expr = parseUnaryExpression()
        stack.append(expr)
        prec = binaryPrecedence(lookahead, previousAllowIn)
    state.allowIn = previousAllowIn
    i = len(stack) - 1
    expr = stack[i]
    markers.pop()
    while i > 1:
        expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr)
        i -= 2
        marker = markers.pop()
        if marker:
            marker.end()
            marker.apply(expr)
    return expr

def parseConditionalExpression():
    expr = None
    previousAllowIn = None
    consequent = None
    alternate = None
    delegate.markStart()
    expr = parseBinaryExpression()
    if match("?"):
        lex()
        previousAllowIn = state.allowIn
        state.allowIn = True
        consequent = parseAssignmentExpression()
        state.allowIn = previousAllowIn
        expect(":")
        alternate = parseAssignmentExpression()
        expr = delegate.markEnd(delegate.createConditionalExpression(expr, consequent, alternate))
    else:
        delegate.markEnd(jsdict({
}))
    return expr

def parseAssignmentExpression():
    token = None
    left = None
    right = None
    node = None
    token = lookahead
    delegate.markStart()
    left = parseConditionalExpression()
    node = left
    if matchAssign():
        if not isLeftHandSide(left):
            throwError(jsdict({
}), Messages.InvalidLHSInAssignment)
        if (strict and (left.type == Syntax.Identifier)) and isRestrictedWord(left.name):
            throwErrorTolerant(token, Messages.StrictLHSAssignment)
        token = lex()
        right = parseAssignmentExpression()
        node = delegate.createAssignmentExpression(token.value, left, right)
    return delegate.markEndIf(node)

def parseExpression():
    expr = None
    delegate.markStart()
    expr = parseAssignmentExpression()
    if match(","):
        expr = delegate.createSequenceExpression([expr])
        while index < length:
            if not match(","):
                break
            lex()
            expr.expressions.append(parseAssignmentExpression())
    return delegate.markEndIf(expr)

def parseStatementList():
    list__py__ = []
    statement = None
    while index < length:
        if match("}"):
            break
        statement = parseSourceElement()
        if ('undefined' if not 'statement' in locals() else typeof(statement)) == "undefined":
            break
        list__py__.append(statement)
    return list__py__

def parseBlock():
    block = None
    skipComment()
    delegate.markStart()
    expect("{")
    block = parseStatementList()
    expect("}")
    return delegate.markEnd(delegate.createBlockStatement(block))

def parseVariableIdentifier():
    token = None
    skipComment()
    delegate.markStart()
    token = lex()
    if token.type != Token.Identifier:
        throwUnexpected(token)
    return delegate.markEnd(delegate.createIdentifier(token.value))

def parseVariableDeclaration(kind=None):
    init = None
    id = None
    skipComment()
    delegate.markStart()
    id = parseVariableIdentifier()
    if strict and isRestrictedWord(id.name):
        throwErrorTolerant(jsdict({
}), Messages.StrictVarName)
    if kind == "const":
        expect("=")
        init = parseAssignmentExpression()
    elif match("="):
        lex()
        init = parseAssignmentExpression()
    return delegate.markEnd(delegate.createVariableDeclarator(id, init))

def parseVariableDeclarationList(kind=None):
    list__py__ = []
    while 1:
        list__py__.append(parseVariableDeclaration(kind))
        if not match(","):
            break
        lex()
        if not (index < length):
            break
    return list__py__

def parseVariableStatement():
    declarations = None
    expectKeyword("var")
    declarations = parseVariableDeclarationList()
    consumeSemicolon()
    return delegate.createVariableDeclaration(declarations, "var")

def parseConstLetDeclaration(kind=None):
    declarations = None
    skipComment()
    delegate.markStart()
    expectKeyword(kind)
    declarations = parseVariableDeclarationList(kind)
    consumeSemicolon()
    return delegate.markEnd(delegate.createVariableDeclaration(declarations, kind))

def parseEmptyStatement():
    expect(";")
    return delegate.createEmptyStatement()

def parseExpressionStatement():
    expr = parseExpression()
    consumeSemicolon()
    return delegate.createExpressionStatement(expr)

def parseIfStatement():
    test = None
    consequent = None
    alternate = None
    expectKeyword("if")
    expect("(")
    test = parseExpression()
    expect(")")
    consequent = parseStatement()
    if matchKeyword("else"):
        lex()
        alternate = parseStatement()
    else:
        alternate = None
    return delegate.createIfStatement(test, consequent, alternate)

def parseDoWhileStatement():
    body = None
    test = None
    oldInIteration = None
    expectKeyword("do")
    oldInIteration = state.inIteration
    state.inIteration = True
    body = parseStatement()
    state.inIteration = oldInIteration
    expectKeyword("while")
    expect("(")
    test = parseExpression()
    expect(")")
    if match(";"):
        lex()
    return delegate.createDoWhileStatement(body, test)

def parseWhileStatement():
    test = None
    body = None
    oldInIteration = None
    expectKeyword("while")
    expect("(")
    test = parseExpression()
    expect(")")
    oldInIteration = state.inIteration
    state.inIteration = True
    body = parseStatement()
    state.inIteration = oldInIteration
    return delegate.createWhileStatement(test, body)

def parseForVariableDeclaration():
    token = None
    declarations = None
    delegate.markStart()
    token = lex()
    declarations = parseVariableDeclarationList()
    return delegate.markEnd(delegate.createVariableDeclaration(declarations, token.value))

def parseForStatement():
    init = None
    test = None
    update = None
    left = None
    right = None
    body = None
    oldInIteration = None
    update = None
    test = update
    init = test
    expectKeyword("for")
    expect("(")
    if match(";"):
        lex()
    else:
        if matchKeyword("var") or matchKeyword("let"):
            state.allowIn = False
            init = parseForVariableDeclaration()
            state.allowIn = True
            if (len(init.declarations) == 1) and matchKeyword("in"):
                lex()
                left = init
                right = parseExpression()
                init = None
        else:
            state.allowIn = False
            init = parseExpression()
            state.allowIn = True
            if matchKeyword("in"):
                if not isLeftHandSide(init):
                    throwError(jsdict({
}), Messages.InvalidLHSInForIn)
                lex()
                left = init
                right = parseExpression()
                init = None
        if ('undefined' if not 'left' in locals() else typeof(left)) == "undefined":
            expect(";")
    if ('undefined' if not 'left' in locals() else typeof(left)) == "undefined":
        if not match(";"):
            test = parseExpression()
        expect(";")
        if not match(")"):
            update = parseExpression()
    expect(")")
    oldInIteration = state.inIteration
    state.inIteration = True
    body = parseStatement()
    state.inIteration = oldInIteration
    return (delegate.createForStatement(init, test, update, body) if ('undefined' if not 'left' in locals() else typeof(left)) == "undefined" else delegate.createForInStatement(left, right, body))

def parseContinueStatement():
    label = None
    key = None
    expectKeyword("continue")
    if (ord(source[index]) if index < len(source) else None) == 59:
        lex()
        if not state.inIteration:
            throwError(jsdict({
}), Messages.IllegalContinue)
        return delegate.createContinueStatement(None)
    if peekLineTerminator():
        if not state.inIteration:
            throwError(jsdict({
}), Messages.IllegalContinue)
        return delegate.createContinueStatement(None)
    if lookahead.type == Token.Identifier:
        label = parseVariableIdentifier()
        key = "$" + label.name
        if not (key in state.labelSet):
            throwError(jsdict({
}), Messages.UnknownLabel, label.name)
    consumeSemicolon()
    if (label == None) and (not state.inIteration):
        throwError(jsdict({
}), Messages.IllegalContinue)
    return delegate.createContinueStatement(label)

def parseBreakStatement():
    label = None
    key = None
    expectKeyword("break")
    if (ord(source[index]) if index < len(source) else None) == 59:
        lex()
        if not (state.inIteration or state.inSwitch):
            throwError(jsdict({
}), Messages.IllegalBreak)
        return delegate.createBreakStatement(None)
    if peekLineTerminator():
        if not (state.inIteration or state.inSwitch):
            throwError(jsdict({
}), Messages.IllegalBreak)
        return delegate.createBreakStatement(None)
    if lookahead.type == Token.Identifier:
        label = parseVariableIdentifier()
        key = "$" + label.name
        if not (key in state.labelSet):
            throwError(jsdict({
}), Messages.UnknownLabel, label.name)
    consumeSemicolon()
    if (label == None) and (not (state.inIteration or state.inSwitch)):
        throwError(jsdict({
}), Messages.IllegalBreak)
    return delegate.createBreakStatement(label)

def parseReturnStatement():
    argument = None
    expectKeyword("return")
    if not state.inFunctionBody:
        throwErrorTolerant(jsdict({
}), Messages.IllegalReturn)
    if (ord(source[index]) if index < len(source) else None) == 32:
        if isIdentifierStart((ord(source[index + 1]) if (index + 1) < len(source) else None)):
            argument = parseExpression()
            consumeSemicolon()
            return delegate.createReturnStatement(argument)
    if peekLineTerminator():
        return delegate.createReturnStatement(None)
    if not match(";"):
        if (not match("}")) and (lookahead.type != Token.EOF):
            argument = parseExpression()
    consumeSemicolon()
    return delegate.createReturnStatement(argument)

def parseWithStatement():
    object = None
    body = None
    if strict:
        throwErrorTolerant(jsdict({
}), Messages.StrictModeWith)
    expectKeyword("with")
    expect("(")
    object = parseExpression()
    expect(")")
    body = parseStatement()
    return delegate.createWithStatement(object, body)

def parseSwitchCase():
    test = None
    consequent = []
    statement = None
    skipComment()
    delegate.markStart()
    if matchKeyword("default"):
        lex()
        test = None
    else:
        expectKeyword("case")
        test = parseExpression()
    expect(":")
    while index < length:
        if (match("}") or matchKeyword("default")) or matchKeyword("case"):
            break
        statement = parseStatement()
        consequent.append(statement)
    return delegate.markEnd(delegate.createSwitchCase(test, consequent))

def parseSwitchStatement():
    discriminant = None
    cases = None
    clause = None
    oldInSwitch = None
    defaultFound = None
    expectKeyword("switch")
    expect("(")
    discriminant = parseExpression()
    expect(")")
    expect("{")
    if match("}"):
        lex()
        return delegate.createSwitchStatement(discriminant)
    cases = []
    oldInSwitch = state.inSwitch
    state.inSwitch = True
    defaultFound = False
    while index < length:
        if match("}"):
            break
        clause = parseSwitchCase()
        if clause.test == None:
            if defaultFound:
                throwError(jsdict({
}), Messages.MultipleDefaultsInSwitch)
            defaultFound = True
        cases.append(clause)
    state.inSwitch = oldInSwitch
    expect("}")
    return delegate.createSwitchStatement(discriminant, cases)

def parseThrowStatement():
    argument = None
    expectKeyword("throw")
    if peekLineTerminator():
        throwError(jsdict({
}), Messages.NewlineAfterThrow)
    argument = parseExpression()
    consumeSemicolon()
    return delegate.createThrowStatement(argument)

def parseCatchClause():
    param = None
    body = None
    skipComment()
    delegate.markStart()
    expectKeyword("catch")
    expect("(")
    if match(")"):
        throwUnexpected(lookahead)
    param = parseVariableIdentifier()
    if strict and isRestrictedWord(param.name):
        throwErrorTolerant(jsdict({
}), Messages.StrictCatchVariable)
    expect(")")
    body = parseBlock()
    return delegate.markEnd(delegate.createCatchClause(param, body))

def parseTryStatement():
    block = None
    handlers = []
    finalizer = None
    expectKeyword("try")
    block = parseBlock()
    if matchKeyword("catch"):
        handlers.append(parseCatchClause())
    if matchKeyword("finally"):
        lex()
        finalizer = parseBlock()
    if (len(handlers) == 0) and (not finalizer):
        throwError(jsdict({
}), Messages.NoCatchOrFinally)
    return delegate.createTryStatement(block, [], handlers, finalizer)

def parseDebuggerStatement():
    expectKeyword("debugger")
    consumeSemicolon()
    return delegate.createDebuggerStatement()

def parseStatement():
    type = lookahead.type
    expr = None
    labeledBody = None
    key = None
    if type == Token.EOF:
        throwUnexpected(lookahead)
    skipComment()
    delegate.markStart()
    if type == Token.Punctuator:
        while 1:
            if lookahead.value == ";":
                return delegate.markEnd(parseEmptyStatement())
            elif lookahead.value == "{":
                return delegate.markEnd(parseBlock())
            elif lookahead.value == "(":
                return delegate.markEnd(parseExpressionStatement())
            else:
                break
            break
    if type == Token.Keyword:
        while 1:
            if lookahead.value == "break":
                return delegate.markEnd(parseBreakStatement())
            elif lookahead.value == "continue":
                return delegate.markEnd(parseContinueStatement())
            elif lookahead.value == "debugger":
                return delegate.markEnd(parseDebuggerStatement())
            elif lookahead.value == "do":
                return delegate.markEnd(parseDoWhileStatement())
            elif lookahead.value == "for":
                return delegate.markEnd(parseForStatement())
            elif lookahead.value == "function":
                return delegate.markEnd(parseFunctionDeclaration())
            elif lookahead.value == "if":
                return delegate.markEnd(parseIfStatement())
            elif lookahead.value == "return":
                return delegate.markEnd(parseReturnStatement())
            elif lookahead.value == "switch":
                return delegate.markEnd(parseSwitchStatement())
            elif lookahead.value == "throw":
                return delegate.markEnd(parseThrowStatement())
            elif lookahead.value == "try":
                return delegate.markEnd(parseTryStatement())
            elif lookahead.value == "var":
                return delegate.markEnd(parseVariableStatement())
            elif lookahead.value == "while":
                return delegate.markEnd(parseWhileStatement())
            elif lookahead.value == "with":
                return delegate.markEnd(parseWithStatement())
            else:
                break
            break
    expr = parseExpression()
    if (expr.type == Syntax.Identifier) and match(":"):
        lex()
        key = "$" + expr.name
        if key in state.labelSet:
            throwError(jsdict({
}), Messages.Redeclaration, "Label", expr.name)
        state.labelSet[key] = True
        labeledBody = parseStatement()
        del state.labelSet[key]
        return delegate.markEnd(delegate.createLabeledStatement(expr, labeledBody))
    consumeSemicolon()
    return delegate.markEnd(delegate.createExpressionStatement(expr))

def parseFunctionSourceElements():
    global strict
    sourceElement = None
    sourceElements = []
    token = None
    directive = None
    firstRestricted = None
    oldLabelSet = None
    oldInIteration = None
    oldInSwitch = None
    oldInFunctionBody = None
    skipComment()
    delegate.markStart()
    expect("{")
    while index < length:
        if lookahead.type != Token.StringLiteral:
            break
        token = lookahead
        sourceElement = parseSourceElement()
        sourceElements.append(sourceElement)
        if sourceElement.expression.type != Syntax.Literal:
            break
        directive = source[(token.range[0] + 1):(token.range[1] - 1)]
        if directive == "use strict":
            strict = True
            if firstRestricted:
                throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral)
        else:
            if (not firstRestricted) and token.octal:
                firstRestricted = token
    oldLabelSet = state.labelSet
    oldInIteration = state.inIteration
    oldInSwitch = state.inSwitch
    oldInFunctionBody = state.inFunctionBody
    state.labelSet = jsdict({
})
    state.inIteration = False
    state.inSwitch = False
    state.inFunctionBody = True
    while index < length:
        if match("}"):
            break
        sourceElement = parseSourceElement()
        if ('undefined' if not 'sourceElement' in locals() else typeof(sourceElement)) == "undefined":
            break
        sourceElements.append(sourceElement)
    expect("}")
    state.labelSet = oldLabelSet
    state.inIteration = oldInIteration
    state.inSwitch = oldInSwitch
    state.inFunctionBody = oldInFunctionBody
    return delegate.markEnd(delegate.createBlockStatement(sourceElements))

def parseParams(firstRestricted=None):
    param = None
    params = []
    token = None
    stricted = None
    paramSet = None
    key = None
    message = None
    expect("(")
    if not match(")"):
        paramSet = jsdict({
})
        while index < length:
            token = lookahead
            param = parseVariableIdentifier()
            key = "$" + token.value
            if strict:
                if isRestrictedWord(token.value):
                    stricted = token
                    message = Messages.StrictParamName
                if key in paramSet:
                    stricted = token
                    message = Messages.StrictParamDupe
            elif not firstRestricted:
                if isRestrictedWord(token.value):
                    firstRestricted = token
                    message = Messages.StrictParamName
                elif isStrictModeReservedWord(token.value):
                    firstRestricted = token
                    message = Messages.StrictReservedWord
                elif key in paramSet:
                    firstRestricted = token
                    message = Messages.StrictParamDupe
            params.append(param)
            paramSet[key] = True
            if match(")"):
                break
            expect(",")
    expect(")")
    return jsdict({
"params": params,
"stricted": stricted,
"firstRestricted": firstRestricted,
"message": message,
})

def parseFunctionDeclaration():
    global strict
    id = None
    params = []
    body = None
    token = None
    stricted = None
    tmp = None
    firstRestricted = None
    message = None
    previousStrict = None
    skipComment()
    delegate.markStart()
    expectKeyword("function")
    token = lookahead
    id = parseVariableIdentifier()
    if strict:
        if isRestrictedWord(token.value):
            throwErrorTolerant(token, Messages.StrictFunctionName)
    else:
        if isRestrictedWord(token.value):
            firstRestricted = token
            message = Messages.StrictFunctionName
        elif isStrictModeReservedWord(token.value):
            firstRestricted = token
            message = Messages.StrictReservedWord
    tmp = parseParams(firstRestricted)
    params = tmp.params
    stricted = tmp.stricted
    firstRestricted = tmp.firstRestricted
    if tmp.message:
        message = tmp.message
    previousStrict = strict
    body = parseFunctionSourceElements()
    if strict and firstRestricted:
        throwError(firstRestricted, message)
    if strict and stricted:
        throwErrorTolerant(stricted, message)
    strict = previousStrict
    return delegate.markEnd(delegate.createFunctionDeclaration(id, params, [], body))

def parseFunctionExpression():
    global strict
    token = None
    id = None
    stricted = None
    firstRestricted = None
    message = None
    tmp = None
    params = []
    body = None
    previousStrict = None
    delegate.markStart()
    expectKeyword("function")
    if not match("("):
        token = lookahead
        id = parseVariableIdentifier()
        if strict:
            if isRestrictedWord(token.value):
                throwErrorTolerant(token, Messages.StrictFunctionName)
        else:
            if isRestrictedWord(token.value):
                firstRestricted = token
                message = Messages.StrictFunctionName
            elif isStrictModeReservedWord(token.value):
                firstRestricted = token
                message = Messages.StrictReservedWord
    tmp = parseParams(firstRestricted)
    params = tmp.params
    stricted = tmp.stricted
    firstRestricted = tmp.firstRestricted
    if tmp.message:
        message = tmp.message
    previousStrict = strict
    body = parseFunctionSourceElements()
    if strict and firstRestricted:
        throwError(firstRestricted, message)
    if strict and stricted:
        throwErrorTolerant(stricted, message)
    strict = previousStrict
    return delegate.markEnd(delegate.createFunctionExpression(id, params, [], body))

def parseSourceElement():
    if lookahead.type == Token.Keyword:
        while 1:
            if (lookahead.value == "let") or (lookahead.value == "const"):
                return parseConstLetDeclaration(lookahead.value)
            elif lookahead.value == "function":
                return parseFunctionDeclaration()
            else:
                return parseStatement()
            break
    if lookahead.type != Token.EOF:
        return parseStatement()

def parseSourceElements():
    global strict
    sourceElement = None
    sourceElements = []
    token = None
    directive = None
    firstRestricted = None
    while index < length:
        token = lookahead
        if token.type != Token.StringLiteral:
            break
        sourceElement = parseSourceElement()
        sourceElements.append(sourceElement)
        if sourceElement.expression.type != Syntax.Literal:
            break
        directive = source[(token.range[0] + 1):(token.range[1] - 1)]
        if directive == "use strict":
            strict = True
            if firstRestricted:
                throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral)
        else:
            if (not firstRestricted) and token.octal:
                firstRestricted = token
    while index < length:
        sourceElement = parseSourceElement()
        if ('undefined' if not 'sourceElement' in locals() else typeof(sourceElement)) == "undefined":
            break
        sourceElements.append(sourceElement)
    return sourceElements

def parseProgram():
    global strict
    body = None
    skipComment()
    delegate.markStart()
    strict = False
    peek()
    body = parseSourceElements()
    return delegate.markEnd(delegate.createProgram(body))

def collectToken():
    start = None
    loc = None
    token = None
    range = None
    value = None
    skipComment()
    start = index
    loc = jsdict({
"start": jsdict({
"line": lineNumber,
"column": index - lineStart,
}),
})
    token = extra.advance()
    loc.end = jsdict({
"line": lineNumber,
"column": index - lineStart,
})
    if token.type != Token.EOF:
        range = [token.range[0], token.range[1]]
        value = source[token.range[0]:token.range[1]]
        extra.tokens.append(jsdict({
"type": TokenName[token.type],
"value": value,
"range": range,
"loc": loc,
}))
    return token

def collectRegex():
    pos = None
    loc = None
    regex = None
    token = None
    skipComment()
    pos = index
    loc = jsdict({
"start": jsdict({
"line": lineNumber,
"column": index - lineStart,
}),
})
    regex = extra.scanRegExp()
    loc.end = jsdict({
"line": lineNumber,
"column": index - lineStart,
})
    if not extra.tokenize:
        if len(extra.tokens) > 0:
            token = extra.tokens[len(extra.tokens) - 1]
            if (token.range[0] == pos) and (token.type == "Punctuator"):
                if (token.value == "/") or (token.value == "/="):
                    extra.tokens.pop()
        extra.tokens.append(jsdict({
"type": "RegularExpression",
"value": regex.literal,
"range": [pos, index],
"loc": loc,
}))
    return regex

def filterTokenLocation():
    i = None
    entry = None
    token = None
    tokens = []
    i = 0
    while 1:
        if not (i < len(extra.tokens)):
            break
        entry = extra.tokens[i]
        token = jsdict({
"type": entry.type,
"value": entry.value,
})
        if extra.range:
            token.range = entry.range
        if extra.loc:
            token.loc = entry.loc
        tokens.append(token)
        i += 1
    extra.tokens = tokens

class LocationMarker(object):
    def __init__(self=None):
        self.marker = [index, lineNumber, index - lineStart, 0, 0, 0]
    
    def end(self=None):
        self.marker[3] = index
        self.marker[4] = lineNumber
        self.marker[5] = index - lineStart
    
    def apply(self=None, node=None):
        if extra.range:
            node.range = [self.marker[0], self.marker[3]]
        if extra.loc:
            node.loc = jsdict({
"start": jsdict({
"line": self.marker[1],
"column": self.marker[2],
}),
"end": jsdict({
"line": self.marker[4],
"column": self.marker[5],
}),
})
        node = delegate.postProcess(node)
    
def createLocationMarker():
    if (not extra.loc) and (not extra.range):
        return None
    skipComment()
    return LocationMarker()

def patch():
    global advance, scanRegExp
    if ('undefined' if not ('tokens' in extra) else typeof(extra.tokens)) != "undefined":
        extra.advance = advance
        extra.scanRegExp = scanRegExp
        advance = collectToken
        scanRegExp = collectRegex

def unpatch():
    global advance, scanRegExp
    if ('undefined' if not ('scanRegExp' in extra) else typeof(extra.scanRegExp)) == "function":
        advance = extra.advance
        scanRegExp = extra.scanRegExp

def tokenize(code, **options):
    global delegate, source, index, lineNumber, lineStart, length, lookahead, state, extra
    options = jsdict(options)
    toString = None
    token = None
    tokens = None
    toString = str
    if (('undefined' if not 'code' in locals() else typeof(code)) != "string") and (not isinstance(code, str)):
        code = toString(code)
    delegate = SyntaxTreeDelegate
    source = code
    index = 0
    lineNumber = (1 if len(source) > 0 else 0)
    lineStart = 0
    length = len(source)
    lookahead = None
    state = jsdict({
"allowIn": True,
"labelSet": jsdict({
}),
"inFunctionBody": False,
"inIteration": False,
"inSwitch": False,
"lastCommentStart": -1,
})
    extra = jsdict({
})
    options = options or jsdict({
})
    options.tokens = True
    extra.tokens = []
    extra.tokenize = True
    extra.openParenToken = -1
    extra.openCurlyToken = -1
    extra.range = (('undefined' if not ('range' in options) else typeof(options.range)) == "boolean") and options.range
    extra.loc = (('undefined' if not ('loc' in options) else typeof(options.loc)) == "boolean") and options.loc
    if (('undefined' if not ('comment' in options) else typeof(options.comment)) == "boolean") and options.comment:
        extra.comments = []
    if (('undefined' if not ('tolerant' in options) else typeof(options.tolerant)) == "boolean") and options.tolerant:
        extra.errors = []
    if length > 0:
        if (typeof(source[0])) == "undefined":
            if isinstance(code, str):
                source = code.valueOf()
    patch()
    try:
        peek()
        if lookahead.type == Token.EOF:
            return extra.tokens
        token = lex()
        while lookahead.type != Token.EOF:
            try:
                token = lex()
            except Exception as lexError:
                token = lookahead
                if extra.errors:
                    extra.errors.append(lexError)
                    break
                else:
                    raise 
        filterTokenLocation()
        tokens = extra.tokens
        if ('undefined' if not ('comments' in extra) else typeof(extra.comments)) != "undefined":
            tokens.comments = extra.comments
        if ('undefined' if not ('errors' in extra) else typeof(extra.errors)) != "undefined":
            tokens.errors = extra.errors
    except Exception as e:
        raise 
    finally:
        unpatch()
        extra = jsdict({
})
    return tokens

def parse(code, **options):
    global delegate, source, index, lineNumber, lineStart, length, lookahead, state, extra
    options = jsdict(options)
    program = None
    toString = None
    toString = str
    if (('undefined' if not 'code' in locals() else typeof(code)) != "string") and (not isinstance(code, str)):
        code = toString(code)
    delegate = SyntaxTreeDelegate
    source = code
    index = 0
    lineNumber = (1 if len(source) > 0 else 0)
    lineStart = 0
    length = len(source)
    lookahead = None
    state = jsdict({
"allowIn": True,
"labelSet": jsdict({
}),
"inFunctionBody": False,
"inIteration": False,
"inSwitch": False,
"lastCommentStart": -1,
"markerStack": [],
})
    extra = jsdict({
})
    if ('undefined' if not 'options' in locals() else typeof(options)) != "undefined":
        extra.range = (('undefined' if not ('range' in options) else typeof(options.range)) == "boolean") and options.range
        extra.loc = (('undefined' if not ('loc' in options) else typeof(options.loc)) == "boolean") and options.loc
        if (extra.loc and (options.source != None)) and (options.source != undefined):
            extra.source = toString(options.source)
        if (('undefined' if not ('tokens' in options) else typeof(options.tokens)) == "boolean") and options.tokens:
            extra.tokens = []
        if (('undefined' if not ('comment' in options) else typeof(options.comment)) == "boolean") and options.comment:
            extra.comments = []
        if (('undefined' if not ('tolerant' in options) else typeof(options.tolerant)) == "boolean") and options.tolerant:
            extra.errors = []
    if length > 0:
        if (typeof(source[0])) == "undefined":
            if isinstance(code, str):
                source = code.valueOf()
    patch()
    try:
        program = parseProgram()
        if ('undefined' if not ('comments' in extra) else typeof(extra.comments)) != "undefined":
            program.comments = extra.comments
        if ('undefined' if not ('tokens' in extra) else typeof(extra.tokens)) != "undefined":
            filterTokenLocation()
            program.tokens = extra.tokens
        if ('undefined' if not ('errors' in extra) else typeof(extra.errors)) != "undefined":
            program.errors = extra.errors
    except Exception as e:
        raise 
    finally:
        unpatch()
        extra = jsdict({
})
    return program


parse('var = 490 \n a=4;')