2

この質問は と の両方Parsecに関連していuu-parsinglibます。パーサー コンビネーターを作成すると、コンパイラーからの文字ストリームが処理されます。文字を解析して入力ストリームに戻す (または別の文字を戻す) ことは何とか可能ですか?

たとえば、入力「test + 5」を解析し、、、、を解析し、tパターンを認識した後e、たとえば文字を文字ストリームに戻したいので、照合している解析プロセスを続行しながらsttestvv + 5

今のところ、これを特定のケースで使用したくはありません。その可能性を深く学びたいと思っています。

4

3 に答える 3

1

これは、pSwitch 関数を使用して uu-parsinglib で簡単に実行できます。しかし、問題は、なぜそうしたいのかということです。v が入力から欠落しているためですか? その場合、uu-parsinglib は自動的にエラー修正を実行するので、このようなことは必要ありません。そうでなければあなたは書くことができます

pSwitch :: (st1 -> (st2, st2 -> st1)) -> P st2 a -> P st1 a
pInsert_v = pSwitch (\st1 -> (prepend v st2, id) (pSucceed ())

vが実際にどのように追加されるかは、実際の状態タイプに依存するため、関数を定義する必要があります

先頭に追加
あなた自身。たとえば、そのような挿入がファイル内の現在の位置にどのように影響するかなどはわかりません。

ドアイツェ・スウィエストラ

于 2013-08-28T15:08:58.047 に答える
1

これらのパーサーを直接使用できるかどうかはわかりませんが、一般的には、パーサーと残り物を注入できるストリーミングを組み合わせることで実現できます。

たとえば、attoparsec-conduitを使用すると、パーサーをコンジットに変えることができます。

sinkParser :: (AttoparsecInput a, MonadThrow m)
           => Parser a b -> Consumer a m b

whereConsumerは特別な種類のコンジットで、出力を生成せず、入力のみを受け取り、最終的な値を返します。

コンジットは残り物をサポートするため、オプションでストリームにプッシュされる値をコンジットに返すパーサーを変換するヘルパー メソッドを作成できます。

import Data.Attoparsec.Types
import Data.Conduit
import Data.Conduit.Attoparsec
import Data.Functor

reinject :: (AttoparsecInput a, MonadThrow m)
    => Parser a (Maybe a, b) -> Consumer a m b
reinject p = do
    (lo, r) <- sinkParser p
    maybe (return ()) leftover lo
    return r

次に、標準パーサーを を使用してコンジットに変換しsinkParser、これらの特別なパーサーを を使用して変換しreinject、パーサーの代わりにコンジットを結合します。

于 2013-08-20T16:56:16.023 に答える