Basic.hs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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. infixr 5 :::
  22. -- | A shorter infix alias for `SCons`
  23. pattern x ::: xs = SCons x xs
  24. -- | A shorter alias for `SAtom`
  25. pattern A x = SAtom x
  26. -- | A (slightly) shorter alias for `SNil`
  27. pattern Nil = SNil
  28. -- | Utility function for parsing a pair of things.
  29. fromPair :: (SExpr t -> Either String a)
  30. -> (SExpr t -> Either String b)
  31. -> SExpr t -> Either String (a, b)
  32. fromPair pl pr (l ::: r ::: Nil) = (,) <$> pl l <*> pr r
  33. fromPair _ _ sx = Left ("Expected two-element list")
  34. -- | Utility function for parsing a list of things.
  35. fromList :: (SExpr t -> Either String a) -> SExpr t -> Either String [a]
  36. fromList p (s ::: ss) = (:) <$> p s <*> fromList p ss
  37. fromList p Nil = pure []
  38. fromList _ sx = Left ("Expected list")
  39. -- | Utility function for parsing a single atom
  40. fromAtom :: SExpr t -> Either String t
  41. fromAtom (A a) = return a
  42. fromAtom _ = Left "Expected atom; found list"
  43. gatherList :: SExpr t -> Either String [SExpr t]
  44. gatherList (x ::: xs) = (:) <$> pure x <*> gatherList xs
  45. gatherList Nil = pure []
  46. gatherList sx = Left ("Expected list")
  47. -- | Parse a two-element list (NOT a dotted pair) using the
  48. -- provided function.
  49. asPair :: ((SExpr t, SExpr t) -> Either String a)
  50. -> SExpr t -> Either String a
  51. asPair f (l ::: r ::: SNil) = f (l, r)
  52. asPair _ sx = Left ("Expected two-element list")
  53. -- | Parse an arbitrary-length list using the provided function.
  54. asList :: ([SExpr t] -> Either String a) -> SExpr t -> Either String a
  55. asList f ls = gatherList ls >>= f
  56. -- | Match a given literal atom, failing otherwise.
  57. isAtom :: Eq t => t -> SExpr t -> Either String ()
  58. isAtom s (A s')
  59. | s == s' = return ()
  60. | otherwise = Left ".."
  61. isAtom _ _ = Left ".."
  62. -- | Parse an atom using the provided function.
  63. asAtom :: (t -> Either String a) -> SExpr t -> Either String a
  64. asAtom f (A s) = f s
  65. asAtom _ sx = Left ("Expected symbol")
  66. -- | Parse an assoc-list using the provided function.
  67. asAssoc :: ([(SExpr t, SExpr t)] -> Either String a)
  68. -> SExpr t -> Either String a
  69. asAssoc f ss = gatherList ss >>= mapM go >>= f
  70. where go (a ::: b ::: Nil) = return (a, b)
  71. go sx = Left ("Expected two-element list")