2016-07-05 13 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 

、その貪欲な性質のテキストとしてコメント欄を消費させるように些細な方法で、テキストチャンクのためのパーサをINGのことだから、質問がされるまでの解析のロジックを表現する方法です入力の終了またはコメントセクションまで?つまり、条件付き先読みパーサーを実装する方法は?私が最初に少しにあなたのコードをリファクタリングしたい、という取り組む前に

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コンビネータを使用することができます入力を消費します。つまり、(それを消費することなく)commentのいずれかに到達するまで、私たちはtext解析を行うことができ、または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))) 
関連する問題