Haskell Parsec ライブラリを使用して、ウィキペディアの XML ダンプを解析して、各ページの特定のリンクを見つけようとしています。リンクは二重括弧で示されます: texttext[[link]]texttext
. シナリオを可能な限り単純化するために、二重中括弧 (ネスト可能) で囲まれていない最初のリンクを探しているとします{{ {{ [[Wrong Link]] }} [[Wrong Link]] }} [[Right Link]]
。ネストされていない二重中括弧で囲まれているリンクを破棄するパーサーを作成しました。
import Text.Parsec
getLink :: String -> Either ParseError String
getLink = parse linkParser "Links"
linkParser = do
beforeLink
link <- many $ noneOf "]"
string "]]"
return link
beforeLink = manyTill (many notLink) (try $ string "[[")
notLink = try doubleCurlyBrac <|> (many1 normalText)
normalText = noneOf "[{"
<|> notFollowedByItself '['
<|> notFollowedByItself '{'
notFollowedByItself c = try ( do x <- char c
notFollowedBy $ char c
return x)
doubleCurlyBrac = between (string "{{") (string "}}") (many $ noneOf "}")
getLinkTest = fmap getLink testList
where testList = [" [[rightLink]] " --Correct link is found
, " {{ [[Wrong_Link]] }} [[rightLink]]" --Correct link is found
, " {{ {{ }} [[Wrong_Link]] }} [[rightLink]]" ] --Wrong link is found
doubleCurlyBrac
ネストされた中括弧内のリンクも破棄するようにパーサーを再帰的にしようとしましたが、成功しませんでした。
doubleCurlyBrac = between (string "{{") (string "}}") betweenBraces
where betweenBraces = doubleCurlyBrac <|> (many $ try $ noneOf "}")
このパーサーは}}
、ネストされた例では、最後のものではなく、最初の の後に入力の消費を停止します。(この場合) ネストされた二重中括弧内のリンクを正しく無視する再帰パーサーを作成するエレガントな方法はありますか? また、使わなくてもできtry
ますか?はtry
入力を消費しないため、パーサーが予期しない不適切な形式の入力でハングすることがよくあります。