2016-11-19 6 views

答えて

2

解決策が見つかりました。あなたは非決定論を扱う必要があります。当初は明確ではありませんでしたが、正解はこのようなものである:基本的に

inner_text = any*; 
tag_cdata = '<![CDATA[' inner_text >text_begin %text_end ']]>' %cdata_end; 

action text_begin { 
    text_begin_at = p; 
} 

action text_end { 
    text_end_at = p; 
} 

action cdata_end { 
    delegate.cdata(data.byteslice(text_begin_at, text_end_at-text_begin_at)) 
} 

あなたは、あなたが以前に取り込まれた情報を使用して、コールバックを発射する前に、完全なCDATAタグを解析されたことを確認するまで、あなたは待ちます。

さらに、私は、Ragelの非決定論のいくつかの形式は、優先順位を使って明示的に処理する必要があることを発見しました。これは少し醜いようですが、それは場合によっては唯一の解決策です。

(a+ >a_begin %a_end | b)*のようなパターンを扱う場合、最も長いサブシーケンスではなく、aが発生するたびにイベントが呼び出されます。このあいまいさは、場合によっては、最長一致のkleeneスター**を使用して解決できます。これは、ラップするのではなく既存のパターンにマッチさせることを好みます。

私には驚きましたが、実際にイベントが呼び出される方法も変更されています。

%%{ 
    machine example; 

    action a_begin {} 
    action a_end {} 

    main := ('a'+ >a_begin %a_end | 'b')*; 
}%% 

が生成されます:

Non-greedy Parser

あなたはそれがa_beginを呼び出すことがわかります例として、これは、コールバックを呼び出すときに、一度に複数の文字をバッファリングすることができないマシンを生成します毎回a_endとなります。

対照的に、我々は、内側のループとイベントが貪欲ハンドリングすることができます:

%%{ 
    machine example; 

    action a_begin {} 
    action a_end {} 

    main := ('a'+ >a_begin %a_end | 'b')**; 
}%% 

生成する:

Greedy Parser

+0

ではありません、それは奇妙なあなたが年に独自の解決策を見つけるとき未来と思う、私は本当にそれを書くのでした! :) – ioquatix

関連する問題