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

近頃、JavascriptでOreScriptなんてのがちょっとはやっていたりしまして。

OreScript書くのにある程度ちゃんと動くパーサコンビネータがあれば便利かも、とおもったので以前書いたパーサコンビネータをいじってみました。

変更点

  • メソッド名などをHaskellにあわせた
  • よくもわるくも、記号含有率をあげた(and -> $に、or -> l に)
  • 相互再帰をサポートした
  • 左再帰(chainl1)をサポートした
  • 右再帰(chanr1)をサポートした

ということで、そこそこの用途に耐えるものになったと思います。

ダウンロード

完全にアンドキュメントです。すみません。ただ、ソースは200行くらいなんで見ればわかるかと。というか、HaskellのParsecのマニュアルを読めば基本一緒なので使い方がわかると思います。

ダウンロード

サンプル

id:amachangさんが書いていたような数式パーサを定義してみましょう。

残念ながらLexerはつくっていないので、空白は受け入れられません。

JAVASCRIPT:
  1. var 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.  
  17. var test = "100*(100+200)/10";
  18.  
  19. var parser = new ExprParser(test);
  20. var parseResult = parser.expr.parse();
  21. if(parseResult.success()) {
  22.   alert(parseResult.result);
  23.   // => 3000
  24. }


すごく、Parsecです・・・

 
 


 
こういうのを最近はやりのCodeReposでやればいいのかなあ。


About this entry