2015年12月20日

というわけで,構文解析ができるようになったmacrodll.dll.こんな感じで使う.例はこの手のお約束の電卓.

#_ = dllfuncw("PEG_NEWSYNTAX", "calc","expr");
#_ = dllfuncw("PEG_SETRULE", "calc", "expr", "(term{+} | '-' term{-}) (('+' term{+}) | ('-' term{-}))*");
#_ = dllfuncw("PEG_SETRULE", "calc", "term", "fctr{=} (('*' fctr{*}) | ('/' fctr{/}))*");
#_ = dllfuncw("PEG_SETRULE", "calc","fctr", "[0-9]+{=} | ('(' expr ')')");
#_ = dllfuncw("PEG_PARSE","calc","-32/4+10*(2+2)");
$a = dllfuncstrw("PEG_EXECUTE","calc");
while($a != ""){
    #v = val(dllfuncstrw("PEG_GETVALUE","calc",0));
    #x = val(dllfuncstrw("PEG_GETVALUE","calc",1));
    if($a == "=")#v = #x;
    else if($a == "+")#v = #v + #x;
    else if($a == "-")#v = #v - #x;
    else if($a == "/")#v = #v / #x;
    else if($a == "*")#v = #v * #x;
    #_ = dllfuncw("PEG_SETVALUE","calc",str(#v));
    $a = dllfuncstrw("PEG_EXECUTE","calc");
}
$answer = dllfuncstrw("PEG_GETVALUE","calc",0); // 答え

使えるのは

  • | :選択,
  • *,+:繰り返し,
  • A - B:AであるがBでない,
  • ?:省略可能,
  • &, !:AND/NOT predicate,
  • '...':文字列,
  • [..]:文字集合.[^...]で否定,
  • . :任意の一文字,
  • A{action}:セマンティックアクション.
のつもり.とりあえずWikipedia./は|にしてあるけど,どうしようか.セマンティックアクションは起こるたびにマクロ側に戻るので,処理して返す.基本的には値は処理しないと闇に消えます.ほしいところには{}をつけておく.(a b){action}とするとactionの場所でa,b両方の値が取得できればいいんだけど,それもできません.現段階では(a{A} b{B})として,Aで上の=みたいな処理をして,Bでaction相当をすることになると思う.まぁ僕も何をどうするとどうなるのかよくわかっていません…….

PEG_SETSKIPで,スキップする文字を指定できる.デフォルトはスペース.dllfunc("PEG_SETSKIP","calc","[abc]")とするとa,b,cが無視される.ここにPEGによる定義を後々入れたいので,[]で囲むのは必須.デフォルトではスペースを飛ばす.

追記:char*からwchar_t*にした.追記2:PEG_ADDRULEからPEG_SETRULEにした.

0 件のコメント:

コメントを投稿

コメントの追加にはサードパーティーCookieの許可が必要です