Parsecを使ってみた

module Parser where
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Char

data Expr = E_Val Val
          | E_Seq [Expr]

instance Show Expr where
  showsPrec d (E_Val v) = showsPrec d v
  showsPrec d (E_Seq []) = showString "()"                          
  showsPrec d (E_Seq (e:[])) = showParen (d == 0) (showsPrec 0 e)
  showsPrec d (E_Seq (e:es)) = showParen (d == 0) (showsPrec 0 e .
                                                   showString " " .
                                                   showsPrec 1 (E_Seq es))

data Val = V_Int Int
         deriving Eq
  
instance Show Val where
  showsPrec d (V_Int num) = showsPrec d num

expr :: Parser Expr
expr = do { char '('
          ; many space
          ; es <- many (do { e <- expr
                           ; many space
                           ; return e
                           })
          ; char ')'
          ; return (E_Seq es)
          }
      <|> int

int = do { ds <- many1 digit
         ; return (E_Val $ V_Int $ read ds)
         }

実行結果はこんな感じ。

*Parser> parseTest expr "( 1 2  (1 2) )"
(1 2 (1 2))

なかなか良さそう。今度からは自作Parser Combinator Libraryモドキを使わずにParsecを使うようにしよう。