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 + -
显示快捷键?