diff --git a/Data/Syntax.hs b/Data/Syntax.hs
--- a/Data/Syntax.hs
+++ b/Data/Syntax.hs
@@ -54,7 +54,7 @@
 
     -- | A specific character.
     char :: Element seq -> syn ()
-    char c = exact c /$/ anyChar
+    char c = rev (exact c) /$/ anyChar
 
     -- | Any character except the given one.
     notChar :: Element seq -> syn (Element seq)
@@ -71,7 +71,7 @@
 
     -- | A specific string.
     string :: seq -> syn ()
-    string s = exact s /$/ take (olength s)
+    string s = rev (exact s) /$/ take (olength s)
 
     -- | A string of length @n@.
     take :: Int -> syn seq
diff --git a/Data/Syntax/Char.hs b/Data/Syntax/Char.hs
--- a/Data/Syntax/Char.hs
+++ b/Data/Syntax/Char.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {- |
 Module      :  Data.Syntax.Char
@@ -14,20 +15,26 @@
 -}
 module Data.Syntax.Char (
     SyntaxChar(..),
+    SyntaxText,
     signed,
     spaces,
     spaces_,
     spaces1,
-    endOfLine
+    endOfLine,
+    digitDec,
+    digitOct,
+    digitHex
     ) where
 
 import Control.Lens.SemiIso
+import Data.Bits
 import Data.Char
 import Data.MonoTraversable
 import Data.Scientific (Scientific)
 import Data.SemiIsoFunctor
 import Data.Syntax
 import Data.Syntax.Combinator
+import Data.Text (Text)
 
 -- | Syntax constrainted to sequences of chars.
 --
@@ -37,11 +44,20 @@
     -- | An unsigned decimal number.
     decimal :: Integral a => syn a
 
+    -- | An unsigned hexadecimal number.
+    hexadecimal :: (Integral a, Bits a) => syn a
+
+    -- | A signed real number.
+    realFloat :: RealFloat a => syn a
+
     -- | A scientific number.
     scientific :: syn Scientific
 
-    {-# MINIMAL decimal, scientific #-}
+    {-# MINIMAL decimal, hexadecimal, realFloat, scientific #-}
 
+-- | An useful synonym for SyntaxChars with Text sequences.
+type SyntaxText syn = SyntaxChar syn Text
+
 -- | A number with an optional leading '+' or '-' sign character.
 signed :: (Real a, SyntaxChar syn seq) => syn a -> syn a
 signed n =  _Negative /$/ char '-' */ n
@@ -62,3 +78,27 @@
 -- | Accepts a single newline. Generates a newline.
 endOfLine :: SyntaxChar syn seq => syn ()
 endOfLine = char '\n'
+
+-- | A decimal digit.
+digitDec :: SyntaxChar syn seq => syn Int
+digitDec = semiIso toChar toInt /$/ anyChar
+  where toInt c | isDigit c = Right (digitToInt c)
+                | otherwise = Left ("Expected a decimal digit, got " ++ [c])
+        toChar i | i >= 0 && i <= 9 = Right (intToDigit i)
+                 | otherwise        = Left ("Expected a decimal digit, got number " ++ show i)
+
+-- | An octal digit.
+digitOct :: SyntaxChar syn seq => syn Int
+digitOct = semiIso toChar toInt /$/ anyChar
+  where toInt c | isOctDigit c = Right (digitToInt c)
+                | otherwise    = Left ("Expected an octal digit, got " ++ [c])
+        toChar i | i >= 0 && i <= 7 = Right (intToDigit i)
+                 | otherwise        = Left ("Expected an octal digit, got number " ++ show i)
+
+-- | A hex digit.
+digitHex :: SyntaxChar syn seq => syn Int
+digitHex = semiIso toChar toInt /$/ anyChar
+  where toInt c | isHexDigit c = Right (digitToInt c)
+                | otherwise    = Left ("Expected a hex digit, got " ++ [c])
+        toChar i | i >= 0 && i <= 15 = Right (intToDigit i)
+                 | otherwise         = Left ("Expected a hex digit, got number " ++ show i)
diff --git a/Data/Syntax/Indent.hs b/Data/Syntax/Indent.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax/Indent.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{- |
+Module      :  Data.Syntax.Indent
+Description :  Indentation.
+Copyright   :  (c) Paweł Nowak
+License     :  MIT
+
+Maintainer  :  Paweł Nowak <pawel834@gmail.com>
+Stability   :  experimental
+
+Provides a very simple indentation as a \"monad\" transformer.
+-}
+module Data.Syntax.Indent (
+    Indent,
+    runIndent,
+    breakLine,
+    indented
+    ) where
+
+import Data.SemiIsoFunctor
+import Data.Syntax
+import Data.Syntax.Char
+import Data.Syntax.Combinator
+import Prelude hiding (takeWhile, take)
+
+-- | Adds indentation to a syntax description.
+newtype Indent m a = Indent { unIndent :: (Int, m ()) -> m a }
+
+instance SemiIsoFunctor m => SemiIsoFunctor (Indent m) where
+    simap f (Indent g) = Indent $ \i -> simap f (g i)
+
+instance SemiIsoApply m => SemiIsoApply (Indent m) where
+    sipure ai = Indent $ \_ -> sipure ai
+    Indent f /*/ Indent g = Indent $ \i -> f i /*/ g i
+
+instance SemiIsoAlternative m => SemiIsoAlternative (Indent m) where
+    siempty = Indent $ \_ -> siempty
+    Indent f /|/ Indent g = Indent $ \i -> f i /|/ g i
+
+instance SemiIsoMonad m => SemiIsoMonad (Indent m) where
+    (Indent m) //= f = Indent $ \i -> m i //= (\x -> unIndent (f x) i)
+
+instance SemiIsoFix m => SemiIsoFix (Indent m) where
+    sifix f = Indent $ \i -> sifix $ \y -> unIndent (f y) i
+
+instance Syntax syn seq => Syntax (Indent syn) seq where
+    anyChar = Indent $ const anyChar
+    char = Indent . const . char
+    notChar = Indent . const . notChar
+    satisfy = Indent . const . satisfy
+    satisfyWith ai = Indent . const . satisfyWith ai
+    string = Indent . const . string
+    take = Indent . const . take
+    takeWhile = Indent . const . takeWhile
+    takeWhile1 = Indent . const . takeWhile1
+    takeTill = Indent . const . takeTill
+    takeTill1 = Indent . const . takeTill1
+
+instance SyntaxChar syn seq => SyntaxChar (Indent syn) seq where
+    decimal = Indent $ const decimal
+    scientific = Indent $ const scientific
+
+-- | @runIndent m tab@ runs the 'Indent' transformer using @tab@ once for each
+-- level of indentation.
+runIndent :: Indent m a -> m () -> m a
+runIndent = ($ 0) . curry . unIndent
+
+-- | Inserts a new line and correct indentation, but does not 
+-- require any formatting when parsing (it just skips all white space).
+breakLine :: SyntaxChar syn seq => Indent syn ()
+breakLine = Indent $ \(i, tab) -> opt (char '\n') /* opt (sireplicate_ i tab) /* spaces_
+
+-- | Increases the indentation level of its argument by one.
+indented :: Indent m a -> Indent m a
+indented (Indent f) = Indent $ \(i, tab) -> f (i + 1, tab)
diff --git a/syntax.cabal b/syntax.cabal
--- a/syntax.cabal
+++ b/syntax.cabal
@@ -1,16 +1,16 @@
 name:                syntax
-version:             0.2.1.0
+version:             0.3.0.0
 synopsis:            Syntax descriptions for unified parsing and pretty-printing.
 description:
   'syntax' allows you to write a single syntax description and instantiate is both as a parser and a pretty printer.
   .
-  The interface is based on a custom Functor/Applicative/Monad hierarchy, provided by the 'semi-iso' package. You fmap using
+  The interface is based on a custom Functor\/Applicative\/Monad hierarchy, provided by the 'semi-iso' package. You fmap using
   a semi-isomorphism instead of function. A semi-isomorphism is a isomorphism that can fail in both directions, with slightly
   weakened laws. It is worth to note that @Iso@s and @Prism@s from 'lens' are valid semi-isomorphisms :)
   .
-  Once you write a description you can, for example turn it into an Attoparsec parser.
+  Once you write a description you can, for example turn it into an Attoparsec parser, or into a 'Data.Syntax.Printer.Text.Printer'.
   .
-  See @syntax-example@ for an example, 'syntax-attoparsec' and 'syntax-pretty' for a parser/printer implementation.
+  See @syntax-example@ and @syntax-example-json@ for examples, @syntax-attoparsec@ and @syntax-printer@ for a parser/printer implementation.
   .
   The library was inspired by:
   .
@@ -18,10 +18,15 @@
   .
   TODO:
   .
-  * a printer library based on Text/ByteString builders (wrapping 'pretty' is inefficient and doesn't use any features of it),
-  * try to implement indentation and Haskell layout rule,
-  * combinators for binary data formats, vectors,
-  * implementation of do notation for SemiIsoMonad with QuasiQuoters.
+  * Research relative monads and relative monad transformers. Indent is basically a Reader monad over a syntax. How would a State monad look?
+  .
+  * Try to implement Haskell layout rule.
+  .
+  * Combinators for binary data formats, vectors.
+  .
+  * Better error messages.
+  .
+  * Maybe an implementation of do notation for SemiIsoMonad with QuasiQuoters, like the codo notation for comonads.
 
 license:             MIT
 license-file:        LICENSE
@@ -40,5 +45,6 @@
   exposed-modules:     Data.Syntax
                        Data.Syntax.Char
                        Data.Syntax.Combinator
-  build-depends:       base >= 4 && < 5, mono-traversable, lens >= 4, semi-iso >= 0.4.1, scientific >= 0.3
+                       Data.Syntax.Indent
+  build-depends:       base >= 4 && < 5, mono-traversable, lens >= 4, semi-iso >= 0.5.0, scientific >= 0.3, text
   default-language:    Haskell2010
