{-|

 Module      : Text.Boomerang

Boomerang is a DSL for creating parsers and pretty-printers using a
single specification. Instead of writing a parser, and then writing a
separate pretty-printer, both are created at once. This saves time,
and ensures that the parser and pretty-printer are inverses and stay
in-sync with each other.

Boomerang is a generalized derivative of the Zwaluw library created by
Sjoerd Visscher and Martijn van Steenbergen:

<http://hackage.haskell.org/package/Zwaluw>

Boomerang is similar in purpose, but different in implementation to:

<http://hackage.haskell.org/package/invertible-syntax>

Here is a simple example. First we enable three language extensions:

@ {\-\# LANGUAGE TemplateHaskell, TypeOperators, OverloadedStrings \#-\} @

In the imports, note that we hide @((.), id)@ from 'Prelude' and use
@((.), id)@ from "Control.Category" instead.

> {-# LANGUAGE TemplateHaskell, TypeOperators, OverloadedStrings #-}
> module Main where
>
> import Prelude hiding ((.), id)
> import Control.Category ((.), id)
> import Control.Monad (forever)
> import Text.Boomerang
> import Text.Boomerang.String
> import Text.Boomerang.TH
> import System.IO (hFlush, stdout)

Next we define a type that we want to be able to pretty-print and define parsers for:

> data Foo
>     = Bar
>     | Baz Int Char
>       deriving (Eq, Show)

Then we generate some combinators for the type:

> $(makeBoomerangs ''Foo)

The combinators will be named after the constructors, but with an r prefixed to them. In this case, @rBar@ and @rBaz@.

Now we can define a grammar:

> foo :: StringBoomerang () (Foo :- ())
> foo =
>     (  rBar
>     <> rBaz . "baz-" . int . "-" . alpha
>     )

@.@ is used to compose parsers together. '<>' is used for choice.

Now we can use @foo@ as a printer or a parser.

Here is an example of a successful parse:

> test1 = parseString foo "baz-2-c"

@
*Main> test1
Right (Baz 2 'c')
@

And another example:

> test2 = parseString foo ""

@
*Main> test2
Right Bar
@

Here is an example of a parse error:

> test3 = parseString foo "baz-2-3"

@
*Main> test3
Left parse error at (0, 6): unexpected '3'; expecting an alphabetic Unicode character
@

we can also use @foo@ to pretty-print a value:

> test4 = unparseString foo (Baz 1 'z')

@
*Main> test4
Just "baz-1-z"
@

Here is a little app that allows you to interactively test @foo@.

> testInvert :: String -> IO ()
> testInvert str =
>     case parseString foo str of
>       (Left e) -> print e
>       (Right f') ->
>           do putStrLn $ "Parsed: " ++ show f'
>              case unparseString foo f' of
>                Nothing  -> putStrLn "unparseString failed to produce a value."
>                (Just s) -> putStrLn $ "Pretty: " ++ s

> main = forever $
>     do putStr "Enter a string to parse: "
>        hFlush stdout
>        l <- getLine
>        testInvert l


-}
module Text.Boomerang
    ( module Text.Boomerang.Combinators
    , module Text.Boomerang.Error
    , module Text.Boomerang.HStack
    , module Text.Boomerang.Prim
    , module Text.Boomerang.Pos
    )
    where

import Text.Boomerang.Combinators
import Text.Boomerang.Error
import Text.Boomerang.HStack
import Text.Boomerang.Prim
import Text.Boomerang.Pos

