on 1593877 help sign in
Data/Syntax.hs+10−69
since splitsnapshots
unifiedsplit
@@ -20,18 +20,15 @@ module Data.Syntax (
20 packed
20 packed
21 ) where
21 ) where
22
22
23−import Prelude hiding (take, takeWhile, id, (.))
23+import Prelude hiding (take, takeWhile)
24−
24+
25−import Control.Category
26−import Control.Category.Reader
25+import Control.Category.Reader
27−import Control.Category.Structures
26+import Control.Category.Structures
28−import Control.Lens.Iso
27+import Control.Lens.Iso
29−import Control.Lens.SemiIso
28+import Control.Lens.SemiIso
30−import Control.SIArrow
29+import Control.SIArrow
31−import Data.MonoTraversable
30+import Data.MonoTraversable
32−import Data.Sequences hiding (take, takeWhile, replicate)
31+import Data.Sequences hiding (take, takeWhile)
33−import qualified Data.Vector as V
34−import qualified Data.Vector.Unboxed as VU
35
32
36-- | An isomorphism between a sequence and a list of its elements.
33-- | An isomorphism between a sequence and a list of its elements.
37packed :: IsSequence seq => Iso' seq [Element seq]
34packed :: IsSequence seq => Iso' seq [Element seq]
@@ -40,7 +37,7 @@ packed = iso otoList fromList
40-- | An abstract syntax description based on semi-isomorphisms.
37-- | An abstract syntax description based on semi-isomorphisms.
41--
38--
42-- This class can be implemented by both parsers and printers.
39-- This class can be implemented by both parsers and printers.
43−--
40+--
44-- The usual use is to write a polymorphic syntax description and instantiate it
41-- The usual use is to write a polymorphic syntax description and instantiate it
45-- both as a parser and a printer. Examples are available in 'syntax-example' and
42-- both as a parser and a printer. Examples are available in 'syntax-example' and
46-- 'syntax-example-json' packages.
43-- 'syntax-example-json' packages.
@@ -99,58 +96,6 @@ class ( SIArrow syn
99 takeTill1 :: (Element (Seq syn) -> Bool) -> syn () (Seq syn)
96 takeTill1 :: (Element (Seq syn) -> Bool) -> syn () (Seq syn)
100 takeTill1 p = takeWhile1 (not . p)
97 takeTill1 p = takeWhile1 (not . p)
101
98
102− -- | Constant size vector. The default implementation uses lists, but
103− -- "syntax-attoparsec" and "syntax-printer" override it with an efficient
104− -- implementation that works on a vector directly.
105− --
106− -- @vecN n e@ describes a size @n@ vector with elements @e@.
107− --
108− -- Also see 'Data.Syntax.Combinator.vec'.
109− vecN :: Int -> syn () a -> syn () (V.Vector a)
110− vecN n e = packed /$/ sireplicate n e
111−
112− -- | Constant size vector with index-aware element. The default implementation
113− -- uses lists, but "syntax-attoparsec" and "syntax-printer" override it with an
114− -- efficient implementation that works on a vector directly.
115− --
116− -- @ivecN n e@ describes a size @n@ vector with elements @e@. Each element
117− -- gets its index and should output a value and the index unchanged.
118− --
119− -- Also see 'Data.Syntax.Combinator.ivec'.
120− ivecN :: Int -> syn Int (Int, a) -> syn () (V.Vector a)
121− ivecN n e = (packed /$/)
122− $ sisequence
123− $ map (\(i, e') -> constant i ^>> e'
124− >>> first (sipure (constant i))
125− >># unit . swapped)
126− $ zip [0 .. n-1] (replicate n e)
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−
154 {-# MINIMAL anyChar #-}
99 {-# MINIMAL anyChar #-}
155
100
156instance Syntax syn => Syntax (ReaderCT env syn) where
101instance Syntax syn => Syntax (ReaderCT env syn) where
@@ -166,10 +111,6 @@ instance Syntax syn => Syntax (ReaderCT env syn) where
166 takeWhile1 = clift . takeWhile1
111 takeWhile1 = clift . takeWhile1
167 takeTill = clift . takeTill
112 takeTill = clift . takeTill
168 takeTill1 = clift . takeTill1
113 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
173
114
174-- | Execute a computation in an isolated context.
115-- | Execute a computation in an isolated context.
175--
116--
Data/Syntax/Combinator.hs+12−149
@@ -1,6 +1,3 @@
1−{-# LANGUAGE RankNTypes #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
3−{-# LANGUAGE FlexibleContexts #-}
4{- |
1{- |
5Module : Data.Syntax.Combinator
2Module : Data.Syntax.Combinator
6Description : Combinators that work with any sequence type.
3Description : Combinators that work with any sequence type.
@@ -12,50 +9,12 @@ Stability : experimental
12
9
13Combinators that work with any sequence type.
10Combinators that work with any sequence type.
14-}
11-}
15−module Data.Syntax.Combinator
12+module Data.Syntax.Combinator where
16− (
17− -- * Combinators.
18− optional,
19− opt,
20− opt_,
21− choice,
22− eitherOf,
23
13
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
14+import Control.Category.Structures
51−import Control.Lens
15+import Control.Lens
52−import Control.Lens.SemiIso
16+import Control.Lens.SemiIso
53−import Control.SIArrow
17+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)
59
18
60-- | One or zero occurences of @f@.
19-- | One or zero occurences of @f@.
61optional :: SIArrow cat => cat () a -> cat () (Maybe a)
20optional :: SIArrow cat => cat () a -> cat () (Maybe a)
@@ -70,15 +29,6 @@ opt_ :: SIArrow cat => cat () () -> cat () ()
70opt_ f = semiIso (const (Left "opt_")) Right /$/ f
29opt_ f = semiIso (const (Left "opt_")) Right /$/ f
71 /+/ sipure id
30 /+/ sipure id
72
31
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−
82-- | @manyTill p end@ applies action p zero or more times until action
32-- | @manyTill p end@ applies action p zero or more times until action
83-- end succeeds, and returns the list of values returned by p.
33-- end succeeds, and returns the list of values returned by p.
84manyTill :: SIArrow cat => cat () a -> cat () () -> cat () [a]
34manyTill :: SIArrow cat => cat () a -> cat () () -> cat () [a]
@@ -93,98 +43,11 @@ sepBy v s = sepBy1 v s /+/ sipure _Empty
93sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
43sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
94sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
44sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
95
45
96−-- | A string of given length.
46+-- | Tries to apply the actions in the list in order, until one of
97−takeArr :: Syntax syn => syn Int (Seq syn)
47+-- them succeeds. Returns the value of the succeeding action.
98−takeArr = sibind $ iso (\n -> constant n #>> take n)
48+choice :: SIArrow cat => [cat () a] -> cat () a
99− (\s -> constant (Seq.olength s) #>> take (Seq.olength s))
49+choice = foldr (/+/) (sifail "choice: all alternatives failed")
100−
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
50
182−-- | Runtime sized unboxed vector with index-aware elements and separators. The size can depend
51+-- | Combine two alternatives.
183−-- on the result of some computation.
52+eitherOf :: SIArrow cat => cat () a -> cat () b -> cat () (Either a b)
184−--
53+eitherOf a b = _Left /$/ a /+/ _Right /$/ b
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,10 +4,9 @@ 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 typeclass hierarchy, provided
7+ Syntax descriptions are written in applicative or arrow style. The library uses a custom hierarchy, provided by the
8− by the "semi-iso" package. Most of the time you will be using operators like '/$/', '/*/' and '/+/' (= '<|>'), just
8+ "semi-iso" package. Most of the time you will be using operators like '/$/' and '/*/', just like parser combinators.
9− like parser combinators. When more power is needed - e.g. when the syntax depends on the parsed or printed value -
9+ When more power is needed - e.g. when the syntax depends on the parsed or printed value - you turn to arrows.
10− you turn to arrows.
11 .
10 .
12 Semi-isomorphisms from "semi-iso" are the basic building block of syntax descriptions. I recommend reading
11 Semi-isomorphisms from "semi-iso" are the basic building block of syntax descriptions. I recommend reading
13 the hackage page of "semi-iso" first, as it contains much more information.
12 the hackage page of "semi-iso" first, as it contains much more information.
@@ -20,10 +19,11 @@ description:
20 Advanced formatting and parsing (for example indentation, haskell layout rule) is implemented as category transformers
19 Advanced formatting and parsing (for example indentation, haskell layout rule) is implemented as category transformers
21 (similar to monad transformers). Currently only simple indentation is implemented (in "Data.Syntax.Indent") - basically
20 (similar to monad transformers). Currently only simple indentation is implemented (in "Data.Syntax.Indent") - basically
22 a reader category transformer that tracks current indentation level. I plan on implementing Haskell layout rule in the
21 a reader category transformer that tracks current indentation level. I plan on implementing Haskell layout rule in the
23− future.
22+ future (as a reusable transformer).
24 .
23 .
25− The library can work with both text and binary data. Alas, there are no binary combinators implemented yet.
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− I will implement them when i have the time (but these category transformers look so much more interesting for now ;).
26+ (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 .