如何使用Parsec通过特定字符串分隔字符串

时间:2015-07-28 03:48:13

标签: parsing haskell parsec

我正在学习parsec,刚遇到以下情况。我想将String分隔为[String]一个特定的String;例如,我得到"abcSEPdef,分隔符是" SEP",因此,在解析之后,我应该得到["abc","def"]

我相信解析器应该看起来像sepBy a_parser (string "SEP");但是,我不知道a_parser应该是怎样的。

4 个答案:

答案 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"]