on master help sign in
Data/Syntax.hs+34−3
since splitsnapshots
unifiedsplit
@@ -30,7 +30,8 @@ import Control.Lens.SemiIso
30import Control.SIArrow
30import Control.SIArrow
31import Data.MonoTraversable
31import Data.MonoTraversable
32import Data.Sequences hiding (take, takeWhile, replicate)
32import 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
34
35
35-- | An isomorphism between a sequence and a list of its elements.
36-- | An isomorphism between a sequence and a list of its elements.
36packed :: IsSequence seq => Iso' seq [Element seq]
37packed :: IsSequence seq => Iso' seq [Element seq]
@@ -105,7 +106,7 @@ class ( SIArrow syn
105 -- @vecN n e@ describes a size @n@ vector with elements @e@.
106 -- @vecN n e@ describes a size @n@ vector with elements @e@.
106 --
107 --
107 -- Also see 'Data.Syntax.Combinator.vec'.
108 -- Also see 'Data.Syntax.Combinator.vec'.
108− vecN :: Int -> syn () a -> syn () (Vector a)
109+ vecN :: Int -> syn () a -> syn () (V.Vector a)
109 vecN n e = packed /$/ sireplicate n e
110 vecN n e = packed /$/ sireplicate n e
110
111
111 -- | Constant size vector with index-aware element. The default implementation
112 -- | Constant size vector with index-aware element. The default implementation
@@ -116,7 +117,7 @@ class ( SIArrow syn
116 -- gets its index and should output a value and the index unchanged.
117 -- gets its index and should output a value and the index unchanged.
117 --
118 --
118 -- Also see 'Data.Syntax.Combinator.ivec'.
119 -- 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)
120 ivecN n e = (packed /$/)
121 ivecN n e = (packed /$/)
121 $ sisequence
122 $ sisequence
122 $ map (\(i, e') -> constant i ^>> e'
123 $ map (\(i, e') -> constant i ^>> e'
@@ -124,6 +125,32 @@ class ( SIArrow syn
124 >># unit . swapped)
125 >># unit . swapped)
125 $ zip [0 .. n-1] (replicate n e)
126 $ zip [0 .. n-1] (replicate n e)
126
127
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+
127 {-# MINIMAL anyChar #-}
154 {-# MINIMAL anyChar #-}
128
155
129instance Syntax syn => Syntax (ReaderCT env syn) where
156instance Syntax syn => Syntax (ReaderCT env syn) where
@@ -139,6 +166,10 @@ instance Syntax syn => Syntax (ReaderCT env syn) where
139 takeWhile1 = clift . takeWhile1
166 takeWhile1 = clift . takeWhile1
140 takeTill = clift . takeTill
167 takeTill = clift . takeTill
141 takeTill1 = clift . takeTill1
168 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
142
173
143-- | Execute a computation in an isolated context.
174-- | Execute a computation in an isolated context.
144--
175--
Data/Syntax/Combinator.hs+73−9
@@ -26,13 +26,24 @@ module Data.Syntax.Combinator
26 sepBy,
26 sepBy,
27 sepBy1,
27 sepBy1,
28
28
29+ -- * Arrowized combinators.
30+ takeArr,
31+
29 -- * Vectors.
32 -- * Vectors.
30 vecNSepBy,
33 vecNSepBy,
31 ivecNSepBy,
34 ivecNSepBy,
32 vec,
35 vec,
33 vecSepBy,
36 vecSepBy,
34 ivec,
37 ivec,
35− ivecSepBy
38+ ivecSepBy,
39+
40+ -- * Unboxed vectors.
41+ uvecNSepBy,
42+ uivecNSepBy,
43+ uvec,
44+ uvecSepBy,
45+ uivec,
46+ uivecSepBy
36 ) where
47 ) where
37
48
38import Control.Category
49import Control.Category
@@ -40,10 +51,11 @@ import Control.Category.Structures
40import Control.Lens
51import Control.Lens
41import Control.Lens.SemiIso
52import Control.Lens.SemiIso
42import Control.SIArrow
53import Control.SIArrow
54+import qualified Data.MonoTraversable as Seq
43import Data.Syntax
55import Data.Syntax
44−import Data.Vector (Vector)
45import qualified Data.Vector as V
56import qualified Data.Vector as V
57+import qualified Data.Vector.Unboxed as VU
46−import Prelude hiding (id, (.))
58+import Prelude hiding (id, (.), take)
47
59
48-- | One or zero occurences of @f@.
60-- | One or zero occurences of @f@.
49optional :: SIArrow cat => cat () a -> cat () (Maybe a)
61optional :: SIArrow cat => cat () a -> cat () (Maybe a)
@@ -81,17 +93,22 @@ sepBy v s = sepBy1 v s /+/ sipure _Empty
81sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
93sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
82sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
94sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
83
95
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+
84-- | Constant size vector with separators.
101-- | Constant size vector with separators.
85--
102--
86-- @vecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
103-- @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)
88vecNSepBy n e sep = ivecNSepBy n (unit ^>> second e) sep
105vecNSepBy n e sep = ivecNSepBy n (unit ^>> second e) sep
89
106
90-- | Constant size vector with separators and index-aware elements.
107-- | Constant size vector with separators and index-aware elements.
91--
108--
92-- @ivecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
109-- @ivecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
93-- Each element gets its index and should output a value and the index unchanged.
110-- 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)
95ivecNSepBy n e sep = ivecN n $ sibind $ iso el (el . fst)
112ivecNSepBy n e sep = ivecN n $ sibind $ iso el (el . fst)
96 where
113 where
97 el k | k < n - 1 = unit ^>> e *** sep >># unit
114 el k | k < n - 1 = unit ^>> e *** sep >># unit
@@ -100,27 +117,74 @@ ivecNSepBy n e sep = ivecN n $ sibind $ iso el (el . fst)
100-- | Runtime sized vector. The size can depend on the result of some computation.
117-- | Runtime sized vector. The size can depend on the result of some computation.
101--
118--
102-- @vec e@ describes a vector with elements @e@.
119-- @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)
104vec e = vecSepBy e (siarr id)
121vec e = vecSepBy e (siarr id)
105
122
106-- | Runtime sized vector with separators. The size can depend on the result of some
123-- | Runtime sized vector with separators. The size can depend on the result of some
107-- computation.
124-- computation.
108--
125--
109-- @vecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
126-- @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)
111vecSepBy e sep = ivecSepBy (unit ^>> second e) sep
128vecSepBy e sep = ivecSepBy (unit ^>> second e) sep
112
129
113-- | Runtime sized vector with index-aware elements. The size can depend on the result
130-- | Runtime sized vector with index-aware elements. The size can depend on the result
114-- of some computation.
131-- of some computation.
115--
132--
116-- @ivec e@ describes a vector with elements @e@.
133-- @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)
118ivec e = ivecSepBy e (siarr id)
135ivec e = ivecSepBy e (siarr id)
119
136
120-- | Runtime sized vector with index-aware elements and separators. The size can depend
137-- | Runtime sized vector with index-aware elements and separators. The size can depend
121-- on the result of some computation.
138-- on the result of some computation.
122--
139--
123-- @ivecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
140-- @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)
125ivecSepBy e sep = sibind $ iso (\n -> constant n #>> ivecNSepBy n e sep)
142ivecSepBy e sep = sibind $ iso (\n -> constant n #>> ivecNSepBy n e sep)
126 (\v -> constant (V.length v) #>> ivecNSepBy (V.length v) 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)
syntax.cabal+7−7
@@ -4,9 +4,10 @@ synopsis: Reversible parsing and pretty-printing.
4description:
4description:
5 "syntax" allows you to write a single syntax description and instantiate is both as a parser and a pretty printer.
5 "syntax" allows you to write a single syntax description and instantiate is both as a parser and a pretty printer.
6 .
6 .
7− Syntax descriptions are written in applicative or arrow style. The library uses a custom hierarchy, provided by the
7+ Syntax descriptions are written in applicative or arrow style. The library uses a custom typeclass hierarchy, provided
8− "semi-iso" package. Most of the time you will be using operators like '/$/' and '/*/', just like parser combinators.
8+ by the "semi-iso" package. Most of the time you will be using operators like '/$/', '/*/' and '/+/' (= '<|>'), just
9− When more power is needed - e.g. when the syntax depends on the parsed or printed value - you turn to arrows.
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.
10 .
11 .
11 Semi-isomorphisms from "semi-iso" are the basic building block of syntax descriptions. I recommend reading
12 Semi-isomorphisms from "semi-iso" are the basic building block of syntax descriptions. I recommend reading
12 the hackage page of "semi-iso" first, as it contains much more information.
13 the hackage page of "semi-iso" first, as it contains much more information.
@@ -19,11 +20,10 @@ description:
19 Advanced formatting and parsing (for example indentation, haskell layout rule) is implemented as category transformers
20 Advanced formatting and parsing (for example indentation, haskell layout rule) is implemented as category transformers
20 (similar to monad transformers). Currently only simple indentation is implemented (in "Data.Syntax.Indent") - basically
21 (similar to monad transformers). Currently only simple indentation is implemented (in "Data.Syntax.Indent") - basically
21 a reader category transformer that tracks current indentation level. I plan on implementing Haskell layout rule in the
22 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.
23 .
24 .
24− Note that the library can work with both text and binary data. There are no binary combinators implemented - yet.
25+ The library can work with both text and binary data. Alas, 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 ;).
26+ I will implement them when i have the time (but these category transformers look so much more interesting for now ;).
27 .
27 .
28 EXAMPLES! See @syntax-example@ and @syntax-example-json@ for examples.
28 EXAMPLES! See @syntax-example@ and @syntax-example-json@ for examples.
29 .
29 .