Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript (http://www.flasher.ru/forum/forumdisplay.php?f=5)
-   -   как пропарсить строку "34/6-(4+1)*(2+1.5)" ? (http://www.flasher.ru/forum/showthread.php?t=52772)

sashOk 17.12.2003 02:42

как пропарсить строку "34/6-(4+1)*(2+1.5)" ?
 
Задача: нужно получить результат математического выражения, заключенного в строку. Пример "34/6-(4+1)*(2+1.5)".
В ActionScript'e есть ф-ция eval(), но она делает совсем не то.
Может, есть какие-то альтернативы? Ато я уже собрался вручную парсить...

lexass 17.12.2003 10:39

альтернатива == ручками

не забудь показать творение =)

YuriiZelenev 17.12.2003 14:15

toNumber to number string to number stringToNumber convertToNumber
 
dolgo promuchieshsya...
Код:

Math.Expression = function() {}

Math.Expression.prototype.operators="+-*/^(";
Math.Expression.prototype.opPriority=[["^"],["neg"],["*","/"],["+","-"]];
Math.Expression.prototype.functions=["abs","acos","asin","atan","ceil","cos","exp","floor","log","random","round","sin","sqrt","tan"];


Math.Expression.prototype.parse = function(str,link) {
        var pos=0;
        var operator,bracket,len;
        if (arguments.length<2) {
                this.parts=new Array();
                link=this.parts;
        }

        while ((operator=this.findOperator(str,pos)).pos!=-1) {
                if (pos<operator.pos) {
                        len=link.length;
                        link[len]=new Object();
                        link[len].type="variable";
                        link[len].value=str.substring(pos,operator.pos);
                        if (!isNaN(Number(link[len].value))) {
                                link[len].type="value";
                                link[len].value=Number(link[len].value);
                        }
                }
                if (operator.op!="(") {
                        len=link.length;
                        link[len]=new Object();
                        link[len].type="operator";
                        if (link[len-1].type=="operator" || len==0) {
                                if (operator.op=="-") link[len].value="neg";
                                else return false;
                        }
                        else link[len].value=operator.op;
                        link[len].priority=this.findPriority(link[len].value);
                        pos=operator.pos+1;
                }
                else {
                        bracket=this.findBracket(str,operator.pos);
                        if (bracket==-1) return false;
                        len=link.length;
                        if (link[len-1].type=="variable") this.findFunction(link[len-1]);
                        link[len]=new Object();
                        link[len].type="expression";
                        link[len].value=new Array();
                        if (!this.parse(str.substring(operator.pos+1,bracket),link[len].value)) return false;
                        pos=bracket+1;                       
                }
        }
        if (pos<str.length) {
                len=link.length;
                link[len]=new Object();
                link[len].type="variable";
                link[len].value=str.substring(pos);
                if (!isNaN(Number(link[len].value))) {
                        link[len].type="value";
                        link[len].value=Number(link[len].value);
                }                       
        }
        return true;
}

Math.Expression.prototype.findOperator = function(str,pos) {
        var foundAt,foundAtTemp;
        foundAt=str.length;
        for (var i=0; i<this.operators.length; i++) {
                foundAtTemp=str.indexOf(this.operators.charAt(i),pos);
                if (foundAtTemp<foundAt && foundAtTemp!=-1) foundAt=foundAtTemp;
        }
        var a=new Object();
        a.pos=(foundAt==str.length) ? -1 : foundAt;
        a.op=str.charAt(foundAt);
        return a;
}

Math.Expression.prototype.findPriority = function(op){
        for (var i=0; i<this.opPriority.length; i++) {
                for (var j=0; j<this.opPriority[i].length; j++) {
                        if (op==this.opPriority[i][j]) return i;
                }
        }       
}


Math.Expression.prototype.findBracket = function(str,pos){
        var open=pos
        var close=pos;
        do {
                close=str.indexOf(")",close+1);
                open=str.indexOf("(",open+1);
        } while (close>open && open!=-1);
        return close;
}

Math.Expression.prototype.findFunction = function(link){
        for (var i in this.functions) {
                if (link.value==this.functions[i]) link.type="function";
        }
}

Math.Expression.prototype.eval = function() {
        this.evaluated=new Array();
        this.copyPartsArray(this.parts,this.evaluated);
        return this.evalExpression(this.evaluated);
}


Math.Expression.prototype.copyPartsArray = function(link,copylink) {
        for (var i in link) {
                copylink[i]=new Object();
                copylink[i].type=link[i].type;
                copylink[i].value=link[i].value;
                copylink[i].priority=link[i].priority;
                if (link[i].type=="expression") {
                        copylink[i].value=new Array();
                        this.copyPartsArray(link[i].value,copylink[i].value);
                }
        }
}

Math.Expression.prototype.evalExpression = function(link) {
        var op;
        var i;
        for (i in link) {
                if (link[i].type=="expression") link[i].value=this.evalExpression(link[i].value);
                if (link[i].type=="variable") link[i].value=this.evalVariable(link[i].value);
        }
        i=0;
        while (i<link.length) {
                if (link[i].type=="function") {
                        link[i].value=this.evalFunction(link[i].value,link[i+1].value);
                        link.splice(i+1,1);
                }
                i++;                       
        }
        for (var i=0; i<this.opPriority.length; i++) {
                var k=0;
                while (k<link.length) {
                        if (link[k].type=="operator" and link[k].priority==i) {
                                op=link[k].value;
                                link[k].type="value";
                                link[k].value=this.evalOperator(link[k].value,link[k-1].value,link[k+1].value);
                                link.splice(k+1,1);
                                if (op!="neg") link.splice(k-1,1);
                                k--;
                        }
                        k++;
                }       
        }
        return link[0].value;
}

Math.Expression.prototype.evalOperator = function(op,v1,v2) {
        if (op=="+") return v1+v2;
        if (op=="-") return v1-v2;
        if (op=="*") return v1*v2;
        if (op=="/") return v1/v2;
        if (op=="^") return v1==0 ? 0 : Math.pow(v1,v2);
        if (op=="neg") return -v2;

}

Math.Expression.prototype.evalVariable = function(v) {
        return eval(v);
}

Math.Expression.prototype.evalFunction = function(func,v) {
        return Math[func](v);
}

Primer:
Код:

//Primer
myExpression = new Math.Expression();
myExpression.parse("34/6-(4+1)*(2+1.5)");
trace(myExpression.eval());

ps:no esli sdelaesh luchshe - pokajesh...

dlya poiska: toNumber to number string to number stringToNumber convertToNumber

YuriiZelenev 17.12.2003 14:30

toNumber() stringToNumber() convertToNumber() toDigit() toDigit to Digit
 
dlya poiska:
toDigit to Digit
toNumber() stringToNumber() convertToNumber() toDigit()
toNumber(); stringToNumber(); convertToNumber(); toDigit();

sergwizard 17.12.2003 22:56

2 YuriiZelenev
И не лениво тебе было это писать? Или у тебя уже была наработка?
Но, классно!

sashOk 15.01.2004 02:13

да, немного опоздал.... :)
Вот моё произведение:
Код:

var operators = Array(
        "+", "-", "*", "/", "^"
);

function Calc(str){
        //Раскрытие скобок:
        var pos1 = 0;
        while( pos1 || (pos1 = str.indexOf("(")) != -1){
                var pos2 = str.indexOf(")",++pos1);
                if(pos2>0){
                        var noBrackets = str.substring(pos1,pos2);
                        pos1 = str.indexOf("(",pos1);
                        if(pos1 > pos2 || pos1 < 0){
                                str = str.split("("+noBrackets+")").join( Calc_noBrackets(noBrackets,0) );
                                pos1 = 0;
                        }
                }else{
                        trace("Error: No ending ')' !");
                        return;
                }
        }
        return Calc_noBrackets(str,0);
}

function Calc_noBrackets(str,opId){
        str = str.split("--").join("+");
        str = str.split("+-").join("-");

        var args = str.split(operators[opId]);
        var result = 0;

        for(var argId=0;argId<args.length;argId++){
                var arg = args[argId];
                for(var nextOpId=opId+1;nextOpId<operators.length;nextOpId++)
                        if(arg.indexOf(operators[nextOpId])>0){
                                arg = Calc_noBrackets(arg,nextOpId);
                                break;
                        }

                arg = new Number(arg);
                if(argId==0)
                        result = arg;
                else switch(operators[opId]){
                        case "^": result  = Math.pow(result,arg); break;
                        case "*": result *= arg; break;
                        case "/": result /= arg; break;
                        case "+": result += arg; break;
                        case "-": result -= arg; break;
                }
        }
        return result;
}

Пример:
Код:

trace( Calc("34/6-(4+1)*(2+1.5)") )

Boldin 15.01.2004 10:48

to sashOk
 
реальный парсер!

начинающий 15.01.2004 14:40

Вложений: 1
Если флешка будет запускаться не из браузера, то дальше можете не читать!

Не мудрствуя лукаво, предлагаю использовать уже имеющееся средство в движке JScript, а не заниматься изобретением велосипеда:

Код:

var str2Parse = "34/6-(4+1)*(2+1.5)";

getURL("javascript: calcDemo.setVariable('result', eval('"+str2Parse+"'))");

_root.onEnterFrame = function() // waiting for browser’s respond
{
        if(result != undefined)
        {
                _root.tf.text = str2Parse + " = " + result;
                delete _root.onEnterFrame;
        }
}

Запустите НТМ-льку из примера - SWF-ку самостоятельно запускать не стОит!


Часовой пояс GMT +4, время: 17:25.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.