gdritter repos s-cargot / b79d70e
Added richer bidirectional pattern synonyms and changed the semantics of ::: to be more consistent Getty Ritter 9 years ago
3 changed file(s) with 129 addition(s) and 4 deletion(s). Collapse all Expand all
11 {-# LANGUAGE PatternSynonyms #-}
2 {-# LANGUAGE ViewPatterns #-}
23
34 module Data.SCargot.Repr.Basic
45 ( -- * Basic 'SExpr' representation
56 R.SExpr(..)
7 -- * Constructing and Deconstructing
8 , cons
9 , uncons
610 -- * Shorthand Patterns
711 , pattern (:::)
812 , pattern A
13 , pattern L
14 , pattern DL
915 , pattern Nil
1016 -- * Lenses
1117 , _car
4854 _cdr _ (A a) = pure (A a)
4955 _cdr _ Nil = pure Nil
5056
57 -- | Produce the head and tail of the s-expression (if possible).
58 --
59 -- >>> uncons (A "el" ::: A "eph" ::: A "ant" ::: Nil)
60 -- Just (A "el",SCons (SAtom "eph") (SCons (SAtom "ant") SNil))
61 uncons :: SExpr a -> Maybe (SExpr a, SExpr a)
62 uncons (SCons x xs) = Just (x, xs)
63 uncons _ = Nothing
64
65 -- | Combine the two s-expressions into a new one.
66 --
67 -- >>> cons (A "el") (L ["eph", A "ant"])
68 -- SCons (SAtom "el) (SCons (SAtom "eph") (SCons (SAtom "ant") SNil))
69 cons :: SExpr a -> SExpr a -> SExpr a
70 cons = SCons
71
72 mkList :: [SExpr a] -> SExpr a
73 mkList [] = SNil
74 mkList (x:xs) = SCons x (mkList xs)
75
76 mkDList :: [SExpr a] -> a -> SExpr a
77 mkDList [] a = SAtom a
78 mkDList (x:xs) a = SCons x (mkDList xs a)
79
80 gatherDList :: SExpr a -> Maybe ([SExpr a], a)
81 gatherDList SNil = Nothing
82 gatherDList SAtom {} = Nothing
83 gatherDList sx = go sx
84 where go SNil = Nothing
85 go (SAtom a) = return ([], a)
86 go (SCons x xs) = do
87 (ys, a) <- go xs
88 return (x:ys, a)
89
5190 infixr 5 :::
5291
5392 -- | A shorter infix alias for `SCons`
93 --
94 -- >>> A "pachy" ::: A "derm"
95 -- SCons (SAtom "pachy") (SAtom "derm")
5496 pattern x ::: xs = SCons x xs
5597
5698 -- | A shorter alias for `SAtom`
99 --
100 -- >>> A "elephant"
101 -- SAtom "elephant"
57102 pattern A x = SAtom x
58103
59104 -- | A (slightly) shorter alias for `SNil`
105 --
106 -- >>> Nil
107 -- SNil
60108 pattern Nil = SNil
109
110 -- | An alias for matching a proper list.
111 --
112 -- >>> L [A "pachy", A "derm"]
113 -- SCons (SAtom "pachy") (SCons (SAtom "derm") SNil)
114 pattern L xs <- (gatherList -> Right xs)
115 where L xs = mkList xs
116
117 -- | An alias for matching a dotted list.
118 --
119 -- >>> DL [A "pachy"] A "derm"
120 -- SCons (SAtom "pachy") (SAtom "derm")
121 pattern DL xs x <- (gatherDList -> Just (xs, x))
122 where DL xs x = mkDList xs x
61123
62124 getShape :: SExpr a -> String
63125 getShape Nil = "empty list"
11 {-# LANGUAGE PatternSynonyms #-}
2 {-# LANGUAGE ViewPatterns #-}
23
34 module Data.SCargot.Repr.Rich
45 ( -- * 'RichSExpr' representation
56 R.RichSExpr(..)
67 , R.toRich
78 , R.fromRich
9 -- * Constructing and Deconstructing
10 , cons
11 , uncons
812 -- * Useful pattern synonyms
913 , pattern (:::)
1014 , pattern A
7175 _cdr _ (A a) = pure (A a)
7276 _cdr _ Nil = pure Nil
7377
78 -- | Produce the head and tail of the s-expression (if possible).
79 --
80 -- >>> uncons (L [A "el", A "eph", A "ant"])
81 -- Just (A "el",L [A "eph",A "ant"])
82 uncons :: RichSExpr a -> Maybe (RichSExpr a, RichSExpr a)
83 uncons R.RSAtom {} = Nothing
84 uncons (R.RSList (x:xs)) = Just (x, R.RSList xs)
85 uncons (R.RSDotted (x:xs) a) = Just (x, R.RSDotted xs a)
86
87 -- | Combine the two s-expressions into a new one.
88 --
89 -- >>> cons (A "el") (L [A "eph", A "ant"])
90 -- L [A "el",A "eph",A "ant"]
91 cons :: RichSExpr a -> RichSExpr a -> RichSExpr a
92 cons x (R.RSList xs) = R.RSList (x:xs)
93 cons x (R.RSDotted xs a) = R.RSDotted (x:xs) a
94 cons x (R.RSAtom a) = R.RSDotted [x] a
95
7496 -- | A shorter infix alias to grab the head
7597 -- and tail of an `RSList`.
76 pattern x ::: xs = R.RSList (x : xs)
98 --
99 -- >>> A "one" ::: L [A "two", A "three"]
100 -- RSList [RSAtom "one",RSAtom "two",RSAtom "three"]
101 pattern x ::: xs <- (uncons -> Just (x, xs))
102 where x ::: xs = cons x xs
77103
78104 -- | A shorter alias for `RSAtom`
105 --
106 -- >>> A "elephant"
107 -- RSAtom "elephant"
79108 pattern A a = R.RSAtom a
80109
81110 -- | A shorter alias for `RSList`
111 --
112 -- >>> L [A "pachy", A "derm"]
113 -- RSList [RSAtom "pachy",RSAtom "derm"]
82114 pattern L xs = R.RSList xs
83115
84116 -- | A shorter alias for `RSDotted`
117 --
118 -- >>> DL [A "pachy"] "derm"
119 -- RSDotted [RSAtom "pachy"] "derm"
85120 pattern DL xs x = R.RSDotted xs x
86121
87122 -- | A shorter alias for `RSList` @[]@
123 --
124 -- >>> Nil
125 -- RSList []
88126 pattern Nil = R.RSList []
89127
90128 -- | Utility function for parsing a pair of things: this parses a two-element list,
11 {-# LANGUAGE PatternSynonyms #-}
2 {-# LANGUAGE ViewPatterns #-}
23
34 module Data.SCargot.Repr.WellFormed
45 ( -- * 'WellFormedSExpr' representation
56 R.WellFormedSExpr(..)
67 , R.toWellFormed
78 , R.fromWellFormed
9 -- * Constructing and Deconstructing
10 , cons
11 , uncons
812 -- * Useful pattern synonyms
913 , pattern (:::)
1014 , pattern L
2630 import Control.Applicative ((<$>), (<*>), pure)
2731 import Data.SCargot.Repr as R
2832
29 -- | A shorter infix alias to grab the head
30 -- and tail of a `WFSList`
31 pattern x ::: xs = R.WFSList (x : xs)
33 uncons :: WellFormedSExpr a -> Maybe (WellFormedSExpr a, WellFormedSExpr a)
34 uncons R.WFSAtom {} = Nothing
35 uncons (R.WFSList (x:xs)) = Just (x, R.WFSList xs)
36
37 cons :: WellFormedSExpr a -> WellFormedSExpr a -> Maybe (WellFormedSExpr a)
38 cons _ (R.WFSAtom {}) = Nothing
39 cons x (R.WFSList xs) = Just (R.WFSList (x:xs))
40
41 -- | A shorter infix alias to grab the head and tail of a `WFSList`. This
42 -- pattern is unidirectional, because it cannot be guaranteed that it
43 -- is used to construct well-formed s-expressions; use the function "cons"
44 -- instead.
45 --
46 -- >>> let sum (x ::: xs) = x + sum xs; sum Nil = 0
47 pattern x ::: xs <- (uncons -> Just (x, xs))
3248
3349 -- | A shorter alias for `WFSList`
50 --
51 -- >>> L [A "pachy", A "derm"]
52 -- WFSList [WFSAtom "pachy",WFSAtom "derm"]
3453 pattern L xs = R.WFSList xs
3554
3655 -- | A shorter alias for `WFSAtom`
56 --
57 -- >>> A "elephant"
58 -- WFSAtom "elephant"
3759 pattern A a = R.WFSAtom a
3860
3961 -- | A shorter alias for `WFSList` @[]@
62 --
63 -- >>> Nil
64 -- WFSList []
4065 pattern Nil = R.WFSList []
4166
4267 getShape :: WellFormedSExpr a -> String