module Language.MicroLisp.SExprParser ( readSExpr , SExpr(..) ) where import Control.Monad import Text.ParserCombinators.Parsec hiding (spaces) data SExpr = SAtom String | SList [SExpr] | SInt Int symbol :: Parser Char symbol = oneOf "!#$%&|*+-/:<=>?@^_~" spaces :: Parser () spaces = skipMany1 space parseAtom :: Parser SExpr parseAtom = do first <- letter <|> symbol rest <- many (letter <|> digit <|> symbol) let atom = first:rest return $ SAtom atom parseNumber :: Parser SExpr parseNumber = (SInt . read) <$> many1 digit parseSList :: Parser SExpr parseSList = SList <$> sepBy parseExpr spaces parseExpr :: Parser SExpr parseExpr = parseAtom <|> parseNumber <|> do char '(' x <- try parseSList char ')' return x -- | Parse an s-expression readSExpr :: String -> Either ParseError SExpr readSExpr input = parse parseExpr "SExpr" input