2013-09-23 106 views
2

我想使用由多個字符組成的分隔符來分隔字符串,但問題是每個這些字符都可能出現在非分隔字符串中。例如,我有foo*X*bar*X*baz,其中分隔符是*X*,所以我想獲得[foo, bar, baz],但其中每一個都可以包含*X如何使用Parsec sepBy模糊解析?

我已經試過

sepBy (many anyChar) delimiter 

但只是吞下整個字符串,給人"foo*X*bar*X*baz",如果我做

sepBy anyChar (optional delimiter) 

它正確地過濾掉分隔符,但不分區名單,返回"foobarbaz"。我不知道我可以嘗試哪種組合。

+0

我們必須爲3個功能:'lookAhead','manyTill'和'between'。 – wit

回答

3

也許你想這樣的事情,

tok = (:) <$> anyToken <*> manyTill anyChar (try (() <$ string sep) <|> eof) 

anyToken阻止我們在輸入的結束無休止的循環下去try讓我們避免被過度急於在消費分隔符。爲測試

的完整代碼,

module ParsecTest where 
import Control.Applicative ((<$), (<$>), (<*>)) 
import Data.List (intercalate) 
import Text.Parsec 
import Text.Parsec.String 

sep,msg :: String 
sep = "*X*" 
msg = intercalate "*X*" ["foXo", "ba*Xr", "bX*az"] 

tok :: Parser String 
tok = (:) <$> anyToken <*> manyTill anyChar (try (() <$ string sep) <|> eof) 

toks :: Parser [String] 
toks = many tok 

test :: Either ParseError [String] 
test = runP toks() "" msg 
+0

這工作完美。必須將manyTill函數重寫爲'manyTill2 p end = scan 其中 scan = do {x < - end; return x} <|> do {x < - p; xs < - scan; return(x:xs)}' 並在分隔符上使用lookAhead,這樣我就可以保留分隔符的分隔符,並且只能在'X'上分區。 –