forked from: basic 4 function calculator

by ohisama forked from basic 4 function calculator (diff: 117)
♥0 | Line 253 | Modified 2013-01-28 22:15:34 | MIT License
play

ActionScript3 source code

/**
 * Copyright ohisama ( http://wonderfl.net/user/ohisama )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ehTo
 */

// forked from codeonwort's basic 4 function calculator
package 
{
    import flash.ui.Keyboard;
    import flash.events.KeyboardEvent;
    import flash.text.TextField;
    import flash.display.Sprite;
    public class Main extends Sprite 
    {
        private var prompt : TextField, result : TextField
        private var input : TextField, output : TextField
        private var tokenizer : Tokenizer
        public function Main() 
        {
            prompt = label("> ", 0, 0)
            input = new TextField
            input.type = "input"
            input.x = prompt.width
            input.width = stage.stageWidth - prompt.width - 5
            input.height = prompt.height
            input.border = true
            //input.borderColor = 0xff0000
            input.text = "3*3"
            input.addEventListener("keyDown", input_keyDown)
            addChild(input)
            result = label("= ", 0, prompt.height + 5)
            output = new TextField
            output.autoSize = "left"
            output.width = stage.stageWidth - prompt.width - 5
            output.x = result.width
            output.y = result.y
            addChild(output)
        }
        private function label(lbl : String, x : Number, y : Number) : TextField 
        {
            var t : TextField = new TextField
            t.autoSize = "left"
            t.x = x
            t.y = y
            t.text = lbl
            addChild(t)
            return t
        }
        private function input_keyDown(e : KeyboardEvent) : void 
        {
            if (e.keyCode == Keyboard.ENTER)
            {
                try
                {
                    tokenizer = new Tokenizer(new Expr(input.text))
                    output.text = expression().toString()
                }
                catch(err : Error)
                {
                    output.text = err.message
                }
            }
        }
        private function expression() : Number 
        {
            var left : Number = term()
            var t : Token
            while (tokenizer.isEmpty() == false)
            {
                t = tokenizer.get()
                switch (t.kind)
                {
                case '+' :
                    left += term()
                break
                case '-' :
                    left -= term()
                break
                default:
                    tokenizer.putback(t)
                    return left
                }
            }
            return left
        }
        private function term() : Number 
        {
            var left : Number = primary()
            var t : Token
            while (tokenizer.isEmpty() == false)
            {
                t = tokenizer.get()
                switch (t.kind)
                {
                case '*' :
                    left *= primary()
                break
                case '/' :
                    var d : Number = primary()
                    if (d == 0) throw new Error("division by 0")
                    left /= d
                break
                default :
                    tokenizer.putback(t)
                    return left
                }
            }
            return left
        }
        private function primary() : Number 
        {
            var t : Token = tokenizer.get()
            switch (t.kind)
            {
            case '(' :
                var d : Number = expression()
                t = tokenizer.get()
                if (t.kind != ')') throw new Error("err")
                return d
            case Token.NUM :
                return t.value
            case '+' :
                return primary()
            case '-' :
                return -primary()
            default :
                throw new Error("err")
            }
        }
    }
}
class Expr 
{
    private var str : String
    public function Expr(s : String) 
    {
        str = ""
        for (var i : int = 0; i < s.length; i++)
        {
            if (s.charAt(i) != " ") str += s.charAt(i)
        }
    }
    public function get() : String 
    {
        var ch : String = str.charAt(0)
        str = str.substr(1)
        return ch
    }
    public function putback(ch : String) : void 
    {
        str = ch + str 
    }
    public function isEmpty() : Boolean 
    {
        return str.length == 0
    }
}
class Token 
{
    public static const NUM : String = 'n'
    public var kind : String
    public var value : Number
    public function Token(k : String, v : Number = NaN) 
    {
        kind = k
        value = v
    }
}
class Tokenizer 
{    
    private var full : Boolean = false
    private var buffer : Vector.<Token>
    private var expr : Expr
    public function Tokenizer(e : Expr) 
    {
        expr = e
        buffer = new Vector.<Token>        
        var char : String
        var tok : Token
        lbl : while (expr.isEmpty() == false)
        {
            char = expr.get()
            switch (char)
            {
            case '(' : 
            case ')' : 
            case '+' : 
            case '-' : 
            case '*' : 
            case '/' :
                tok = new Token(char)
            break
            case '.' : 
            case '0' : 
            case '1' : 
            case '2' : 
            case '3' : 
            case '4' :
            case '5' : 
            case '6' : 
            case '7' : 
            case '8' : 
            case '9' :
                expr.putback(char)
                tok = new Token(Token.NUM, getNumber())
            break
            default :
                throw new Error("invalid token")
            }
            buffer.unshift(tok)
        }
    }
    public function get() : Token 
    {
        if (buffer.length != 0)
        {
            return buffer.pop()
        }
        throw new Error("buffer is empty")
    }
    public function isEmpty() : Boolean 
    {
        return buffer.length == 0
    }
    private function getNumber() : Number 
    {
        var str : String = ""
        var ch : String
        lbl : while (true)
        {
            ch = expr.get()
            switch (ch)
            {
                case '.' : 
                case '0' : 
                case '1' : 
                case '2' : 
                case '3' : 
                case '4' :
                case '5' : 
                case '6' : 
                case '7' : 
                case '8' : 
                case '9' :
                    str += ch
                break
                default :
                    expr.putback(ch)
                break lbl
            }
        }
        var n : Number = Number(str)
        if (isNaN(n)) throw new Error("invalid number representation")
        return n
    }
    public function putback(t : Token) : void 
    {
        buffer.push(t)
    }
}