2013-09-23 3 views
2

여러 문자로 구성된 구분 기호를 사용하여 문자열을 구분하려고 시도하고 있지만 문제는 각 문자가 구분되지 않는 문자열에서 단독으로 나타날 수 있다는 것입니다. 예를 들어 foo*X*bar*X*baz이 있는데 여기서 구분 기호는 *X*이므로 [foo, bar, baz]을 얻고 싶습니다. 그러나 각 요소에는 * 또는 X이 포함될 수 있습니다. ,Parsec과 모호한 구문 분석을 어떻게 구분합니까?

나는

sepBy (many anyChar) delimiter 

을 시도했지만 그건 그냥 내가

sepBy anyChar (optional delimiter) 

가 올바르게 구분 기호를 필터링 할 경우 "foo*X*bar*X*baz"을 제공, 전체 문자열을 삼켜하지만 목록을 분할하지 않습니다 "foobarbaz"을 반환합니다. 어떤 조합을 시도해 볼 수 있을지 모르겠다.

+0

우리는 3 개 기능을 가지고 있습니다. – wit

답변

3

은 아마도 당신은 try 우리가 분리 문자 소비에 과도하게 열망되지 않도록 할 수 있습니다,

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

anyToken 입력의 끝에서 영원히 반복에서 우리를 방지, 같은 것을 원한다. `lookAhead`,`manyTill`와`between` : 테스트에 대한

전체 코드,

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 <- 스캔; return (x : xs)}' 그리고 구분 기호의 구분 기호를 유지할 수 있도록 구분 기호에 lookAhead를 사용하고 구분 기호 만 'X'에 보관하십시오. –

관련 문제