Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Jonas Raoni Soares Silva http://www.jsfromhell.com

« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS 

Math Parser //JavaScript Class


This class is able to parse math expressions and also run user defined functions.

On JavaScript there's the "eval" function, that can do such things well, but this code objective was just to give me fun or a new challenge =)~

[UPDATED CODE AND HELP CAN BE FOUND HERE]

Usage:

x = new MathProcessor;
try{alert(x.parse("1+2-(3*4) + medium(2,3) - frac( 2.2231)"));}
catch(e){alert(e);}


It's possible to add more functions to the class, just add them into the "methods" property ;]

Well, that's it :)

//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/classes/math-processor [v1.0]

MathProcessor = function(){ //v1.0
    var o = this;
    o.o = {
        "+": function(a, b){ return +a + b; },
        "-": function(a, b){ return a - b; },
        "%": function(a, b){ return a % b; },
        "/": function(a, b){ return a / b; },
        "*": function(a, b){ return a * b; },
        "^": function(a, b){ return Math.pow(a, b); },
        "~": function(a, b){ return Math.sqrt(a, b); }
    };
    o.s = { "^": 3, "~": 3, "*": 2, "/": 2, "%": 1, "+": 0, "-": 0 };
    o.u = {"+": 1, "-": -1}, o.p = {"(": 1, ")": -1};
};

MathProcessor.prototype.parse = function(e){
    for(var n, x, o = [], s = [x = this.RPN(e.replace(/ /g, "").split(""))]; s.length;)
        for((n = s[s.length-1], --s.length); n[2]; o[o.length] = n, s[s.length] = n[3], n = n[2]);
    for(; (n = o.pop()) != undefined; n[0] = this.o[n[0]](isNaN(n[2][0]) ? this.f(n[2][0]) : n[2][0], isNaN(n[3][0]) ? this.f(n[3][0]) : n[3][0]));
    return +x[0];
};

MathProcessor.prototype.methods = {
    "div": function(a, b){ return parseInt(a / b); },
    "frac": function(a){ return a - parseInt(a); },
    "sum": function(n1, n2, n3, n){ for(var r = 0, a, l = (a = arguments).length; l; r += a[--l]); return r; },
    "medium": function(a, b){ return (a + b) / 2; }
};

MathProcessor.prototype.error = function(s){
    throw new Error("MathProcessor: " + (s || "Erro na expressão"));
}

MathProcessor.prototype.RPN = function(e){
    var _, r, c = r = [, , , 0];
    if(e[0] in this.u || !e.unshift("+"))
        for(; e[1] in this.u; e[0] = this.u[e.shift()] * this.u[e[0]] + 1 ? "+" : "-");
    (c[3] = [this.u[e.shift()], c, , 0])[1][0] = "*", (r = [, , c, 0])[2][1] = r;
    (c[2] = this.v(e))[1] = c;
    (!e.length && (r = c)) || (e[0] in this.s && ((c = r)[0] = e.shift(), !e.length && this.error()));
     while(e.length){
        if(e[0] in this.u){
            for(; e[1] in this.u; e[0] = this.u[e.shift()] * this.u[e[0]] + 1 ? "+" : "-");
            (c = c[3] = ["*", c, , 0])[2] = [-1, c, , 0];
        }
        (c[3] = this.v(e))[1] = c;
        e[0] in this.s && (c = this.s[e[0]] > this.s[c[0]] ?
            ((c[3] = (_ = c[3], c[2]))[1][2] = [e.shift(), c, _, 0])[2][1] = c[2]
            : r == c ? (r = [e.shift(), , c, 0])[2][1] = r
            : ((r[2] = (_ = r[2], [e.shift(), r, ,0]))[2] = _)[1] = r[2]);
    }
    return r;
};

MathProcessor.prototype.v = function(e){
    if("0123456789.".indexOf(e[0]) + 1){
        for(var i = -1, l = e.length; ++i < l && "0123456789.".indexOf(e[i]) + 1;);
        return [+e.splice(0,i).join(""), , , 0];
    }
    else if(e[0] == "("){
        for(var i = 0, l = e.length, j = 1; ++i < l && (e[i] in this.p && (j += this.p[e[i]]), j););
        return this.RPN(l = e.splice(0,i), l.shift(), !j && e.shift());
    }
    else{
        var i = 0, c = e[0].toLowerCase();
        if((c >= "a" && c <= "z") || c == "_"){
            while(((c = e[++i].toLowerCase()) >= "a" && c <= "z") || c == "_" || (c >= 0 && c <= 9));
            if(c == "("){
                for(var l = e.length, j = 1; ++i < l && (e[i] in this.p && (j += this.p[e[i]]), j););
                return [e.splice(0,i+1).join(""), , , 0];
            }
        }
    }
    this.error();
}

MathProcessor.prototype.f = function(e){
    var i = 0, n;
    if(((e = e.split(""))[i] >= "a" && e[i] <= "z") || e[i] == "_"){
        while((e[++i] >= "a" && e[i] <= "z") || e[i] == "_" || (e[i] >= 0 && e[i] <= 9));
        if(e[i] == "("){
            !this.methods[n = e.splice(0, i).join("")] && this.error("Função \"" + n + "\" não encontrada"), e.shift();
            for(var a = [], i = -1, j = 1; e[++i] && (e[i] in this.p && (j += this.p[e[i]]), j);)
                j == 1 && e[i] == "," && (a.push(this.parse(e.splice(0, i).join(""))), e.shift(), i = -1);
            a.push(this.parse(e.splice(0,i).join(""))), !j && e.shift();
        }
        return this.methods[n].apply(this, a);
    }
};

Function Overloader //JavaScript Class


This class allows javascript functions to be overloaded.

[UPDATED CODE AND HELP CAN BE FOUND HERE]




Usage:

myFunction = new Overloader;

myFunction.overload(function(x){
	document.write("Receives: NUMBER<br />");
}, Number);

myFunction.overload(function(x){
	document.write("Receives: STRING<br />");
}, String);

myFunction.overload(function(x,y){
	document.write("Receives: FUNCTION, NUMBER<br />");
}, Function, Number);

myFunction.overload(function(x,y){
	document.write("Receives: NUMBER, STRING<br />");
}, Number, String);

//test...
myFunction(function(){}, 123); //function + number version
myFunction(123); //number version
myFunction("ABC"); //string version
myFunction(123, "ABC"); //number + string version
myFunction({}); /*There's no Object version, so the function will choose the one that has more arguments in common and if there isnt a "best match", it will use the first function that was overloaded...*/



Here's the code

//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/classes/overloader [v1.0]

Overloader = function(){ //v1.0
	var f = function(args){
		var i, h = "#";
		for(i in args = [].slice.call(arguments))
			h += args[i].constructor;
		if(!(h = f._methods[h])){
			var x, j, k, m = -1;
			for(i in f._methods){
				for(j in args.length > (k = 0, x = f._methods[i][1]).length ? x : args)
					(args[j] instanceof x[j] || args[j].constructor == x[j]) && ++k;
				k > m && (h = f._methods[i], m = k);
			}
		}
		return h ? h[0].apply(f, args) : undefined;
	};
	f._methods = {};
	f.overload = function(f, args){
		this._methods["#" + (args = [].slice.call(arguments, 1)).join("")] = [f, args];
	};
	f.unoverload = function(args){
		return delete this._methods["#" + [].slice.call(arguments).join("")];
	};
	return f;
};
« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS