⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 narcissus.py

📁 Harvestman-最新版本
💻 PY
📖 第 1 页 / 共 3 页
字号:
        print 'Advancing cursor by',len(match.group(0)) + cursor_advance
        self.cursor += len(match.group(0)) + cursor_advance
#         # print self.cursor
        token.end = self.cursor
#         # print token.end
        token.lineno = self.lineno
#         # print token.lineno

        print 'Returning',token.type
        return token.type

    def unget(self):

        self.lookahead += 1
        if self.lookahead == 4:
            raise NarcissusError("PANIC: too much lookahead!", self)
        self.tokenIndex = (self.tokenIndex - 1) & 3
        return None

class NarcissusError(Exception):

    def __init__(self, msg, tokenizer):
        self.msg = msg
        self.line = str(tokenizer.lineno)

    def __str__(self):
        return '\n'.join((self.msg, "on line " + self.line))


class Token(object):

    __slots__ = ['type','value','start','end','assignOp','lineno']
    
    def __init__(self):
        self.type = None
        self.value = None
        self.start = None
        self.end = None
        self.assignOp = None
        self.lineno = None

    def lower(self):
        return self.value.lower()
    
class CompilerContext(object):

    __slots__ = ['inFunction', 'stmtStack','funDecls','varDecls',
                 'bracketLevel','curlyLevel','parenLevel','hookLevel',
                 'ecmaStrictMode','inForLoopInit']

    def __init__(self, inFunction):
        self.inFunction = inFunction
        self.stmtStack = []
        self.funDecls = []
        self.varDecls = []

        self.bracketLevel = self.curlyLevel = self.parenLevel = self.hookLevel = 0
        self.ecmaStrictMode = self.inForLoopInit = False


CURSOR = 0
IND = 0

# class Node => TODO
class Node(list):

    __slots__ =  ['type','value','lineno','start','end','tokenizer','initializer',
                  'name','params','funDecls','varDecls', 'body', 'functionForm',
                  'assignOp', 'expression', 'condition', 'thenPart', 'elsePart',
                  'readOnly', 'isLoop', 'setup', 'postfix', 'update', 'exception',
                  'object', 'iterator', 'varDecl', 'label', 'target', 'tryBlock',
                  'catchClauses', 'varName', 'guard', 'block', 'discriminant', 'cases',
                  'defaultIndex', 'caseLabel', 'statements', 'statement','children']
    
    def __init__(self, t, type=None):
        # Blanket initialize all params
        for var in self.__class__.__slots__:
            setattr(self, var, None)
            
        token = t.token()
#         # print 'token=>',token
        if token:
            if type:
                self.type = type
            else:
                self.type = token.type
            self.value = token.value
            self.lineno = token.lineno
            self.start = token.start
            self.end = token.end
        else:
            self.type = type
            self.lineno = t.lineno

        # T is the Tokenizer instance
        self.tokenizer = t

    # Always use push$ to add operands to an expression, to update start and end.
    def append(self, kid):
        # print "Pushing...", kid.__class__, kid.type
        if kid.start and self.start:
            if kid.start < self.start:
                self.start = kid.start

        if kid.end and self.end:
            if self.end < kid.end:
                self.end = kid.end

        return super(Node, self).append(kid)

    push = append
    def __str__(self):

        s = ''
        attrs = [self.value, self.lineno, self.start, self.end,
                 self.name, self.params, self.funDecls, self.varDecls,
                 self.body, self.functionForm, self.assignOp, self.expression,
                 self.condition, self.thenPart, self.elsePart ]

        global IND
        IND += 1

        for x in range(len(self)):
            item = self[x]
            if item != self and isinstance(item, Node):
                s = s + str(item)

        for x in range(len(attrs)):
            # Some commented out code here, not adding it
            item = attrs[x]
            if isinstance(item, Node):
                s = s + str(item)

        IND -= 1
        if IND == 0:
             print self.tokenizer.source[CURSOR:],

        return ""
            
    def getSource(self):
        return self.tokenizer.source[self.start:self.start+self.end]
    
    def filename(self):
        return self.tokenizer.filename
        

def Script(t, x):
    n = Statements(t, x)
    n.type = consts["SCRIPT"]
    n.funDecls = x.funDecls
    n.varDecls = x.varDecls

    return n

# Statement stack and nested statement handler.
# nb. Narcissus allowed a function reference, here we use Statement explicitly
def nest(t, x, node, end_ = None):
    x.stmtStack.append(node)
    n = Statement(t, x)
    x.stmtStack.pop()
    if end_:
        t.mustMatch(end_)
    return n

def Statements(t, x):

    n = Node(t, consts["BLOCK"])
    x.stmtStack.append(n)

    while (not t.done()) and (t.peek() != consts["RIGHT_CURLY"]):
        # print 'Loop'
#         # print 'Starting to push'
        s = Statement(t, x)
        # print 'Type =>',s.type
        n.push(s)
#         # print "Push ended"
        
    x.stmtStack.pop()
    return n

def Block(t, x):
    t.mustMatch(consts["LEFT_CURLY"])
    n = Statements(t, x)
    t.mustMatch(consts["RIGHT_CURLY"])
    return n

DECLARED_FORM = 0
EXPRESSED_FORM = 1
STATEMENT_FORM = 2

def Statement(t, x):
    # Cases for statements ending in a right curly return early, avoiding the
    # common semicolon insertion magic after this switch.

    # t is an instance of Tokenizer
    tt = t.get()
    print 'TT is',tt
    if tt == consts["FUNCTION"]:
        print 'TT is a function', consts["FUNCTION"]
        return FunctionDefinition(t, x, True, 
                                  (len(x.stmtStack) > 1) and STATEMENT_FORM or DECLARED_FORM)
    elif tt == consts["LEFT_CURLY"]:
        n = Statements(t, x)
        t.mustMatch(consts["RIGHT_CURLY"])
        return n
                
    elif tt == consts["IF"]:
        n = Node(t)
        n.condition = ParenExpression(t, x)
        x.stmtStack.append(n)
        n.thenPart = Statement(t, x)
        if t.match(consts["ELSE"]):
            n.elsePart = Statement(t, x)
        else:
            n.elsePart = None
            
        x.stmtStack.pop()
        return n

    elif tt == consts["SWITCH"]:
        n = Node(t)
        t.mustMatch(consts["LEFT_PAREN"])
        n.discriminant = Expression(t, x)
        t.mustMatch(consts["RIGHT_PAREN"])
        n.cases = []
        n.defaultIndex = -1
        x.stmtStack.append(n)
        t.mustMatch(consts["LEFT_CURLY"])
        
        while True:
            tt = t.get()
            print 'TT IS',tt
            if tt == consts["RIGHT_CURLY"]: break
            if tt == consts["DEFAULT"] or tt == consts["CASE"]:
                if tt == consts["DEFAULT"] and n.defaultIndex >= 0:
                    raise NarcissusError("More than one switch default", t)

                n2 = Node(t)
                if tt == consts["DEFAULT"]:
                    n.defaultIndex = len(n.cases)
                else:
                    n2.caseLabel = Expression(t, x, consts["COLON"])

                                        
            else:
                raise NarcissusError("Invalid switch case", t)

            t.mustMatch(consts["COLON"])
            n2.statements = Node(t, consts["BLOCK"])

            while True:
                tt = t.peek()
                if (tt == consts["CASE"]) or \
                    (tt==consts["DEFAULT"]) or \
                    (tt==consts["RIGHT_CURLY"]):
                    break

                print 'Yeah dude!'
                n2.statements.append(Statement(t, x))

            n.cases.append(n2)
            # End of while...
            
        x.stmtStack.pop()
        return n

    elif tt == consts["FOR"]:
        n = Node(t)
        n.isLoop = True

        n2 = None
        
        t.mustMatch(consts["LEFT_PAREN"])
        tt = t.peek()
        if tt != consts["SEMICOLON"]:
            x.inForLoopInit = True
            if tt == consts["VAR"] or tt == consts["CONST"]:
                print 'Got',t.get()
                n2 = Variables(t, x)
            else:
                n2 = Expression(t, x)

            x.inForLoopInit = False

        if n2 and t.match(consts["IN"]):
            n.type = consts["FOR_IN"]
            if n2.type == consts["VAR"]:
                if len(n2) != 1:
                    raise NarcissusError("Invalid for..in left-hand side", t)

                n.iterator = n2[0]
                n.varDecl = n2
            else:
                n.iterator = n2
                n.varDecl = None

            n.object = Expression(t, x)
        else:
            n.setup = n2 or None
            t.mustMatch(consts["SEMICOLON"])
            if (t.peek() == consts["SEMICOLON"]):
                n.condition = None
            else:
                n.condition = Expression(t, x)
            t.mustMatch(consts["SEMICOLON"])
            if (t.peek() == consts["RIGHT_PAREN"]):
                n.update = None
            else:
                n.update = Expression(t, x)

        t.mustMatch(consts["RIGHT_PAREN"])
        n.body = nest(t, x, n)
        return n

    elif tt == consts["WHILE"]:
        n = Node(t)
        n.isLoop = True
        n.condition = ParenExpression(t, x)
        n.body = nest(t, x, n)
        return n

    elif tt == consts["DO"]:
        n = Node(t)
        n.isLoop = True
        n.body = nest(t, x, n, consts["WHILE"])
        n.condition = ParenExpression(t, x)
        if not x.ecmaStrictMode:
            # <script language="JavaScript"> (without version hints) may need
            # automatic semicolon insertion without a newline after do-while.
            # See http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
            t.match(consts["SEMICOLON"])
            return n
        
    elif (tt == consts["BREAK"]) or (tt == consts["CONTINUE"]):
        n = Node(t)
        if t.peekOnSameLine() == consts["IDENTIFIER"]:
            print 'Gewt',t.get()
            n.label = t.token().value

        ss = x.stmtStack
        i = len(ss)

        label = n.label
        if label:
            while True:
                i -= 1
                if i < 0:
                    raise NarcissusError("Label not found", t)
                if (ss[i].label != label): break
                
        else:
            while True:
                i -= 1

                if i<0:
                    if tt == consts["BREAK"]:
                        raise NarcissusError("Invalid break", t)
                    else:
                        raise NarcissusError("Invalid continue", t)

                if ss[i].isLoop or (tt==consts["BREAK"] and ss[i].type == consts["SWITCH"]):
                    break

        n.target = ss[i]        

    elif tt == consts["TRY"]:
        n = Node(t)
        n.tryBlock = Block(t, x)
        n.catchClauses = List2()

        while t.match(consts["CATCH"]):
            n2 = Node(t)
            t.mustMatch(consts["LEFT_PAREN"])
            n2.varName = t.mustMatch(consts["IDENTIFIER"]).value
            if t.match(consts["IF"]):
                if x.ecmaStrictMode:                
                    raise NarcissusError("Illegal catch guard", t)
                if len(n.catchClauses) and (not n.catchClauses.last().guard):
                    raise NarcissusError("Guarded catch after unguarded", t)
                n2.guard = Expression(t, x)
            else:
                n2.guard = None

            t.mustMatch(consts["RIGHT_PAREN"])
            n2.block = Block(t, x)
            n.catchClauses.append(n2)

        if t.match(consts["FINALLY"]):
            n.finallyBlock = Block(t, x) 
        if (not len(n.catchClauses)) and (not n.finallyBlock):
            raise NarcissusError("Invalid try statement", t)
        
        return n

    elif tt == consts["CATCH"]:
        pass
    elif tt == consts["FINALLY"]:
        raise NarcissusError(str(tokens[tt]) + " without preceding try", t)
    elif tt == consts["THROW"]:
        n = Node(t)
        n.exception = Expression(t, x)
    elif tt == consts["RETURN"]:
        print 'In Return'
        if not x.inFunction:
            raise NarcissusError("Invalid return", t)
        n = Node(t)
        tt = t.peekOnSameLine()
        if (tt != consts["END"]) and \
           (tt != consts["NEWLINE"]) and \
           (tt != consts["SEMICOLON"]) and \
           (tt != consts["RIGHT_CURLY"]):
            print 'Okay!'
            n.value = Expression(t, x)
            print "Val => " + str(n.value)

    elif tt == consts["WITH"]:
        n = Node(t)
        n.object = ParenExpression(t, x)
        n.body = nest(t, x, n)
        return n
            
    elif (tt == consts["VAR"]) or (tt==consts["CONST"]):
        n = Variables(t, x)

    elif tt == consts["DEBUGGER"]:
        n = Node(t)

    elif (tt==consts["NEWLINE"]) or (tt==consts["SEMICOLON"]):
        print 'out here'
        n = Node(t, consts["SEMICOLON"])
        n.expression = None
        return n

    else:
#         # print 'out there'
        if (tt==consts["IDENTIFIER"]) and (t.peek() == consts["COLON"]):
            label = t.token().value
            ss = x.stmtStack
            for x in range(len(ss)-1):
                if ss[i].label == label:
                    raise NarcissusError("Duplicate label", t)

            print 'GAWT',t.get()
            n = Node(t, consts["LABEL"])
            n.label = label
            n.statement = nest(t, x, n)
            return n

        t.unget()
        n = Node(t, consts["SEMICOLON"])
        n.expression = Expression(t, x)
        n.end = n.expression.end


    if t.lineno == t.token().lineno:
        tt = t.peekOnSameLine()
        print 'TT*=>',tt

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -