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

あとで続きかく