parser.rb

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

RB
1,205
字号
                                @tokenIndex = (@tokenIndex + 1) & 3                token = @tokens[@tokenIndex]                (@tokens[@tokenIndex] = token = Token.new) unless token                if input.length == 0                        #puts "end!!!"                        return (token.type = $consts["END"])                end                cursor_advance = 0                if (match = $fpRegExp.match(input))                        puts "Matched here1"                                    token.type = $consts["NUMBER"]                        token.value = match[0].to_f                elsif (match = /\A0[xX][\da-fA-F]+|\A0[0-7]*|\A\d+/.match(input))                        puts "Matched here2"                                    token.type = $consts["NUMBER"]                        token.value = match[0].to_i                elsif (match = /\A(\w|\$)+/.match(input))                        puts "MATCH: Matched here3 " + input                        id = match[0]                        token.type = $keywords[id] || $consts["IDENTIFIER"]                        token.value = id                elsif (match = /\A"(?:\\.|[^"])*"|\A'(?:[^']|\\.)*'/.match(input))                        puts "Matched here4"                                    token.type = $consts["STRING"]                        token.value = match[0].to_s                elsif @scanOperand and (match = /\A\/((?:\\.|[^\/])+)\/([gi]*)/.match(input))                        puts "Matched here5"                                    token.type = $consts["REGEXP"]                        token.value = Regexp.new(match[1] ) #, match[2])                elsif (match = $opRegExp.match(input))                        puts "Matched here6 " + input                                    op = match[0]                        if $assignOpsHash[op] && input[op.length, 1] == '='                                puts "Token type is ASSIGN"                                token.type = $consts["ASSIGN"]                                token.assignOp = $consts[$opTypeNames[op]]                                cursor_advance = 1 # length of '='                        else                                puts "TOKEN TYPE NOT ASSIGN"                                #puts $consts[$opTypeNames[op]].to_s + " " + $opTypeNames[op] + " " + op                                token.type = $consts[$opTypeNames[op]]                                puts token.type.to_s + " " + self.scanOperand.to_s + " " + $consts["MINUS"].to_s                                if @scanOperand and (token.type == $consts["PLUS"] || token.type == $consts["MINUS"])                                        puts "Adding to token type!"                                        token.type += $consts["UNARY_PLUS"] - $consts["PLUS"]                                end                                token.assignOp = nil                        end                        token.value = op                else                        raise SyntaxError.new("Illegal token", self)                end                token.start = @cursor                puts "Group0 => " + match[0]                puts 'Advancing cursor by ' + (match[0].length + cursor_advance).to_s                @cursor += match[0].length + cursor_advance                token.end = @cursor                token.lineno = @lineno                                puts "Returning " + token.type.to_s                return token.type        end        def unget                #puts "start: lookahead: " + @lookahead.to_s + " tokenIndex: " + @tokenIndex.to_s                @lookahead += 1                raise SyntaxError.new("PANIC: too much lookahead!", self) if @lookahead == 4                @tokenIndex = (@tokenIndex - 1) & 3                #puts "end:   lookahead: " + @lookahead.to_s + " tokenIndex: " + @tokenIndex.to_s                return nil        endendclass SyntaxError        def initialize (msg, tokenizer)                puts msg                puts "on line " + tokenizer.lineno.to_s        endendclass Token        attr_accessor :type, :value, :start, :end, :lineno, :assignOpendclass CompilerContext        attr_accessor :inFunction, :stmtStack, :funDecls, :varDecls        attr_accessor :bracketLevel, :curlyLevel, :parenLevel, :hookLevel        attr_accessor :ecmaStrictMode, :inForLoopInit        def initialize (inFunction)                @inFunction = inFunction                @stmtStack = []                @funDecls = []                @varDecls = []                                @bracketLevel = @curlyLevel = @parenLevel = @hookLevel = 0                @ecmaStrictMode = @inForLoopInit = false        endendclass Node < Array        attr_accessor :type, :value, :lineno, :start, :end, :tokenizer, :initializer        attr_accessor :name, :params, :funDecls, :varDecls, :body, :functionForm        attr_accessor :assignOp, :expression, :condition, :thenPart, :elsePart        attr_accessor :readOnly, :isLoop, :setup, :postfix, :update, :exception        attr_accessor :object, :iterator, :varDecl, :label, :target, :tryBlock        attr_accessor :catchClauses, :varName, :guard, :block, :discriminant, :cases        attr_accessor :defaultIndex, :caseLabel, :statements, :statement        def initialize (t, type = nil)                token = t.token                if token                        if type != nil                                @type = type                        else                                @type = token.type                        end                        @value = token.value                        @lineno = token.lineno                        @start = token.start                        @end = token.end                else                        @type = type                        @lineno = t.lineno                end                @tokenizer = t                #for (var i = 2; i < arguments.length; i++)                #this.push(arguments[i]);        end        alias superPush push        # Always use push to add operands to an expression, to update start and end.        def push (kid)                if kid.start and @start                        @start = kid.start if kid.start < @start                end                if kid.end and @end                        @end = kid.end if @end < kid.end                end                return superPush(kid)        end#       def to_s#               a = []#               #               #for (var i in this) {#               #       if (this.hasOwnProperty(i) && i != 'type')#               #               a.push({id: i, value: this[i]});#               #}#               #a.sort(function (a,b) { return (a.id < b.id) ? -1 : 1; });#               iNDENTATION = "    "#               n = (Node.indentLevel += 1)#               t = $tokens[@type]#               s = "{\n" + iNDENTATION.repeat(n) +#                               "type: " + (/^\W/.test(t) and opTypeNames[t] or t.upcase)#               #for (i = 0; i < a.length; i++)#               #       s += ",\n" + INDENTATION.repeat(n) + a[i].id + ": " + a[i].value#                       s += ",\n" + iNDENTATION.repeat(n) + @value + ": " + a[i].value#               n = (Node.indentLevel -= 1)#               s += "\n" + iNDENTATION.repeat(n) + "}"#               return s#       end        def to_s                        attrs = [@value,                        @lineno, @start, @end,                        @name, @params, @funDecls, @varDecls, @body, @functionForm,                        @assignOp, @expression, @condition, @thenPart, @elsePart]                                #puts $tokens[@condition.type] if @condition != nil                                #if /\A[a-z]/ =~ $tokens[@type] # identifier                #       print @tokenizer.source.slice($cursor, @start - $cursor) if $cursor < @start                #       print '<span class="identifier">'                #       print @tokenizer.source.slice(@start, $tokens[@type].length)                #       print '</span>'                #       $cursor = @start + $tokens[@type].length                #end                                #puts (" " * $ind) + "{" + $tokens[@type] + "\n" if /\A[a-z]/ =~ $tokens[@type]                #puts (" " * $ind) + " " + @start.to_s + "-" + @end.to_s + "\n"                $ind += 1                #puts @value                self.length.times do |i|                        self[i].to_s if self[i] != self and self[i].class == Node                end                attrs.length.times do |attr|                        if $tokens[@type] == "if"                        #       puts $tokens[attrs[attr].type] if attrs[attr].class == Node and attrs[attr] !== self                        end                        attrs[attr].to_s if attrs[attr].class == Node #and attrs[attr] != self                        #puts (" " * $ind).to_s + attrs[attr].to_s if attrs[attr].to_s != nil and attrs[attr] != self                end                $ind -= 1                #puts "\n}\n"                                if $ind == 0                        print @tokenizer.source.slice($cursor, @tokenizer.source.length - $cursor)                end                                return ""        end        def getSource                return @tokenizer.source.slice(@start, @end)        end        def filename                return @tokenizer.filename        endend$cursor = 0$ind = 0def Script (t, x)        n = Statements(t, x)        n.type = $consts["SCRIPT"]        n.funDecls = x.funDecls        n.varDecls = x.varDecls        return nend# Statement stack and nested statement handler.# nb. Narcissus allowed a function reference, here we use Statement explicitlydef nest (t, x, node, end_ = nil)        x.stmtStack.push(node)        n = Statement(t, x)        x.stmtStack.pop        end_ and t.mustMatch(end_)        return nenddef Statements (t, x)        n = Node.new(t, $consts["BLOCK"])        x.stmtStack.push(n)        n.push(Statement(t, x)) while !t.done and t.peek != $consts["RIGHT_CURLY"]        x.stmtStack.pop        return nenddef Block (t, x)        t.mustMatch($consts["LEFT_CURLY"])        n = Statements(t, x)        t.mustMatch($consts["RIGHT_CURLY"])        return nendDECLARED_FORM = 0EXPRESSED_FORM = 1STATEMENT_FORM = 2def Statement (t, x)        tt = t.get        puts "TT is " + tt.to_s        # Cases for statements ending in a right curly return early, avoiding the        # common semicolon insertion magic after this switch.        case tt                when $consts["FUNCTION"]                       puts "TT is a function"                        return FunctionDefinition(t, x, true,                                 (x.stmtStack.length > 1) && STATEMENT_FORM || DECLARED_FORM)                when $consts["LEFT_CURLY"]                        n = Statements(t, x)                        t.mustMatch($consts["RIGHT_CURLY"])                        return n                                when $consts["IF"]                        n = Node.new(t)                        n.condition = ParenExpression(t, x)                        x.stmtStack.push(n)                        n.thenPart = Statement(t, x)                        n.elsePart = t.match($consts["ELSE"]) ? Statement(t, x) : nil                        x.stmtStack.pop()                        return n                when $consts["SWITCH"]                        n = Node.new(t)                        t.mustMatch($consts["LEFT_PAREN"])                        n.discriminant = Expression(t, x)                        t.mustMatch($consts["RIGHT_PAREN"])                        n.cases = []                        n.defaultIndex = -1                        x.stmtStack.push(n)                        t.mustMatch($consts["LEFT_CURLY"])                        while (tt = t.get) != $consts["RIGHT_CURLY"]                                case tt

⌨️ 快捷键说明

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