Basic.hs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. {-# LANGUAGE PatternSynonyms #-}
  2. module Data.SCargot.Repr.Basic
  3. ( -- * Basic 'SExpr' representation
  4. R.SExpr(..)
  5. -- * Shorthand Patterns
  6. , pattern (:::)
  7. , pattern A
  8. , pattern Nil
  9. -- * Useful processing functions
  10. , fromPair
  11. , fromList
  12. , fromAtom
  13. , asPair
  14. , asList
  15. , isAtom
  16. , asAtom
  17. , asAssoc
  18. ) where
  19. import Control.Applicative ((<$>), (<*>), pure)
  20. import Data.SCargot.Repr as R
  21. -- | A shorter infix alias for `SCons`
  22. pattern x ::: xs = SCons x xs
  23. -- | A shorter alias for `SAtom`
  24. pattern A x = SAtom x
  25. -- | A (slightly) shorter alias for `SNil`
  26. pattern Nil = SNil
  27. -- | Utility function for parsing a pair of things.
  28. fromPair :: (SExpr t -> Either String a)
  29. -> (SExpr t -> Either String b)
  30. -> SExpr t -> Either String (a, b)
  31. fromPair pl pr (l ::: r ::: Nil) = (,) <$> pl l <*> pr r
  32. fromPair _ _ sx = Left ("Expected two-element list")
  33. -- | Utility function for parsing a list of things.
  34. fromList :: (SExpr t -> Either String a) -> SExpr t -> Either String [a]
  35. fromList p (s ::: ss) = (:) <$> p s <*> fromList p ss
  36. fromList p Nil = pure []
  37. fromList _ sx = Left ("Expected list")
  38. -- | Utility function for parsing a single atom
  39. fromAtom :: SExpr t -> Either String t
  40. fromAtom (A a) = return a
  41. fromAtom _ = Left "Expected atom; found list"
  42. gatherList :: SExpr t -> Either String [SExpr t]
  43. gatherList (x ::: xs) = (:) <$> pure x <*> gatherList xs
  44. gatherList Nil = pure []
  45. gatherList sx = Left ("Expected list")
  46. -- | Parse a two-element list (NOT a dotted pair) using the
  47. -- provided function.
  48. asPair :: ((SExpr t, SExpr t) -> Either String a)
  49. -> SExpr t -> Either String a
  50. asPair f (l ::: r ::: SNil) = f (l, r)
  51. asPair _ sx = Left ("Expected two-element list")
  52. -- | Parse an arbitrary-length list using the provided function.
  53. asList :: ([SExpr t] -> Either String a) -> SExpr t -> Either String a
  54. asList f ls = gatherList ls >>= f
  55. -- | Match a given literal atom, failing otherwise.
  56. isAtom :: Eq t => t -> SExpr t -> Either String ()
  57. isAtom s (A s')
  58. | s == s' = return ()
  59. | otherwise = Left ".."
  60. isAtom _ _ = Left ".."
  61. -- | Parse an atom using the provided function.
  62. asAtom :: (t -> Either String a) -> SExpr t -> Either String a
  63. asAtom f (A s) = f s
  64. asAtom _ sx = Left ("Expected symbol")
  65. -- | Parse an assoc-list using the provided function.
  66. asAssoc :: ([(SExpr t, SExpr t)] -> Either String a)
  67. -> SExpr t -> Either String a
  68. asAssoc f ss = gatherList ss >>= mapM go >>= f
  69. where go (a ::: b ::: Nil) = return (a, b)
  70. go sx = Left ("Expected two-element list")