diff --git a/Data/Syntax.hs b/Data/Syntax.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax.hs
@@ -0,0 +1,124 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{- |
+Module      :  Data.Syntax
+Description :  Abstract syntax description.
+Copyright   :  (c) Paweł Nowak
+License     :  MIT
+
+Maintainer  :  Paweł Nowak <pawel834@gmail.com>
+Stability   :  experimental
+
+Abstract syntax descriptions based on semi-isomorphisms.
+-}
+module Data.Syntax (
+    -- * Syntax.
+    Syntax(..),
+    -- * Common isomorphisms.
+    packed
+    ) where
+
+import Prelude hiding (take, takeWhile)
+
+import Control.Lens
+import Control.Lens.SemiIso
+import Data.MonoTraversable
+import Data.SemiIsoFunctor
+import Data.Sequences hiding (take, takeWhile)
+
+-- | An isomorphism between a sequence and a list of its elements.
+packed :: IsSequence seq => Iso' seq [Element seq]
+packed = iso otoList fromList
+
+-- | An abstract syntax description based on semi-isomorphisms.
+--
+-- This class can be implemented by both parsers and printers (and maybe more?).
+-- 
+-- The usual use is to write a polymorphic syntax description and instantiate it
+-- both as a parser and a printer. An example syntax description:
+--
+-- > | A simple untyped lambda calculus.
+-- > data AST = Var Text
+-- >          | App AST AST
+-- >          | Abs Text AST
+-- >     deriving (Show)
+-- >
+-- > $(makePrisms ''AST)
+-- >
+-- > -- | A variable name.
+-- > name :: Syntax syn Text => syn Text
+-- > name = S.takeWhile1 isAlphaNum
+-- >
+-- > -- | Encloses a symbol in parentheses.
+-- > parens :: Syntax syn Text => syn a -> syn a
+-- > parens m = S.char '(' */ S.spaces_ */ m /* S.spaces_ /* S.char ')'
+-- >
+-- > -- | An atom is a variable or an expression in parentheses.
+-- > atom :: Syntax syn Text => syn AST
+-- > atom =  _Var /$/ name
+-- >     /|/ parens expr
+-- >
+-- > -- | An expression of our lambda calculus.
+-- > expr :: Syntax syn Text => syn AST
+-- > expr =  _App /$/ atom /* S.spaces1 /*/ atom
+-- >     /|/ _Abs /$/ S.char '\\'   /* S.spaces_
+-- >               */ name          /* S.spaces
+-- >              /*  S.string "->" /* S.spaces
+-- >              /*/ expr 
+-- >     /|/ atom
+--
+-- Methods of this class try to mimic "Data.Attoparsec.Text" interface.
+class ( SemiIsoAlternative syn
+      , IsSequence seq
+      , Eq seq
+      , Eq (Element seq)) 
+      => Syntax syn seq | syn -> seq 
+    where
+    
+    -- | Any character.
+    anyChar :: syn (Element seq)
+
+    -- | A specific character.
+    char :: Element seq -> syn ()
+    char c = exact c /$/ anyChar
+
+    -- | Any character except the given one.
+    notChar :: Element seq -> syn (Element seq)
+    notChar c = filtered (/= c) /$/ anyChar
+
+    -- | Any character satisfying a predicate.
+    satisfy :: (Element seq -> Bool) -> syn (Element seq)
+    satisfy p = filtered p /$/ anyChar
+
+    -- | Transforms a character using a SemiIso and filters out values
+    -- not satisfying the predicate.
+    satisfyWith :: ASemiIso' a (Element seq) -> (a -> Bool) -> syn a
+    satisfyWith ai p = filtered p . ai /$/ anyChar
+
+    -- | A specific string.
+    string :: seq -> syn ()
+    string s = exact s /$/ take (olength s)
+
+    -- | A string of length @n@.
+    take :: Int -> syn seq
+    take n = packed /$/ sireplicate n anyChar
+
+    -- | Maximal string which elements satisfy a predicate.
+    takeWhile :: (Element seq -> Bool) -> syn seq
+    takeWhile p = packed /$/ simany (satisfy p)
+
+    -- | Maximal non-empty string which elements satisfy a predicate.
+    takeWhile1 :: (Element seq -> Bool) -> syn seq
+    takeWhile1 p = packed /$/ sisome (satisfy p)
+
+    -- | Maximal string which elements do not satisfy a predicate.
+    takeTill :: (Element seq -> Bool) -> syn seq
+    takeTill p = takeWhile (not . p)
+
+    -- | Maximal non-empty string which elements do not satisfy a predicate.
+    takeTill1 :: (Element seq -> Bool) -> syn seq
+    takeTill1 p = takeWhile1 (not . p)
+
+    {-# MINIMAL anyChar #-}
diff --git a/Data/Syntax/Char.hs b/Data/Syntax/Char.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax/Char.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ConstraintKinds #-}
+{- |
+Module      :  Data.Syntax.Char
+Description :  Char specific combinators.
+Copyright   :  (c) Paweł Nowak
+License     :  MIT
+
+Maintainer  :  Paweł Nowak <pawel834@gmail.com>
+Stability   :  experimental
+
+Common combinators that work with sequences of chars.
+
+There are A LOT of combinators missing.
+-}
+module Data.Syntax.Char (
+    SyntaxChar,
+    spaces,
+    spaces_,
+    spaces1,
+    spaces1_,
+    endOfLine
+    ) where
+
+import           Control.Lens.SemiIso
+import           Data.Char
+import           Data.MonoTraversable
+import           Data.Monoid
+import           Data.SemiIsoFunctor
+import           Data.Syntax (Syntax)
+import qualified Data.Syntax as S
+
+-- | Syntax constrainted to sequences of chars.
+type SyntaxChar syn seq = (Syntax syn seq, Element seq ~ Char)
+
+-- | Accepts zero or more spaces. Generates a single space.
+spaces :: SyntaxChar syn seq => syn ()
+spaces = constant (opoint ' ') /$/ S.takeWhile isSpace
+
+-- | Accepts zero or more spaces. Generates no output.
+spaces_ :: SyntaxChar syn seq => syn ()
+spaces_ = constant mempty /$/ S.takeWhile isSpace
+
+-- | Accepts one or more spaces. Generates a single space.
+spaces1 :: SyntaxChar syn seq => syn ()
+spaces1 = constant (opoint ' ') /$/ S.takeWhile1 isSpace
+
+-- | Accepts one or more spaces. Generates no output.
+spaces1_ :: SyntaxChar syn seq => syn ()
+spaces1_ = constant mempty /$/ S.takeWhile1 isSpace
+
+-- | Accepts a single newline. Generates a newline.
+endOfLine :: SyntaxChar syn seq => syn ()
+endOfLine = S.char '\n'
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014 Paweł Nowak
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/syntax.cabal b/syntax.cabal
new file mode 100644
--- /dev/null
+++ b/syntax.cabal
@@ -0,0 +1,28 @@
+name:                syntax
+version:             0.1.0.0
+synopsis:            Abstract syntax descriptions for parsing and pretty-printing.
+description:         Write single syntax description, get both parser and pretty-printer.
+                     .
+                     Syntax descriptions are based on semi-isomorphisms from @semi-iso@ library.
+                     .
+                     The library is very young. There are lots of useful combinators that could be written.
+                     .
+                     See @syntax-example@ for an example.
+license:             MIT
+license-file:        LICENSE
+author:              Paweł Nowak
+maintainer:          Paweł Nowak <pawel834@gmail.com>
+copyright:           Paweł Nowak 2014
+category:            Data
+build-type:          Simple
+cabal-version:       >=1.10
+
+source-repository head
+  type:     git
+  location: git@github.com:Pawel834/syntax.git
+
+library
+  exposed-modules:     Data.Syntax
+                       Data.Syntax.Char
+  build-depends:       base >= 4 && < 5, mono-traversable, lens, semi-iso
+  default-language:    Haskell2010
