@@ -1,3 +1,6 @@
1+{-# LANGUAGE RankNTypes #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+{-# LANGUAGE FlexibleContexts #-}
14{- |
25Module : Data.Syntax.Combinator
36Description : Combinators that work with any sequence type.
@@ -9,11 +12,50 @@ Stability : experimental
912
1013Combinators that work with any sequence type.
1114-}
12−module Data.Syntax.Combinator where
15+module Data.Syntax.Combinator
16+ (
17+ -- * Combinators.
18+ optional,
19+ opt,
20+ opt_,
21+ choice,
22+ eitherOf,
1323
14−import Control.Lens
15−import Control.Lens.SemiIso
16−import Control.SIArrow
24+ -- * Lists.
25+ manyTill,
26+ sepBy,
27+ sepBy1,
28+
29+ -- * Arrowized combinators.
30+ takeArr,
31+
32+ -- * Vectors.
33+ vecNSepBy,
34+ ivecNSepBy,
35+ vec,
36+ vecSepBy,
37+ ivec,
38+ ivecSepBy,
39+
40+ -- * Unboxed vectors.
41+ uvecNSepBy,
42+ uivecNSepBy,
43+ uvec,
44+ uvecSepBy,
45+ uivec,
46+ uivecSepBy
47+ ) where
48+
49+import Control.Category
50+import Control.Category.Structures
51+import Control.Lens
52+import Control.Lens.SemiIso
53+import Control.SIArrow
54+import qualified Data.MonoTraversable as Seq
55+import Data.Syntax
56+import qualified Data.Vector as V
57+import qualified Data.Vector.Unboxed as VU
58+import Prelude hiding (id, (.), take)
1759
1860-- | One or zero occurences of @f@.
1961optional :: SIArrow cat => cat () a -> cat () (Maybe a)
@@ -28,6 +70,15 @@ opt_ :: SIArrow cat => cat () () -> cat () ()
2870opt_ f = semiIso (const (Left "opt_")) Right /$/ f
2971 /+/ sipure id
3072
73+-- | Tries to apply the actions in the list in order, until one of
74+-- them succeeds. Returns the value of the succeeding action.
75+choice :: SIArrow cat => [cat () a] -> cat () a
76+choice = foldr (/+/) (sifail "choice: all alternatives failed")
77+
78+-- | Combine two alternatives.
79+eitherOf :: SIArrow cat => cat () a -> cat () b -> cat () (Either a b)
80+eitherOf a b = _Left /$/ a /+/ _Right /$/ b
81+
3182-- | @manyTill p end@ applies action p zero or more times until action
3283-- end succeeds, and returns the list of values returned by p.
3384manyTill :: SIArrow cat => cat () a -> cat () () -> cat () [a]
@@ -42,11 +93,98 @@ sepBy v s = sepBy1 v s /+/ sipure _Empty
4293sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
4394sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
4495
45−-- | Tries to apply the actions in the list in order, until one of
46−-- them succeeds. Returns the value of the succeeding action.
47−choice :: SIArrow cat => [cat () a] -> cat () a
48−choice = foldr (/+/) (sifail "choice: all alternatives failed")
96+-- | A string of given length.
97+takeArr :: Syntax syn => syn Int (Seq syn)
98+takeArr = sibind $ iso (\n -> constant n #>> take n)
99+ (\s -> constant (Seq.olength s) #>> take (Seq.olength s))
49100
50−-- | Combine two alternatives.
51−eitherOf :: SIArrow cat => cat () a -> cat () b -> cat () (Either a b)
52−eitherOf a b = _Left /$/ a /+/ _Right /$/ b
101+-- | Constant size vector with separators.
102+--
103+-- @vecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
104+vecNSepBy :: Syntax syn => Int -> syn () a -> syn () () -> syn () (V.Vector a)
105+vecNSepBy n e sep = ivecNSepBy n (unit ^>> second e) sep
106+
107+-- | Constant size vector with separators and index-aware elements.
108+--
109+-- @ivecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
110+-- Each element gets its index and should output a value and the index unchanged.
111+ivecNSepBy :: Syntax syn => Int -> syn Int (Int, a) -> syn () () -> syn () (V.Vector a)
112+ivecNSepBy n e sep = ivecN n $ sibind $ iso el (el . fst)
113+ where
114+ el k | k < n - 1 = unit ^>> e *** sep >># unit
115+ | otherwise = e
116+
117+-- | Runtime sized vector. The size can depend on the result of some computation.
118+--
119+-- @vec e@ describes a vector with elements @e@.
120+vec :: Syntax syn => syn () a -> syn Int (V.Vector a)
121+vec e = vecSepBy e (siarr id)
122+
123+-- | Runtime sized vector with separators. The size can depend on the result of some
124+-- computation.
125+--
126+-- @vecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
127+vecSepBy :: Syntax syn => syn () a -> syn () () -> syn Int (V.Vector a)
128+vecSepBy e sep = ivecSepBy (unit ^>> second e) sep
129+
130+-- | Runtime sized vector with index-aware elements. The size can depend on the result
131+-- of some computation.
132+--
133+-- @ivec e@ describes a vector with elements @e@.
134+ivec :: Syntax syn => syn Int (Int, a) -> syn Int (V.Vector a)
135+ivec e = ivecSepBy e (siarr id)
136+
137+-- | Runtime sized vector with index-aware elements and separators. The size can depend
138+-- on the result of some computation.
139+--
140+-- @ivecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
141+ivecSepBy :: Syntax syn => syn Int (Int, a) -> syn () () -> syn Int (V.Vector a)
142+ivecSepBy e sep = sibind $ iso (\n -> constant n #>> ivecNSepBy n e sep)
143+ (\v -> constant (V.length v) #>> ivecNSepBy (V.length v) e sep)
144+
145+-- | Constant size unboxed vector with separators.
146+--
147+-- @uvecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
148+uvecNSepBy :: (Syntax syn, VU.Unbox a) => Int -> syn () a -> syn () () -> syn () (VU.Vector a)
149+uvecNSepBy n e sep = uivecNSepBy n (unit ^>> second e) sep
150+
151+-- | Constant size unboxed vector with separators and index-aware elements.
152+--
153+-- @uivecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
154+-- Each element gets its index and should output a value and the index unchanged.
155+uivecNSepBy :: (Syntax syn, VU.Unbox a) => Int -> syn Int (Int, a)
156+ -> syn () () -> syn () (VU.Vector a)
157+uivecNSepBy n e sep = uivecN n $ sibind $ iso el (el . fst)
158+ where
159+ el k | k < n - 1 = unit ^>> e *** sep >># unit
160+ | otherwise = e
161+
162+-- | Runtime sized unboxed vector. The size can depend on the result of some computation.
163+--
164+-- @uvec e@ describes a vector with elements @e@.
165+uvec :: (Syntax syn, VU.Unbox a) => syn () a -> syn Int (VU.Vector a)
166+uvec e = uvecSepBy e (siarr id)
167+
168+-- | Runtime sized unboxed vector with separators. The size can depend on the result of some
169+-- computation.
170+--
171+-- @uvecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
172+uvecSepBy :: (Syntax syn, VU.Unbox a) => syn () a -> syn () () -> syn Int (VU.Vector a)
173+uvecSepBy e sep = uivecSepBy (unit ^>> second e) sep
174+
175+-- | Runtime sized unboxed vector with index-aware elements. The size can depend on the result
176+-- of some computation.
177+--
178+-- @uivec e@ describes a vector with elements @e@.
179+uivec :: (Syntax syn, VU.Unbox a) => syn Int (Int, a) -> syn Int (VU.Vector a)
180+uivec e = uivecSepBy e (siarr id)
181+
182+-- | Runtime sized unboxed vector with index-aware elements and separators. The size can depend
183+-- on the result of some computation.
184+--
185+-- @uivecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
186+uivecSepBy :: (Syntax syn, VU.Unbox a) => syn Int (Int, a)
187+ -> syn () () -> syn Int (VU.Vector a)
188+uivecSepBy e sep = sibind $ iso (\n -> constant n #>> uivecNSepBy n e sep)
189+ (\v -> constant (VU.length v)
190+ #>> uivecNSepBy (VU.length v) e sep)