Skip to content

Instantly share code, notes, and snippets.

@Lifelovinglight
Created July 3, 2016 14:56
Show Gist options
  • Save Lifelovinglight/5ac09d68664a9fcf511a09ce2ed33a00 to your computer and use it in GitHub Desktop.
Save Lifelovinglight/5ac09d68664a9fcf511a09ce2ed33a00 to your computer and use it in GitHub Desktop.
S-expression de/serializer using typeclasses
module Sexp (Sexp, parseSexp) where
import Text.Parsec
import Text.Parsec.Char
import Data.Char
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Map (Map)
import qualified Data.Map as Map
data Sexp = AtomSymbol Text
| AtomString Text
| AtomNumber Integer
| Sexp [Sexp]
instance Show Sexp where
show (AtomSymbol a) = show a
show (AtomString a) = show a
show (AtomNumber a) = show a
show (Sexp a) = parenthesize . unwords $ show <$> a
where parenthesize :: String -> String
parenthesize a = '(':a++")"
class SexpSerializable a where
serialize :: a -> Sexp
deserialize :: Sexp -> Maybe a
instance SexpSerializable Text where
serialize a = AtomString (Text.pack $ show a)
deserialize (AtomString a) = Just a
deserialize _ = Nothing
instance SexpSerializable Integer where
serialize a = AtomNumber a
deserialize (AtomNumber a) = Just a
deserialize _ = Nothing
instance (SexpSerializable a, Eq a) => SexpSerializable [a] where
serialize a = Sexp $ serialize <$> a
deserialize (Sexp a) = if any (== Nothing) ln
then Nothing
else Just $ (\(Just a) -> a) <$> ln
where ln = deserialize <$> a
deserialize _ = Nothing
parseSexp :: String -> Either ParseError Sexp
parseSexp = parse sexpParser ""
sexpParser :: Parsec String () Sexp
sexpParser =
skipWhitespace
>> between (char '(') (char ')')
(Sexp <$> sepBy (choice
[
AtomString . Text.pack <$> between quote quote (many $ noneOf "\"")
, AtomNumber . (read :: String -> Integer) <$> many1 digit
, AtomSymbol . Text.pack . fmap toLower <$> many1 letter
, sexpParser
])
skipWhitespace)
where skipWhitespace = skipMany $ oneOf " \n\t\r"
quote = char '"'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment