我正在学习parsec,刚遇到以下情况。我想将String
分隔为[String]
一个特定的String
;例如,我得到"abcSEPdef
,分隔符是" SEP",因此,在解析之后,我应该得到["abc","def"]
我相信解析器应该看起来像sepBy a_parser (string "SEP")
;但是,我不知道a_parser
应该是怎样的。
答案 0 :(得分:3)
使用manyTill
几次就可以了:
uptoSEP = manyTill anyChar (eof <|> (string "SEP" >> return ()))
splitSEP = manyTill uptoSEP eof
E.g:
ghci> parseTest splitSEP "abcSEPdefSEPxyz"
["abc","def","xyz"]
您需要启用{-# LANGUAGE NoMonomorphismRestriction #-}
pragma。
答案 1 :(得分:1)
找到&#34; SEP&#34;的否定,并让该解析器为parseNonSEP。 理论上确保parseNonSEP属于常规语言的范畴,因为常规语言在否定时被关闭,并且应该有一种直接的方式来实现它。
然后,
sepBy pareseNonSEP(字符串&#34; SEP&#34;)
将完成这项工作。
嗯,我上面提到的是一个相当理论的方法:) 更多parsec风格的方式可能是向前看输入令牌列表而不实际消耗输入和/或使用回溯,例如try,notFollowedBy,lookAhead。
见
http://hackage.haskell.org/package/parsec-3.1.9/docs/Text-Parsec-Combinator.html
答案 2 :(得分:0)
我终于找到了将split
包合并到parsec
中的方法:
module Sep where
import Text.ParserCombinators.Parsec
import qualified Data.List.Split as DLS
mysep :: String -> Parser [String]
mysep sep = getInput >>= return . DLS.splitOn sep
答案 3 :(得分:0)
replace-megaparsec
包有一个
sepCap
组合器,用于拆分字符串并捕获分隔。
import Replace.Megaparsec
import Text.Megaparsec
parseTest (sepCap (chunk "SEP" :: Parsec Void String String)) "abcSEPdef"
[Left "abc",Right "SEP",Left "def"]