@@ -10,28 +10,22 @@ License : MIT
10Maintainer : Paweł Nowak <pawel834@gmail.com>
10Maintainer : Paweł Nowak <pawel834@gmail.com>
11Stability : experimental
11Stability : experimental
13−Reversible parsing and pretty-printing.
13+Abstract syntax descriptions based on semi-isomorphisms.
15module Data.Syntax (
15module Data.Syntax (
16 -- * Syntax.
16 -- * Syntax.
17 Syntax(..),
17 Syntax(..),
19 -- * Common isomorphisms.
18 -- * Common isomorphisms.
23−import Prelude hiding (take, takeWhile, id, (.))
22+import Prelude hiding (take, takeWhile)
25−import Control.Category
26−import Control.Category.Reader
27−import Control.Category.Structures
28−import Control.Lens.Iso
24+import Control.Lens.Iso
29−import Control.Lens.SemiIso
25+import Control.Lens.SemiIso
30−import Control.SIArrow
26+import Control.SIArrow
31−import Data.MonoTraversable
27+import Data.MonoTraversable
32−import Data.Sequences hiding (take, takeWhile, replicate)
28+import Data.Sequences hiding (take, takeWhile)
33−import qualified Data.Vector as V
34−import qualified Data.Vector.Unboxed as VU
36-- | An isomorphism between a sequence and a list of its elements.
30-- | An isomorphism between a sequence and a list of its elements.
37packed :: IsSequence seq => Iso' seq [Element seq]
31packed :: IsSequence seq => Iso' seq [Element seq]
@@ -39,11 +33,11 @@ packed = iso otoList fromList
40-- | An abstract syntax description based on semi-isomorphisms.
34-- | An abstract syntax description based on semi-isomorphisms.
42−-- This class can be implemented by both parsers and printers.
36+-- This class can be implemented by both parsers and printers (and maybe more?).
44-- The usual use is to write a polymorphic syntax description and instantiate it
38-- 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
39+-- both as a parser and a printer. An example is available in the 'syntax-example'
46−-- 'syntax-example-json' packages.
40+-- package.
48-- Methods of this class try to mimic "Data.Attoparsec.Text" interface.
42-- Methods of this class try to mimic "Data.Attoparsec.Text" interface.
49class ( SIArrow syn
43class ( SIArrow syn
@@ -76,7 +70,7 @@ class ( SIArrow syn
76 satisfyWith ai p = bifiltered p . ai /$/ anyChar
70 satisfyWith ai p = bifiltered p . ai /$/ anyChar
78 -- | A specific string.
72 -- | A specific string.
79− string :: Seq syn -> syn () ()
73+ string :: (Seq syn) -> syn () ()
80 string s = rev (exact s) /$/ take (olength s)
74 string s = rev (exact s) /$/ take (olength s)
82 -- | A string of length @n@.
76 -- | A string of length @n@.
@@ -99,90 +93,4 @@ class ( SIArrow syn
99 takeTill1 :: (Element (Seq syn) -> Bool) -> syn () (Seq syn)
93 takeTill1 :: (Element (Seq syn) -> Bool) -> syn () (Seq syn)
100 takeTill1 p = takeWhile1 (not . p)
94 takeTill1 p = takeWhile1 (not . p)
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.
106− -- @vecN n e@ describes a size @n@ vector with elements @e@.
108− -- Also see 'Data.Syntax.Combinator.vec'.
109− vecN :: Int -> syn () a -> syn () (V.Vector a)
110− vecN n e = packed /$/ sireplicate n e
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.
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.
119− -- Also see 'Data.Syntax.Combinator.ivec'.
120− ivecN :: Int -> syn Int (Int, a) -> syn () (V.Vector a)
121− ivecN n e = (packed /$/)
123− $ map (\(i, e') -> constant i ^>> e'
124− >>> first (sipure (constant i))
126− $ zip [0 .. n-1] (replicate n e)
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.
132− -- @vecN n e@ describes a size @n@ vector with elements @e@.
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
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.
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.
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 /$/)
149− $ map (\(i, e') -> constant i ^>> e'
150− >>> first (sipure (constant i))
152− $ zip [0 .. n-1] (replicate n e)
154 {-# MINIMAL anyChar #-}
96 {-# MINIMAL anyChar #-}
156−instance Syntax syn => Syntax (ReaderCT env syn) where
157− type Seq (ReaderCT env syn) = Seq syn
158− anyChar = clift anyChar
160− notChar = clift . notChar
161− satisfy = clift . satisfy
162− satisfyWith ai = clift . satisfyWith ai
163− string = clift . string
165− takeWhile = clift . takeWhile
166− takeWhile1 = clift . takeWhile1
167− takeTill = clift . takeTill
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
174−-- | Execute a computation in an isolated context.
176−-- The motivating example: you want to write a function
178−-- > serializeList :: Syntax syn => syn () a -> syn () [a]
180−-- Notice that we cannot just use simany, because the first @syn () a@
181−-- could eat the entire sequence (even though we printed more than 1 value!), so
182−-- we have to insert some kind of separators between the element. But how can we
183−-- be sure that @syn () a@ will not eat our separators? We can't! Thats why we
184−-- have to do the parsing in two stages: first extract the sequence between separators,
185−-- then run the @syn () a@ on this sequence.
186−class Syntax syn => Isolable syn where
187− -- | Turns a computation into one executed in an isolated context.
188− isolate :: syn () b -> syn (Seq syn) b