6

Parsecを使用してHaskellでパーサーを作成しようとしています。現在、私は解析できるプログラムを持っています

test x [1,2,3] end

これを行うコードは次のとおりです。

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

ここで、commaSepは次のように定義されます。

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

これで、同様のステートメントを解析する方法がいくつかあります。具体的には、次のとおりです。

test x [1...3] end

Haskell、そしてそのことについてはParsecに慣れていないので、私が気付いていない、これを行うためのいくつかの素晴らしい簡潔な方法があると確信しています。どんな助けでもいただければ幸いです。

再度、感謝します。

4

1 に答える 1

14

Control.Applicativeのような関数を使用します(*>)。これらの関数は、パーセクのモナディックインターフェイスを避け、アプリケーションインターフェイスを好む場合に役立ちます。これは、パーセクが私の意見ではそのように読みやすくなるためです。

基本的なアプリケーション機能に慣れていない場合は、コメントを残して説明します。よくわからない場合は、 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"
于 2012-07-17T15:47:53.247 に答える