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

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

comments powered by Disqus