parser.rb
来自「Harvestman-最新版本」· RB 代码 · 共 1,205 行 · 第 1/4 页
RB
1,205 行
gotoloopContinue = catch(:gotoloop) do#loop: while true puts "Before getting TT" if ((tt = t.get) == $consts["END"]) break end puts "TT ==> " + tt.to_s # Stop only if tt matches the optional stop parameter, and that # token is not quoted by some kind of bracket. if tt == stop and x.bracketLevel == bl and x.curlyLevel == cl and x.parenLevel == pl and x.hookLevel == hl throw :gotoloop, true end case tt when $consts["SEMICOLON"] # NB: cannot be empty, Statement handled that. throw :gotoloop, true; when $consts["ASSIGN"], $consts["HOOK"], $consts["COLON"] if t.scanOperand throw :gotoloop, true end # Use >, not >=, for right-associative ASSIGN and HOOK/COLON. while operators.length > 0 && $opPrecedence[operators.last.type] && $opPrecedence[operators.last.type] > $opPrecedence[tt] reduce(operators, operands, t) end if tt == $consts["COLON"] n = operators.last raise SyntaxError.new("Invalid label", t) if n.type != $consts["HOOK"] n.type = $consts["CONDITIONAL"] x.hookLevel -= 1 else operators.push(Node.new(t)) if tt == $consts["ASSIGN"] operands.last.assignOp = t.token.assignOp else x.hookLevel += 1 # tt == HOOK end end t.scanOperand = true when $consts["COMMA"], # Treat comma as left-associative so reduce can fold left-heavy # COMMA trees into a single array. $consts["OR"], $consts["AND"], $consts["BITWISE_OR"], $consts["BITWISE_XOR"], $consts["BITWISE_AND"], $consts["EQ"], $consts["NE"], $consts["STRICT_EQ"], $consts["STRICT_NE"], $consts["LT"], $consts["LE"], $consts["GE"], $consts["GT"], $consts["INSTANCEOF"], $consts["LSH"], $consts["RSH"], $consts["URSH"], $consts["PLUS"], $consts["MINUS"], $consts["MUL"], $consts["DIV"], $consts["MOD"], $consts["DOT"], $consts["IN"] # An in operator should not be parsed if we're parsing the head of # a for (...) loop, unless it is in the then part of a conditional # expression, or parenthesized somehow. if tt == $consts["IN"] and x.inForLoopInit and x.hookLevel == 0 and x.bracketLevel == 0 and x.curlyLevel == 0 and x.parenLevel == 0 throw :gotoloop, true end if t.scanOperand throw :gotoloop, true end reduce(operators, operands, t) while operators.length > 0 && $opPrecedence[operators.last.type] && $opPrecedence[operators.last.type] >= $opPrecedence[tt] if tt == $consts["DOT"] t.mustMatch($consts["IDENTIFIER"]) node = Node.new(t, $consts["DOT"]) node.push(operands.pop) node.push(Node.new(t)) operands.push(node) else operators.push(Node.new(t)) t.scanOperand = true end when $consts["DELETE"], $consts["VOID"], $consts["TYPEOF"], $consts["NOT"], $consts["BITWISE_NOT"], $consts["UNARY_PLUS"], $consts["UNARY_MINUS"], $consts["NEW"] if !t.scanOperand throw :gotoloop, true end operators.push(Node.new(t)) when $consts["INCREMENT"], $consts["DECREMENT"] if t.scanOperand operators.push(Node.new(t)) # prefix increment or decrement else # Use >, not >=, so postfix has higher precedence than prefix. reduce(operators, operands, t) while operators.length > 0 && $opPrecedence[operators.last.type] && $opPrecedence[operators.last.type] > $opPrecedence[tt] n = Node.new(t, tt) n.push(operands.pop) n.postfix = true operands.push(n) end when $consts["FUNCTION"] if !t.scanOperand throw :gotoloop, true end # puts "EXPRESSED FORM=> " + $consts["EXPRESSED_FORM"] operands.push(FunctionDefinition(t, x, false, $consts["EXPRESSED_FORM"])) t.scanOperand = false when $consts["NULL"], $consts["THIS"], $consts["TRUE"], $consts["FALSE"], $consts["IDENTIFIER"], $consts["NUMBER"], $consts["STRING"], $consts["REGEXP"] if !t.scanOperand puts "THrowing" throw :gotoloop, true end puts "No throw" operands.push(Node.new(t)) t.scanOperand = false when $consts["LEFT_BRACKET"] if t.scanOperand # Array initialiser. Parse using recursive descent, as the # sub-grammar here is not an operator grammar. n = Node.new(t, $consts["ARRAY_INIT"]) while (tt = t.peek) != $consts["RIGHT_BRACKET"] if tt == $consts["COMMA"] t.get n.push(nil) next end n.push(Expression(t, x, $consts["COMMA"])) break if !t.match($consts["COMMA"]) end t.mustMatch($consts["RIGHT_BRACKET"]) operands.push(n) t.scanOperand = false else # Property indexing operator. operators.push(Node.new(t, $consts["INDEX"])) t.scanOperand = true x.bracketLevel += 1 end when $consts["RIGHT_BRACKET"] if t.scanOperand or x.bracketLevel == bl throw :gotoloop, true end while reduce(operators, operands, t).type != $consts["INDEX"] nil end x.bracketLevel -= 1 when $consts["LEFT_CURLY"] if !t.scanOperand throw :gotoloop, true end # Object initialiser. As for array initialisers (see above), # parse using recursive descent. x.curlyLevel += 1 n = Node.new(t, $consts["OBJECT_INIT"])catch(:gotoobject_init) do#object_init: if !t.match($consts["RIGHT_CURLY"]) begin tt = t.get if (t.token.value == "get" or t.token.value == "set") and t.peek == $consts["IDENTIFIER"] raise SyntaxError.new("Illegal property accessor", t) if x.ecmaStrictMode n.push(FunctionDefinition(t, x, true, $consts["EXPRESSED_FORM"])) else case tt when $consts["IDENTIFIER"], $consts["NUMBER"], $consts["STRING"] id = Node.new(t) when $consts["RIGHT_CURLY"] raise SyntaxError.new("Illegal trailing ,", t) if x.ecmaStrictMode throw :gotoobject_init else raise SyntaxError.new("Invalid property name", t) end t.mustMatch($consts["COLON"]) n2 = Node.new(t, $consts["PROPERTY_INIT"]) n2.push(id) n2.push(Expression(t, x, $consts["COMMA"])) n.push(n2) end end while t.match($consts["COMMA"]) t.mustMatch($consts["RIGHT_CURLY"]) end operands.push(n) t.scanOperand = false x.curlyLevel -= 1end when $consts["RIGHT_CURLY"] raise SyntaxError.new("PANIC: right curly botch", t) if !t.scanOperand and x.curlyLevel != cl throw :gotoloop, true when $consts["LEFT_PAREN"] if t.scanOperand operators.push(Node.new(t, $consts["GROUP"])) else reduce(operators, operands, t) while operators.length > 0 && $opPrecedence[operators.last.type] && $opPrecedence[operators.last.type] > $opPrecedence[$consts["NEW"]] # Handle () now, to regularize the n-ary case for n > 0. # We must set scanOperand in case there are arguments and # the first one is a regexp or unary+/-. n = operators.last puts n.to_s + " " + n.type.to_s + " " + $consts["NEW"].to_s t.scanOperand = true puts "I WENT HERE" if t.match($consts["RIGHT_PAREN"]) if n && n.type == $consts["NEW"] puts "INSIDE" operators.pop n.push(operands.pop) puts "AFTER*" else puts "OUTSIDE" n = Node.new(t, $consts["CALL"]) n.push(operands.pop) n.push(Node.new(t, $consts["LIST"])) end puts "AFTER2*" operands.push(n) t.scanOperand = false #puts "woah" puts "BEFOREBREAK" break end if n && n.type == $consts["NEW"] n.type = $consts["NEW_WITH_ARGS"] else operators.push(Node.new(t, $consts["CALL"])) end end x.parenLevel += 1 when $consts["RIGHT_PAREN"] if t.scanOperand or x.parenLevel == pl throw :gotoloop, true end #while (tt = reduce(operators, operands, t).type) != $consts["GROUP"] \ # and tt != $consts["CALL"] and tt != $consts["NEW_WITH_ARGS"] # nil #end while true puts "Operators => " + operators.length.to_s + " " + operands.length.to_s tt = reduce(operators, operands, t) puts "TT=> " + tt.to_s + " " + tt.type.to_s if tt.type == $consts["GROUP"] or tt.type == $consts["CALL"] or tt.type == $consts["NEW_WITH_ARGS"] puts "Breaking..." break end end if tt != $consts["GROUP"] n = operands.last if n[1].type != $consts["COMMA"] n2 = n[1] n[1] = Node.new(t, $consts["LIST"]) n[1].push(n2) else n[1].type = $consts["LIST"] end end x.parenLevel -= 1 # Automatic semicolon insertion means we may scan across a newline # and into the beginning of another statement. If so, break out of # the while loop and let the t.scanOperand logic handle errors. else throw :gotoloop, true end endendend raise SyntaxError.new("Missing : after ?", t) if x.hookLevel != hl raise SyntaxError.new("Missing operand", t) if t.scanOperand # Resume default mode, scanning for operands, not operators. t.scanOperand = true puts "Ungetting" puts t.unget reduce(operators, operands, t) while operators.length > 0 return operands.popenddef parse (source, filename, line = 1) t = Tokenizer.new(source, filename, line) x = CompilerContext.new(false) n = Script(t, x) raise SyntaxError.new("Syntax error", t) if !t.done return nend
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?