2016-07-05 2 views
3

내부에 주석이있는 텍스트를 나타내는 데이터 구조가 있다고 가정합니다. 따라서 문자열attoparsec의 조건부 미리보기

"Text, {-comment-}, and something else" 

코멘트 청크 및 E에 대한

T "Text, " (C "comment" (T ", and something else" E)) 

파서로 인코딩 할 수 있었던 것처럼

data TWC 
    = T Text TWC -- text 
    | C Text TWC -- comment 
    | E -- end 
    deriving Show 

아주 사소한 :

twcP :: Parser TWC 
twcP = eP <|> cP <|> tP 

cP :: Parser TWC 
cP = do 
    _ <- string "{-" 
    c <- manyTill anyChar (string "-}") 
    rest <- cP <|> tP <|> eP 
    return (C (pack c) rest) 

eP :: Parser TWC 
eP = do 
    endOfInput 
    return E 

구현 이러한 사소한 방법으로 텍스트 청크에 대한 파서를 보내고하는

tP :: Parser TWC 
tP = do 
    t <- many1 anyChar 
    rest <- cP <|> eP 
    return (T (pack t) rest) 

이 때문에

> parseOnly twcP "text{-comment-}" 
Right (T "text{-comment-}" E) 
it ∷ Either String TWC 

그래서 그것의 욕심이 자연의 텍스트로 코멘트 섹션을 소비하기 위해선, 질문까지 분석의 논리를 표현하는 방법이다 입력 끝 또는 코멘트 섹션까지? 즉, 조건부 미리보기 파서를 구현하는 방법은 무엇입니까? 나는 처음에 약간의 코드를 리팩토링 할

tP = do 
    t <- many1 anyChar 

을 그를 해결하기 전에 :

답변

5

당신이 옳은 것은 문제가있는 코드는 주석에서 멈추지 않고 텍스트를 탐욕 구문 분석 tP의 첫 번째 줄입니다 도우미를 소개하고 text 도우미에 고립 된 문제가있는 코드로, 실용적 스타일을 사용 :

-- Like manyTill, but pack the result to Text. 
textTill :: Alternative f => f Char -> f b -> f Text 
textTill p end = pack <$> manyTill p end 

-- Parse one comment string 
comment :: Parser Text 
comment = string "{-" *> textTill anyChar (string "-}") 

-- Parse one non-comment text string (problematic implementation) 
text :: Parser Text 
text = pack <$> many1 anyChar 

-- TWC parsers: 

twcP :: Parser TWC 
twcP = eP <|> cP <|> tP 

cP :: Parser TWC 
cP = C <$> comment <*> twcP 

eP :: Parser TWC 
eP = E <$ endOfInput 

tP :: Parser TWC 
tP = T <$> text <*> twcP 

이 내다을 구현하기 위해, 우리는 파서 witho를 적용 lookAhead 콤비를 사용할 수 있습니다 ut는 입력을 소비합니다. 즉,이 중 하나에 도달 할 때까지 우리가 text 구문 분석을 할 수있는 comment (그것을 사용하지 않고), 또는 endOfInput : 그 구현

-- Parse one non-comment text string (working implementation) 
text :: Parser Text 
text = textTill anyChar (void (lookAhead comment) <|> endOfInput) 

, 예상대로 twcP 동작합니다

ghci> parseOnly twcP "text{-comment-} post" 
Right (T "text" (C "comment" (T " post" E)))