parser.rb

来自「Harvestman-最新版本」· RB 代码 · 共 1,205 行 · 第 1/4 页

RB
1,205
字号
                                        when $consts["DEFAULT"], $consts["CASE"]                                                if tt == $consts["DEFAULT"] and n.defaultIndex >= 0                                                        raise SyntaxError.new("More than one switch default", t)                                                end                                                n2 = Node.new(t)                                                if tt == $consts["DEFAULT"]                                                        n.defaultIndex = n.cases.length                                                else                                                        n2.caseLabel = Expression(t, x, $consts["COLON"])                                                end                                                                                else                                                raise SyntaxError.new("Invalid switch case", t)                                end                                t.mustMatch($consts["COLON"])                                n2.statements = Node.new(t, $consts["BLOCK"])                                while (tt = t.peek) != $consts["CASE"] and tt != $consts["DEFAULT"] and tt != $consts["RIGHT_CURLY"]                                        n2.statements.push(Statement(t, x))                                end                                n.cases.push(n2)                        end                        x.stmtStack.pop                        return n                                when $consts["FOR"]                        n = Node.new(t)                        n.isLoop = true                        t.mustMatch($consts["LEFT_PAREN"])                        if (tt = t.peek) != $consts["SEMICOLON"]                                x.inForLoopInit = true                                if tt == $consts["VAR"] or tt == $consts["CONST"]                                        t.get                                        n2 = Variables(t, x)                                else                                        n2 = Expression(t, x)                                end                                x.inForLoopInit = false                        end                        if n2 and t.match($consts["IN"])                                n.type = $consts["FOR_IN"]                                if n2.type == $consts["VAR"]                                        if n2.length != 1                                                raise SyntaxError.new("Invalid for..in left-hand side", t)                                        end                                        # NB: n2[0].type == IDENTIFIER and n2[0].value == n2[0].name.                                        n.iterator = n2[0]                                        n.varDecl = n2                                else                                        n.iterator = n2                                        n.varDecl = nil                                end                                n.object = Expression(t, x)                        else                                n.setup = n2 or nil                                t.mustMatch($consts["SEMICOLON"])                                n.condition = (t.peek == $consts["SEMICOLON"]) ? nil : Expression(t, x)                                t.mustMatch($consts["SEMICOLON"])                                n.update = (t.peek == $consts["RIGHT_PAREN"]) ? nil : Expression(t, x)                        end                        t.mustMatch($consts["RIGHT_PAREN"])                        n.body = nest(t, x, n)                        return n                                when $consts["WHILE"]                        n = Node.new(t)                        n.isLoop = true                        n.condition = ParenExpression(t, x)                        n.body = nest(t, x, n)                        return n                                when $consts["DO"]                        n = Node.new(t)                        n.isLoop = true                        n.body = nest(t, x, n, $consts["WHILE"])                        n.condition = ParenExpression(t, x)                        if !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                        end                                when $consts["BREAK"], $consts["CONTINUE"]                        n = Node.new(t)                        if t.peekOnSameLine == $consts["IDENTIFIER"]                                t.get                                n.label = t.token.value                        end                        ss = x.stmtStack                        i = ss.length                        label = n.label                        if label                                begin                                        i -= 1                                        raise SyntaxError.new("Label not found", t) if i < 0                                end while (ss[i].label != label)                        else                                begin                                        i -= 1                                        raise SyntaxError.new("Invalid " + ((tt == $consts["BREAK"]) and "break" or "continue"), t) if i < 0                                end while !ss[i].isLoop and (tt != $consts["BREAK"] or ss[i].type != $consts["SWITCH"])                        end                        n.target = ss[i]                                when $consts["TRY"]                        n = Node.new(t)                        n.tryBlock = Block(t, x)                        n.catchClauses = []                        while t.match($consts["CATCH"])                                n2 = Node.new(t)                                t.mustMatch($consts["LEFT_PAREN"])                                n2.varName = t.mustMatch($consts["IDENTIFIER"]).value                                if t.match($consts["IF"])                                        raise SyntaxError.new("Illegal catch guard", t) if x.ecmaStrictMode                                        if n.catchClauses.length and !n.catchClauses.last.guard                                                raise SyntaxError.new("Guarded catch after unguarded", t)                                        end                                        n2.guard = Expression(t, x)                                else                                        n2.guard = nil                                end                                t.mustMatch($consts["RIGHT_PAREN"])                                n2.block = Block(t, x)                                n.catchClauses.push(n2)                        end                        n.finallyBlock = Block(t, x) if t.match($consts["FINALLY"])                        if !n.catchClauses.length and !n.finallyBlock                                raise SyntaxError.new("Invalid try statement", t)                        end                        return n                                when $consts["CATCH"]                when $consts["FINALLY"]                        raise SyntaxError.new(tokens[tt] + " without preceding try", t)                                when $consts["THROW"]                        n = Node.new(t)                        n.exception = Expression(t, x)                                when $consts["RETURN"]                        puts "In Return"                        raise SyntaxError.new("Invalid return", t) unless x.inFunction                        n = Node.new(t)                        tt = t.peekOnSameLine                        if tt != $consts["END"] and tt != $consts["NEWLINE"] and tt != $consts["SEMICOLON"] and tt != $consts["RIGHT_CURLY"]                                n.value = Expression(t, x)                                puts "Val => " + n.value.to_s                        end                                when $consts["WITH"]                        n = Node.new(t)                        n.object = ParenExpression(t, x)                        n.body = nest(t, x, n)                        return n                                when $consts["VAR"], $consts["CONST"]                        n = Variables(t, x)                                when $consts["DEBUGGER"]                        n = Node.new(t)                        when $consts["NEWLINE"], $consts["SEMICOLON"]                        n = Node.new(t, $consts["SEMICOLON"])                        n.expression = nil                        return n                else                        if tt == $consts["IDENTIFIER"] and t.peek == $consts["COLON"]                                label = t.token.value                                ss = x.stmtStack                                (ss.length - 1).times do |i|                                        raise SyntaxError.new("Duplicate label", t) if ss[i].label == label                                end                                t.get                                n = Node.new(t, $consts["LABEL"])                                n.label = label                                n.statement = nest(t, x, n)                                return n                        end                        t.unget                        n = Node.new(t, $consts["SEMICOLON"])                        n.expression = Expression(t, x)                        n.end = n.expression.end        end        if t.lineno == t.token.lineno                tt = t.peekOnSameLine                puts "TT*=> " + tt.to_s                if tt != $consts["END"] and tt != $consts["NEWLINE"] and tt != $consts["SEMICOLON"] and tt != $consts["RIGHT_CURLY"]                        raise SyntaxError.new("Missing ; before statement", t)                end        end        t.match($consts["SEMICOLON"])        return nenddef FunctionDefinition (t, x, requireName, functionForm)        f = Node.new(t)        if f.type != $consts["FUNCTION"]                f.type = (f.value == "get") and $consts["GETTER"] or $consts["SETTER"]        end        if t.match($consts["IDENTIFIER"])                f.name = t.token.value        elsif requireName                raise SyntaxError.new("Missing function identifier", t)        end        t.mustMatch($consts["LEFT_PAREN"])        f.params = []        while (tt = t.get) != $consts["RIGHT_PAREN"]                raise SyntaxError.new("Missing formal parameter", t) unless tt == $consts["IDENTIFIER"]                f.params.push(t.token.value)                t.mustMatch($consts["COMMA"]) unless t.peek == $consts["RIGHT_PAREN"]        end                t.mustMatch($consts["LEFT_CURLY"])        x2 = CompilerContext.new(true)        f.body = Script(t, x2)        t.mustMatch($consts["RIGHT_CURLY"])        f.end = t.token.end        f.functionForm = functionForm        x.funDecls.push(f) if functionForm == $consts["DECLARED_FORM"]        return fenddef Variables (t, x)        n = Node.new(t)        begin                t.mustMatch($consts["IDENTIFIER"])                n2 = Node.new(t)                n2.name = n2.value                if t.match($consts["ASSIGN"])                        raise SyntaxError.new("Invalid variable initialization", t) if t.token.assignOp                        n2.initializer = Expression(t, x, $consts["COMMA"])                end                n2.readOnly = (n.type == $consts["CONST"])                n.push(n2)                x.varDecls.push(n2)        end while t.match($consts["COMMA"])        return nenddef ParenExpression (t, x)        t.mustMatch($consts["LEFT_PAREN"])        n = Expression(t, x)        t.mustMatch($consts["RIGHT_PAREN"])        return nenddef Expression(t, x, stop = nil)        operators = []        operands = []        bl = x.bracketLevel        cl = x.curlyLevel        pl = x.parenLevel        hl = x.hookLevel                def reduce(operators, operands, t)                #  puts "Operators length => " + operators.length.to_s                n = operators.pop                puts "N => " + n.to_s                op = n.type                arity = $opArity[op]                puts "Arity=> " + arity.to_s                if arity == -2                        if operands.length >= 2                                # Flatten left-associative trees.                                left = operands[operands.length - 2]                                puts "Left=> " + left.to_s                                if left.type == op                                        puts "Dude!"                                        right = operands.pop                                        left.push(right)                                        return left                                end                        end                        arity = 2                end                                # Always use push to add operands to n, to update start and end.                a = operands.slice!(operands.length - arity, operands.length)                arity.times do |i|                        n.push(a[i])                end                                # Include closing bracket or postfix operator in [start,end).                n.end = t.token.end if n.end < t.token.end                                operands.push(n)                return n        endgotoloopContinue = falseuntil gotoloopContinue or (t.token and t.token.type == $consts["END"])

⌨️ 快捷键说明

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