パーサジェネレータ
spirit風味のパーサジェネレータです。
作成動機
SAXを作成するために作りました。
特徴
BNFに近い書き方ができます。
Rule r = new Rule; r = ch_p('a') >> 'b'+_ >> 'c'*_; //r = a b+ c*
ライセンス
NYSL Version 0.9982 に従います。
サンプル
letsboost::spiritのサンプルを参考にしました。
import mikanya.parser; import mikanya.container.stack; import std.conv; import std.utf; import std.cstream; Stack!(int) stk; static this(){stk = new Stack!(int);} //アクションも使えます。 void clear(){stk.value.length = 0;} int answer(){return stk.top();} int toppop(){int a = stk.top(); stk.pop(); return a;} void PUSH(ScannerT[] match) { char[] s = toUTF8(match); int n = toInt(s); stk.push(n); } void ADD(ScannerT[] match) { int b = toppop(), a = toppop(); stk.push(a+b); } void SUB(ScannerT[] match) { int b = toppop(), a = toppop(); stk.push(a-b); } void MUL(ScannerT[] match) { int b = toppop(), a = toppop(); stk.push(a*b); } void DIV(ScannerT[] match) { int b = toppop(), a = toppop(); stk.push(a/b); } void main() { //文法定義 auto expr = new Rule; auto term = new Rule; auto fctr = new Rule; auto group = new Rule; auto num = new Rule; expr = term >> ( ('+' >> term)[&ADD] | ('-' >> term)[&SUB] )*_; term = fctr >> ( ('*' >> fctr)[&MUL] | ('/' >> fctr)[&DIV] )*_; fctr = (num+_)[&PUSH] | group; group = '(' >> expr >> ')'; num = ch_p('0') | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; char[] line; line = din.readLine(); while(line.length) { if(expr.parse(toUTF16(line))) dout.writefln(answer()); else dout.writefln("error"); clear(); line = din.readLine(); } }