我试图解析以下行:
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
答案 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 (== '=')
之后,您可以选择以任何方式解析剩余的输入。