Repr.hs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. {-# LANGUAGE DeriveFunctor #-}
  2. module Data.SCargot.Repr
  3. ( -- * Elementary SExpr representation
  4. SExpr(..)
  5. -- * Rich SExpr representation
  6. , RichSExpr(..)
  7. , toRich
  8. , fromRich
  9. -- * Well-Formed SExpr representation
  10. , WellFormedSExpr(..)
  11. , toWellFormed
  12. , fromWellFormed
  13. ) where
  14. -- | All S-Expressions can be understood as a sequence
  15. -- of @cons@ cells (represented here by 'SCons'), the
  16. -- empty list @nil@ (represented by 'SNil') or an
  17. -- @atom@.
  18. data SExpr atom
  19. = SCons (SExpr atom) (SExpr atom)
  20. | SAtom atom
  21. | SNil
  22. deriving (Eq, Show, Read, Functor)
  23. -- | Sometimes, the cons-based interface is too low
  24. -- level, and we'd rather have the lists themselves
  25. -- exposed. In this case, we have 'RSList' to
  26. -- represent a well-formed cons list, and 'RSDotted'
  27. -- to represent an improper list of the form
  28. -- @(a b c . d)@. This representation is based on
  29. -- the shape of the parsed S-Expression, and not on
  30. -- how it was represented, so @(a . (b))@ is going to
  31. -- be represented as @RSList[RSAtom a, RSAtom b]@
  32. -- despite having been originally represented as a
  33. -- dotted list.
  34. data RichSExpr atom
  35. = RSList [RichSExpr atom]
  36. | RSDotted [RichSExpr atom] atom
  37. | RSAtom atom
  38. deriving (Eq, Show, Read, Functor)
  39. -- | It should always be true that
  40. --
  41. -- > fromRich (toRich x) == x
  42. --
  43. -- and that
  44. --
  45. -- > toRich (fromRich x) == x
  46. toRich :: SExpr atom -> RichSExpr atom
  47. toRich (SAtom a) = RSAtom a
  48. toRich (SCons x xs) = go xs (toRich x:)
  49. where go (SAtom a) rs = RSDotted (rs []) a
  50. go SNil rs = RSList (rs [])
  51. go (SCons x xs) rs = go xs (rs . (toRich x:))
  52. -- | This follows the same laws as 'toRich'.
  53. fromRich :: RichSExpr atom -> SExpr atom
  54. fromRich (RSAtom a) = SAtom a
  55. fromRich (RSList xs) = foldr SCons SNil (map fromRich xs)
  56. fromRich (RSDotted xs x) = foldr SCons (SAtom x) (map fromRich xs)
  57. -- | A well-formed s-expression is one which does not
  58. -- contain any dotted lists. This means that not
  59. -- every value of @SExpr a@ can be converted to a
  60. -- @WellFormedSExpr a@, although the opposite is
  61. -- fine.
  62. data WellFormedSExpr atom
  63. = WFSList [WellFormedSExpr atom]
  64. | WFSAtom atom
  65. deriving (Eq, Show, Read, Functor)
  66. -- | This will be @Nothing@ if the argument contains an
  67. -- improper list. It should hold that
  68. --
  69. -- > toWellFormed (fromWellFormed x) == Right x
  70. --
  71. -- and also (more tediously) that
  72. --
  73. -- > case fromWellFormed (toWellFormed x) of
  74. -- > Left _ -> True
  75. -- > Right y -> x == y
  76. toWellFormed :: SExpr atom -> Either String (WellFormedSExpr atom)
  77. toWellFormed SNil = return (WFSList [])
  78. toWellFormed (SAtom a) = return (WFSAtom a)
  79. toWellFormed (SCons x xs) = do
  80. x' <- toWellFormed x
  81. go xs (x':)
  82. where go (SAtom a) rs = Left "Found atom in cdr position"
  83. go SNil rs = return (WFSList (rs []))
  84. go (SCons x xs) rs = do
  85. x' <- toWellFormed x
  86. go xs (rs . (x':))
  87. -- | Convert a WellFormedSExpr back into a SExpr.
  88. fromWellFormed :: WellFormedSExpr atom -> SExpr atom
  89. fromWellFormed (WFSAtom a) = SAtom a
  90. fromWellFormed (WFSList xs) =
  91. foldr SCons SNil (map fromWellFormed xs)