@@ -1,3 +1,6 @@
1+{-# LANGUAGE RankNTypes #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+{-# LANGUAGE FlexibleContexts #-}
2Module : Data.Syntax.Combinator
5Module : Data.Syntax.Combinator
3Description : Combinators that work with any sequence type.
6Description : Combinators that work with any sequence type.
@@ -9,11 +12,50 @@ Stability : experimental
10Combinators that work with any sequence type.
13Combinators that work with any sequence type.
12−module Data.Syntax.Combinator where
15+module Data.Syntax.Combinator
14−import Control.Lens
24+ -- * Lists.
29+ -- * Arrowized combinators.
40+ -- * Unboxed vectors.
49+import Control.Category
50+import Control.Category.Structures
15−import Control.Lens.SemiIso
52+import Control.Lens.SemiIso
16−import Control.SIArrow
53+import Control.SIArrow
54+import qualified Data.MonoTraversable as Seq
56+import qualified Data.Vector as V
57+import qualified Data.Vector.Unboxed as VU
58+import Prelude hiding (id, (.), take)
18-- | One or zero occurences of @f@.
60-- | One or zero occurences of @f@.
19optional :: SIArrow cat => cat () a -> cat () (Maybe a)
61optional :: SIArrow cat => cat () a -> cat () (Maybe a)
@@ -28,6 +70,15 @@ opt_ :: SIArrow cat => cat () () -> cat () ()
28opt_ f = semiIso (const (Left "opt_")) Right /$/ f
70opt_ f = semiIso (const (Left "opt_")) Right /$/ f
29 /+/ sipure id
71 /+/ sipure id
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")
78+-- | Combine two alternatives.
79+eitherOf :: SIArrow cat => cat () a -> cat () b -> cat () (Either a b)
80+eitherOf a b = _Left /$/ a /+/ _Right /$/ b
31-- | @manyTill p end@ applies action p zero or more times until action
82-- | @manyTill p end@ applies action p zero or more times until action
32-- end succeeds, and returns the list of values returned by p.
83-- end succeeds, and returns the list of values returned by p.
33manyTill :: SIArrow cat => cat () a -> cat () () -> cat () [a]
84manyTill :: SIArrow cat => cat () a -> cat () () -> cat () [a]
@@ -42,11 +93,98 @@ sepBy v s = sepBy1 v s /+/ sipure _Empty
42sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
93sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
43sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
94sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
45−-- | Tries to apply the actions in the list in order, until one of
96+-- | A string of given length.
46−-- them succeeds. Returns the value of the succeeding action.
97+takeArr :: Syntax syn => syn Int (Seq syn)
47−choice :: SIArrow cat => [cat () a] -> cat () a
98+takeArr = sibind $ iso (\n -> constant n #>> take n)
48−choice = foldr (/+/) (sifail "choice: all alternatives failed")
99+ (\s -> constant (Seq.olength s) #>> take (Seq.olength s))
50−-- | Combine two alternatives.
101+-- | Constant size vector with separators.
51−eitherOf :: SIArrow cat => cat () a -> cat () b -> cat () (Either a b)
102+--
52−eitherOf a b = _Left /$/ a /+/ _Right /$/ b
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
107+-- | Constant size vector with separators and index-aware elements.
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)
114+ el k | k < n - 1 = unit ^>> e *** sep >># unit
117+-- | Runtime sized vector. The size can depend on the result of some computation.
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)
123+-- | Runtime sized vector with separators. The size can depend on the result of some
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
130+-- | Runtime sized vector with index-aware elements. The size can depend on the result
131+-- of some computation.
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)
137+-- | Runtime sized vector with index-aware elements and separators. The size can depend
138+-- on the result of some computation.
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)
145+-- | Constant size unboxed vector with separators.
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
151+-- | Constant size unboxed vector with separators and index-aware elements.
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)
159+ el k | k < n - 1 = unit ^>> e *** sep >># unit
162+-- | Runtime sized unboxed vector. The size can depend on the result of some computation.
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)
168+-- | Runtime sized unboxed vector with separators. The size can depend on the result of some
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
175+-- | Runtime sized unboxed vector with index-aware elements. The size can depend on the result
176+-- of some computation.
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)
182+-- | Runtime sized unboxed vector with index-aware elements and separators. The size can depend
183+-- on the result of some computation.
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)