-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Invertible grammar combinators for S-expressions
--   
--   Serialisation to and deserialisation from S-expressions derived from a
--   single grammar definition.
@package sexp-grammar
@version 2.0.1

module Language.Sexp.Located

-- | Deserialise a <a>Sexp</a> from a string
decode :: ByteString -> Either String Sexp

-- | Parse a <a>Sexp</a> from a string.
parseSexp :: FilePath -> ByteString -> Either String Sexp

-- | Parse multiple <a>Sexp</a> from a string.
parseSexps :: FilePath -> ByteString -> Either String [Sexp]

-- | Parse a <a>Sexp</a> from a string, starting from a given position.
--   Useful for embedding into other parsers.
parseSexpWithPos :: Position -> ByteString -> Either String Sexp

-- | Parse multiple <a>Sexp</a> from a string, starting from a given
--   position. Useful for embedding into other parsers.
parseSexpsWithPos :: Position -> ByteString -> Either String [Sexp]

-- | Serialise a <a>Sexp</a> into a compact string
encode :: Sexp -> ByteString

-- | Serialise a <a>Sexp</a> into a pretty-printed string
format :: Sexp -> ByteString

-- | S-expression type annotated with positions. Useful for further
--   parsing.
type Sexp = Fix (Compose (LocatedBy Position) SexpF)

-- | S-expression functor
data SexpF e
AtomF :: !Atom -> SexpF e
ParenListF :: [e] -> SexpF e
BracketListF :: [e] -> SexpF e
BraceListF :: [e] -> SexpF e
ModifiedF :: !Prefix -> e -> SexpF e

-- | S-expression atom type
data Atom
AtomNumber :: {-# UNPACK #-} !Scientific -> Atom
AtomString :: {-# UNPACK #-} !Text -> Atom
AtomSymbol :: {-# UNPACK #-} !Text -> Atom

-- | S-expression quotation type
data Prefix
Quote :: Prefix
Backtick :: Prefix
Comma :: Prefix
CommaAt :: Prefix
Hash :: Prefix

-- | Annotation functor for positions
data LocatedBy a e
(:<) :: !a -> e -> LocatedBy a e

-- | Position: file name, line number, column number
data Position
Position :: FilePath -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Position

-- | Right-to-left composition of functors. The composition of applicative
--   functors is always applicative, but the composition of monads is not
--   always a monad.
newtype Compose (f :: k -> *) (g :: k1 -> k) (a :: k1) :: forall k k1. () => k -> * -> k1 -> k -> k1 -> *
Compose :: f g a -> Compose
[getCompose] :: Compose -> f g a
newtype Fix (f :: * -> *)
Fix :: f Fix f -> Fix
dummyPos :: Position
fromSimple :: Fix SexpF -> Fix (Compose (LocatedBy Position) SexpF)
toSimple :: Fix (Compose (LocatedBy Position) SexpF) -> Fix SexpF
instance GHC.Show.Show Language.Sexp.Located.Sexp

module Language.Sexp

-- | Deserialise a <a>Sexp</a> from a string
decode :: ByteString -> Either String Sexp

-- | Deserialise potentially multiple <a>Sexp</a> from a string
decodeMany :: ByteString -> Either String [Sexp]

-- | Serialise a <a>Sexp</a> into a compact string
encode :: Sexp -> ByteString

-- | Serialise a <a>Sexp</a> into a pretty-printed string
format :: Sexp -> ByteString
type Sexp = Fix SexpF

-- | S-expression functor
data SexpF e
AtomF :: !Atom -> SexpF e
ParenListF :: [e] -> SexpF e
BracketListF :: [e] -> SexpF e
BraceListF :: [e] -> SexpF e
ModifiedF :: !Prefix -> e -> SexpF e

-- | S-expression atom type
data Atom
AtomNumber :: {-# UNPACK #-} !Scientific -> Atom
AtomString :: {-# UNPACK #-} !Text -> Atom
AtomSymbol :: {-# UNPACK #-} !Text -> Atom

-- | S-expression quotation type
data Prefix
Quote :: Prefix
Backtick :: Prefix
Comma :: Prefix
CommaAt :: Prefix
Hash :: Prefix
instance GHC.Show.Show Language.Sexp.Sexp

module Language.SexpGrammar.Generic

-- | Provide a data constructor/stack isomorphism to a grammar working on
--   stacks. Works for types with one data constructor. For sum types use
--   <a>match</a> and <a>Coproduct</a>.
with :: (Generic a, MkPrismList Rep a, MkStackPrism f, Rep a ~ M1 D d M1 C c f, StackPrismLhs f t ~ b, Constructor c) => Grammar p b a :- t -> Grammar p s a :- t -> Grammar p s a :- t

-- | Combine all grammars provided in <a>Coproduct</a> list into a single
--   grammar.
match :: (Generic a, MkPrismList Rep a, Match Rep a bs t, bs ~ Coll Rep a t) => Coproduct p s bs a t -> Grammar p s a :- t

-- | Heterogenous list of grammars, each one matches a data constructor of
--   type <tt>a</tt>. <a>With</a> is used to provide a data
--   constructor/stack isomorphism to a grammar working on stacks.
--   <a>End</a> ends the list of matches.
data Coproduct p s (bs :: [*]) a t
[With] :: Coproduct p s b : bs1 a t
[End] :: Coproduct p s ([] :: [*]) a t


-- | Write your grammar once and get both parser and pretty-printer, for
--   free.
--   
--   <pre>
--   import GHC.Generics
--   import Data.Text (Text)
--   import Language.SexpGrammar
--   import Language.SexpGrammar.Generic
--   
--   data Person = Person
--     { pName    :: Text
--     , pAddress :: Text
--     , pAge     :: Maybe Int
--     } deriving (Show, Generic)
--   
--   instance SexpIso Person where
--     sexpIso = with $ \person -&gt;  -- Person is isomorphic to:
--       list (                           -- a list with
--         el (sym "person") &gt;&gt;&gt;          -- a symbol "person",
--         el string         &gt;&gt;&gt;          -- a string, and
--         props (                        -- a property-list with
--           "address" .:  string &gt;&gt;&gt;     -- a keyword :address and a string value, and
--           "age"     .:? int))  &gt;&gt;&gt;     -- an optional keyword :age with int value.
--       person
--   </pre>
--   
--   So now we can use this isomorphism to parse S-expessions to
--   <tt>Person</tt> record and pretty-print <tt>Person</tt> records back
--   to S-expression.
--   
--   <pre>
--   (person "John Doe" :address "42 Whatever str." :age 25)
--   </pre>
--   
--   will parse into:
--   
--   <pre>
--   Person {pName = "John Doe", pAddress = "42 Whatever str.", pAge = Just 25}
--   </pre>
--   
--   and the record will pretty-print back into:
--   
--   <pre>
--   (person "John Doe" :address "42 Whatever str." :age 25)
--   </pre>
module Language.SexpGrammar

-- | S-expression type annotated with positions. Useful for further
--   parsing.
type Sexp = Fix (Compose (LocatedBy Position) SexpF)

-- | Position: file name, line number, column number
data Position

-- | A common type of grammar that operates on S-expressions. This grammar
--   accepts a single <a>Sexp</a> value and converts it into a value of
--   type <tt>a</tt>.
type SexpGrammar a = forall t. Grammar Position (Sexp :- t) (a :- t)

-- | Representation of an invertible grammar -- a grammar that can be run
--   either "forwards" and "backwards".
--   
--   For a grammar <tt>Grammar p a b</tt>, running it forwards will take a
--   value of type <tt>a</tt> and possibly produce a value of type
--   <tt>b</tt>. Running it backwards will take a value of type <tt>b</tt>
--   and possibly produce an <tt>a</tt>. If a value cannot be produced, an
--   error message is generated.
--   
--   As a common example, running a <a>Grammar</a> forwards corresponds to
--   parsing and running backwards corresponds to prettyprinting.
--   
--   That is, the grammar defines a partial isomorphism between two values.
data Grammar p a b

-- | "Cons" pair of a heterogenous list or a stack with potentially
--   polymophic tail. E.g. <tt>"first" :- 2 :- (3,4) :- t</tt>
--   
--   Isomorphic to a tuple with two elments, but is much more convenient
--   for nested pairs.
data (:-) h t

-- | A class for types that could be converted to and inferred from
--   s-expressions defined by <a>Sexp</a>.
class SexpIso a
sexpIso :: SexpIso a => SexpGrammar a

-- | Run grammar in generating (right-to-left) direction
--   
--   <pre>
--   toSexp g = runGrammarString Sexp.dummyPos . backward (sealed g)
--   </pre>
toSexp :: SexpGrammar a -> a -> Either String Sexp

-- | Serialize a value using <a>SexpIso</a> instance
encode :: SexpIso a => a -> Either String ByteString

-- | Serialise a value using a provided grammar
encodeWith :: SexpGrammar a -> a -> Either String ByteString

-- | Serialise and pretty-print a value using its <a>SexpIso</a> instance
encodePretty :: SexpIso a => a -> Either String ByteString

-- | Serialise and pretty-print a value using a provided grammar
encodePrettyWith :: SexpGrammar a -> a -> Either String ByteString

-- | Run grammar in parsing (left-to-right) direction
--   
--   <pre>
--   fromSexp g = runGrammarString Sexp.dummyPos . forward (sealed g)
--   </pre>
fromSexp :: SexpGrammar a -> Sexp -> Either String a

-- | Deserialise a value using its <a>SexpIso</a> instance
decode :: SexpIso a => ByteString -> Either String a

-- | Deserialise a value using provided grammar, use a provided file name
--   for error messages
decodeWith :: SexpGrammar a -> FilePath -> ByteString -> Either String a

-- | Left-to-right composition
(>>>) :: Category cat => cat a b -> cat b c -> cat a c
infixr 1 >>>

-- | Right-to-left composition
(<<<) :: Category cat => cat b c -> cat a b -> cat a c
infixr 1 <<<

-- | Extract/inject a position from/to a <a>Sexp</a>.
position :: Grammar Position (Sexp :- t) (Position :- Sexp :- t)

-- | Grammar matching fractional number atoms to <a>Scientific</a> values.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith real (3.141592653589793^3)
--   Right "31.006276680299813114880451174049119330924860257"
--   </pre>
real :: Grammar Position (Sexp :- t) (Scientific :- t)

-- | Grammar matching fractional number atoms to <a>Double</a> values.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith double (3.141592653589793^3)
--   Right "31.006276680299816"
--   </pre>
double :: Grammar Position (Sexp :- t) (Double :- t)

-- | Grammar matching integer number atoms to <a>Int</a> values.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith int (2^63)
--   Right "-9223372036854775808"
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith int (2^63-1)
--   Right "9223372036854775807"
--   </pre>
int :: Grammar Position (Sexp :- t) (Int :- t)

-- | Grammar matching integer number atoms to <a>Integer</a> values.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith integer (2^100)
--   Right "1267650600228229401496703205376"
--   </pre>
integer :: Grammar Position (Sexp :- t) (Integer :- t)

-- | Grammar matching string literal atoms to <a>Text</a> values.
--   
--   <pre>
--   &gt;&gt;&gt; let grammar = list (el string &gt;&gt;&gt; el int) &gt;&gt;&gt; pair
--   
--   &gt;&gt;&gt; encodeWith grammar ("some-string", 42)
--   Right "(\"some-string\" 42)"
--   </pre>
string :: Grammar Position (Sexp :- t) (Text :- t)

-- | Grammar matching symbol literal atoms to <a>Text</a> values.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith symbol "some-symbol"
--   Right "some-symbol"
--   </pre>
symbol :: Grammar Position (Sexp :- t) (Text :- t)

-- | Grammar matching symbol literal atoms starting with ':' to <a>Text</a>
--   values without the colon char.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith keyword "username"
--   Right ":username"
--   </pre>
keyword :: Grammar Position (Sexp :- t) (Text :- t)

-- | Grammar matching symbol literal atoms to a specified symbol.
--   
--   <pre>
--   &gt;&gt;&gt; let grammar = list (el (sym "username") &gt;&gt;&gt; el string)
--   
--   &gt;&gt;&gt; encodeWith grammar "Julius Caesar"
--   Right "(username \"Julius Caesar\")"
--   </pre>
sym :: Text -> Grammar Position (Sexp :- t) t

-- | Grammar matching symbol literal atoms to a specified symbol prepended
--   with ':'.
--   
--   <pre>
--   &gt;&gt;&gt; let grammar = list (el (kwd "password") &gt;&gt;&gt; el int)
--   
--   &gt;&gt;&gt; encodeWith grammar 42
--   Right "(:password 42)"
--   </pre>
kwd :: Text -> Grammar Position (Sexp :- t) t

-- | Elements of a list that is being parsed/constructed.
data List

-- | Parenthesis list grammar. Runs a specified grammar on a sequence of
--   S-exps in a parenthesized list.
--   
--   <pre>
--   &gt;&gt;&gt; let grammar = list (el symbol &gt;&gt;&gt; el int) &gt;&gt;&gt; pair
--   
--   &gt;&gt;&gt; encodeWith grammar ("foo", 42)
--   Right "(foo 42)"
--   </pre>
list :: Grammar Position (List :- t) (List :- t') -> Grammar Position (Sexp :- t) t'

-- | Bracket list grammar. Runs a specified grammar on a sequence of S-exps
--   in a bracketed list.
--   
--   <pre>
--   &gt;&gt;&gt; let grammar = bracketList (rest int)
--   
--   &gt;&gt;&gt; encodeWith grammar [2, 3, 5, 7, 11, 13]
--   Right "[2 3 5 7 11 13]"
--   </pre>
bracketList :: Grammar Position (List :- t) (List :- t') -> Grammar Position (Sexp :- t) t'

-- | Brace list grammar. Runs a specified grammar on a sequence of S-exps
--   in a list enclosed in braces.
--   
--   <pre>
--   &gt;&gt;&gt; let grammar = braceList (props (key "x" real &gt;&gt;&gt; key "y" real)) &gt;&gt;&gt; pair
--   
--   &gt;&gt;&gt; encodeWith grammar (3.1415, -1)
--   Right "{:x 3.1415 :y -1}"
--   </pre>
braceList :: Grammar Position (List :- t) (List :- t') -> Grammar Position (Sexp :- t) t'

-- | Element of a sequence grammar. Runs a specified grammar on a next
--   element of a sequence. The underlying grammar can produce zero or more
--   values on the stack.
--   
--   E.g.:
--   
--   <ul>
--   <li><tt>el (sym "lambda")</tt> consumes a symbol "lambda" and produces
--   no values on the stack.</li>
--   <li><tt>el symbol</tt> consumes a symbol and produces a <a>Text</a>
--   value corresponding to the symbol.</li>
--   </ul>
el :: Grammar Position (Sexp :- t) t' -> Grammar Position (List :- t) (List :- t')

-- | The rest of a sequence grammar. Runs a specified grammar on each of
--   remaining elements of a sequence and collect them. Expects zero or
--   more elements in the sequence.
--   
--   <pre>
--   &gt;&gt;&gt; let grammar = list (el (sym "check-primes") &gt;&gt;&gt; rest int)
--   
--   &gt;&gt;&gt; encodeWith grammar [2, 3, 5, 7, 11, 13]
--   Right "(check-primes 2 3 5 7 11 13)"
--   </pre>
rest :: (forall t. Grammar Position (Sexp :- t) (a :- t)) -> Grammar Position (List :- t) (List :- [a] :- t)

-- | Key/value pairs of a property list that is being parsed/constructed.
data PropertyList

-- | Property list in a sequence grammar. Collects pairs of keywords and
--   S-expressions from remaining sequence elements and runs a specified
--   grammar on them. Expects zero or more pairs in the sequence. If
--   sequence of pairs interrupts with a non-keyword, the rest of this
--   sequence is left untouched.
--   
--   Collected <a>PropertyList</a> is then available for random-access
--   lookup combinators <a>key</a>, <a>optKey</a>, <a>.:</a>, <a>.:?</a> or
--   bulk extraction <a>restKeys</a> combinator.
--   
--   <pre>
--   &gt;&gt;&gt; :{
--    let grammar = braceList (
--          props (key "real" real &gt;&gt;&gt; key "img" real) &gt;&gt;&gt; onTail pair &gt;&gt;&gt; el (sym "/") &gt;&gt;&gt;
--          props (key "real" real &gt;&gt;&gt; key "img" real) &gt;&gt;&gt; onTail pair) &gt;&gt;&gt; pair
--    in encodeWith grammar ((0, -1), (1, 0))
--   :}
--   Right "{:real 0 :img -1 / :real 1 :img 0}"
--   </pre>
props :: Grammar Position (PropertyList :- t) (PropertyList :- t') -> Grammar Position (List :- t) (List :- t')

-- | Property by a key grammar. Looks up an S-expression by a specified key
--   and runs a specified grammar on it. Expects the key to be present.
--   
--   Note: performs linear lookup, <i>O(n)</i>
key :: Text -> (forall t. Grammar Position (Sexp :- t) (a :- t)) -> Grammar Position (PropertyList :- t) (PropertyList :- a :- t)

-- | Optional property by a key grammar. Like <a>key</a> but puts
--   <a>Nothing</a> in correspondence to the missing key and <a>Just</a> to
--   the present.
--   
--   Note: performs linear lookup, <i>O(n)</i>
optKey :: Text -> (forall t. Grammar Position (Sexp :- t) (a :- t)) -> Grammar Position (PropertyList :- t) (PropertyList :- Maybe a :- t)

-- | Property by a key grammar. Infix version of <a>key</a>.
(.:) :: Text -> (forall t. Grammar Position (Sexp :- t) (a :- t)) -> Grammar Position (PropertyList :- t) (PropertyList :- a :- t)
infix 3 .:

-- | Optional property by a key grammar. Infix version of <a>optKey</a>.
(.:?) :: Text -> (forall t. Grammar Position (Sexp :- t) (a :- t)) -> Grammar Position (PropertyList :- t) (PropertyList :- Maybe a :- t)
infix 3 .:?

-- | Remaining properties grammar. Extracts all key-value pairs and applies
--   a grammar on every element.
restKeys :: (forall t. Grammar Position (Sexp :- Text :- t) (a :- t)) -> Grammar Position (PropertyList :- t) (PropertyList :- [a] :- t)

-- | S-expression quotation type
data Prefix
Quote :: Prefix
Backtick :: Prefix
Comma :: Prefix
CommaAt :: Prefix
Hash :: Prefix

-- | Grammar matching a prefixed S-expression, runs a sub-grammar on a
--   <tt>Sexp</tt> under the prefix.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith (prefixed Backtick symbol) "foo"
--   Right "`foo"
--   </pre>
prefixed :: Prefix -> Grammar Position (Sexp :- t) (a :- t) -> Grammar Position (Sexp :- t) (a :- t)

-- | Grammar matching a prefixed S-expression, runs a sub-grammar on a
--   <tt>Sexp</tt> under the quotation.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith (quoted symbol) "foo"
--   Right "'foo"
--   </pre>
quoted :: Grammar Position (Sexp :- t) (a :- t) -> Grammar Position (Sexp :- t) (a :- t)

-- | Grammar matching a prefixed S-expression, runs a sub-grammar on a
--   <tt>Sexp</tt> under the hash prefix.
--   
--   <pre>
--   &gt;&gt;&gt; encodeWith (hashed symbol) "foo"
--   Right "#foo"
--   </pre>
hashed :: Grammar Position (Sexp :- t) (a :- t) -> Grammar Position (Sexp :- t) (a :- t)

-- | Data type to encode mismatches during parsing or generation, kept
--   abstract. Use <a>expected</a> and <a>unexpected</a> constructors to
--   build a mismatch report.
data Mismatch

-- | Construct a mismatch report with specified expectation. Can be
--   appended to other expectations and <a>unexpected</a> reports to
--   clarify a mismatch.
expected :: Text -> Mismatch

-- | Construct a mismatch report with information what occurred during the
--   processing but was not expected.
unexpected :: Text -> Mismatch

module Language.SexpGrammar.TH

-- | Build a prism and the corresponding grammar that will match on the
--   given constructor and convert it to reverse sequence of :- stacks.
--   
--   E.g. consider a data type:
--   
--   <pre>
--   data FooBar a b c = Foo a b c | Bar
--   </pre>
--   
--   For constructor Foo
--   
--   <pre>
--   fooGrammar = $(grammarFor 'Foo)
--   </pre>
--   
--   will expand into
--   
--   <pre>
--   fooGrammar = PartialIso
--     (\(c :- b :- a :- t) -&gt; Foo a b c :- t)
--     (\case { Foo a b c :- t -&gt; Just $ c :- b :- a :- t; _ -&gt; Nothing })
--   </pre>
--   
--   Note the order of elements on the stack:
--   
--   <pre>
--   ghci&gt; :t fooGrammar
--   fooGrammar :: Grammar p (c :- (b :- (a :- t))) (FooBar a b c :- t)
--   </pre>
grammarFor :: Name -> ExpQ

-- | Build prisms and corresponding grammars for all data constructors of
--   given type. Expects grammars to zip built ones with.
--   
--   <pre>
--   $(match ''Maybe)
--   </pre>
--   
--   Will expand into a lambda:
--   
--   <pre>
--   (\nothingG justG -&gt; ($(grammarFor 'Nothing) . nothingG) &lt;&gt;
--                       ($(grammarFor 'Just)    . justG))
--   </pre>
match :: Name -> ExpQ
