100オーダーな優先順位付き演算子定義構文解析器

優先順位をリストで管理してやることで、とびとびの値の優先順位を付けられる
ようなパーサを作ってみました。

サンプル
http://sakurai.s59.xrea.com/diary/100order.html

以下ソース

<script>
Object.prototype.toString = function() {
	var str = [];
	for (var i in this) 
		str.push(i+":"+this[i])
	return "{"+str.join(",")+"}"
}
function Operators(p,op,f,n) {
	this.priority = p
	this.operators = {}
	this.operators[op] = f
	this.next = n
}
Operators.prototype.set = function (op, no, f) {with(this){
	if (priority == no) 
		return operators[op]=f,this
	if (next == null)
		return next = new Operators(no, op, f, null)
	if (priority < no && next.priority > no)
		return next = new Operators(no, op, f, next)
	return next.set(op, no, f)
}}

var infixs = new Operators(0)
infixs.set("+",100,function(a,b){return [a,"+",b]})
infixs.set("-",100,function(a,b){return [a,"-",b]})
infixs.set("*",200,function(a,b){return [a,"*",b]})
infixs.set("/",200,function(a,b){return [a,"/",b]})

Array.prototype.toString = function(){return "("+this.join(" ")+")"}
function c() {
	document.getElementById("out").value =
	eval(document.getElementById("in").value)
}
function eval(str){
	function peek() {
		return str.match(/^[ \r\n\t]*([0-9]+|\+|\-|\*|\/|\(|\)|$)/)[1]
	}
	function pop() {
		return peek(),str = RegExp.rightContext,RegExp.$1
	}
	function exp() {
		return expn(infixs.next)
	}
	function expn(infixs) {
		if (infixs == null) return fact()
		var c = expn(infixs.next)
		var f = infixs.operators[peek()]
		if(f) return pop(), f(c,expn(infixs))
		return c
	}
	function fact() {
		var c = pop()
		if(Number(c))return Number(c)
		if(c == "("){c = exp(); if(pop() == ")")return c}
		throw new Error("error")
	}
	return exp()
}
</script>
<input id=in>
<input id=out>
<input type=button onclick=c()>