我正在尝试解析以下行:
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:
所以参数s 可能是零次或多次出现。我不确定如何检测:
使用sepBy
. 如果我使用 Parsec,我会考虑使用sepEndBy
https://hackage.haskell.org/package/parsec-3.1.13.0/docs/Text-ParserCombinators-Parsec-Combinator.html#v:sepEndBy。
我正在寻找,sepBy
直到它看到:
. 我想我可以先消耗所有内容:
,然后运行parse
消耗字符串的“内部” onn,但是处理所有失败情况(部分等)似乎很乏味,我认为必须有更好的方法。
这是我的代码:
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
我想我对如何sepBy
运作有了更好的理解。本质上,您不必考虑“剩余”文本,因为使用 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 (== '=')
您可以以您选择的任何方式自由解析剩余的输入。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句