2012-07-17 12 views
6

私はParsecを使ってHaskellにパーサを書き込もうとしています。現在、私はいくつかの方法が私のためにそこにあるHaskell Parsec Parser for Encountering [...]

test x [1,2,3] end 

commaSepが

commaSep  = skipMany1 (space <|> char ',') 

として定義されて

testParser = do { 
    reserved "test"; 
    v <- identifier; 
    symbol "["; 
    l <- sepBy natural commaSep; 
    symbol "]"; 
    p <- pParser; 
    return $ Test v (List l) p 
} <?> "end" 

を次のようにこれが与えられていたコードを解析できるプログラムを持っています同様の文を解析するために、具体的には:

test x [1...3] end 

ハスケルとParsecには新しいことがあるので、私は気づいていない、これを行うためのすばらしい簡潔な方法があると確信しています。どんな助けもありがとう。

もう一度おねがいします。

+0

期間の数は一定か可変であるべきですか?数字とピリオドの間、ピリオドの間にはスペースが許されていますか?ちなみに、最初のパーサーは 'test x [1、、2、,, 3] end'にマッチします。多分それはあなたが望むものではありません。 – dflemstr

+0

期間の数は一定でなければなりません。つまり、[1 ... 3]はどの場合でも正確に3つの期間で構成する必要があります。間にある空白は[1 ... 3]のように無視する必要があります。うまくいけば、私はもう少し後のことを明確にします。 –

答えて

14

Control.Applicativeの一部の機能を(*>)のように使用します。これらの関数は、Parsecのモナディックインタフェースを避けたい場合に便利です。アプリケーションインタフェースが好きなのは、パーサーが私の意見では読みやすくなるからです。

基本的なアプリケーション機能に精通していない場合は、コメントを残して説明します。あなたが確信が持てない場合はHoogleにそれらを見ることができます。


私はあなたの問題を理解してきたように、あなたはこのようないくつかのデータ構造のためのパーサをしたい:

data Test = Test String Numbers 
data Numbers = List [Int] | Range Int Int 

このようなデータ構造を解析できるパーサは(次のようになり、私はしましたコードをコンパイルしませんでしたが、それは動作するはずです):

-- parses "test <identifier> [<numbers>] end" 
testParser :: Parser Test 
testParser = 
    Test <$> reserved "test" *> identifier 
     <*> symbol "[" *> numbersParser <* symbol "]" 
     <* reserved "end" 
     <?> "test" 

numbersParser :: Parser Numbers 
numbersParser = try listParser <|> rangeParser 

-- parses "<natural>, <natural>, <natural>" etc 
listParser :: Parser Numbers 
listParser = 
    List <$> sepBy natural (symbol ",") 
     <?> "list" 

-- parses "<natural> ... <natural>" 
rangeParser :: Parser Numbers 
rangeParser = 
    Range <$> natural <* symbol "..." 
     <*> natural 
     <?> "range" 
+0

ああ、本当にありがとう、それは私が必要としていたものです。再度、感謝します! –

+1

@VincentRussoこれは 'fmap'と同義です。 – phg

+0

申し訳ありませんが、私はまだ正しいことをしようとしています。 l < - try(sepBy natural commaSep <|> natural symbol "..." natural)のような何かを行うことはできますか? 私の実装はここでは機能しませんが、似たようなことがありますか?あなたの例は素晴らしいですが、パーサが現在実装されている方法は、上の例でうまくいきません。皆さんのお手伝いをもう一度おねがいします。 –