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

-- | A flexible, extensible s-expression library.
--   
--   S-Cargot is a library for working with s-expressions in a modular and
--   extensible way, opting for genericity and flexibility instead of
--   speed. Instead of understanding one particular form of s-expression,
--   the S-Cargot library exposes tools for parsing or emitting different
--   kinds of s-expressions, including features not normally included in an
--   s-expression library like reader macros or tight control over
--   indentation in pretty-printing.
@package s-cargot
@version 0.1.6.0

module Data.SCargot.Common

-- | Parse an identifier according to the R5RS Scheme standard. This will
--   not normalize case, even though the R5RS standard specifies that all
--   identifiers be normalized to lower case first.
--   
--   An R5RS identifier is, broadly speaking, alphabetic or numeric and may
--   include various symbols, but no escapes.
parseR5RSIdent :: Parser Text

-- | Parse an identifier according to the R6RS Scheme standard. An R6RS
--   identifier may include inline hexadecimal escape sequences so that,
--   for example, foo is equivalent to f\x6f;o, and is
--   more liberal than R5RS as to which Unicode characters it may accept.
parseR6RSIdent :: Parser Text

-- | Parse an identifier according to the R7RS Scheme standard. An R7RS
--   identifier, in addition to a typical identifier format, can also be a
--   chunk of text surrounded by vertical bars that can contain spaces and
--   other characters. Unlike R6RS, it does not allow escapes to be
--   included in identifiers unless those identifiers are surrounded by
--   vertical bars.
parseR7RSIdent :: Parser Text

-- | Parse an identifier of unicode characters of the form
--   XID_Start XID_Continue*, which corresponds
--   strongly to the identifiers found in most C-like languages. Note that
--   the XID_Start category does not include the underscore, so
--   __foo is not a valid XID identifier. To parse identifiers
--   that may include leading underscores, use parseXIDIdentGeneral.
parseXIDIdentStrict :: Parser Text

-- | Parse an identifier of unicode characters of the form
--   (XID_Start | '_') XID_Continue*, which
--   corresponds strongly to the identifiers found in most C-like
--   languages. Unlike parseXIDIdentStrict, this will also accept an
--   underscore as leading character, which corresponds more closely to
--   programming languages like C and Java, but deviates somewhat from the
--   <http://unicode.org/reports/tr31/ Unicode Identifier and
--   Pattern Syntax standard>.
parseXIDIdentGeneral :: Parser Text

-- | Parse a Haskell identifer: a sequence of alphanumeric characters,
--   underscores, or a single quote. This matches both variable and
--   constructor names.
parseHaskellIdent :: Parser Text

-- | Parse a Haskell variable identifier: a sequence of alphanumeric
--   characters, underscores, or single quote that begins with a lower-case
--   letter.
parseHaskellVariable :: Parser Text

-- | Parse a Haskell constructor: a sequence of alphanumeric characters,
--   underscores, or single quote that begins with an upper-case letter.
parseHaskellConstructor :: Parser Text

-- | Given a parser for some kind of numeric literal, this will attempt to
--   parse a leading + or a leading - followed by the
--   numeric literal, and if a - is found, negate that literal.
signed :: Num a => Parser a -> Parser a

-- | Parses a number, determining which numeric base to use by examining
--   the literal's prefix: 0x for a hexadecimal number,
--   0z for a dozenal number, 0o for an octal number, and
--   0b for a binary number (as well as the upper-case versions of
--   the same.) If the base is omitted entirely, then it is treated as a
--   decimal number.
prefixedNumber :: Parser Integer

-- | Parses a number in the same way as prefixedNumber, with an
--   optional leading + or -.
signedPrefixedNumber :: Parser Integer

-- | A parser for non-signed binary numbers
binNumber :: Parser Integer

-- | A parser for signed binary numbers, with an optional leading
--   + or -.
signedBinNumber :: Parser Integer

-- | A parser for non-signed octal numbers
octNumber :: Parser Integer

-- | A parser for signed octal numbers, with an optional leading +
--   or -.
signedOctNumber :: Parser Integer

-- | A parser for non-signed decimal numbers
decNumber :: Parser Integer

-- | A parser for signed decimal numbers, with an optional leading
--   + or -.
signedDecNumber :: Parser Integer

-- | A parser for non-signed duodecimal (dozenal) numbers. This understands
--   both the ASCII characters a and b
--   and the Unicode characters 'x218a' (↊) and 'x218b'
--   (↋) as digits with the decimal values 10 and 11
--   respectively.
dozNumber :: Parser Integer

-- | A parser for signed duodecimal (dozenal) numbers, with an optional
--   leading + or -.
signedDozNumber :: Parser Integer

-- | A parser for non-signed hexadecimal numbers
hexNumber :: Parser Integer

-- | A parser for signed hexadecimal numbers, with an optional leading
--   + or -.
signedHexNumber :: Parser Integer

-- | A parser for Common Lisp's arbitrary-base number syntax, of the form
--   #[base]r[number], where the base is given in decimal. Note
--   that this syntax begins with a #, which means it might
--   conflict with defined reader macros.
commonLispNumberAnyBase :: Parser Integer

-- | A parser for GNU m4's arbitrary-base number syntax, of the form
--   0r[base]:[number], where the base is given in decimal.
gnuM4NumberAnyBase :: Parser Integer

data Location
Span :: !SourcePos -> !SourcePos -> Location

-- | Add support for source locations while parsing S-expressions, as
--   described in this Reddit thread.
data Located a
At :: !Location -> a -> Located a

-- | Adds a source span to a parser.
located :: Parser a -> Parser (Located a)

-- | A default location value
dLocation :: Location
instance GHC.Show.Show Data.SCargot.Common.Location
instance GHC.Classes.Ord Data.SCargot.Common.Location
instance GHC.Classes.Eq Data.SCargot.Common.Location
instance GHC.Show.Show a => GHC.Show.Show (Data.SCargot.Common.Located a)
instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.SCargot.Common.Located a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.SCargot.Common.Located a)

module Data.SCargot.Repr

-- | All S-Expressions can be understood as a sequence of cons
--   cells (represented here by SCons), the empty list nil
--   (represented by SNil) or an atom.
data SExpr atom
SCons :: SExpr atom -> SExpr atom -> SExpr atom
SAtom :: atom -> SExpr atom
SNil :: SExpr atom

-- | Sometimes the cons-based interface is too low level, and we'd rather
--   have the lists themselves exposed. In this case, we have RSList
--   to represent a well-formed cons list, and RSDotted to represent
--   an improper list of the form (a b c . d). This representation
--   is based on the structure of the parsed S-Expression, and not on how
--   it was originally represented: thus, (a . (b)) is going to be
--   represented as RSList[RSAtom a, RSAtom b] despite having been
--   originally represented as a dotted list.
data RichSExpr atom
RSList :: [RichSExpr atom] -> RichSExpr atom
RSDotted :: [RichSExpr atom] -> atom -> RichSExpr atom
RSAtom :: atom -> RichSExpr atom

-- | It should always be true that
--   
--   
--   fromRich (toRich x) == x
--   
--   
--   and that
--   
--   
--   toRich (fromRich x) == x
--   
toRich :: SExpr atom -> RichSExpr atom

-- | This follows the same laws as toRich.
fromRich :: RichSExpr atom -> SExpr atom

-- | A well-formed s-expression is one which does not contain any dotted
--   lists. This means that not every value of SExpr a can be
--   converted to a WellFormedSExpr a, although the opposite is
--   fine.
data WellFormedSExpr atom
WFSList :: [WellFormedSExpr atom] -> WellFormedSExpr atom
WFSAtom :: atom -> WellFormedSExpr atom

-- | This will be Nothing if the argument contains an improper
--   list. It should hold that
--   
--   
--   toWellFormed (fromWellFormed x) == Right x
--   
--   
--   and also (more tediously) that
--   
--   
--   case toWellFormed x of
--     Left _  -> True
--     Right y -> x == fromWellFormed y
--   
toWellFormed :: SExpr atom -> Either String (WellFormedSExpr atom)

-- | Convert a WellFormedSExpr back into a SExpr.
fromWellFormed :: WellFormedSExpr atom -> SExpr atom
instance Data.Traversable.Traversable Data.SCargot.Repr.SExpr
instance Data.Foldable.Foldable Data.SCargot.Repr.SExpr
instance Data.Data.Data atom => Data.Data.Data (Data.SCargot.Repr.SExpr atom)
instance GHC.Base.Functor Data.SCargot.Repr.SExpr
instance GHC.Read.Read atom => GHC.Read.Read (Data.SCargot.Repr.SExpr atom)
instance GHC.Show.Show atom => GHC.Show.Show (Data.SCargot.Repr.SExpr atom)
instance GHC.Classes.Eq atom => GHC.Classes.Eq (Data.SCargot.Repr.SExpr atom)
instance Data.Traversable.Traversable Data.SCargot.Repr.RichSExpr
instance Data.Foldable.Foldable Data.SCargot.Repr.RichSExpr
instance Data.Data.Data atom => Data.Data.Data (Data.SCargot.Repr.RichSExpr atom)
instance GHC.Base.Functor Data.SCargot.Repr.RichSExpr
instance GHC.Read.Read atom => GHC.Read.Read (Data.SCargot.Repr.RichSExpr atom)
instance GHC.Show.Show atom => GHC.Show.Show (Data.SCargot.Repr.RichSExpr atom)
instance GHC.Classes.Eq atom => GHC.Classes.Eq (Data.SCargot.Repr.RichSExpr atom)
instance Data.Traversable.Traversable Data.SCargot.Repr.WellFormedSExpr
instance Data.Foldable.Foldable Data.SCargot.Repr.WellFormedSExpr
instance Data.Data.Data atom => Data.Data.Data (Data.SCargot.Repr.WellFormedSExpr atom)
instance GHC.Base.Functor Data.SCargot.Repr.WellFormedSExpr
instance GHC.Read.Read atom => GHC.Read.Read (Data.SCargot.Repr.WellFormedSExpr atom)
instance GHC.Show.Show atom => GHC.Show.Show (Data.SCargot.Repr.WellFormedSExpr atom)
instance GHC.Classes.Eq atom => GHC.Classes.Eq (Data.SCargot.Repr.WellFormedSExpr atom)
instance GHC.IsList.IsList (Data.SCargot.Repr.WellFormedSExpr atom)
instance Data.String.IsString atom => Data.String.IsString (Data.SCargot.Repr.WellFormedSExpr atom)
instance Data.String.IsString atom => Data.String.IsString (Data.SCargot.Repr.RichSExpr atom)
instance GHC.IsList.IsList (Data.SCargot.Repr.RichSExpr atom)
instance Data.String.IsString atom => Data.String.IsString (Data.SCargot.Repr.SExpr atom)
instance GHC.IsList.IsList (Data.SCargot.Repr.SExpr atom)

module Data.SCargot.Print

-- | Turn a single s-expression into a string according to a given
--   SExprPrinter.
encodeOne :: SExprPrinter atom carrier -> carrier -> Text

-- | Turn a list of s-expressions into a single string according to a given
--   SExprPrinter.
encode :: SExprPrinter atom carrier -> [carrier] -> Text

-- | Turn a single s-expression into a lazy Text according to a
--   given SExprPrinter.
encodeOneLazy :: SExprPrinter atom carrier -> carrier -> Text

-- | Turn a list of s-expressions into a lazy Text according to a
--   given SExprPrinter.
encodeLazy :: SExprPrinter atom carrier -> [carrier] -> Text

-- | A SExprPrinter value describes how to print a given value as an
--   s-expression. The carrier type parameter indicates the value
--   that will be printed, and the atom parameter indicates the
--   type that will represent tokens in an s-expression structure.
data SExprPrinter atom carrier

-- | The Indent type is used to determine how to indent subsequent
--   s-expressions in a list, after printing the head of the list. This
--   only applies if the entire list cannot be printed within the allowable
--   maxWidth; a sub-maxWidth printing will not add newlines or
--   indentation.
data Indent

-- | A Swing indent will indent subsequent exprs some fixed amount
--   more than the current line.
--   
--   
--   (foo
--     bar
--     baz
--     quux)
--   
--   
--   Any indentAmount applies relative to the entry at the head of
--   the list; in the above example, the indentAmount is 1.
Swing :: Indent

-- | A SwingAfter n indent will try to print the first
--   n expressions after the head on the same line as the head,
--   and all after will be swung. SwingAfter 0 is
--   equivalent to Swing.
--   
--   
--   (foo bar
--     baz
--     quux)
--   
--   
--   The indentAmount is handled in the same way as for the
--   Swing setting.
SwingAfter :: Int -> Indent

-- | An Align indent will print the first expression after the head
--   on the same line, and subsequent expressions will be aligned with that
--   one. Note that this ignores any indentAmount specified for the
--   printer.
--   
--   
--   (foo bar
--        baz
--        quux)
--   
Align :: Indent

-- | Modify the carrier type of a SExprPrinter by describing how to
--   convert the new type back to the previous type. For example, to
--   pretty-print a well-formed s-expression, we can modify the
--   SExprPrinter value as follows:
--   
--   
--   >>> let printer = setFromCarrier fromWellFormed (basicPrint id)
--   
--   >>> encodeOne printer (WFSList [WFSAtom "ele", WFSAtom "phant"])
--   "(ele phant)"
--   
setFromCarrier :: (c -> b) -> SExprPrinter a b -> SExprPrinter a c

-- | Dictate a maximum width for pretty-printed s-expressions.
--   
--   
--   >>> let printer = setMaxWidth 8 (basicPrint id)
--   
--   >>> encodeOne printer (L [A "one", A "two", A "three"])
--   "(one \n  two\n  three)"
--   
setMaxWidth :: Int -> SExprPrinter atom carrier -> SExprPrinter atom carrier

-- | Allow the serialized s-expression to be arbitrarily wide. This makes
--   all pretty-printing happen on a single line.
--   
--   
--   >>> let printer = removeMaxWidth (basicPrint id)
--   
--   >>> encodeOne printer (L [A "one", A "two", A "three"])
--   "(one two three)"
--   
removeMaxWidth :: SExprPrinter atom carrier -> SExprPrinter atom carrier

-- | Set the number of spaces that a subsequent line will be indented after
--   a swing indentation.
--   
--   
--   >>> let printer = setMaxWidth 12 (basicPrint id)
--   
--   >>> encodeOne printer (L [A "elephant", A "pachyderm"])
--   "(elephant \n  pachyderm)"
--   
--   >>> encodeOne (setIndentAmount 4) (L [A "elephant", A "pachyderm"])
--   "(elephant \n    pachyderm)"
--   
setIndentAmount :: Int -> SExprPrinter atom carrier -> SExprPrinter atom carrier

-- | Dictate how to indent subsequent lines based on the leading
--   subexpression in an s-expression. For details on how this works,
--   consult the documentation of the Indent type.
--   
--   
--   >>> let indent (A "def") = SwingAfter 1; indent _ = Swing
--   
--   >>> let printer = setIndentStrategy indent (setMaxWidth 8 (basicPrint id))
--   
--   >>> encodeOne printer (L [ A "def", L [ A "func", A "arg" ], A "body" ])
--   "(def (func arg)\n  body)"
--   
--   >>> encodeOne printer (L [ A "elephant", A "among", A "pachyderms" ])
--   "(elephant \n  among\n  pachyderms)"
--   
setIndentStrategy :: (SExpr atom -> Indent) -> SExprPrinter atom carrier -> SExprPrinter atom carrier

-- | A default SExprPrinter struct that will always swing subsequent
--   expressions onto later lines if they're too long, indenting them by
--   two spaces, and uses a soft maximum width of 80 characters
basicPrint :: (atom -> Text) -> SExprPrinter atom (SExpr atom)

-- | A default SExprPrinter struct that will always print a
--   SExpr as a single line.
flatPrint :: (atom -> Text) -> SExprPrinter atom (SExpr atom)

-- | A default SExprPrinter struct that will always swing subsequent
--   expressions onto later lines if they're too long, indenting them by
--   two spaces, but makes no effort to keep the pretty-printed sources
--   inside a maximum width. In the case that we want indented printing but
--   don't care about a "maximum" width, we can print more efficiently than
--   in other situations.
unconstrainedPrint :: (atom -> Text) -> SExprPrinter atom (SExpr atom)
instance GHC.Show.Show Data.SCargot.Print.Indent
instance GHC.Classes.Eq Data.SCargot.Print.Indent
instance GHC.Show.Show Data.SCargot.Print.Size
instance GHC.Show.Show Data.SCargot.Print.Intermediate

module Data.SCargot.Parse

-- | Decode several S-expressions according to a given SExprParser.
--   This will return a list of every S-expression that appears at the
--   top-level of the document.
decode :: SExprParser atom carrier -> Text -> Either String [carrier]

-- | Decode a single S-expression. If any trailing input is left after the
--   S-expression (ignoring comments or whitespace) then this will fail:
--   for those cases, use decode, which returns a list of all the
--   S-expressions found at the top level.
decodeOne :: SExprParser atom carrier -> Text -> Either String carrier

-- | A SExprParser describes a parser for a particular value that
--   has been serialized as an s-expression. The atom parameter
--   corresponds to a Haskell type used to represent the atoms, and the
--   carrier parameter corresponds to the parsed S-Expression
--   structure.
data SExprParser atom carrier

-- | A Reader represents a reader macro: it takes a parser for the
--   S-Expression type and performs as much or as little parsing as it
--   would like, and then returns an S-expression.
type Reader atom = (Parser (SExpr atom) -> Parser (SExpr atom))

-- | A Comment represents any kind of skippable comment. This parser
--   must be able to fail if a comment is not being recognized, and
--   it must not consume any input in case of failure.
type Comment = Parser ()

-- | Create a basic SExprParser when given a parser for an atom
--   type.
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> let parser = mkParser (many1 alphaNum)
--   
--   >>> decode parser "(ele phant)"
--   Right [SCons (SAtom "ele") (SCons (SAtom "phant") SNil)]
--   
mkParser :: Parser atom -> SExprParser atom (SExpr atom)

-- | Modify the carrier type for a SExprParser. This is used
--   internally to convert between various SExpr representations,
--   but could also be used externally to add an extra conversion layer
--   onto a SExprParser.
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> import Data.SCargot.Repr (toRich)
--   
--   >>> let parser = setCarrier (return . toRich) (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(ele phant)"
--   Right [RSlist [RSAtom "ele",RSAtom "phant"]]
--   
setCarrier :: (b -> Either String c) -> SExprParser a b -> SExprParser a c

-- | Add the ability to execute some particular reader macro, as defined by
--   its initial character and the Parser which returns the parsed
--   S-Expression. The Reader is passed a Parser which can be
--   recursively called to parse more S-Expressions, and begins parsing
--   after the reader character has been removed from the stream.
--   
--   
--   >>> import Text.Parsec (alphaNum, char, many1)
--   
--   >>> let vecReader p = (char ']' *> pure SNil) <|> (SCons <$> p <*> vecReader p)
--   
--   >>> let parser = addReader '[' vecReader (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(an [ele phant])"
--   Right [SCons (SAtom "an") (SCons (SCons (SAtom "ele") (SCons (SAtom "phant") SNil)) SNil)]
--   
addReader :: Char -> Reader a -> SExprParser a c -> SExprParser a c

-- | Add the ability to ignore some kind of comment. This gets factored
--   into whitespace parsing, and it's very important that the parser
--   supplied be able to fail (as otherwise it will cause an
--   infinite loop), and also that it not consume any input (which
--   may require it to be wrapped in try.)
--   
--   
--   >>> import Text.Parsec (alphaNum, anyChar, manyTill, many1, string)
--   
--   >>> let comment = string "//" *> manyTill anyChar newline *> pure ()
--   
--   >>> let parser = setComment comment (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(ele //a comment\n  phant)"
--   Right [SCons (SAtom "ele") (SCons (SAtom "phant") SNil)]
--   
setComment :: Comment -> SExprParser a c -> SExprParser a c

-- | Convert the final output representation from the SExpr type to
--   the RichSExpr type.
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> let parser = asRich (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(ele phant)"
--   Right [RSlist [RSAtom "ele",RSAtom "phant"]]
--   
asRich :: SExprParser a (SExpr b) -> SExprParser a (RichSExpr b)

-- | Convert the final output representation from the SExpr type to
--   the WellFormedSExpr type.
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> let parser = asWellFormed (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(ele phant)"
--   Right [WFSList [WFSAtom "ele",WFSAtom "phant"]]
--   
asWellFormed :: SExprParser a (SExpr b) -> SExprParser a (WellFormedSExpr b)

-- | Add the ability to understand a quoted S-Expression. Many Lisps use
--   'sexpr as sugar for (quote sexpr). This assumes that
--   the underlying atom type implements the IsString class, and
--   will create the quote atom using fromString "quote".
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> let parser = withQuote (mkParser (many1 alphaNum))
--   
--   >>> decode parser "'elephant"
--   Right [SCons (SAtom "quote") (SCons (SAtom "foo") SNil)]
--   
withQuote :: IsString t => SExprParser t (SExpr t) -> SExprParser t (SExpr t)

module Data.SCargot.Comments

-- | Lisp-style line-oriented comments start with ; and last until
--   the end of the line. This is usually the comment syntax you want.
withLispComments :: SExprParser t a -> SExprParser t a

-- | Many scripting and shell languages use these, which begin with
--   # and last until the end of the line.
withOctothorpeComments :: SExprParser t a -> SExprParser t a

-- | MATLAB, Prolog, PostScript, and others use comments which begin with
--   % and last until the end of the line.
withPercentComments :: SExprParser t a -> SExprParser t a

-- | MATLAB block comments are started with %{ and end with
--   %}.
withPercentBlockComments :: SExprParser t a -> SExprParser t a

-- | C++-like line-oriented comment start with // and last until
--   the end of the line.
withCLikeLineComments :: SExprParser t a -> SExprParser t a

-- | C-like block comments start with @@. They do not nest.
withCLikeBlockComments :: SExprParser t a -> SExprParser t a

-- | C-like comments include both line- and block-comments, the former
--   starting with // and the latter contained within //.
withCLikeComments :: SExprParser t a -> SExprParser t a

-- | Haskell line-oriented comments start with -- and last until
--   the end of the line.
withHaskellLineComments :: SExprParser t a -> SExprParser t a

-- | Haskell block comments start with {- and end with
--   -}. They do not nest.
withHaskellBlockComments :: SExprParser t a -> SExprParser t a

-- | Haskell comments include both the line-oriented -- comments
--   and the block-oriented {- ... -} comments
withHaskellComments :: SExprParser t a -> SExprParser t a

-- | Given a string, produce a comment parser that matches that initial
--   string and ignores everything until the end of the line.
lineComment :: String -> Comment

-- | Given two strings, a begin and an end delimiter, produce a parser that
--   matches the beginning delimiter and then ignores everything until it
--   finds the end delimiter. This does not consider nesting, so, for
--   example, a comment created with
--   
--   
--   curlyComment :: Comment
--   curlyComment = simpleBlockComment "{" "}"
--   
--   
--   will consider
--   
--   
--   { this { comment }
--   
--   
--   to be a complete comment, despite the apparent improper nesting. This
--   is analogous to standard C-style comments in which
--   
--   
--   
--   
--   is a complete comment.
simpleBlockComment :: String -> String -> Comment

module Data.SCargot

-- | Decode several S-expressions according to a given SExprParser.
--   This will return a list of every S-expression that appears at the
--   top-level of the document.
decode :: SExprParser atom carrier -> Text -> Either String [carrier]

-- | Decode a single S-expression. If any trailing input is left after the
--   S-expression (ignoring comments or whitespace) then this will fail:
--   for those cases, use decode, which returns a list of all the
--   S-expressions found at the top level.
decodeOne :: SExprParser atom carrier -> Text -> Either String carrier

-- | Turn a list of s-expressions into a single string according to a given
--   SExprPrinter.
encode :: SExprPrinter atom carrier -> [carrier] -> Text

-- | Turn a single s-expression into a string according to a given
--   SExprPrinter.
encodeOne :: SExprPrinter atom carrier -> carrier -> Text

-- | A SExprParser describes a parser for a particular value that
--   has been serialized as an s-expression. The atom parameter
--   corresponds to a Haskell type used to represent the atoms, and the
--   carrier parameter corresponds to the parsed S-Expression
--   structure.
data SExprParser atom carrier

-- | A Reader represents a reader macro: it takes a parser for the
--   S-Expression type and performs as much or as little parsing as it
--   would like, and then returns an S-expression.
type Reader atom = (Parser (SExpr atom) -> Parser (SExpr atom))

-- | A Comment represents any kind of skippable comment. This parser
--   must be able to fail if a comment is not being recognized, and
--   it must not consume any input in case of failure.
type Comment = Parser ()

-- | Create a basic SExprParser when given a parser for an atom
--   type.
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> let parser = mkParser (many1 alphaNum)
--   
--   >>> decode parser "(ele phant)"
--   Right [SCons (SAtom "ele") (SCons (SAtom "phant") SNil)]
--   
mkParser :: Parser atom -> SExprParser atom (SExpr atom)

-- | Modify the carrier type for a SExprParser. This is used
--   internally to convert between various SExpr representations,
--   but could also be used externally to add an extra conversion layer
--   onto a SExprParser.
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> import Data.SCargot.Repr (toRich)
--   
--   >>> let parser = setCarrier (return . toRich) (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(ele phant)"
--   Right [RSlist [RSAtom "ele",RSAtom "phant"]]
--   
setCarrier :: (b -> Either String c) -> SExprParser a b -> SExprParser a c

-- | Add the ability to execute some particular reader macro, as defined by
--   its initial character and the Parser which returns the parsed
--   S-Expression. The Reader is passed a Parser which can be
--   recursively called to parse more S-Expressions, and begins parsing
--   after the reader character has been removed from the stream.
--   
--   
--   >>> import Text.Parsec (alphaNum, char, many1)
--   
--   >>> let vecReader p = (char ']' *> pure SNil) <|> (SCons <$> p <*> vecReader p)
--   
--   >>> let parser = addReader '[' vecReader (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(an [ele phant])"
--   Right [SCons (SAtom "an") (SCons (SCons (SAtom "ele") (SCons (SAtom "phant") SNil)) SNil)]
--   
addReader :: Char -> Reader a -> SExprParser a c -> SExprParser a c

-- | Add the ability to ignore some kind of comment. This gets factored
--   into whitespace parsing, and it's very important that the parser
--   supplied be able to fail (as otherwise it will cause an
--   infinite loop), and also that it not consume any input (which
--   may require it to be wrapped in try.)
--   
--   
--   >>> import Text.Parsec (alphaNum, anyChar, manyTill, many1, string)
--   
--   >>> let comment = string "//" *> manyTill anyChar newline *> pure ()
--   
--   >>> let parser = setComment comment (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(ele //a comment\n  phant)"
--   Right [SCons (SAtom "ele") (SCons (SAtom "phant") SNil)]
--   
setComment :: Comment -> SExprParser a c -> SExprParser a c

-- | Convert the final output representation from the SExpr type to
--   the RichSExpr type.
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> let parser = asRich (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(ele phant)"
--   Right [RSlist [RSAtom "ele",RSAtom "phant"]]
--   
asRich :: SExprParser a (SExpr b) -> SExprParser a (RichSExpr b)

-- | Convert the final output representation from the SExpr type to
--   the WellFormedSExpr type.
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> let parser = asWellFormed (mkParser (many1 alphaNum))
--   
--   >>> decode parser "(ele phant)"
--   Right [WFSList [WFSAtom "ele",WFSAtom "phant"]]
--   
asWellFormed :: SExprParser a (SExpr b) -> SExprParser a (WellFormedSExpr b)

-- | Add the ability to understand a quoted S-Expression. Many Lisps use
--   'sexpr as sugar for (quote sexpr). This assumes that
--   the underlying atom type implements the IsString class, and
--   will create the quote atom using fromString "quote".
--   
--   
--   >>> import Text.Parsec (alphaNum, many1)
--   
--   >>> let parser = withQuote (mkParser (many1 alphaNum))
--   
--   >>> decode parser "'elephant"
--   Right [SCons (SAtom "quote") (SCons (SAtom "foo") SNil)]
--   
withQuote :: IsString t => SExprParser t (SExpr t) -> SExprParser t (SExpr t)

-- | A SExprPrinter value describes how to print a given value as an
--   s-expression. The carrier type parameter indicates the value
--   that will be printed, and the atom parameter indicates the
--   type that will represent tokens in an s-expression structure.
data SExprPrinter atom carrier

-- | The Indent type is used to determine how to indent subsequent
--   s-expressions in a list, after printing the head of the list. This
--   only applies if the entire list cannot be printed within the allowable
--   maxWidth; a sub-maxWidth printing will not add newlines or
--   indentation.
data Indent

-- | A Swing indent will indent subsequent exprs some fixed amount
--   more than the current line.
--   
--   
--   (foo
--     bar
--     baz
--     quux)
--   
--   
--   Any indentAmount applies relative to the entry at the head of
--   the list; in the above example, the indentAmount is 1.
Swing :: Indent

-- | A SwingAfter n indent will try to print the first
--   n expressions after the head on the same line as the head,
--   and all after will be swung. SwingAfter 0 is
--   equivalent to Swing.
--   
--   
--   (foo bar
--     baz
--     quux)
--   
--   
--   The indentAmount is handled in the same way as for the
--   Swing setting.
SwingAfter :: Int -> Indent

-- | An Align indent will print the first expression after the head
--   on the same line, and subsequent expressions will be aligned with that
--   one. Note that this ignores any indentAmount specified for the
--   printer.
--   
--   
--   (foo bar
--        baz
--        quux)
--   
Align :: Indent

-- | A default SExprPrinter struct that will always swing subsequent
--   expressions onto later lines if they're too long, indenting them by
--   two spaces, and uses a soft maximum width of 80 characters
basicPrint :: (atom -> Text) -> SExprPrinter atom (SExpr atom)

-- | A default SExprPrinter struct that will always print a
--   SExpr as a single line.
flatPrint :: (atom -> Text) -> SExprPrinter atom (SExpr atom)

-- | A default SExprPrinter struct that will always swing subsequent
--   expressions onto later lines if they're too long, indenting them by
--   two spaces, but makes no effort to keep the pretty-printed sources
--   inside a maximum width. In the case that we want indented printing but
--   don't care about a "maximum" width, we can print more efficiently than
--   in other situations.
unconstrainedPrint :: (atom -> Text) -> SExprPrinter atom (SExpr atom)

-- | Modify the carrier type of a SExprPrinter by describing how to
--   convert the new type back to the previous type. For example, to
--   pretty-print a well-formed s-expression, we can modify the
--   SExprPrinter value as follows:
--   
--   
--   >>> let printer = setFromCarrier fromWellFormed (basicPrint id)
--   
--   >>> encodeOne printer (WFSList [WFSAtom "ele", WFSAtom "phant"])
--   "(ele phant)"
--   
setFromCarrier :: (c -> b) -> SExprPrinter a b -> SExprPrinter a c

-- | Dictate a maximum width for pretty-printed s-expressions.
--   
--   
--   >>> let printer = setMaxWidth 8 (basicPrint id)
--   
--   >>> encodeOne printer (L [A "one", A "two", A "three"])
--   "(one \n  two\n  three)"
--   
setMaxWidth :: Int -> SExprPrinter atom carrier -> SExprPrinter atom carrier

-- | Allow the serialized s-expression to be arbitrarily wide. This makes
--   all pretty-printing happen on a single line.
--   
--   
--   >>> let printer = removeMaxWidth (basicPrint id)
--   
--   >>> encodeOne printer (L [A "one", A "two", A "three"])
--   "(one two three)"
--   
removeMaxWidth :: SExprPrinter atom carrier -> SExprPrinter atom carrier

-- | Set the number of spaces that a subsequent line will be indented after
--   a swing indentation.
--   
--   
--   >>> let printer = setMaxWidth 12 (basicPrint id)
--   
--   >>> encodeOne printer (L [A "elephant", A "pachyderm"])
--   "(elephant \n  pachyderm)"
--   
--   >>> encodeOne (setIndentAmount 4) (L [A "elephant", A "pachyderm"])
--   "(elephant \n    pachyderm)"
--   
setIndentAmount :: Int -> SExprPrinter atom carrier -> SExprPrinter atom carrier

-- | Dictate how to indent subsequent lines based on the leading
--   subexpression in an s-expression. For details on how this works,
--   consult the documentation of the Indent type.
--   
--   
--   >>> let indent (A "def") = SwingAfter 1; indent _ = Swing
--   
--   >>> let printer = setIndentStrategy indent (setMaxWidth 8 (basicPrint id))
--   
--   >>> encodeOne printer (L [ A "def", L [ A "func", A "arg" ], A "body" ])
--   "(def (func arg)\n  body)"
--   
--   >>> encodeOne printer (L [ A "elephant", A "among", A "pachyderms" ])
--   "(elephant \n  among\n  pachyderms)"
--   
setIndentStrategy :: (SExpr atom -> Indent) -> SExprPrinter atom carrier -> SExprPrinter atom carrier

module Data.SCargot.Atom

-- | A convenience function for defining an atom parser from a wrapper
--   function and a parser. This is identical to fmap specialized to
--   operate over Parser values, and is provided as sugar.
atom :: (t -> atom) -> Parser t -> Parser atom

-- | A convenience function for defining a SExprSpec from a list
--   of possible atom parsers, which will be tried in sequence before
--   failing.
mkAtomParser :: [Parser atom] -> SExprParser atom (SExpr atom)

module Data.SCargot.Repr.Basic

-- | All S-Expressions can be understood as a sequence of cons
--   cells (represented here by SCons), the empty list nil
--   (represented by SNil) or an atom.
data SExpr atom
SCons :: SExpr atom -> SExpr atom -> SExpr atom
SAtom :: atom -> SExpr atom
SNil :: SExpr atom

-- | Combine the two s-expressions into a new one.
--   
--   
--   >>> cons (A "el") (L ["eph", A "ant"])
--   SCons (SAtom "el) (SCons (SAtom "eph") (SCons (SAtom "ant") SNil))
--   
cons :: SExpr a -> SExpr a -> SExpr a

-- | Produce the head and tail of the s-expression (if possible).
--   
--   
--   >>> uncons (A "el" ::: A "eph" ::: A "ant" ::: Nil)
--   Just (A "el",SCons (SAtom "eph") (SCons (SAtom "ant") SNil))
--   
uncons :: SExpr a -> Maybe (SExpr a, SExpr a)

-- | A shorter infix alias for SCons
--   
--   
--   >>> A "pachy" ::: A "derm"
--   SCons (SAtom "pachy") (SAtom "derm")
--   
pattern (:::) :: SExpr a -> SExpr a -> SExpr a
infixr 5 :::

-- | A shorter alias for SAtom
--   
--   
--   >>> A "elephant"
--   SAtom "elephant"
--   
pattern A :: a -> SExpr a

-- | An alias for matching a proper list.
--   
--   
--   >>> L [A "pachy", A "derm"]
--   SExpr (SAtom "pachy") (SExpr (SAtom "derm") SNil)
--   
pattern L :: [SExpr a] -> SExpr a

-- | An alias for matching a dotted list.
--   
--   
--   >>> DL [A "pachy"] A "derm"
--   SExpr (SAtom "pachy") (SAtom "derm")
--   
pattern DL :: [SExpr a] -> a -> SExpr a

-- | A (slightly) shorter alias for SNil
--   
--   
--   >>> Nil
--   SNil
--   
pattern Nil :: SExpr a

-- | A traversal with access to the first element of a pair.
--   
--   
--   >>> import Lens.Family
--   
--   >>> set _car (A "elephant") (A "one" ::: A "two" ::: A "three" ::: Nil)
--   A "elelphant" ::: A "two" ::: A "three" ::: Nil
--   
--   >>> set _car (A "two" ::: A "three" ::: Nil) (A "one" ::: A "elephant")
--   (A "two" ::: A "three" ::: Nil) ::: A "elephant"
--   
_car :: Applicative f => (SExpr a -> f (SExpr a)) -> SExpr a -> f (SExpr a)

-- | A traversal with access to the second element of a pair.
--   
--   
--   >>> import Lens.Family
--   
--   >>> set _cdr (A "elephant") (A "one" ::: A "two" ::: A "three" ::: Nil)
--   A "one" ::: A "elephant"
--   
--   >>> set _cdr (A "two" ::: A "three" ::: Nil) (A "one" ::: A "elephant")
--   A "one" ::: A "two" ::: A "three" ::: Nil
--   
_cdr :: Applicative f => (SExpr a -> f (SExpr a)) -> SExpr a -> f (SExpr a)

-- | Utility function for parsing a pair of things.
--   
--   
--   >>> fromPair (isAtom "pachy") (asAtom return) (A "pachy" ::: A "derm" ::: Nil)
--   Right ((), "derm")
--   
--   >>> fromPair (isAtom "pachy") fromAtom (A "pachy" ::: Nil)
--   Left "Expected two-element list"
--   
fromPair :: (SExpr t -> Either String a) -> (SExpr t -> Either String b) -> SExpr t -> Either String (a, b)

-- | Utility function for parsing a list of things.
fromList :: (SExpr t -> Either String a) -> SExpr t -> Either String [a]

-- | Utility function for parsing a single atom
fromAtom :: SExpr t -> Either String t

-- | Parse a two-element list (NOT a dotted pair) using the provided
--   function.
--   
--   
--   >>> let go (A l) (A r) = return (l ++ r); go _ _ = Left "expected atoms"
--   
--   >>> asPair go (A "pachy" ::: A "derm" ::: Nil)
--   Right "pachyderm"
--   
--   >>> asPair go (A "elephant" ::: Nil)
--   Left "asPair: expected two-element list; found list of length 1"
--   
asPair :: ((SExpr t, SExpr t) -> Either String a) -> SExpr t -> Either String a

-- | Parse an arbitrary-length list using the provided function.
--   
--   
--   >>> let go xs = concat <$> mapM fromAtom xs
--   
--   >>> asList go (A "el" ::: A "eph" ::: A "ant" ::: Nil)
--   Right "elephant"
--   
--   >>> asList go (A "el" ::: A "eph" ::: A "ant")
--   Left "asList: expected list; found dotted list of length 3"
--   
asList :: ([SExpr t] -> Either String a) -> SExpr t -> Either String a

-- | Match a given literal atom, failing otherwise.
--   
--   
--   >>> isAtom "elephant" (A "elephant")
--   Right ()
--   
--   >>> isAtom "elephant" (A "elephant" ::: Nil)
--   Left "isAtom: expected atom; found list"
--   
isAtom :: Eq t => t -> SExpr t -> Either String ()

-- | Parse an atom using the provided function.
--   
--   
--   >>> import Data.Char (toUpper)
--   
--   >>> asAtom (return . map toUpper) (A "elephant")
--   Right "ELEPHANT"
--   
--   >>> asAtom (return . map toUpper) Nil
--   Left "asAtom: expected atom; found empty list"
--   
asAtom :: (t -> Either String a) -> SExpr t -> Either String a

-- | Parse an assoc-list using the provided function.
--   
--   
--   >>> let def (x, y) = do { a <- fromAtom x; b <- fromAtom y; return (a ++ ": " ++ b) }
--   
--   >>> let defList xs = do { defs <- mapM def xs; return (unlines defs) }
--   
--   >>> asAssoc defList ((A "legs" ::: A "four" ::: Nil) ::: (A "trunk" ::: A "one" ::: Nil) ::: Nil)
--   Right "legs: four\ntrunk: one\n"
--   
--   >>> asAssoc defList ((A "legs" ::: A "four" ::: Nil) ::: (A "elephant") ::: Nil)
--   Left "asAssoc: expected pair; found list of length 1"
--   
asAssoc :: ([(SExpr t, SExpr t)] -> Either String a) -> SExpr t -> Either String a

module Data.SCargot.Language.HaskLike

-- | An atom type that understands Haskell-like values as well as
--   Scheme-like identifiers.
data HaskLikeAtom

-- | An identifier, parsed according to the R5RS Scheme standard
HSIdent :: Text -> HaskLikeAtom

-- | A string, parsed according to the syntax for string literals in the
--   Haskell report
HSString :: Text -> HaskLikeAtom

-- | An arbitrary-sized integer value, parsed according to the syntax for
--   integer literals in the Haskell report
HSInt :: Integer -> HaskLikeAtom

-- | A double-precision floating-point value, parsed according to the
--   syntax for floats in the Haskell report
HSFloat :: Double -> HaskLikeAtom

-- | This SExprParser understands s-expressions that contain
--   Scheme-like tokens, as well as string literals, integer literals, and
--   floating-point literals. Each of these values is parsed according to
--   the lexical rules in the Haskell report, so the same set of string
--   escapes, numeric bases, and floating-point options are available. This
--   spec does not parse comments and does not understand any reader
--   macros.
--   
--   
--   >>> decode haskLikeParser "(0x01 \"\\x65lephant\")"
--   Right [SCons (SAtom (HSInt 1)) (SCons (SAtom (HSString "elephant")) SNil)]
--   
haskLikeParser :: SExprParser HaskLikeAtom (SExpr HaskLikeAtom)

-- | This SExprPrinter emits s-expressions that contain Scheme-like
--   tokens as well as string literals, integer literals, and
--   floating-point literals, which will be emitted as the literals
--   produced by Haskell's show function. This printer will produce
--   a flat s-expression with no indentation of any kind.
--   
--   
--   >>> encode haskLikePrinter [L [A (HSInt 1), A (HSString "elephant")]]
--   "(1 \"elephant\")"
--   
haskLikePrinter :: SExprPrinter HaskLikeAtom (SExpr HaskLikeAtom)

-- | A haskLikeParser which produces Located values
--   
--   
--   >>> decode locatedHaskLikeParser $ pack "(0x01 \"\\x65lephant\")"
--   Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 6)) (HSInt 1))) (SCons (SAtom (At (Span (line 1, column 7) (line 1, column 20)) (HSString "elephant"))) SNil)]
--   
--   
--   
--   >>> decode locatedHaskLikeParser $ pack "(1 elephant)"
--   Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) (HSInt 1))) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) (HSIdent "elephant"))) SNil)]
--   
locatedHaskLikeParser :: SExprParser (Located HaskLikeAtom) (SExpr (Located HaskLikeAtom))

-- | A SExprPrinter for Located values. Works exactly like
--   haskLikePrinter It ignores the location tags when printing the
--   result.
--   
--   
--   >>> let (Right dec) = decode locatedHaskLikeParser $ pack "(1 elephant)"
--   [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) (HSInt 1))) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) (HSIdent "elephant"))) SNil)]
--   
--   
--   
--   >>> encode locatedHaskLikePrinter dec
--   "(1 elephant)"
--   
locatedHaskLikePrinter :: SExprPrinter (Located HaskLikeAtom) (SExpr (Located HaskLikeAtom))

-- | Parse a Haskell string literal as defined by the Haskell 2010 language
--   specification.
parseHaskellString :: Parser Text

-- | Parse a Haskell floating-point number as defined by the Haskell 2010
--   language specification.
parseHaskellFloat :: Parser Double

-- | Parse a Haskell integer literal as defined by the Haskell 2010
--   language specification.
parseHaskellInt :: Parser Integer
instance GHC.Show.Show Data.SCargot.Language.HaskLike.HaskLikeAtom
instance GHC.Classes.Eq Data.SCargot.Language.HaskLike.HaskLikeAtom
instance Data.String.IsString Data.SCargot.Language.HaskLike.HaskLikeAtom
instance Data.String.IsString (Data.SCargot.Common.Located Data.SCargot.Language.HaskLike.HaskLikeAtom)

module Data.SCargot.Language.Basic

-- | A SExprParser that understands atoms to be sequences of
--   alphanumeric characters as well as the punctuation characters
--   [-*/+<>=!?], and does no processing of them.
--   
--   
--   >>> decode basicParser "(1 elephant)"
--   Right [SCons (SAtom "1") (SCons (SAtom "elephant") SNil)]
--   
basicParser :: SExprParser Text (SExpr Text)

-- | A SExprPrinter that prints textual atoms directly (without
--   quoting or any other processing) onto a single line.
--   
--   
--   >>> encode basicPrinter [L [A "1", A "elephant"]]
--   "(1 elephant)"
--   
basicPrinter :: SExprPrinter Text (SExpr Text)

-- | A basicParser which produces Located values
--   
--   
--   >>> decode locatedBasicParser $ pack "(1 elephant)"
--   Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) "1")) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) "elephant")) SNil)]
--   
--   
--   
--   >>> decode locatedBasicParser $ pack "(let ((x 1))\n  x)"
--   Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 5)) "let")) (SCons (SCons (SCons (SAtom (At (Span (line 1, column 8) (line 1, column 9)) "x")) (SCons (SAtom (At (Span (line 1, column 10) (line 1, column 11)) "1")) SNil)) SNil) (SCons (SAtom (At (Span (line 2, column 3) (line 2, column 4)) "x")) SNil))]
--   
locatedBasicParser :: SExprParser (Located Text) (SExpr (Located Text))

-- | A SExprPrinter for Located values. Works exactly like
--   basicPrinter It ignores the location tags when printing the
--   result.
--   
--   
--   >>> let (Right dec) = decode locatedBasicParser $ pack "(1 elephant)"
--   [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) "1")) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) "elephant")) SNil)]
--   
--   
--   
--   >>> encode locatedBasicPrinter dec
--   "(1 elephant)"
--   
locatedBasicPrinter :: SExprPrinter (Located Text) (SExpr (Located Text))

module Data.SCargot.Repr.Rich

-- | Sometimes the cons-based interface is too low level, and we'd rather
--   have the lists themselves exposed. In this case, we have RSList
--   to represent a well-formed cons list, and RSDotted to represent
--   an improper list of the form (a b c . d). This representation
--   is based on the structure of the parsed S-Expression, and not on how
--   it was originally represented: thus, (a . (b)) is going to be
--   represented as RSList[RSAtom a, RSAtom b] despite having been
--   originally represented as a dotted list.
data RichSExpr atom
RSList :: [RichSExpr atom] -> RichSExpr atom
RSDotted :: [RichSExpr atom] -> atom -> RichSExpr atom
RSAtom :: atom -> RichSExpr atom

-- | It should always be true that
--   
--   
--   fromRich (toRich x) == x
--   
--   
--   and that
--   
--   
--   toRich (fromRich x) == x
--   
toRich :: SExpr atom -> RichSExpr atom

-- | This follows the same laws as toRich.
fromRich :: RichSExpr atom -> SExpr atom

-- | Combine the two s-expressions into a new one.
--   
--   
--   >>> cons (A "el") (L [A "eph", A "ant"])
--   L [A "el",A "eph",A "ant"]
--   
cons :: RichSExpr a -> RichSExpr a -> RichSExpr a

-- | Produce the head and tail of the s-expression (if possible).
--   
--   
--   >>> uncons (L [A "el", A "eph", A "ant"])
--   Just (A "el",L [A "eph",A "ant"])
--   
uncons :: RichSExpr a -> Maybe (RichSExpr a, RichSExpr a)

-- | A shorter infix alias to grab the head and tail of an RSList.
--   
--   
--   >>> A "one" ::: L [A "two", A "three"]
--   RSList [RSAtom "one",RSAtom "two",RSAtom "three"]
--   
pattern (:::) :: RichSExpr a -> RichSExpr a -> RichSExpr a

-- | A shorter alias for RSAtom
--   
--   
--   >>> A "elephant"
--   RSAtom "elephant"
--   
pattern A :: a -> RichSExpr a

-- | A shorter alias for RSList
--   
--   
--   >>> L [A "pachy", A "derm"]
--   RSList [RSAtom "pachy",RSAtom "derm"]
--   
pattern L :: [RichSExpr a] -> RichSExpr a

-- | A shorter alias for RSDotted
--   
--   
--   >>> DL [A "pachy"] "derm"
--   RSDotted [RSAtom "pachy"] "derm"
--   
pattern DL :: [RichSExpr a] -> a -> RichSExpr a

-- | A shorter alias for RSList []
--   
--   
--   >>> Nil
--   RSList []
--   
pattern Nil :: RichSExpr a

-- | A traversal with access to the first element of a pair.
--   
--   
--   >>> import Lens.Family
--   
--   >>> set _car (A "elephant") (L [A "one", A "two", A "three"])
--   L [A "elelphant",A "two",A "three"]
--   
--   >>> set _car (L [A "two", A "three"]) (DL [A "one"] "elephant")
--   DL [L[A "two",A "three"]] "elephant"
--   
_car :: Applicative f => (RichSExpr a -> f (RichSExpr a)) -> RichSExpr a -> f (RichSExpr a)

-- | A traversal with access to the second element of a pair. Using this to
--   modify an s-expression may result in changing the constructor used,
--   changing a list to a dotted list or vice versa.
--   
--   
--   >>> import Lens.Family
--   
--   >>> set _cdr (A "elephant") (L [A "one", A "two", A "three"])
--   DL [A "one"] "elephant"
--   
--   >>> set _cdr (L [A "two", A "three"]) (DL [A "one"] "elephant")
--   L [A "one",A "two",A "three"]
--   
_cdr :: Applicative f => (RichSExpr a -> f (RichSExpr a)) -> RichSExpr a -> f (RichSExpr a)

-- | Utility function for parsing a pair of things: this parses a
--   two-element list, and not a cons pair.
--   
--   
--   >>> fromPair (isAtom "pachy") (asAtom return) (L [A "pachy", A "derm"])
--   Right ((), "derm")
--   
--   >>> fromPair (isAtom "pachy") fromAtom (L [A "pachy"])
--   Left "Expected two-element list"
--   
fromPair :: (RichSExpr t -> Either String a) -> (RichSExpr t -> Either String b) -> RichSExpr t -> Either String (a, b)

-- | Utility function for parsing a proper list of things.
--   
--   
--   >>> fromList fromAtom (L [A "this", A "that", A "the-other"])
--   Right ["this","that","the-other"]
--   
--   >>> fromList fromAtom (DL [A "this", A "that"] "the-other"])
--   Left "asList: expected proper list; found dotted list"
--   
fromList :: (RichSExpr t -> Either String a) -> RichSExpr t -> Either String [a]

-- | Utility function for parsing a single atom
--   
--   
--   >>> fromAtom (A "elephant")
--   Right "elephant"
--   
--   >>> fromAtom (L [A "elephant"])
--   Left "fromAtom: expected atom; found list"
--   
fromAtom :: RichSExpr t -> Either String t

-- | Parses a two-element list using the provided function.
--   
--   
--   >>> let go (A l) (A r) = return (l ++ r); go _ _ = Left "expected atoms"
--   
--   >>> asPair go (L [A "pachy", A "derm"])
--   Right "pachyderm"
--   
--   >>> asPair go (L [A "elephant"])
--   Left "asPair: expected two-element list; found list of length 1"
--   
asPair :: ((RichSExpr t, RichSExpr t) -> Either String a) -> RichSExpr t -> Either String a

-- | Parse an arbitrary-length list using the provided function.
--   
--   
--   >>> let go xs = concat <$> mapM fromAtom xs
--   
--   >>> asList go (L [A "el", A "eph", A "ant"])
--   Right "elephant"
--   
--   >>> asList go (DL [A "el", A "eph"] "ant")
--   Left "asList: expected list; found dotted list"
--   
asList :: ([RichSExpr t] -> Either String a) -> RichSExpr t -> Either String a

-- | Match a given literal atom, failing otherwise.
--   
--   
--   >>> isAtom "elephant" (A "elephant")
--   Right ()
--   
--   >>> isAtom "elephant" (L [A "elephant"])
--   Left "isAtom: expected atom; found list"
--   
isAtom :: Eq t => t -> RichSExpr t -> Either String ()

-- | Match an empty list, failing otherwise.
--   
--   
--   >>> isNil (L [])
--   Right ()
--   
--   >>> isNil (A "elephant")
--   Left "isNil: expected nil; found atom"
--   
isNil :: RichSExpr t -> Either String ()

-- | Parse an atom using the provided function.
--   
--   
--   >>> import Data.Char (toUpper)
--   
--   >>> asAtom (return . map toUpper) (A "elephant")
--   Right "ELEPHANT"
--   
--   >>> asAtom (return . map toUpper) (L [])
--   Left "asAtom: expected atom; found list"
--   
asAtom :: (t -> Either String a) -> RichSExpr t -> Either String a

-- | Parse an assoc-list using the provided function.
--   
--   
--   >>> let def (x, y) = do { a <- fromAtom x; b <- fromAtom y; return (a ++ ": " ++ b) }
--   
--   >>> let defList xs = do { defs <- mapM def xs; return (unlines defs) }
--   
--   >>> asAssoc defList (L [ L [A "legs", A "four"], L [ A "trunk", A "one"] ])
--   Right "legs: four\ntrunk: one\n"
--   
--   >>> asAssoc defList (L [ L [A "legs", A "four"], L [ A "elephant"] ])
--   Left "asAssoc: expected pair; found list of length 1"
--   
asAssoc :: ([(RichSExpr t, RichSExpr t)] -> Either String a) -> RichSExpr t -> Either String a
car :: (RichSExpr t -> Either String t') -> [RichSExpr t] -> Either String t'
cdr :: ([RichSExpr t] -> Either String t') -> [RichSExpr t] -> Either String t'

module Data.SCargot.Repr.WellFormed

-- | A well-formed s-expression is one which does not contain any dotted
--   lists. This means that not every value of SExpr a can be
--   converted to a WellFormedSExpr a, although the opposite is
--   fine.
data WellFormedSExpr atom
WFSList :: [WellFormedSExpr atom] -> WellFormedSExpr atom
WFSAtom :: atom -> WellFormedSExpr atom

-- | This will be Nothing if the argument contains an improper
--   list. It should hold that
--   
--   
--   toWellFormed (fromWellFormed x) == Right x
--   
--   
--   and also (more tediously) that
--   
--   
--   case toWellFormed x of
--     Left _  -> True
--     Right y -> x == fromWellFormed y
--   
toWellFormed :: SExpr atom -> Either String (WellFormedSExpr atom)

-- | Convert a WellFormedSExpr back into a SExpr.
fromWellFormed :: WellFormedSExpr atom -> SExpr atom

-- | Combine the two-expressions into a new one. This will return
--   Nothing if the resulting s-expression is not well-formed.
--   
--   
--   >>> cons (A "el") (L [A "eph", A "ant"])
--   Just (WFSList [WFSAtom "el",WFSAtom "eph",WFSAtom "ant"])
--   
--   >>> cons (A "pachy") (A "derm"))
--   Nothing
--   
cons :: WellFormedSExpr a -> WellFormedSExpr a -> Maybe (WellFormedSExpr a)

-- | Produce the head and tail of the s-expression (if possible).
--   
--   
--   >>> uncons (L [A "el", A "eph", A "ant"])
--   Just (WFSAtom "el",WFSList [WFSAtom "eph",WFSAtom "ant"])
--   
uncons :: WellFormedSExpr a -> Maybe (WellFormedSExpr a, WellFormedSExpr a)

-- | A shorter infix alias to grab the head and tail of a WFSList.
--   This pattern is unidirectional, because it cannot be guaranteed that
--   it is used to construct well-formed s-expressions; use the function
--   "cons" instead.
--   
--   
--   >>> let sum (x ::: xs) = x + sum xs; sum Nil = 0
--   
pattern (:::) :: WellFormedSExpr a -> WellFormedSExpr a -> WellFormedSExpr a

-- | A shorter alias for WFSList
--   
--   
--   >>> L [A "pachy", A "derm"]
--   WFSList [WFSAtom "pachy",WFSAtom "derm"]
--   
pattern L :: [WellFormedSExpr t] -> WellFormedSExpr t

-- | A shorter alias for WFSAtom
--   
--   
--   >>> A "elephant"
--   WFSAtom "elephant"
--   
pattern A :: t -> WellFormedSExpr t

-- | A shorter alias for WFSList []
--   
--   
--   >>> Nil
--   WFSList []
--   
pattern Nil :: WellFormedSExpr t

-- | Utility function for parsing a pair of things.
--   
--   
--   >>> fromPair (isAtom "pachy") (asAtom return) (L [A "pachy", A "derm"])
--   Right ((), "derm")
--   
--   >>> fromPair (isAtom "pachy") fromAtom (L [A "pachy"])
--   Left "Expected two-element list"
--   
fromPair :: (WellFormedSExpr t -> Either String a) -> (WellFormedSExpr t -> Either String b) -> WellFormedSExpr t -> Either String (a, b)

-- | Utility function for parsing a list of things.
--   
--   
--   >>> fromList fromAtom (L [A "this", A "that", A "the-other"])
--   Right ["this","that","the-other"]
--   
--   >>> fromList fromAtom (A "pachyderm")
--   Left "asList: expected proper list; found dotted list"
--   
fromList :: (WellFormedSExpr t -> Either String a) -> WellFormedSExpr t -> Either String [a]

-- | Utility function for parsing a single atom
--   
--   
--   >>> fromAtom (A "elephant")
--   Right "elephant"
--   
--   >>> fromAtom (L [A "elephant"])
--   Left "fromAtom: expected atom; found list"
--   
fromAtom :: WellFormedSExpr t -> Either String t

-- | Parses a two-element list using the provided function.
--   
--   
--   >>> let go (A l) (A r) = return (l ++ r); go _ _ = Left "expected atoms"
--   
--   >>> asPair go (L [A "pachy", A "derm"])
--   Right "pachyderm"
--   
--   >>> asPair go (L [A "elephant"])
--   Left "asPair: expected two-element list; found list of length 1"
--   
asPair :: ((WellFormedSExpr t, WellFormedSExpr t) -> Either String a) -> WellFormedSExpr t -> Either String a

-- | Parse an arbitrary-length list using the provided function.
--   
--   
--   >>> let go xs = concat <$> mapM fromAtom xs
--   
--   >>> asList go (L [A "el", A "eph", A "ant"])
--   Right "elephant"
--   
--   >>> asList go (A "pachyderm")
--   Left "asList: expected list; found atom"
--   
asList :: ([WellFormedSExpr t] -> Either String a) -> WellFormedSExpr t -> Either String a

-- | Match a given literal atom, failing otherwise.
--   
--   
--   >>> isAtom "elephant" (A "elephant")
--   Right ()
--   
--   >>> isAtom "elephant" (L [A "elephant"])
--   Left "isAtom: expected atom; found list"
--   
isAtom :: Eq t => t -> WellFormedSExpr t -> Either String ()

-- | Match an empty list, failing otherwise.
--   
--   
--   >>> isNil (L [])
--   Right ()
--   
--   >>> isNil (A "elephant")
--   Left "isNil: expected nil; found atom"
--   
isNil :: WellFormedSExpr t -> Either String ()

-- | Parse an atom using the provided function.
--   
--   
--   >>> import Data.Char (toUpper)
--   
--   >>> asAtom (return . map toUpper) (A "elephant")
--   Right "ELEPHANT"
--   
--   >>> asAtom (return . map toUpper) (L [])
--   Left "asAtom: expected atom; found list"
--   
asAtom :: (t -> Either String a) -> WellFormedSExpr t -> Either String a

-- | Parse an assoc-list using the provided function.
--   
--   
--   >>> let def (x, y) = do { a <- fromAtom x; b <- fromAtom y; return (a ++ ": " ++ b) }
--   
--   >>> let defList xs = do { defs <- mapM def xs; return (unlines defs) }
--   
--   >>> asAssoc defList (L [ L [A "legs", A "four"], L [ A "trunk", A "one"] ])
--   Right "legs: four\ntrunk: one\n"
--   
--   >>> asAssoc defList (L [ L [A "legs", A "four"], L [ A "elephant"] ])
--   Left "asAssoc: expected pair; found list of length 1"
--   
asAssoc :: ([(WellFormedSExpr t, WellFormedSExpr t)] -> Either String a) -> WellFormedSExpr t -> Either String a

-- | Run the parser on the first element of a Haskell list of
--   WellFormedSExpr values, failing if the list is empty. This is
--   useful in conjunction with the asList function.
car :: (WellFormedSExpr t -> Either String t') -> [WellFormedSExpr t] -> Either String t'

-- | Run the parser on all but the first element of a Haskell list of
--   WellFormedSExpr values, failing if the list is empty. This is
--   useful in conjunction with the asList function.
cdr :: ([WellFormedSExpr t] -> Either String t') -> [WellFormedSExpr t] -> Either String t'
