6

私はParsecを使用して次のようなものを解析しようとしています:

property :: CharParser SomeObject
property = do
    name
    parameters
    value
    return SomeObjectInstance { fill in records here }

私はiCalendar仕様を実装しており、XMLにname:attributes:contentトリプレットがあるのと非常によく似たname:parameters:valueトリプレットがあります。実際、iCalendarをXML形式に非常に簡単に変換できます(私は実際には利点を理解できないと思いました)。

私のポイントは、パラメーターはまったく順序を指定する必要はなく、各パラメーターは異なるタイプである可能性があるということです。1つのパラメーターは文字列で、もう1つのパラメーターは別の要素の数値IDです。それらはまだ類似性を共有していない可能性があります。最終的には、パーサーに返してほしい「SomeObjectInstance」の正しいレコードフィールドに正しく配置したいと思います。この種のことを行うにはどうすればよいですか(または、誰かがこのようなデータを解析しなければならなかった例を教えていただけますか)?

ありがとう、私の質問はおそらく少し混乱していることを知っていますが、それは私が何をする必要があるかについての私の理解のレベルを反映しています。

編集:私は期待される出力を与えないようにしようとしていました(それが隠されているためではなく、大きいため)が、ここに入力ファイルの例があります(ウィキペディアから):

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-// hacksw / handcal // NONSGML v1.0 // EN
BEGIN:VEVENT
UID:uid1@example.com
DTSTAMP:19970714T170000Z
ORGANIZER; CN = John Doe:MAILTO:john.doe@example .com
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
概要:バスティーユデーパーティー
END:VEVENT
END:VCALENDAR

ご覧のとおり、VCalendar内に1つのVEventが含まれているので、ここでそれらを表すデータ構造を作成しました。

そのタイプのファイルをデータ構造に解析するパーサーを作成しようとしていますが、任意のタイプの任意の順序で来るプロパティを処理する必要があるビットに固執しています。日付、時刻、整数、文字列、uid、電気ショック療法。iCalendarの仕様全体を繰り返さなくても、それがより理にかなっていることを願っています。

4

2 に答える 2

6

ParsecにはParsec.Permモジュールがあり、XMLファイルの属性タグなどの順序付けられていないが線形の(つまり、構文ツリーの同じレベルにある)要素を正確に解析します。

残念ながら、Permモジュールはほとんど文書化されていません。最良の参考資料は、Haddockのドキュメントページで参照されているParsing Permutation Phrasesの論文ですが、それでも、使用方法ではなく、主にテクニックの説明です。

于 2010-09-14T07:50:52.787 に答える
1

さて、との間BEGIN:VEVENTEND:VEVENTは、多くのキーと値のペアがあります。keyValuePairしたがって、を返すルールを記述します(key, value)。次に、ルール内でペアのリストを取得しますVEVENTmany KeyValuePairそれが終わったら、フォールドを使用してVEVENTレコードに指定された値を入力します。foldに指定する関数では、パターンマッチングを使用して、値を格納するフィールドを見つけます。アキュムレータの開始値として、オプションのフィールドがに設定されているVEventレコードを使用しますNothing。例:

pairs <- many keyValuePairs
vevent = foldr f (VEvent {sequence = Nothing}) pairs
    where f ("SUMMARY", v) ve = ve {summary = v}
          f ("DSTART", v) ve = ve {dstart = read v}

...等々。他のコンポーネントについても同じようにします。

編集:フォールドの実行可能なサンプルコードは次のとおりです。

data VEvent = VEvent {
        summary :: String,
        dstart :: String,
        sequenceSt :: Maybe String
        } deriving Show

vevent pairs = foldr f (VEvent {sequenceSt = Nothing}) pairs
    where f ("SUMMARY", v) ve = ve {summary = v}
          f ("DSTART", v) ve = ve {dstart = v}
          f ("SEQUENCEST", v) ve = ve {sequenceSt = Just v}

main = do print $ vevent [("SUMMARY", "lala"), ("DSTART", "lulu")]
          print $ vevent [("SUMMARY", "lala"), ("DSTART", "lulu"), ("SEQUENCEST", "lili")]

出力:

VEvent {summary = "lala", dstart = "lulu", sequenceSt = Nothing}
VEvent {summary = "lala", dstart = "lulu", sequenceSt = Just "lili"}

これにより、コンパイル時に警告が生成されることに注意してください。警告を回避するには、オプション以外のすべてのフィールドをundefined明示的に初期化します。

于 2010-09-14T05:16:53.770 に答える