近頃、JavascriptでOreScriptなんてのがちょっとはやっていたりしまして。
OreScript書くのにある程度ちゃんと動くパーサコンビネータがあれば便利かも、とおもったので以前書いたパーサコンビネータをいじってみました。
変更点
- メソッド名などをHaskellにあわせた
- よくもわるくも、記号含有率をあげた(and -> $に、or -> l に)
- 相互再帰をサポートした
- 左再帰(chainl1)をサポートした
- 右再帰(chanr1)をサポートした
ということで、そこそこの用途に耐えるものになったと思います。
ダウンロード
完全にアンドキュメントです。すみません。ただ、ソースは200行くらいなんで見ればわかるかと。というか、HaskellのParsecのマニュアルを読めば基本一緒なので使い方がわかると思います。
サンプル
id:amachangさんが書いていたような数式パーサを定義してみましょう。
残念ながらLexerはつくっていないので、空白は受け入れられません。
var ExprParser = Inforno.Parsec.Parsers.define(function(){with(this){var mul = function(a,b){return a*b;};var div = function(a,b){return a/b;};var add = function(a,b){return a+b;};var sub = function(a,b){return a-b;};this.numbers = many1( chrLike(function(c) { return (c >= '0' && c <= '9'); }) ) .ret(function(ns){return parseInt(ns.join(""));});this.expr = chainl1(p("term"), p("addop"));this.term = chainl1(p("factor"), p("mulop"));this.factor = (between(chr("("), p("expr"), chr(")"))) .l (numbers)this.mulop = (chr("*") .retval(mul)) .l (chr("/") .retval(div));this.addop = (chr("+") .retval(add)) .l (chr("-") .retval(sub));}});var test = "100*(100+200)/10";var parser = new ExprParser(test);var parseResult = parser.expr.parse();if(parseResult.success()) {alert(parseResult.result);// => 3000}
すごく、Parsecです・・・
こういうのを最近はやりのCodeReposでやればいいのかなあ。