Rich.hs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. {-# LANGUAGE PatternSynonyms #-}
  2. module Data.SCargot.Repr.Rich
  3. ( -- * 'RichSExpr' representation
  4. R.RichSExpr(..)
  5. , R.toRich
  6. , R.fromRich
  7. -- * Useful pattern synonyms
  8. , pattern (:::)
  9. , pattern A
  10. , pattern L
  11. , pattern DL
  12. , pattern Nil
  13. -- * Useful processing functions
  14. , fromPair
  15. , fromList
  16. , fromAtom
  17. , asPair
  18. , asList
  19. , isAtom
  20. , asAtom
  21. , asAssoc
  22. ) where
  23. import Control.Applicative ((<$>), (<*>), pure)
  24. import Data.SCargot.Repr as R
  25. -- | A shorter infix alias to grab the head
  26. -- and tail of an `RSList`.
  27. pattern x ::: xs = R.RSList (x : xs)
  28. -- | A shorter alias for `RSAtom`
  29. pattern A a = R.RSAtom a
  30. -- | A shorter alias for `RSList`
  31. pattern L xs = R.RSList xs
  32. -- | A shorter alias for `RSDotted`
  33. pattern DL xs x = R.RSDotted xs x
  34. -- | A shorter alias for `RSList []`
  35. pattern Nil = R.RSList []
  36. -- | Utility function for parsing a pair of things.
  37. fromPair :: (RichSExpr t -> Either String a)
  38. -> (RichSExpr t -> Either String b)
  39. -> RichSExpr t -> Either String (a, b)
  40. fromPair pl pr = asPair $ \(l,r) -> (,) <$> pl l <*> pr r
  41. -- | Utility function for parsing a list of things.
  42. fromList :: (RichSExpr t -> Either String a) -> RichSExpr t -> Either String [a]
  43. fromList p = asList $ \ss -> mapM p ss
  44. -- | Utility function for parsing a single atom
  45. fromAtom :: RichSExpr t -> Either String t
  46. fromAtom (L _) = Left "Expected atom; found list"
  47. fromAtom (A a) = return a
  48. -- | RichSExpr a -> Either String two-element list (NOT a dotted pair) using the
  49. -- provided function.
  50. asPair :: ((RichSExpr t, RichSExpr t) -> Either String a)
  51. -> RichSExpr t -> Either String a
  52. asPair f (L [l, r]) = f (l, r)
  53. asPair _ sx = Left ("Expected two-element list")
  54. -- | Parse an arbitrary-length list using the provided function.
  55. asList :: ([RichSExpr t] -> Either String a)
  56. -> RichSExpr t -> Either String a
  57. asList f (L ls) = f ls
  58. asList _ sx = Left ("Expected list")
  59. -- | Match a given literal atom, failing otherwise.
  60. isAtom :: Eq t => t -> RichSExpr t -> Either String ()
  61. isAtom s (A s')
  62. | s == s' = return ()
  63. | otherwise = Left ".."
  64. isAtom _ _ = Left ".."
  65. -- | Parse an atom using the provided function.
  66. asAtom :: (t -> Either String a) -> RichSExpr t -> Either String a
  67. asAtom f (A s) = f s
  68. asAtom _ sx = Left ("Expected atom; got list")
  69. -- | Parse an assoc-list using the provided function.
  70. asAssoc :: Show t => ([(RichSExpr t, RichSExpr t)] -> Either String a)
  71. -> RichSExpr t -> Either String a
  72. asAssoc f (L ss) = gatherPairs ss >>= f
  73. where gatherPairs (L [a, b] : ss) = (:) <$> pure (a, b) <*> gatherPairs ss
  74. gatherPairs [] = pure []
  75. gatherPairs _ = Left "..."
  76. asAssoc _ sx = Left ("Expected assoc list; got " ++ show sx)
  77. car :: (RichSExpr t -> Either String t') -> [RichSExpr t] -> Either String t'
  78. car f (x:_) = f x
  79. car _ [] = Left "car: Taking car of zero-element list"
  80. cdr :: ([RichSExpr t] -> Either String t') -> [RichSExpr t] -> Either String t'
  81. cdr f (_:xs) = f xs
  82. cdr _ [] = Left "cdr: Taking cdr of zero-element list"