質問

私は最後の要素が、すべて1つのパーサによって解析される必要がある場所を解析する必要がリストを持って、そして最後の要素は、別のパーサで解析する必要があります。

a = "p1 p1b ... p2"
or
a = "p2"

もともと、私が試した

parser = do parse1 <- many parser1
            parse2 <- parser2
            return AParse parse1 parse2

問題はparse1がparse2入力を消費することができるということです。だから、parse1常にリスト全体を消費し、そして何もparse2を残しています。

parse2を適用し、文字列の最後の要素以外のすべてにparse1を適用すると言う、とする方法はありますか?

役に立ちましたか?

解決

いかがます:

parseTrain car caboose = choice
    [ fmap (:[]) $ try (caboose `endBy` eof), 
    , liftM2 (:) car (parseTrain car caboose) 
    [

それは作るので、私は、このパーサは、組成ないEOFのバグ。即ちあなたが言うことができませんでした。

char '(' >> parseTrain p1 p2 >> char ')'

このcompsitionallyを行うと、パーサーのために非常に困難です。それはどのようにあらゆる機会にしようとし、それが失敗した場合に見ずに、「)」文字に移動する知っていることになっていますか?そうすることで、時間を指数関数可能性があります。

あなたはそれが組成する必要がある場合は、

、あなたの問題は、あなたが利用することができ、いくつかの付加的な構造を持っているのですか?あなたは、たとえば、すべての要素のリストを解析し、事実の後、最後の1を処理することはできますか?

他のヒント

それはそうのように定義されているので、あなたがparser1を考慮することができた場合:

parser1 = (try parser2) <|> parser1extra

すると問題は、後に終了しなければなりませんparser1extraまたはparser2のリストになります。あなたはそれをコーディングすることができます。

parserList =
    liftM2 (:) (try parser1extra) parserList
    <|>
    liftM2 (:) (try parser2) (option [] parserList)

これらのパーサは任意のプレフィックスの重複がある場合は、またはに応じてtryコールを必要としない場合があります。

あなたがリストでは、戻り値を

たくない場合は、代わりにあなたのAParseのデータは、その後、あなたはそれをこのように書き直すことができます:

parserList =
    do
        a <- try parser1extra
        prefix a parserList
    <|>
    do
        a <- try parser2
        option (AParse [] a) (prefix a parserList)

    where prefix a p = do
            (AParse as t) <- p
            return $ (AParse (a:as) t)

あるいは、完全な例:

import Control.Monad
import Text.ParserCombinators.Parsec

parseNum = do { v <- many1 digit; spaces; return v }
parseWord = do { v <- many1 letter; spaces; return v }
parsePart = parseNum <|> parseWord

parsePartListEndingInWord =
    liftM2 (:) (try parseNum) parsePartListEndingInWord
    <|>
    liftM2 (:) (try parseWord) (option [] parsePartListEndingInWord)

実際には、呼び出しはparseNumとして、この場合に必要とされていないしようとすると何の共通のプレフィックスと一致していないparseWord。実際parsePartListEndingInWordを参照しないように注意してくださいparsePartが、その代わりに、parsePartの定義を構成する2つのオプション

<時間>

(オリジナル答え、多少異なった状況を解決する:)

どのようなものについて:

parserTest = between (char '[') (char ']') $ do
    p1s <- try parser1 `endBy` char ',' 
    p2 <- parser2
    return $ AParse p1s p2

アップparseTestにあなたのパーサの外に句読点を撮影し、あなたがあなたのために仕事をするためにコンビネータのbetweenendByを使用することができます。最後に、tryparser1parser2は共通のプレフィックスに一致する場合、endByは共通のプレフィックスの先頭に正しいフルバックアップを実行するようにあります。

あなたのパーサによっては、あなたがあなたのサブパーサ内の句読点マッチングを残すことができ、あなたが必要とするすべてのtry周りparser1なる可能性があります:

parseTest = do parse1 <- many (try parser1)
               parse2 <- parser2
               return AParse parse1 parse2

私は一種の二つのアプローチを組み合わせます

parserList = try (do a <- parser2
                     eof
                     return $ AParse [] a)
             <|>
             do a <- parser1
                prefix a parserList
             where
                prefix a p = do
                    (AParse as t) <- p
                    return $ AParse a:as t

私は、これが私の目的のために働くだろうと思います。 ありがとう!

これは、トリックを行います。

parser1 `manyTill` (try parser2)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top