4

StreamカスタムタイプでParsecを使用しています。このストリームは本質的にはそうですStringが、文字列内で見つかった入力を他の文字列に展開することがあります (エイリアス展開を考えてください)。たとえば、「§4.1 ¶3」が与えられた場合、「セクション 4.1 パラグラフ 3」をパーサーにフィードする可能性があります。

私はこれをすべて機能させています。私のタイプは次のようになります。

data DealiasingStream = ...
instance (Monad m) => Stream DealiasingStream m Char where ...

type ShellParser = Parsec DealiasingStream ()

の従属型DealiasingStreamは だけであることに注意してくださいChar。これにより、パーサーShellParserがすべての標準文字パーサーを使用できるようになります。

私の質問は、私のストリームへの元の入力に関する位置を Parsec に報告させることです。のドキュメントにStreamは次のように書かれています:

Streamインスタンスは、ストリーム状態で「ストリーム内の位置」を維持する責任がありますs。自明でない方法でモナドを使用していない限り、これは自明です。

実際、私のストリーム タイプは、いつでもレポートしたい位置を認識しています... しかし、Parsec にそれを使用させる方法がわかりません! SourcePosParsecは、内部の一部として独自のものを維持しているようStateです。そして、これはさまざまなtokenプリムによって更新されるようです。したがって、標準のCharパーサーでは、私の制御が及ばないのです。

これをどのように行うべきですか?

4

2 に答える 2

1

などの関数を書き換えずに位置を制御する簡単な方法はありませんchar

ドキュメントが意味することは、インスタンスがトークンStreamの位置情報を記録する責任があるということです。その情報は、またはのような関数で使用できます(適切な位置計算関数をそれらに提供することにより)。tokentokenPrim

Charしたがって、位置情報を含むデータ型にラップし、位置計算に柔軟なtokenやのようなプリミティブを使用して基本関数を書き直す必要があります。tokenPrim

于 2012-11-21T22:43:55.657 に答える
-1

SourcePosの関数を使用して新しいものを作成し、のを使用Text.Parsec.Posしてパーサーに設定setPositionできますText.Parsec.Prim

編集:

トークンタイプを変更していないため、カスタムストリームが必要な理由がわかりません。標準のパーサーを使用して、ルールCharで拡張と位置の更新を実行できる必要があります。whitespaceこれはcpp、マクロを展開するために使用し、カスタムwhitespaceルールを使用してコマンドを検索します。#lineコマンドは、を使用して位置を更新するために使用しsetPositionます。これを使用して展開を検索し、展開の前に。を付けて入力ストリームを変更しgetInput、結果を。でパーサーに戻すことができますsetInput。のドキュメントは、ディレクティブsetInputを拡張するための使用を提案していますが、これは本質的に同じ問題です。#include

于 2012-11-21T17:20:16.823 に答える