boomerang-1.3.4: Text/Boomerang.hs
{-|
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