如何在attoparsec中使用带有结束字符的sepBy?

时间:2018-03-16 09:59:00

标签: haskell attoparsec

我试图解析以下行:

ItemCount count@Int: You have purchased #{showInt count} #{plural count "item" "items"}

基本上我试图获得:

  Message {
      key = "ItemCount",
      value = "You have purchased #{showInt count} #{plural count \"item\" \"items\"}.",
      parameters = [Parameter {name = "count", paramType = "Int"}]
      }

第一位ItemCount count@Int:可以是:

ItemCount:

ItemCount count@Int count2@Int:

因此参数可能是零或更多的出现。我不确定在使用:时如何检测sepBy。如果我使用Parsec,我会使用sepEndBy https://hackage.haskell.org/package/parsec-3.1.13.0/docs/Text-ParserCombinators-Parsec-Combinator.html#v:sepEndBy

我有点寻找sepBy,直到它看到:的字符。我想我可以先消耗所有内容直到:,然后运行内部' parse onn消耗了字符串,但处理所有失败案例(Partial等)似乎很乏味,而且我认为必须有更好的方法。

这是我的代码:

import Control.Applicative
import Data.Attoparsec.Text
import Data.Text (Text)

data Parameter = Parameter { name :: Text, paramType :: Text } deriving (Eq, Show)
data Message = Message { key :: Text, value :: Text, parameters :: [Parameter] } deriving (Eq, Show)
data KeyAndParameters = KeyAndParameters Text [Parameter]

parseParameter :: Parser Parameter
parseParameter = do
  n <- takeWhile1 (notInClass "@")
  _ <- char '@'
  t <- takeWhile1 (const True)
  return $ Parameter { name = n, paramType = t }

parseKeyAndParameters :: Parser KeyAndParameters
parseKeyAndParameters = do
  keyV <- takeWhile1 (notInClass " :")
  params <- parseParameter `sepBy` (char ' ')
  return $ KeyAndParameters keyV params

1 个答案:

答案 0 :(得分:0)

我想我对sepBy的运作方式有了更好的理解。基本上你不必采取剩下的&#39;考虑到文本,与attoparsec一样,你不必消耗所有输出直到结束(与Parsec不同)。

例如,给定1+2+3=6作为输入和以下内容:

parseExample :: Parser ([Text], Text)
parseExample = do
  numbers <- takeWhile1 (notInClass "=+") `sepBy` char '+'
  skip (== '=')
  total <- takeWhile1 (const True)
  return $ (numbers, total)

将返回:( [ "1" , "2" , "3" ] , "6")

skip (== '=')之后,您可以选择以任何方式解析剩余的输入。