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