Trifectaを触ってみた
Haskellのパーサーライブラリといえば、
Peggyなどもありますが、やはりParsecというイメージが強い。
で、これまで書いたprojectなんかも殆どParsecを使って書いてきました。
そしたらつい先日、TrifectaとかいうEkmettさんのライブラリが存在することを知りました。
特徴についてはA Parsing Trifectaなんかにも書かれています。
ParsecのようなMonadicパーサーは使いやすく、それに対してMonoidsは並列でincrementalである、と。
この二つを、記述上ではParsecを踏襲して作成したライブラリだそうです。
というわけで、まだその機能の全容を把握できたわけではないのですが、とりあえずこれを使ってXMLパーサを書いてみた。
こんな感じで定義。
同時に、いい感じにShowクラスのインスタンスにしておきます。
data XML = XML{ tag :: String, content :: String, attribute :: [(String,String)], child :: Maybe XML }
import Text.Trifecta import Control.Applicative runXML :: Parser [XML] runXML = (:) <$> xml <*> (runXML <|> return []) xml :: Parser XML xml = do (tag,attrs) <- (,) <$> (symbol "<" *> many alphaNum) <*> attributes (mkXML tag attrs) <$> value <*> node tag attributes :: Parser [(String,String)] attributes = do spaces [] <$ symbol ">" <|> (:) <$> elem <*> attributes where elem = (,) <$> attr <*> attrValue attr = many alphaNum term = spaces *> symbol "=" <* spaces attrValue = term *> stringLiteral <* spaces value :: Parser String value = many (noneOf "<") node :: String -> Parser (Maybe XML) node tagName = Nothing <$ isEnd <|> Just <$> xml <* isEnd where isEnd = symbol $ "</" ++ tagName ++ ">" mkXML :: String -> [(String,String)] -> String -> Maybe XML -> XML mkXML tag attr content child = XML {tag = tag, content = content, attribute = attr, child = child} main = do file <- getLine parseTest (runXML <* eof) =<< readFile file
という感じで、ほとんどParsecと使用感変わらず使うことが出来ます。