def __init__(self, code, options={}, delegate=None) :
        self.ErrorHandler=ErrorHandler()
        self.Scanner=Scanner(code, self.ErrorHandler)
        self.Node= Node()   #节点创建

        self.LookAhead=RawToken(type=2, value='', lineNumber=self.Scanner.LineNumber, lineStart=0, start=0, end=0 )
        self.HasLineTerminator=False
        self.Context = Context(isModule=False, allowAwait=False, allowIn=True, allowStrictDirective=True, allowYield= True,
            firstCoverInitializedNameError=None, isAssignmentTarget=False, isBindingElement=False, inFunctionBody=False,
            inIteration=False,inSwitch=False, labelSet= {}, strict=False)

        self.OperatorPrecedence = {
            ')': 0,
            ';': 0,
            ',': 0,
            ']': 0,
            '||': 1,
            'OR':1,
            '&&': 2,
            'AND':2,
            '|': 3,
            '^': 4,
            '&': 5,
            '==': 6,
            '!=': 6,
            '<>': 6,
            '===': 6,
            '=': 6,
            '!==': 6,
            '<': 7,
            '>': 7,
            '<=': 7,
            '>=': 7,
            '<<': 8,
            '>>': 8,
            '>>>': 8,
            '+': 9,
            '-': 9,
            '*': 11,
            '/': 11,
            '%': 11,
        }

        self.StartMarker = Marker(index=0, line=self.Scanner.LineNumber, column=0)
        self.LastMarker = Marker(index=0, line=self.Scanner.LineNumber, column=0)
class Tokenizer():
    def __init__(self, code) :
        self.ErrorHandler=ErrorHandler()   #错误信息处理类
        self.Scanner=Scanner(code,self.ErrorHandler)
        self.Buffer=[]

    def GetNextToken(self) :
        if len(self.Buffer) <=0 :
            comments=self.Scanner.ScanComments()
            if not self.Scanner.IsEOF() :
                token=self.Scanner.Lex()

                entry= BufferEntry( type=TOKEN_NAME[token.Type], value=self.Scanner.Source[token.Start: token.End])

                self.Buffer.append(entry)

        if len(self.Buffer) <=0 : return None

        return self.Buffer.pop(0)
 def __init__(self, code) :
     self.ErrorHandler=ErrorHandler()   #错误信息处理类
     self.Scanner=Scanner(code,self.ErrorHandler)
     self.Buffer=[]
class JSParser:
    def __init__(self, code, options={}, delegate=None) :
        self.ErrorHandler=ErrorHandler()
        self.Scanner=Scanner(code, self.ErrorHandler)
        self.Node= Node()   #节点创建

        self.LookAhead=RawToken(type=2, value='', lineNumber=self.Scanner.LineNumber, lineStart=0, start=0, end=0 )
        self.HasLineTerminator=False
        self.Context = Context(isModule=False, allowAwait=False, allowIn=True, allowStrictDirective=True, allowYield= True,
            firstCoverInitializedNameError=None, isAssignmentTarget=False, isBindingElement=False, inFunctionBody=False,
            inIteration=False,inSwitch=False, labelSet= {}, strict=False)

        self.OperatorPrecedence = {
            ')': 0,
            ';': 0,
            ',': 0,
            ']': 0,
            '||': 1,
            'OR':1,
            '&&': 2,
            'AND':2,
            '|': 3,
            '^': 4,
            '&': 5,
            '==': 6,
            '!=': 6,
            '<>': 6,
            '===': 6,
            '=': 6,
            '!==': 6,
            '<': 7,
            '>': 7,
            '<=': 7,
            '>=': 7,
            '<<': 8,
            '>>': 8,
            '>>>': 8,
            '+': 9,
            '-': 9,
            '*': 11,
            '/': 11,
            '%': 11,
        }

        self.StartMarker = Marker(index=0, line=self.Scanner.LineNumber, column=0)
        self.LastMarker = Marker(index=0, line=self.Scanner.LineNumber, column=0)

    def Initialize(self) :
        self.NextToken()
        self.LastMarker=Marker(index=self.Scanner.Index, line=self.Scanner.LineNumber, column=self.Scanner.Index-self.Scanner.LineStart)

    def CreateNode(self) :
        return Marker(index=self.StartMarker.Index, line=self.StartMarker.Line, column=self.StartMarker.Column)

    def StartNode(self, token, lastLineStart=0):
        column = token.Start - token.LineStart
        line = token.LineNumber
        if column < 0 :
	        column += lastLineStart
	        line-=1

        return Marker(index=token.Start, line= line, column=column)

    def Match(self, value) : 
        return self.LookAhead.Type==7  and self.LookAhead.Value==value # 7=Punctuator

    def Expect(self, value) :
        token=self.NextToken()
        if token.Type!=7  or token.Value!=value :  # 7=Punctuator
            self.ThrowUnexpectedToken(token)

    # 是否是赋值操作符
    def MatchAssign(self) :
        if self.LookAhead.Type!=7 :
            return False  #7=Punctuator
        op=self.LookAhead.Value
        return op in (':', ':=')

    def GetTokenRaw(self, token) :
        return self.Scanner.Source[token.Start : token.End]

    def NextToken(self) :
        token=self.LookAhead
        self.LastMarker.Index=self.Scanner.Index
        self.LastMarker.Line=self.Scanner.LineNumber
        self.LastMarker.Column=self.Scanner.Index-self.Scanner.LineStart
        self.CollectComments() # 过滤注释 空格

        if self.Scanner.Index != self.StartMarker.Index :
            self.StartMarker.Index = self.Scanner.Index
            self.StartMarker.Line = self.Scanner.LineNumber
            self.StartMarker.Column = self.Scanner.Index - self.Scanner.LineStart

        next=self.Scanner.Lex()
        self.HasLineTerminator= token.LineNumber!=next.LineNumber 
        if next and self.Context.Strict and next.Type==3 : #3=Identifier
            print ('[JSParser::NextToken] not support')

        self.LookAhead=next

        return token

    def CollectComments(self) :
        self.Scanner.ScanComments()

    def ParseScript(self) :
        node=self.CreateNode()
        body=self.ParseDirectivePrologues()
        
        while self.LookAhead.Type!=2: #2=/*EOF*/)
            body.append(self.ParseStatementListItem())

        return self.Finalize(node,self.Node.Script(body))

    # https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive
    def ParseDirective(self):
        token=self.LookAhead
        node=self.CreateNode()
        expr=self.ParseExpression()
        return None

    def ParseDirectivePrologues(self) :
        firstRestricted=None
        body=[]
        while True :
            token=self.LookAhead
            if token.Type!=8 : #8=/*StringLiteral*
                break
            statement = self.ParseDirective()
            body.append(statement)

        return body

    # https://tc39.github.io/ecma262/#sec-block
    def ParseStatementListItem(self) :
        statement=None
        self.Context.IsAssignmentTarget=True
        self.Context.IsBindingElement=True
        if self.LookAhead.Type==4 : # 4=/*Keyword*/
            pass
        else :
            statement=self.ParseStatement()

        return statement

    # https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations
    def ParseStatement(self):
        statement=None
        type = self.LookAhead.Type
        if type in (1,5,6,8,10,9) : # BooleanLiteral, NullLiteral, NumericLiteral, StringLiteral, Template, RegularExpression
            statement = self.ParseExpressionStatement()

        elif  type==7 :     # 7=/* Punctuator */:
            value = self.LookAhead.Value
            if value == '(' :
                statement = self.ParseExpressionStatement()
            elif value == ';' :
                statement = self.ParseEmptyStatement()
            else :
                statement = self.ParseExpressionStatement()

        elif type==3 : # 3=/* Identifier */:  
            statement = self.ParseLabelledStatement()
           
        elif type==4: # 4= /* Keyword */
            print('[JSParser::ParseStatementListItem] not support Keyword')
        else :
            statement="error"

        return statement


    # https://tc39.github.io/ecma262/#sec-empty-statement
    def ParseEmptyStatement(self):
        node=self.CreateNode()
        self.Expect(';')
        return self.Finalize(node, self.Node.EmptyStatement())


    # https://tc39.github.io/ecma262/#sec-labelled-statements
    def ParseLabelledStatement(self):
        node=self.CreateNode()
        expr=self.ParseExpression()
        self.ConsumeSemicolon()
        statement = self.Node.ExpressionStatement(expr)

        return self.Finalize(node, statement)

    #  https://tc39.github.io/ecma262/#sec-comma-operator
    def ParseExpression(self) :
        startToken=self.LookAhead
        expr=self.IsolateCoverGrammar(self.ParseAssignmentExpression)
        if self.Match(',') :
            expressions=[]
            expressions.append(expr)
            while self.LookAhead.Type!=2 : #/*EOF*/
                if not self.Match(',') :
                    break
                self.NextToken()
                expressions.append(self.IsolateCoverGrammar(self.ParseAssignmentExpression))

            expr=self.Finalize(self.StartNode(startToken),self.Node.SequenceExpression(expressions))

        return expr

    def ParseAssignmentExpression(self) :
        expr=None
        startToken=self.LookAhead
        token=startToken
        expr=self.ParseConditionalExpression()

        if self.MatchAssign() :
            if not self.Context.IsAssignmentTarget :
                marker=expr.Marker
                self.ThrowUnexpectedError(marker.Index,marker.Line,marker.Column,Messages.InvalidLHSInAssignment)

            if not self.Match('=') and not self.Match(':') :
                self.Context.IsAssignmentTarget=False
                self.Context.IsBindingElement=False
            else :
                self.ReinterpretExpressionAsPattern(expr)

            token=self.NextToken()
            operator=token.Value
            right=self.IsolateCoverGrammar(self.ParseAssignmentExpression)
            expr=self.Finalize(self.StartNode(startToken), self.Node.AssignmentExpression(operator, expr, right))
            self.Context.FirstCoverInitializedNameError=None

        return expr

    def ParseConditionalExpression(self) :
        startToken=self.LookAhead
        expr=self.InheritCoverGrammar(self.ParseBinaryExpression)

        return expr

    def ParseBinaryExpression(self) :
        startToken=self.LookAhead
        expr=self.InheritCoverGrammar(self.ParseExponentiationExpression)
        token=self.LookAhead
        prec=self.BinaryPrecedence(token)
        if prec>0 :
            self.NextToken()
            self.Context.IsAssignmentTarget=False
            self.Context.IsBindingElement=False
            markers=[startToken,self.LookAhead]
            left=expr
            right=self.IsolateCoverGrammar(self.ParseExponentiationExpression)
            stack=[left,token.Value,right]
            precedences = [prec]
            while True :
                prec=self.BinaryPrecedence(self.LookAhead)
                if prec<=0 : 
                    break

                while len(stack)>2 and prec<=precedences[-1] :
                    right=stack.pop()
                    operator=stack.pop()
                    precedences.pop()
                    left=stack.pop()
                    markers.pop()
                    node=self.StartNode(markers[-1])
                    stack.append(self.Finalize(node, self.Node.BinaryExpression(operator, left, right)))

                # Shift
                stack.append(self.NextToken().Value)
                precedences.append(prec)
                markers.append(self.LookAhead)
                stack.append(self.IsolateCoverGrammar(self.ParseExponentiationExpression))

            i=len(stack)-1
            expr=stack[i]
            lastMarker=markers.pop()
            while i>1 :
                marker=markers.pop()
                lastLineStart=lastMarker and lastMarker.LineStart
                node=self.StartNode(marker, lastLineStart)
                operator=stack[i-1]
                expr=self.Finalize(node, self.Node.BinaryExpression(operator, stack[i - 2], expr))
                i-=2
                lastMarker=marker

        return expr
    
    def ParseExponentiationExpression(self) :
        startToken=self.LookAhead
        expr=self.InheritCoverGrammar(self.ParseUnaryExpression)

        return expr

    def ParseUnaryExpression(self) :
        expr=None
        if self.Match('+') or self.Match('-') :
            node=self.StartNode(self.LookAhead)
            token=self.NextToken()
            expr=self.InheritCoverGrammar(self.ParseUnaryExpression)
            expr=self.Finalize(node, self.Node.UnaryExpression(token.Value, expr))
            self.Context.IsAssignmentTarget=False
            self.Context.IsBindingElement=False
        else :
            expr=self.ParseUpdateExpression()

        return expr

    # https://tc39.github.io/ecma262/#sec-update-expressions
    def ParseUpdateExpression(self) :
        startToken=self.LookAhead
        expr=self.InheritCoverGrammar(self.ParseLeftHandSideExpressionAllowCall)

        return expr

    def ParseLeftHandSideExpressionAllowCall(self) :
        startToken=self.LookAhead
        expr=self.InheritCoverGrammar(self.ParsePrimaryExpression)

        while True :
            if self.Match('(') :
                self.Context.IsBindingElement=False
                self.Context.IsAssignmentTarget=False
                args=self.ParseArguments() # 解析 调用参数
                expr=self.Finalize(self.StartNode(startToken), self.Node.CallExpression(expr,args))
            else :
                break

        return expr

    # https://tc39.github.io/ecma262/#sec-left-hand-side-expressions
    def ParseArguments(self) :
        self.Expect('(')
        args=[]
        if not self.Match(')') :
            while True :
                expr=self.IsolateCoverGrammar(self.ParseAssignmentExpression)
                args.append(expr)

                if self.Match(')') :
                    break

                self.ExpectCommaSeparator()

                if self.Match(')'):
                    break

        self.Expect(')')
        return args

    # Quietly expect a comma when in tolerant mode, otherwise delegates to expect().
    def ExpectCommaSeparator(self) :
        self.Expect(',')

    # https://tc39.github.io/ecma262/#sec-primary-expression
    def ParsePrimaryExpression(self) :
        node=self.CreateNode()
        type=self.LookAhead.Type
        if type==3 : # Identifier 
            expr=self.Finalize(node, self.Node.Identifier(self.NextToken().Value))
        elif type in (6,8) : # 6=NumericLiteral, 8=StringLiteral
            self.Context.IsAssignmentTarget=False
            self.Context.IsBindingElement=False
            token=self.NextToken()
            raw=self.GetTokenRaw(token)
            expr=self.Finalize(node, self.Node.Literal(token.Value,raw))
        elif type==7 : # 7=Punctuator
            value=self.LookAhead.Value
            if value=='(':
                self.Context.IsBindingElement=False
                expr=self.InheritCoverGrammar(self.ParseGroupExpression)
            else :
                self.ThrowUnexpectedToken(self.NextToken())
        else :
            self.ThrowUnexpectedToken(self.NextToken())

        return expr

    def ParseGroupExpression(self) :
        self.Expect('(')
        if self.Match(')') :
            self.NextToken()
        else :
            startToken=self.LookAhead
            params=[]
            arrow=False
            self.Context.IsBindingElement=True
            expr=self.InheritCoverGrammar(self.ParseAssignmentExpression)
            if self.Match(',') :
                expressions=[]
                self.Context.IsAssignmentTarget=False
                expressions.append(expr)
                while self.LookAhead.Type!=2 :  # /* EOF */)
                    if not self.Match(',') :
                        break

                    self.NextToken()
                    if not self.Match(')') :
                        self.NextToken()
                    
            if not arrow :
                self.Expect(')')
                self.Context.IsBindingElement=False

        return expr

    # https://tc39.github.io/ecma262/#sec-expression-statement
    def ParseExpressionStatement(self) :
        node=self.CreateNode()
        expr=self.ParseExpression()
        self.ConsumeSemicolon()

        return self.Finalize(node,self.Node.ExpressionStatement(expr))

    def ConsumeSemicolon(self) :
        if self.Match(';') :
            self.NextToken()
        elif not self.HasLineTerminator :
            # if (this.LookAhead.Type!=2/*EOF*/ && !this.Match('}'))

            self.LastMarker.Index=self.StartMarker.Index
            self.LastMarker.Line=self.StartMarker.Line
            self.LastMarker.Column=self.StartMarker.Column

    def ReinterpretExpressionAsPattern(self, expr) :
        if expr.Type in (Syntax.Identifier, Syntax.AssignmentExpression) :
            pass
        else :
            pass

    def Finalize(self,marker,node) :
        node.Marker=Marker( line=marker.Line, column=marker.Column, index=marker.Index )
        return node

    def BinaryPrecedence(self, token) :
        op = token.Value

        if token.Type == 7 :    # /* Punctuator */
            precedence = self.OperatorPrecedence.get(op, 0)
        else :
            precedence = 0
        
        return precedence

    def IsolateCoverGrammar(self, parseFunction) :
        previousIsBindingElement=self.Context.IsBindingElement
        previousIsAssignmentTarget=self.Context.IsAssignmentTarget
        previousFirstCoverInitializedNameError=self.Context.FirstCoverInitializedNameError

        self.Context.IsBindingElement=True
        self.Context.IsAssignmentTarget=True
        self.Context.FirstCoverInitializedNameError=None
        result=parseFunction()

        if self.Context.FirstCoverInitializedNameError is not None :
            # 错误 this.throwUnexpectedToken(this.context.firstCoverInitializedNameError);
            pass

        self.Context.IsBindingElement=previousIsBindingElement
        self.Context.IsAssignmentTarget=previousIsAssignmentTarget
        self.Context.FirstCoverInitializedNameError=previousFirstCoverInitializedNameError

        return result

    def InheritCoverGrammar(self,parseFunction) :
        previousIsBindingElement = self.Context.IsBindingElement
        previousIsAssignmentTarget = self.Context.IsAssignmentTarget
        previousFirstCoverInitializedNameError = self.Context.FirstCoverInitializedNameError
        self.Context.IsBindingElement = True
        self.Context.IsAssignmentTarget = True
        self.Context.FirstCoverInitializedNameError = None

        result = parseFunction()

        self.Context.IsBindingElement = self.Context.IsBindingElement and previousIsBindingElement
        self.Context.IsAssignmentTarget = self.Context.IsAssignmentTarget and previousIsAssignmentTarget
        self.Context.FirstCoverInitializedNameError = previousFirstCoverInitializedNameError or self.Context.FirstCoverInitializedNameError

        return result

    def ThrowUnexpectedToken(self, token=None,message=None) :
        raise self.UnexpectedTokenError(token,message)

    def ThrowUnexpectedError(self, index,line,column,message=None) :
        if message is not None : 
            msg=message
        else :
            msg="执行异常"

        return self.ErrorHandler.ThrowError(index,line,column,msg)

    def UnexpectedTokenError(self,token=None,message=None) :
        msg=message or Messages.UnexpectedToken
        value='ILLEGAL'
        if token :
            if not message :
                pass
            value=token.Value

        msg=msg.replace("%0",unicode(value),1)
        if token and isinstance(token.LineNumber, int) :
            index=token.Start
            line=token.LineNumber
            lastMarkerLineStart=self.LastMarker.Index-self.LastMarker.Column
            column=token.Start-lastMarkerLineStart+1
            return self.ErrorHandler.CreateError(index,line,column,msg)
        else :
            index=self.LastMarker.Index
            line=self.LastMarker.Line
            column=self.LastMarker.Column+1
            return self.ErrorHandler.CreateError(index,line,column,msg)