2分木のバリデーター改

とりあえず、もうちょっと綺麗にしてみました。
①2分木の名前でswitchする。
②全ての値を2分木にしてしまう。
とすることで、すっきりしたバリデータになりました。
これなら、文法定義から生成で来そうな気もします。

<script>
function Msg(a, b, c) {
	this[0] = a;
	this[1] = b;
	this[2] = c;
}

Msg.prototype.toString = function(){
	if(this[1]=="id") return this[0];
	else              return "["+this[0]+","+this[1]+","+this[2]+"]";
}
Msg.prototype._ = function (f1, f2) { return f1(this[0]) && f2(this[2]); }

function _(a, b, c) {
	if (!(a instanceof Msg)) a = new Msg(a, "id", "");
	if (!(c instanceof Msg)) c = new Msg(c, "id", "");
	return new Msg(a, b, c);
}

function valid($) {
	return _stmt($);
}

function _stmt($) {
	switch ($[1]) {
	case "if": return $._(_exp, _else);
	case "C":  return $._(_stmt, _stmt);
	case "()": return $._(_exp, _arglist);
	default:   return _exp($);
	}
}

function _else($) {
	switch ($[1]) {
	case "else": return $._(_exp, _exp);
	default:     return _exp($);
	}
}

function _id($) {
	switch ($[1]) {
	case "id": return true;
	default:   return false;
	}
}

function _assignLeft($) {
	switch ($[1]) {
	case "id": return _id($);
	default: return _array($);
	}
}

function _arglist($) {
	switch ($[1]) {
	case ",": return $._(_arglist, _arglist);
	default:  return _id($);
	}
}

function _array($) {
	switch ($[1]) {
	case "[]": return $._(_assignLeft, _exp);
	default:   return false;
	}
}

function _exp($) {
	switch ($[1]) {
	case "=":  return $._(_assignLeft, _exp);
	case "+":
	case "*":  return $._(_exp, _exp);
	default:   return false;
	case "id": return true;
	}
}

function p(d) {
	document.write("<b>"+d+"</b><br/>");
}

function test($) {
	var f = valid($);
	if(!f) document.write("<font color=#ff0000>error "+$+"</font><br>");
}

test(_(1,"+", _(2, "*", 3)));
test(_(1,"*", _(2, "+", 3)));
test(_(1,"if", _(2, "else", 3)));
test(_(1,"if", _(2, "els", 3)));
test(_(1,"if", _(2, "else", _(3,"else",4))));
test(_(1,"if", 3));
test(_(1,"C",_(1,"if", 3)));
test(_(1,"else",2));
test(_("a","=",2));
test(_(_("a","=","b"),"=",2));
test(_("a","=",_("b","=",2)));
test(_(_("a","[]",2),"=",2));
test(_(_("a","[]",_("a","=","b")),"=",2));
test(_("a","()",5));
test(_("a","()",_(5,",",6)));
test(_("a","()",_(5,",",_(6,",",7))));
test(_("a","()",_(5,",",_(6,";",7))));
</script>