OreScriptがはやってるならパーサコンビネータの需要もあるのかな?

近頃、 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 でやればいいのかなあ。

comments powered by Disqus