文法の出発点は次のとおりです。
%%{
machine xo;
char = "x" | "o";
group = "(" char* ")";
main := group;
}%%
(xxxx(oo)()xx)
たとえば、 を処理します。ネストされたグループを許可するように拡張するにはどうすればよいですか。例えば(xxxx(o(x)o)()xx
?
通常、1 台の Ragel マシンでは再帰がサポートされないことはわかっています。したがって、これは機能しません:
group = "(" ( char | group )* ")";
Ragel State Machine Compiler User Guide (PDF)から: (強調のために太字のテキストを追加):
「一般に、Ragel は再帰構造を処理できません。これは、文法が通常の言語として解釈されるためです。ただし、何を解析する必要があるかによっては、手動コーディング手法を使用して再帰部分を実装することが実用的な場合があります。これは、再帰構造が括弧のバランスをとるなど、単純で認識しやすいです。」
「再帰構造を解析する 1 つのアプローチは、カウンターをインクリメントおよびデクリメントするアクションを使用するか、再帰構造への入り口と出口を認識し、fcall と fret を使用して適切なマシン定義にジャンプすることです。別の方法として、セマンティック条件を使用してカウンターをテストすることもできます。変数。
「より伝統的なアプローチは、再帰構造に入ったときに別の解析関数 (ホスト言語で表現された) を呼び出し、後で終了が認識されたときに戻ることです。」
ネストされたブラケットに関するメーリング リストのディスカッションから、同じ 3 つのアプローチが言及されています。
prepush と postpop を使用して成長可能なスタックを指定してから、fcall と fret を使用します。
カウントしてから、アクションまたは条件で確認します。
再帰構造に入ったときに、(ホスト言語で) 新しい解析関数を呼び出します。
できれば上記の例を使用して、Ruby でのそれぞれの例を教えてもらえますか? ありがとう!