Parsecお勉強メモ
とりあえずパーサまではつくってみようと思う。
基本
Parser パース結果型
hogehogeparser :: Parser HogeHoge
テスト用テンプレ:
module Main where import Text.ParserCombinators.Parsec import Text.ParserCombinators.Parsec.Expr import Text.ParserCombinators.Parsec.Language import qualified Text.ParserCombinators.Parsec.Token as P -- ここにコードかく run :: Show a => Parser a -> String -> IO () run p input = case (parse p "" input) of Left err -> do{ putStr "parse error at " ; print err } Right x -> print x
パーサをつなげる
それdo記法で:
ab :: Parser Int ab = do char 'a' char 'b' return 1 abnest :: Parser Int abnest = do char 'a' x <- abc char 'b' return (x + 1) <|> return 0 -- run abnest "aaabbb" -> 3
ちなみに<|>演算子は左パーサが一文字目で失敗したときのみ右パーサにfallbackする。2文字目以降の失敗でもfallbackするようにするにはtryをつかう。でもあんまり乱用するな!らしい。
左再帰はかけない
左再帰は書けないので、これは書けても:
parens :: Parser () parens = do{ char '(' ; parens ; char ')' ; parens } <|> return ()
これでparensを最初にもってくるとうごかない?
これは実行時にスタックオーバーフローする。
parens :: Parser () parens = do{ parens ; char '(' ; parens ; char ')' ; return () } <|> return ()
シーケンス
manyは正規表現の*、many1は+に相当。skipMany1?はmanyの結果返さないバージョン。
/[abc]/はoneOf "abc"と書ける。
letterは/[a-zA-Z]/なんだろうか。
式パーサ ParsecExpr
あとで続きかく