General.hs 2.6 KB

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