on master help sign in
3 files changed+114−19
since splitsnapshots
unifiedsplit
Data/Syntax.hs+34−3 Data/Syntax/Combinator.hs+73−9 syntax.cabal+7−7
Data/Syntax.hs+34−3
@@ -30,7 +30,8 @@ import Control.Lens.SemiIso
3030import Control.SIArrow
3131import Data.MonoTraversable
3232import Data.Sequences hiding (take, takeWhile, replicate)
33−import Data.Vector (Vector)
33+import qualified Data.Vector as V
34+import qualified Data.Vector.Unboxed as VU
3435
3536-- | An isomorphism between a sequence and a list of its elements.
3637packed :: IsSequence seq => Iso' seq [Element seq]
@@ -105,7 +106,7 @@ class ( SIArrow syn
105106 -- @vecN n e@ describes a size @n@ vector with elements @e@.
106107 --
107108 -- Also see 'Data.Syntax.Combinator.vec'.
108− vecN :: Int -> syn () a -> syn () (Vector a)
109+ vecN :: Int -> syn () a -> syn () (V.Vector a)
109110 vecN n e = packed /$/ sireplicate n e
110111
111112 -- | Constant size vector with index-aware element. The default implementation
@@ -116,7 +117,7 @@ class ( SIArrow syn
116117 -- gets its index and should output a value and the index unchanged.
117118 --
118119 -- Also see 'Data.Syntax.Combinator.ivec'.
119− ivecN :: Int -> syn Int (Int, a) -> syn () (Vector a)
120+ ivecN :: Int -> syn Int (Int, a) -> syn () (V.Vector a)
120121 ivecN n e = (packed /$/)
121122 $ sisequence
122123 $ map (\(i, e') -> constant i ^>> e'
@@ -124,6 +125,32 @@ class ( SIArrow syn
124125 >># unit . swapped)
125126 $ zip [0 .. n-1] (replicate n e)
126127
128+ -- | Constant size unboxed vector. The default implementation uses lists, but
129+ -- "syntax-attoparsec" and "syntax-printer" override it with an efficient
130+ -- implementation that works on a vector directly.
131+ --
132+ -- @vecN n e@ describes a size @n@ vector with elements @e@.
133+ --
134+ -- Also see 'Data.Syntax.Combinator.vec'.
135+ uvecN :: VU.Unbox a => Int -> syn () a -> syn () (VU.Vector a)
136+ uvecN n e = packed /$/ sireplicate n e
137+
138+ -- | Constant size unboxed vector with index-aware element. The default implementation
139+ -- uses lists, but "syntax-attoparsec" and "syntax-printer" override it with an
140+ -- efficient implementation that works on a vector directly.
141+ --
142+ -- @ivecN n e@ describes a size @n@ vector with elements @e@. Each element
143+ -- gets its index and should output a value and the index unchanged.
144+ --
145+ -- Also see 'Data.Syntax.Combinator.ivec'.
146+ uivecN :: VU.Unbox a => Int -> syn Int (Int, a) -> syn () (VU.Vector a)
147+ uivecN n e = (packed /$/)
148+ $ sisequence
149+ $ map (\(i, e') -> constant i ^>> e'
150+ >>> first (sipure (constant i))
151+ >># unit . swapped)
152+ $ zip [0 .. n-1] (replicate n e)
153+
127154 {-# MINIMAL anyChar #-}
128155
129156instance Syntax syn => Syntax (ReaderCT env syn) where
@@ -139,6 +166,10 @@ instance Syntax syn => Syntax (ReaderCT env syn) where
139166 takeWhile1 = clift . takeWhile1
140167 takeTill = clift . takeTill
141168 takeTill1 = clift . takeTill1
169+ vecN n e = ReaderCT $ vecN n . runReaderCT e
170+ ivecN n e = ReaderCT $ ivecN n . runReaderCT e
171+ uvecN n e = ReaderCT $ uvecN n . runReaderCT e
172+ uivecN n e = ReaderCT $ uivecN n . runReaderCT e
142173
143174-- | Execute a computation in an isolated context.
144175--
Data/Syntax/Combinator.hs+73−9
@@ -26,13 +26,24 @@ module Data.Syntax.Combinator
2626 sepBy,
2727 sepBy1,
2828
29+ -- * Arrowized combinators.
30+ takeArr,
31+
2932 -- * Vectors.
3033 vecNSepBy,
3134 ivecNSepBy,
3235 vec,
3336 vecSepBy,
3437 ivec,
35− ivecSepBy
38+ ivecSepBy,
39+
40+ -- * Unboxed vectors.
41+ uvecNSepBy,
42+ uivecNSepBy,
43+ uvec,
44+ uvecSepBy,
45+ uivec,
46+ uivecSepBy
3647 ) where
3748
3849import Control.Category
@@ -40,10 +51,11 @@ import Control.Category.Structures
4051import Control.Lens
4152import Control.Lens.SemiIso
4253import Control.SIArrow
54+import qualified Data.MonoTraversable as Seq
4355import Data.Syntax
44−import Data.Vector (Vector)
4556import qualified Data.Vector as V
46−import Prelude hiding (id, (.))
57+import qualified Data.Vector.Unboxed as VU
58+import Prelude hiding (id, (.), take)
4759
4860-- | One or zero occurences of @f@.
4961optional :: SIArrow cat => cat () a -> cat () (Maybe a)
@@ -81,17 +93,22 @@ sepBy v s = sepBy1 v s /+/ sipure _Empty
8193sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
8294sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
8395
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))
100+
84101-- | Constant size vector with separators.
85102--
86103-- @vecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
87−vecNSepBy :: Syntax syn => Int -> syn () a -> syn () () -> syn () (Vector a)
104+vecNSepBy :: Syntax syn => Int -> syn () a -> syn () () -> syn () (V.Vector a)
88105vecNSepBy n e sep = ivecNSepBy n (unit ^>> second e) sep
89106
90107-- | Constant size vector with separators and index-aware elements.
91108--
92109-- @ivecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
93110-- Each element gets its index and should output a value and the index unchanged.
94−ivecNSepBy :: Syntax syn => Int -> syn Int (Int, a) -> syn () () -> syn () (Vector a)
111+ivecNSepBy :: Syntax syn => Int -> syn Int (Int, a) -> syn () () -> syn () (V.Vector a)
95112ivecNSepBy n e sep = ivecN n $ sibind $ iso el (el . fst)
96113 where
97114 el k | k < n - 1 = unit ^>> e *** sep >># unit
@@ -100,27 +117,74 @@ ivecNSepBy n e sep = ivecN n $ sibind $ iso el (el . fst)
100117-- | Runtime sized vector. The size can depend on the result of some computation.
101118--
102119-- @vec e@ describes a vector with elements @e@.
103−vec :: Syntax syn => syn () a -> syn Int (Vector a)
120+vec :: Syntax syn => syn () a -> syn Int (V.Vector a)
104121vec e = vecSepBy e (siarr id)
105122
106123-- | Runtime sized vector with separators. The size can depend on the result of some
107124-- computation.
108125--
109126-- @vecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
110−vecSepBy :: Syntax syn => syn () a -> syn () () -> syn Int (Vector a)
127+vecSepBy :: Syntax syn => syn () a -> syn () () -> syn Int (V.Vector a)
111128vecSepBy e sep = ivecSepBy (unit ^>> second e) sep
112129
113130-- | Runtime sized vector with index-aware elements. The size can depend on the result
114131-- of some computation.
115132--
116133-- @ivec e@ describes a vector with elements @e@.
117−ivec :: Syntax syn => syn Int (Int, a) -> syn Int (Vector a)
134+ivec :: Syntax syn => syn Int (Int, a) -> syn Int (V.Vector a)
118135ivec e = ivecSepBy e (siarr id)
119136
120137-- | Runtime sized vector with index-aware elements and separators. The size can depend
121138-- on the result of some computation.
122139--
123140-- @ivecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
124−ivecSepBy :: Syntax syn => syn Int (Int, a) -> syn () () -> syn Int (Vector a)
141+ivecSepBy :: Syntax syn => syn Int (Int, a) -> syn () () -> syn Int (V.Vector a)
125142ivecSepBy e sep = sibind $ iso (\n -> constant n #>> ivecNSepBy n e sep)
126143 (\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)
syntax.cabal+7−7
@@ -4,9 +4,10 @@ synopsis: Reversible parsing and pretty-printing.
44description:
55 "syntax" allows you to write a single syntax description and instantiate is both as a parser and a pretty printer.
66 .
7− Syntax descriptions are written in applicative or arrow style. The library uses a custom hierarchy, provided by the
8− "semi-iso" package. Most of the time you will be using operators like '/$/' and '/*/', just like parser combinators.
9− When more power is needed - e.g. when the syntax depends on the parsed or printed value - you turn to arrows.
7+ Syntax descriptions are written in applicative or arrow style. The library uses a custom typeclass hierarchy, provided
8+ by the "semi-iso" package. Most of the time you will be using operators like '/$/', '/*/' and '/+/' (= '<|>'), just
9+ like parser combinators. When more power is needed - e.g. when the syntax depends on the parsed or printed value -
10+ you turn to arrows.
1011 .
1112 Semi-isomorphisms from "semi-iso" are the basic building block of syntax descriptions. I recommend reading
1213 the hackage page of "semi-iso" first, as it contains much more information.
@@ -19,11 +20,10 @@ description:
1920 Advanced formatting and parsing (for example indentation, haskell layout rule) is implemented as category transformers
2021 (similar to monad transformers). Currently only simple indentation is implemented (in "Data.Syntax.Indent") - basically
2122 a reader category transformer that tracks current indentation level. I plan on implementing Haskell layout rule in the
22− future (as a reusable transformer).
23+ future.
2324 .
24− Note that the library can work with both text and binary data. There are no binary combinators implemented - yet.
25− Alas, these are not only useful combinators missing! I will slowly but steadily implement them over time
26− (but these category transformers look so much more interesting for now ;).
25+ The library can work with both text and binary data. Alas, there are no binary combinators implemented yet.
26+ I will implement them when i have the time (but these category transformers look so much more interesting for now ;).
2727 .
2828 EXAMPLES! See @syntax-example@ and @syntax-example-json@ for examples.
2929 .