Parsear S-Expr en Haskell

A continuación va la definición de un modulo Haskell para parsear s-expressions. No es necesario que entiendan su definición, pero sí deben saber usarlo. El tipo de dato para representar una s-expression es SExpr, y la función de parsing se llama parseSExpr.

SExprParser.hs
module SExprParser (SExpr(..), parseSExpr) where
 
import Text.ParserCombinators.Parsec hiding (spaces)
import Control.Monad
 
-- representation of an s-expr
-- (improper lists are not supported)
data SExpr = Atom String
           | List [SExpr]
           | Number Integer
           | Bool Bool
           | String String
             deriving Show
 
symbol :: Parser Char
symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
 
spaces :: Parser ()
spaces = skipMany1 space
 
parseExpr = parseAtom
            <|> parseNumber
            <|> parseString
            <|> do char '('
                   x <- parseList
                   char ')'
                   return x
 
parseAtom :: Parser SExpr
parseAtom = do first <- letter <|> symbol
               rest <- many (letter <|> digit <|> symbol)
               let atom = first:rest
               return $ case atom of 
                          "#t" -> Bool True
                          "#f" -> Bool False
                          _    -> Atom atom
 
parseList = liftM List $ sepBy parseExpr spaces
 
parseNumber = liftM (Number . read) $ many1 digit
 
parseString :: Parser SExpr
parseString = do char '"'
                 x <- many (noneOf "\"")
                 char '"'
                 return $ String x
 
parseSExpr :: String -> SExpr
parseSExpr prog = case (parse parseExpr "error" prog) of 
                    Left e -> error $ show e
                    Right sexpr -> sexpr

Para usar el parser, simplemente importe SExprParser (en un archivo, o en ghci):

> import SExprParser
> parseSExpr "(+ 1 (- 2 3))"
List [Atom "+",Number 1,List [Atom "-",Number 2,Number 3]]