Repr.hs 3.1 KB

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