In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

basic 4 function calculator

basic 4 fn calc
learnd from stroustrup's c++ book.
Get Adobe Flash player
by codeonwort 16 Jul 2012
/**
 * Copyright codeonwort ( http://wonderfl.net/user/codeonwort )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/aTGf
 */

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() {
            // write as3 code here..
            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.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(")가 없음")
                    return d
                case Token.NUM :
                    return t.value
                case '+' :
                    return primary()
                case '-' :
                    return -primary()
                default :
                    throw new Error("기본항을 찾을 수 없다")
            }
        }
        
    }
    
}

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)
    }
    
}