General.hs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. module Data.SExpression.General where
  2. import Control.Applicative
  3. import Data.Attoparsec.Text
  4. import Data.Map.String (Map)
  5. import qualified Data.Map.String as M
  6. type ReaderMacroMap atom = Map Char (Reader atom)
  7. type Reader atom = (Parser (SExpr atom) -> Parser (SExpr atom))
  8. type Serializer atom = atom -> Text
  9. -- | A 'SExprSpec' describes a parser and emitter for a particular
  10. -- variant of S-Expressions. The @atom@ type corresponds to a
  11. -- Haskell type used to represent the atoms, and the @carrier@
  12. -- type corresponds to the parsed S-Expression structure. This
  13. -- is deliberately opaque so that it must be constructed and
  14. -- modified with other helper functions.
  15. data SExprSpec atom carrier = SExprSpec
  16. { sesPAtom :: Parser atom
  17. , sesSAtom :: Serializer atom
  18. , rmMap :: ReaderMacroMap atom
  19. , postparse :: SExpr atom -> Either String carrier
  20. , preserial :: carrier -> SExpr atom
  21. }
  22. -- | This creates a basic 'SExprSpec' when given a parser and serializer
  23. -- for an atom type.
  24. mkSpec :: Parser atom -> Serializer atom -> SExprSpec atom (SExpr atom)
  25. mkSpec p s = SExprSpec
  26. { sesPAtom = p
  27. , sesSAtom = s
  28. , rmMap = M.empty
  29. , postparse = return
  30. , preserial = id
  31. }
  32. -- | This is used to modify the carrier type for a 'SExprSpec'. This is
  33. -- used internally to convert between various 'SExpr' representations,
  34. -- but could also be used externally to add an extra conversion layer
  35. -- onto a 'SExprSpec', e.g. for a custom Lisp-like language:
  36. --
  37. -- > mySpec :: SExprSpec MyAtomType MyAST
  38. -- > mySpec = convertSpec sexprToMyAST myASTToSexpr spec
  39. -- > where spec = mkSpec myParser mySerializer
  40. convertSpec :: (b -> Either String c) -> (c -> b) -> SExprSpec a b -> SExprSpec a c
  41. convertSpec f g spec = spec
  42. { postparse = postparse spec >=> f
  43. , preserial = g . preserial spec
  44. }
  45. addReader :: Char -> Reader a -> SExprSpec a c -> SExprSpec a c
  46. addReader c reader spec = spec { rmMap = insert c reader (rmMap spec) }
  47. quote :: atom -> Reader atom
  48. quote q parse = go <$> parse
  49. where go v = SCons q (SCons v SNil)
  50. toRich :: SExprSpec a (SExpr b) -> SExprSpec a (RichSExpr b)
  51. toRich = convertSpec (return . toRich) fromRich
  52. toWellFormed :: SExprSpec a (SExpr b) -> SExprSpec a (WellFormedSExpr b)
  53. toWellFormed = convertSpec toWellFormed fromWellFormed
  54. parseGenericSExpr :: Parser atom -> ReaderMacroMap atom -> Parser (SExpr atom)
  55. -- |
  56. parseSExpr :: SExprSpec atom carrier -> Text -> Either String carrier
  57. parseSExpr spec = undefined
  58. -- | blah
  59. serializeSExpr :: SExprSpec atom carrier -> carrier -> Text
  60. serializeSExpr spec = serializeGenericSExpr ses . preserial