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 __init__(self, ast, option=None) :
        self.AST=ast   # 语法树

        self.ErrorHandler=ErrorHandler()
        self.VarTable={}           # 变量表
        self.OutVarTable=[]        # 输出变量
        self.Arguments=[]

        # 脚本自动变量表, 只读
        self.ConstVarTable={
            # 个股数据
            'CLOSE':None, 'VOL':None, 'OPEN':None, 'HIGH':None, 'LOW':None, 'AMOUNT':None,
            'C':None, 'V':None, 'O':None, 'H':None, 'L':None, 'VOLR':None,

            # 日期类
            'DATE':None, 'YEAR':None, 'MONTH':None, 'PERIOD':None, 'WEEK':None,

            # 大盘数据
            'INDEXA':None, 'INDEXC':None, 'INDEXH':None, 'INDEXL':None, 'INDEXO':None, 'INDEXV':None, 'INDEXADV':None, 'INDEXDEC':None,

            # 到最后交易日的周期数
            'CURRBARSCOUNT':None,
            # 流通股本(手)
            'CAPITAL':None,
            # 换手率
            'EXCHANGE':None,
            'SETCODE':None  
        }  

        if option and option.ProcCreateSymbolData:
            self.SymbolData=option.ProcCreateSymbolData(ast=ast,option=option, procThrow=self.ThrowUnexpectedNode)
        else :
            self.SymbolData=JSSymbolData(ast=ast,option=option, procThrow=self.ThrowUnexpectedNode)
        self.Algorithm=JSAlgorithm(errorHandler=self.ErrorHandler,symbolData=self.SymbolData)
        self.Draw=JSDraw(errorHandler=self.ErrorHandler,symbolData=self.SymbolData)
        
        self.JobList=[]    # 执行的任务队列

        if option and option.Arguments:
             self.Arguments=option.Arguments
Exemple #3
0
class JSExecute:
    def __init__(self, ast, option=None):
        self.AST = ast  # 语法树

        self.ErrorHandler = ErrorHandler()
        self.VarTable = {}  # 变量表
        self.OutVarTable = []  # 输出变量
        self.Arguments = []

        # 脚本自动变量表, 只读
        self.ConstVarTable = {
            # 个股数据
            'CLOSE': None,
            'VOL': None,
            'OPEN': None,
            'HIGH': None,
            'LOW': None,
            'AMOUNT': None,
            'C': None,
            'V': None,
            'O': None,
            'H': None,
            'L': None,
            'VOLR': None,

            # 日期类
            'DATE': None,
            'YEAR': None,
            'MONTH': None,
            'PERIOD': None,
            'WEEK': None,

            # 大盘数据
            'INDEXA': None,
            'INDEXC': None,
            'INDEXH': None,
            'INDEXL': None,
            'INDEXO': None,
            'INDEXV': None,
            'INDEXADV': None,
            'INDEXDEC': None,

            # 到最后交易日的周期数
            'CURRBARSCOUNT': None,
            # 流通股本(手)
            'CAPITAL': None,
            # 换手率
            'EXCHANGE': None,
            'SETCODE': None
        }

        self.SymbolData = JSSymbolData(ast=ast,
                                       option=option,
                                       procThrow=self.ThrowUnexpectedNode)
        self.Algorithm = JSAlgorithm(errorHandler=self.ErrorHandler,
                                     symbolData=self.SymbolData)
        self.Draw = JSDraw(errorHandler=self.ErrorHandler,
                           symbolData=self.SymbolData)

        self.JobList = []  # 执行的任务队列

        if option and option.Arguments:
            self.Arguments = option.Arguments

    def Execute(self):
        self.SymbolData.RunDownloadJob(self.JobList)  # 准备数据
        outVar = self.RunAST()
        return outVar

    def ReadSymbolData(self, name, node):
        if name in ('CLOSE', 'C', 'VOL', 'V', 'OPEN', 'O', 'HIGH', 'H', 'LOW',
                    'L', 'AMOUNT'):
            return self.SymbolData.GetSymbolCacheData(name)
        elif name == 'VOLR':  # 量比
            pass
            # return self.SymbolData.GetVolRateCacheData(node)
        elif name in ('INDEXA', 'INDEXC', 'INDEXH', 'INDEXO', 'INDEXV',
                      'INDEXL', 'INDEXADV', 'INDEXDEC'):  # 大盘数据
            return self.SymbolData.GetIndexCacheData(name)
        elif name == 'CURRBARSCOUNT':
            pass
            # return self.SymbolData.GetCurrBarsCount()
        elif name == 'CAPITAL':
            return self.SymbolData.GetFinanceCacheData(
                JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CAPITAL_DATA, node=node)
        elif name == 'EXCHANGE':
            return self.SymbolData.GetFinanceCacheData(
                JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_EXCHANGE_DATA, node=node)
        elif name == 'SETCODE':
            return self.SymbolData.SETCODE()

        elif name == 'DATE':
            return self.SymbolData.DATE()
        elif name == 'YEAR':
            return self.SymbolData.YEAR()
        elif name == 'MONTH':
            return self.SymbolData.MONTH()
        elif name == 'WEEK':
            return self.SymbolData.WEEK()
        elif name == 'PERIOD':
            return self.SymbolData.PERIOD()

    # 读取变量
    def ReadVariable(self, name, node):
        if name in self.ConstVarTable:
            data = self.ConstVarTable[name]

            if not data:  # 动态加载,用到再加载
                data = self.ReadSymbolData(name, node)
                self.ConstVarTable[name] = data
            return data

        if name in self.VarTable:
            return self.VarTable[name]

        self.ThrowUnexpectedNode(node, '变量' + name + '不存在')
        return None

    # 单数据转成数组 个数和历史数据一致
    def SingleDataToArrayData(self, value):
        count = len(self.SymbolData.Data.Data)
        result = [value] * count
        return result

    def RunAST(self):
        # 预定义的变量
        for item in self.Arguments:
            self.VarTable[item.Name] = item.Value

        if not self.AST or not self.AST.Body:
            self.ThrowError()

        for item in self.AST.Body:
            self.VisitNode(item)
            if item.Type == Syntax.ExpressionStatement and item.Expression:
                if item.Expression.Type == Syntax.AssignmentExpression and item.Expression.Operator == ':' and item.Expression.Left:
                    assignmentItem = item.Expression
                    varName = assignmentItem.Left.Name
                    outVar = self.VarTable[varName]
                    if not isinstance(outVar, list):
                        outVar = self.SingleDataToArrayData(outVar)

                    self.OutVarTable.append(
                        OutVariable(name=varName, data=outVar, type=0))

                elif (item.Expression.Type == Syntax.CallExpression):
                    callItem = item.Expression
                    if (JSDraw.IsDrawFunction(callItem.Callee.Name)):
                        draw = callItem.Draw
                        draw.Name = callItem.Callee.Name
                        self.OutVarTable.append(
                            OutVariable(name=draw.Name, draw=draw, type=1))

                elif (item.Expression.Type == Syntax.SequenceExpression):
                    varName = None
                    draw = None
                    color = None
                    lineWidth = None
                    colorStick = False
                    pointDot = False
                    circleDot = False
                    lineStick = False
                    stick = False
                    volStick = False
                    isShow = True
                    isExData = False
                    for itemExpression in item.Expression.Expression:
                        if (itemExpression.Type == Syntax.AssignmentExpression
                                and itemExpression.Operator == ':'
                                and itemExpression.Left):
                            varName = itemExpression.Left.Name
                            varValue = self.VarTable[varName]
                            if not JSComplierHelper.IsArray(varValue):
                                varValue = self.SingleDataToArrayData(varValue)
                                self.VarTable[
                                    varName] = varValue  # 把单数值转化成数组放到变量表里

                        elif (itemExpression.Type == Syntax.Identifier):
                            value = itemExpression.Name
                            if (value == 'COLORSTICK'):
                                colorStick = True
                            elif (value == 'POINTDOT'):
                                pointDot = True
                            elif (value == 'CIRCLEDOT'):
                                circleDot = True
                            elif (value == 'LINESTICK'):
                                lineStick = True
                            elif (value == 'STICK'):
                                stick = True
                            elif (value == 'VOLSTICK'):
                                volStick = True
                            elif (value.find('COLOR') == 0):
                                color = value
                            elif (value.find('LINETHICK') == 0):
                                lineWidth = value
                            elif (value.find('NODRAW') == 0):
                                isShow = False
                            elif (value.find('EXDATA') == 0):
                                isExData = True  # 扩展数据, 不显示再图形里面

                        elif (itemExpression.Type == Syntax.Literal):  #常量
                            aryValue = self.SingleDataToArrayData(
                                itemExpression.Value)
                            varName = str(itemExpression.Value)
                            self.VarTable[varName, aryValue]  # 把常量放到变量表里

                        elif (itemExpression.Type == Syntax.CallExpression
                              and JSDraw.IsDrawFunction(
                                  itemExpression.Callee.Name)):
                            draw = itemExpression.Draw
                            draw.Name = itemExpression.Callee.Name

                    if (pointDot and varName):  # 圆点
                        outVar = self.VarTable[varName]
                        if (not JSComplierHelper.IsArray(outVar)):
                            outVar = self.SingleDataToArrayData(outVar)
                        value = OutVariable(name=varName, data=outVar, type=3)
                        value.Radius = 2
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        self.OutVarTable.append(value)

                    elif (circleDot and varName):  # 圆点
                        outVar = self.VarTable[varName]
                        if not JSComplierHelper.IsArray(outVar):
                            outVar = self.SingleDataToArrayData(outVar)
                        value = OutVariable(name=varName, data=outVar, type=3)
                        value.Radius = 1.3
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        self.OutVarTable.append(value)

                    elif (lineStick and varName):  # LINESTICK  同时画出柱状线和指标线
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=4)
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        self.OutVarTable.append(value)

                    elif (stick and varName):  # STICK 画柱状线
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=5)
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        self.OutVarTable.append(value)

                    elif (volStick and varName):  # VOLSTICK   画彩色柱状线
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=6)
                        if color:
                            value.Color = color
                        self.OutVarTable.append(value)

                    elif (varName and color):
                        outVar = self.VarTable[varName]
                        if not JSComplierHelper.IsArray(outVar):
                            outVar = self.SingleDataToArrayData(outVar)
                        value = OutVariable(name=varName, data=outVar, type=0)
                        value.Color = color
                        if (lineWidth):
                            value.LineWidth = lineWidth
                        if (isShow == False):
                            value.IsShow = False
                        if (isExData == True):
                            value.IsExData = True
                        self.OutVarTable.append(value)

                    elif (draw and color):
                        value = OutVariable(name=draw.Name, data=draw, type=1)
                        value.Color = color
                        self.OutVarTable.append(value)

                    elif (colorStick and varName
                          ):  # CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=2)
                        value.Color = color
                        self.OutVarTable.append(value)

                    elif (varName):
                        outVar = self.VarTable[varName]
                        value = OutVariable(name=varName, data=outVar, type=0)
                        if color:
                            value.Color = color
                        if lineWidth:
                            value.LineWidth = lineWidth
                        if isShow == False:
                            value.IsShow = False
                        if isExData == True:
                            value.IsExData = True
                        self.OutVarTable.append(value)

        return self.OutVarTable

    def VisitNode(self, node):
        if node.Type == Syntax.SequenceExpression:
            self.VisitSequenceExpression(node)
        elif node.Type == Syntax.ExpressionStatement:
            self.VisitNode(node.Expression)
        elif node.Type == Syntax.AssignmentExpression:
            self.VisitAssignmentExpression(node)
        elif node.Type in (Syntax.BinaryExpression, Syntax.LogicalExpression):
            self.VisitBinaryExpression(node)
        elif node.Type == Syntax.CallExpression:
            self.VisitCallExpression(node)

    def VisitSequenceExpression(self, node):
        for item in node.Expression:
            self.VisitNode(item)

    # 函数调用
    def VisitCallExpression(self, node):
        funcName = node.Callee.Name
        args = []
        for item in node.Arguments:
            if item.Type == Syntax.BinaryExpression or item.Type == Syntax.LogicalExpression:
                value = self.VisitBinaryExpression(item)
            elif item.Type == Syntax.CallExpression:
                value = self.VisitCallExpression(item)
            else:
                value = self.GetNodeValue(item)
            args.append(value)

        # console.log('[JSExecute::VisitCallExpression]' , funcName, '(', args.toString() ,')');

        if funcName == 'DYNAINFO':  # 行情最新数据
            node.Out = self.SymbolData.GetLatestCacheData(int(args[0]))
        elif funcName == 'STICKLINE':
            node.Draw = self.Draw.STICKLINE(args[0], args[1], args[2], args[3],
                                            args[4])
            node.Out = []
        elif funcName == 'DRAWTEXT':
            node.Draw = self.Draw.DRAWTEXT(args[0], args[1], args[2])
            node.Out = []
        elif funcName == 'SUPERDRAWTEXT':
            node.Draw = self.Draw.SUPERDRAWTEXT(args[0], args[1], args[2],
                                                args[3], args[4])
            node.Out = []
        elif funcName == 'DRAWICON':
            node.Draw = self.Draw.DRAWICON(args[0], args[1], int(args[2]))
            node.Out = []
        elif funcName == 'DRAWLINE':
            node.Draw = self.Draw.DRAWLINE(args[0], args[1], args[2], args[3],
                                           int(args[4]))
            node.Out = node.Draw.DrawData
        elif funcName == 'DRAWBAND':
            node.Draw = self.Draw.DRAWBAND(args[0], args[1], args[2], args[3])
            node.Out = []
        elif funcName == 'DRAWKLINE':
            node.Draw = self.Draw.DRAWKLINE(args[0], args[1], args[2], args[3])
            node.Out = []
        elif funcName == 'DRAWKLINE_IF':
            node.Draw = self.Draw.DRAWKLINE_IF(args[0], args[1], args[2],
                                               args[3], args[4])
            node.Out = []
        elif funcName in ('PLOYLINE', 'POLYLINE'):
            node.Draw = self.Draw.POLYLINE(args[0], args[1])
            node.Out = node.Draw.DrawData
        elif funcName == 'DRAWNUMBER':
            node.Draw = self.Draw.DRAWNUMBER(args[0], args[1], args[2])
            node.Out = node.Draw.DrawData.Value
        elif funcName == "DRAWCHANNEL":
            node.Draw = self.Draw.DRAWCHANNEL(args[0],
                                              args[1], args[2], args[3],
                                              int(args[4]), args[5], args[6])
            node.Out = []
        elif funcName == 'CODELIKE':
            node.Out = self.SymbolData.CODELIKE(args[0])
        elif funcName == 'NAMELIKE':
            node.Out = self.SymbolData.NAMELIKE(args[0])
        elif funcName == 'REFDATE':
            node.Out = self.SymbolData.REFDATE(args[0], args[1])
        elif funcName == 'FINANCE':
            node.Out = self.SymbolData.GetFinanceCacheData(args[0], node)
        elif funcName == "MARGIN":
            node.Out = self.SymbolData.GetMarginCacheData(int(args[0]), node)
        elif funcName == "HK2SHSZ":
            node.Out = self.SymbolData.GetHKToSHSZCacheData(args[0], node)
        elif funcName == "NEWS":
            node.Out = self.SymbolData.GetNewsAnalysisCacheData(args[0], node)
        elif funcName in ('UPCOUNT', 'DOWNCOUNT'):
            node.Out = self.SymbolData.GetIndexIncreaseCacheData(
                funcName, args[0], node)
        else:
            node.Out = self.Algorithm.CallFunction(funcName, args, node)

        return node.Out

    # 赋值
    def VisitAssignmentExpression(self, node):
        left = node.Left
        if left.Type != Syntax.Identifier:
            self.ThrowUnexpectedNode(node)

        varName = left.Name
        right = node.Right
        value = None

        if right.Type == Syntax.BinaryExpression or right.Type == Syntax.LogicalExpression:
            value = self.VisitBinaryExpression(right)
        elif right.Type == Syntax.CallExpression:
            value = self.VisitCallExpression(right)
        elif right.Type == Syntax.Literal:
            value = right.Value
        elif right.Type == Syntax.Identifier:  # 右值是变量
            value = self.ReadVariable(right.Name, right)

        # console.log('[JSExecute::VisitAssignmentExpression]' , varName, ' = ',value);
        self.VarTable[varName] = value

    # 逻辑运算
    def VisitBinaryExpression(self, node):
        stack = []
        stack.append(node)
        temp = None

        while len(stack) != 0:
            temp = stack[-1]
            if isinstance(
                    temp,
                (BinaryExpression, AssignmentExpression
                 )) and temp.Left and node != temp.Left and node != temp.Right:
                stack.append(temp.Left)
            elif isinstance(
                    temp,
                (BinaryExpression,
                 AssignmentExpression)) and temp.Right and node != temp.Right:
                stack.append(temp.Right)
            else:
                value = stack.pop()
                if value.Type == Syntax.BinaryExpression:  # 只遍历操作符就可以
                    leftValue = self.GetNodeValue(value.Left)
                    rightValue = self.GetNodeValue(value.Right)

                    # console.log('[JSExecute::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue);
                    value.Out = None  # 保存中间值

                    if value.Operator == '-':
                        value.Out = self.Algorithm.Subtract(
                            leftValue, rightValue)
                    elif value.Operator == '*':
                        value.Out = self.Algorithm.Multiply(
                            leftValue, rightValue)
                    elif value.Operator == '/':
                        value.Out = self.Algorithm.Divide(
                            leftValue, rightValue)
                    elif value.Operator == '+':
                        value.Out = self.Algorithm.Add(leftValue, rightValue)
                    elif value.Operator == '>':
                        value.Out = self.Algorithm.GT(leftValue, rightValue)
                    elif value.Operator == '>=':
                        value.Out = self.Algorithm.GTE(leftValue, rightValue)
                    elif value.Operator == '<':
                        value.Out = self.Algorithm.LT(leftValue, rightValue)
                    elif value.Operator == '<=':
                        value.Out = self.Algorithm.LTE(leftValue, rightValue)
                    elif value.Operator in ('=', '=='):
                        value.Out = self.Algorithm.EQ(leftValue, rightValue)
                    elif value.Operator in ('!=', '<>'):
                        value.Out = self.Algorithm.NEQ(leftValue, rightValue)

                    # console.log('[JSExecute::VisitBinaryExpression] BinaryExpression',value);
                elif value.Type == Syntax.LogicalExpression:
                    leftValue = self.GetNodeValue(value.Left)
                    rightValue = self.GetNodeValue(value.Right)

                    # console.log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue);
                    value.Out = None  # 保存中间值

                    if value.Operator in ('&&', 'AND'):
                        value.Out = self.Algorithm.And(leftValue, rightValue)
                    elif value.Operator in ('||', 'OR'):
                        value.Out = self.Algorithm.Or(leftValue, rightValue)

                    # console.log('[JSExecute::VisitBinaryExpression] LogicalExpression',value);

                node = temp

        return node.Out

    def GetNodeValue(self, node):
        if node.Type == Syntax.Literal:  #数字
            return node.Value
        elif node.Type == Syntax.UnaryExpression:
            if node.Operator == '-':
                value = self.GetNodeValue(node.Argument)
                return self.Algorithm.Subtract(0, value)
            return node.Argument.Value
        elif node.Type == Syntax.Identifier:
            value = self.ReadVariable(node.Name, node)
            return value
        elif node.Type in (Syntax.BinaryExpression, Syntax.LogicalExpression):
            return node.Out
        elif node.Type == Syntax.CallExpression:
            return self.VisitCallExpression(node)
        else:
            self.ThrowUnexpectedNode(node)

    def ThrowUnexpectedNode(self, node, message="执行异常"):
        marker = node.Marker
        msg = message

        return self.ErrorHandler.ThrowError(marker.Index, marker.Line,
                                            marker.Column, msg)

    def ThrowError(self):
        pass
 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)