diff --git a/Algebra/Parser.hs b/Algebra/Parser.hs
new file mode 100644
--- /dev/null
+++ b/Algebra/Parser.hs
@@ -0,0 +1,183 @@
+-- |A module providing simple Parser combinator functionality. Useful
+-- for small parsing tasks such as identifier parsing or command-line
+-- argument parsing
+module Algebra.Parser (
+  module Algebra,
+  -- * The ParserT Type
+  ParserT(..),Parser,ParserA(..),_ParserA,
+
+  -- ** The Stream class
+  Stream(..),emptyStream,
+
+  -- ** Converting to/from Parsers
+  parserT,parser,ioParser,
+
+  -- * Basic combinators
+  (<+>),(>*>),(<*<),
+  token,satisfy,
+  oneOf,noneOf,single,
+  several,
+  remaining,eoi,
+
+  -- ** Specialized utilities
+  readable,number,digit,letter,alNum,quotedString,space,spaces,eol,
+  
+  -- * Basic combinators
+  many,many1,sepBy,sepBy1,skipMany,skipMany1,
+  chainl,chainr,option                   
+  ) where
+
+import Algebra
+
+import Data.Char
+import Data.Containers.Sequence
+
+newtype ParserT s m a = ParserT (StateT s (ListT m) a)
+                        deriving (Unit,Functor,Applicative,Monoid,Semigroup,
+                                  Monad,MonadFix,MonadList,MonadState s,MonadWriter w)
+type Parser c a = ParserT c Id a
+deriving instance Monad m => MonadError Void (ParserT c m)
+instance MonadTrans (ParserT s) where
+  lift = ParserT . lift . lift
+instance ConcreteMonad (ParserT s) where
+  generalize = parserT %%~ map (pure.yb _Id)
+_ParserT :: Iso (ParserT s m a) (ParserT t n b) (StateT s (ListT m) a) (StateT t (ListT n) b)
+_ParserT = iso ParserT (\(ParserT p) -> p)
+parserT :: (Functor n,Functor m) => Iso (ParserT s m a) (ParserT t n b) (s -> m [(s,a)]) (t -> n [(t,b)])
+parserT = mapping listT.stateT._ParserT
+parser :: Iso (Parser s a) (Parser t b) (s -> [(s,a)]) (t -> [(t,b)])
+parser = mapping _Id.parserT
+
+ioParser :: Parser a b -> (a -> IO b)
+ioParser p s = case (p^..parser) s of
+  [] -> error "Error in parsing"
+  (_,a):_ -> return a
+
+-- |The @(+)@ operator with lower priority
+(<+>) :: Semigroup m => m -> m -> m
+(<+>) = (+)
+(>*>) :: Monad m => ParserT a m b -> ParserT b m c -> ParserT a m c
+(>*>) = (>>>)^..(_ParserA<.>_ParserA<.>_ParserA)
+(<*<) :: Monad m => ParserT b m c -> ParserT a m b -> ParserT a m c
+(<*<) = flip (>*>)
+
+newtype ParserA m s a = ParserA (ParserT s m a)
+_ParserA :: Iso (ParserA m s a) (ParserA m' s' a') (ParserT s m a) (ParserT s' m' a')
+_ParserA = iso ParserA (\(ParserA p) -> p)
+parserA :: Iso (ParserA m s a) (ParserA m' s' a') (StateA (ListT m) s a) (StateA (ListT m') s' a') 
+parserA = from stateA._ParserT._ParserA
+instance Monad m => Category (ParserA m) where
+  id = ParserA get
+  (.) = (.)^.(parserA<.>parserA<.>parserA)
+instance Monad m => Split (ParserA m) where
+  (<#>) = (<#>)^.(parserA<.>parserA<.>parserA)
+instance Monad m => Choice (ParserA m) where
+  (<|>) = (<|>)^.(parserA<.>parserA<.>parserA)
+instance Monad m => Arrow (ParserA m) where
+  arr f = arr f^.parserA
+
+-- |The remaining Stream to parse
+remaining :: Monad m => ParserT s m s
+remaining = get
+-- |Consume a token from the Stream
+token :: (Monad m,Stream c s) => ParserT s m c
+{-# SPECIALIZE token :: Monad m => ParserT [c] m c #-}
+token = get >>= \s -> case uncons s of
+  Nothing -> zero
+  Just (c,t) -> put t >> pure c
+
+-- |Parse zero, one or more successive occurences of a parser.
+many :: Monad m => ParserT c m a -> ParserT c m [a]
+many p = many1 p <+> pure []
+-- |Parse one or more successiveé occurences of a parser.
+many1 :: Monad m => ParserT c m a -> ParserT c m [a]
+many1 p = (:)<$>p<*>many p
+-- |Skip many occurences of a parser
+skipMany :: Monad m => ParserT c m a -> ParserT c m ()
+skipMany p = skipMany1 p <+> pure () 
+-- |Skip multiple occurences of a parser
+skipMany1 :: Monad m => ParserT c m a -> ParserT c m ()
+skipMany1 p = p >> skipMany p
+
+-- |Consume a token and succeed if it verifies a predicate
+satisfy :: (Monad m, Stream c s) => (c -> Bool) -> ParserT s m c
+{-# SPECIALIZE satisfy :: Monad m => (c -> Bool) -> ParserT [c] m c #-}
+satisfy p = token <*= guard . p
+-- |Consume a single fixed token or fail.
+single :: (Eq c, Monad m, Stream c s) => c -> ParserT s m ()
+single = void . satisfy . (==)
+
+-- |Consume a structure of characters or fail
+several :: (Eq c, Monad m, Foldable t, Stream c s) => t c -> ParserT s m ()
+{-# SPECIALIZE several :: (Eq c, Monad m) => [c] -> ParserT [c] m () #-}
+several l = traverse_ single l
+
+-- |Try to consume a parser. Return a default value when it fails.
+option :: Monad m => a -> ParserT s m a -> ParserT s m a
+option a p = p+pure a
+
+-- |Succeed only if we are by the End Of Input.
+eoi :: (Monad m,Stream c s) => ParserT s m ()
+eoi = remaining >>= guard.emptyStream
+-- |The end of line
+eol :: (Monad m,Stream Char s) => ParserT s m ()
+eol = single '\n'
+
+-- |Parse one or more successive occurences of a parser separated by
+-- occurences of a second parser.
+sepBy1 ::Monad m => ParserT c m a -> ParserT c m b -> ParserT c m [a]
+sepBy1 p sep = (:)<$>p<*>many (sep >> p)
+-- |Parse zero or more successive occurences of a parser separated by
+-- occurences of a second parser.
+sepBy ::Monad m => ParserT c m a -> ParserT c m b -> ParserT c m [a]
+sepBy p sep = option [] (sepBy1 p sep)
+
+-- |Parse a member of a set of values
+oneOf :: (Eq c, Monad m, Foldable t, Stream c s) => t c -> ParserT s m c
+oneOf = satisfy . flip elem
+-- |Parse anything but a member of a set
+noneOf :: (Eq c, Monad m, Foldable t, Stream c s) => t c -> ParserT s m c
+noneOf = satisfy . map not . flip elem
+
+-- |Parse a litteral decimal number
+number :: (Monad m,Stream Char s,Num n) => ParserT s m n
+number = fromInteger.read <$> many1 digit
+-- |Parse a single decimal digit
+digit :: (Monad m,Stream Char s) => ParserT s m Char
+digit = satisfy isDigit
+alNum :: (Monad m,Stream Char s) => ParserT s m Char
+alNum = satisfy isAlphaNum
+letter :: (Monad m,Stream Char s) => ParserT s m Char
+letter = satisfy isAlpha
+-- |Parse a delimited string, unsing '\\' as the quoting character
+quotedString :: (Monad m,Stream Char s) => Char -> ParserT s m String
+quotedString d = between (single d) (single d) (many ch)
+  where ch = single '\\' >> unquote<$>token
+             <+> noneOf (d:"\\")
+        unquote 'n' = '\n'
+        unquote 't' = '\t'
+        unquote c = c
+-- |A single space
+space :: (Monad m,Stream Char s) => ParserT s m Char
+space = satisfy isSpace
+-- |Many spaces
+spaces :: (Monad m,Stream Char s) => ParserT s m String
+spaces = many1 space
+
+infixl 1 `sepBy`,`sepBy1`
+infixr 0 <+>
+
+-- |Chain an operator with an initial value and several tail values.
+chainr :: (Stream c s,Monad m) => ParserT s m a -> ParserT s m (b -> a -> a) -> ParserT s m b -> ParserT s m a
+chainr expr op e = compose<$>many (op<**>e)<*>expr
+-- |Chain an operator with an initial value
+chainl :: (Stream c s,Monad m) => ParserT s m a -> ParserT s m (a -> b -> a) -> ParserT s m b -> ParserT s m a
+chainl expr op e = compose<$>many (flip<$>op<*>e)<**>expr
+
+-- |Test if a Stream is empty
+emptyStream :: Stream c s => s -> Bool
+emptyStream = maybe True (const False) . uncons
+
+readable :: (Monad m,Read a) => ParserT String m a 
+readable = generalize $ map2 swap (readsPrec 0)^.parser
+
diff --git a/Algebra/Parser/Regex.hs b/Algebra/Parser/Regex.hs
new file mode 100644
--- /dev/null
+++ b/Algebra/Parser/Regex.hs
@@ -0,0 +1,29 @@
+module Algebra.Parser.Regex (regex,runRegex) where
+
+import Algebra.Parser
+
+runRegex :: String -> String -> [([(String,String)],String)]
+runRegex re = join (pure re >*> regex)^..parser <&> map snd
+
+regex :: Parser String (Parser String ([(String,String)],String))
+regex = _union
+  where _union = (adjacent`sepBy`single '|') <&> sum
+        adjacent = many postfixed <&> map concat.sequence
+        atom = dot <+> range <+> otherChar <+> between (single '(') (single ')') _union
+        postfixed = comp<$>atom<*>many postfun
+          where postfun = satisfy (`elem`"*+?") <&> \c -> case c of
+                  '*' -> map sum.many
+                  '+' -> map sum.many1
+                  '?' -> (+ pure ([],""))
+                  _ -> undefined
+                comp a fs = compose fs a
+        dot = shallow token <$ single '.'
+        otherChar = shallow.char<$>noneOf "()[*?|+"
+        range = between (single '[') (single ']') ranges
+          where ranges = sum <$> many subRange
+                subRange = mkRange<$>subChar<*single '-' <*>subChar
+                           <+> shallow.char<$>subChar
+                mkRange a b = shallow $ satisfy (\c -> c>=a && c<=b)
+                subChar = noneOf "]"
+        shallow = (([],).pure<$>)
+        char c = c<$single c
diff --git a/Data/Serialize.hs b/Data/Serialize.hs
new file mode 100644
--- /dev/null
+++ b/Data/Serialize.hs
@@ -0,0 +1,136 @@
+{-# LANGUAGE ScopedTypeVariables, LambdaCase #-}
+module Data.Serialize (
+  -- * You'll need this
+  module Algebra.Parser,
+  
+  -- * Serialization
+  Serializable(..),Builder,bytesBuilder,chunkBuilder,serialize,serial,
+  -- ** Convenience functions
+  word8,Word8,Word32,Word64,Either3(..),
+  ) where
+
+import Algebra.Parser hiding (uncons)
+import Data.ByteString.Lazy.Builder
+import qualified Data.ByteString as BSS
+import qualified Data.ByteString.Lazy as BS
+import Data.ByteString.Unsafe 
+import Data.Word
+import Foreign.Ptr
+import Foreign.Storable
+import qualified Data.Monoid as M
+import System.Endian
+import Data.Bits (shiftR,shiftL)
+import Data.Containers
+import Data.ByteString.Lazy.UTF8 (uncons)
+
+class Serializable t where
+  encode :: t -> Builder
+  serializable :: Parser Bytes t 
+
+serialize :: Serializable t => t -> Bytes
+serialize = toLazyByteString . encode
+
+serial :: (Serializable t,Serializable t') => Traversal t t' Bytes Bytes
+serial = prism (serializable^.from parser & \f a -> map snd (foldr (const . Right) (Left a) (f a))) (const serialize)
+
+bytesBuilder :: Bytes:<->:Builder
+bytesBuilder = iso lazyByteString toLazyByteString
+chunkBuilder :: Chunk:<->:Builder
+chunkBuilder = iso byteString (by chunk.toLazyByteString)
+
+instance Semigroup Word8 ; instance Monoid Word8
+instance Semigroup Word32 ; instance Monoid Word32
+instance Semigroup Word64 ; instance Monoid Word64
+
+instance Semigroup Builder where (+) = M.mappend
+instance Monoid Builder where zero = M.mempty
+
+withChunk :: Chunk -> (Ptr b -> IO a) -> a
+withChunk b f = unsafeUseAsCString b (f . castPtr)^.thunk
+
+storable :: forall a. Storable a => Parser Bytes a
+storable = p^.parser
+  where p s | BSS.length ch >= sz = pure (t,res)
+            | otherwise = zero
+          where res = withChunk ch peek :: a
+                (h,t) = BS.splitAt (fromIntegral sz) s
+                ch = h^.chunk
+                sz = sizeOf res
+  
+instance Serializable Char where
+  encode = charUtf8
+  serializable = gets uncons >>= \case
+    Just (c,t) -> c <$ put t
+    Nothing -> zero
+instance Serializable Word8 where
+  encode = word8
+  serializable = storable
+instance Serializable Word32 where
+  encode = word32BE
+  serializable = fromBE32<$>storable
+instance Serializable Word64 where
+  encode = word64BE
+  serializable = fromBE64<$>storable
+instance Serializable Int where
+  encode n = encode (size bytes :: Word8) + foldMap (encode . w8) bytes
+    where bytes = takeWhile (>0) $ iterate (`shiftR`8) n
+          w8 = fromIntegral :: Int -> Word8
+  serializable = serializable >>= \n -> do
+    bytes <- sequence (serializable <$ [1..n :: Word8])
+    return $ sum (zipWith shiftL (map (fromIntegral :: Word8 -> Int) bytes) [0,8..])
+instance Serializable Integer where
+  encode n = encode s + foldMap (word8 . fromIntegral) (take s l)
+    where l = iterate (`shiftR`8) (if n>=0 then n else (-n))
+          s = length (takeWhile (/=0) l)
+  serializable = do
+    n <- serializable
+    doTimes n serializable <&> sum . zipWith (\sh b -> fromIntegral (b :: Word8)`shiftL`sh) [0,8..]
+instance Serializable a => Serializable (Maybe a) where
+  encode (Just a) = word8 1 + encode a
+  encode Nothing = word8 0
+  serializable = serializable >>= \w -> case w :: Word8 of
+    0 -> return Nothing
+    1 -> Just<$>serializable
+    _ -> error "Invalid encoding for Maybe serialized value"
+instance Serializable a => Serializable [a] where
+  encode l = encode (length l) + foldMap encode l
+  serializable = serializable >>= \n -> doTimes n serializable
+instance (Ord k,Serializable k,Serializable a) => Serializable (Map k a) where
+  encode m = encode (m^.keyed & toList)
+  serializable = serializable <&> fromList
+instance (Ord k,Ord a,Serializable k,Serializable a) => Serializable (Bimap k a) where
+  encode m = encode (toMap m^.keyed & toList)
+  serializable = serializable <&> fromList
+instance (Ord a,Serializable a) => Serializable (Set a) where
+  encode = encode . toList
+  serializable = serializable <&> fromList . map (,zero)
+instance (Serializable a,Serializable b) => Serializable (a:*:b) where
+  encode (a,b) = encode a+encode b
+  serializable = (,)<$>serializable<*>serializable
+instance (Serializable a,Serializable b,Serializable c) => Serializable (a,b,c) where
+  encode (a,b,c) = encode a+encode b+encode c
+  serializable = (,,)<$>serializable<*>serializable<*>serializable
+instance (Serializable a,Serializable b,Serializable c,Serializable d) => Serializable (a,b,c,d) where
+  encode (a,b,c,d) = encode a+encode b+encode c+encode d
+  serializable = (,,,)<$>serializable<*>serializable<*>serializable<*>serializable
+instance (Serializable a,Serializable b,Serializable c,Serializable d,Serializable e) => Serializable (a,b,c,d,e) where
+  encode (a,b,c,d,e) = encode a+encode b+encode c+encode d+encode e
+  serializable = (,,,,)<$>serializable<*>serializable<*>serializable<*>serializable<*>serializable
+instance (Serializable a,Serializable b) => Serializable (a:+:b) where
+  encode (Left a) = word8 0+encode a
+  encode (Right b) = word8 1+encode b
+  serializable = storable >>= \x -> case x :: Word8 of
+    0 -> Left<$>serializable
+    1 -> Right<$>serializable
+    _ -> zero
+
+data Either3 a b c = Alt3_1 a | Alt3_2 b | Alt3_3 c
+instance (Serializable a,Serializable b,Serializable c) => Serializable (Either3 a b c) where
+  encode (Alt3_1 a) = word8 0+encode a
+  encode (Alt3_2 b) = word8 1+encode b
+  encode (Alt3_3 c) = word8 2+encode c
+  serializable = storable >>= \x -> case x :: Word8 of
+    0 -> Alt3_1<$>serializable
+    1 -> Alt3_2<$>serializable
+    2 -> Alt3_3<$>serializable
+    _ -> zero
diff --git a/Data/Syntax.hs b/Data/Syntax.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE UndecidableInstances, LambdaCase, ParallelListComp, ViewPatterns #-}
+module Data.Syntax where
+
+import Algebra
+import Data.Containers
+import qualified Prelude as P
+import Algebra.Parser.Regex
+
+type Env f = Map String (ThunkT f)
+type Eval f = Env f -> ThunkT f
+type ThunkT f = f (SyntaxT f)
+data SyntaxT f = ValList [ThunkT f]
+              | Dictionary (Env f)
+              | Text String
+              | Function (ThunkT f -> ThunkT f)
+instance Show (ThunkT f) => Show (SyntaxT f) where
+  show (ValList l) = show l
+  show (Dictionary d) = "{"+show (toList (map show d^.keyed))+"}"
+  show (Text t) = show t
+  show (Function _) = "<fun>"
+
+dict :: Traversal' (SyntaxT f) (Env f)
+dict = prism f g
+  where f (Dictionary d) = Right d
+        f c = Left c
+        g (Dictionary _) d = Dictionary d
+        g x _ = x
+
+nil :: SyntaxT f
+nil = ValList zero
+variable :: Unit f => String -> SyntaxT f -> SyntaxT f
+variable n v = Dictionary (fromList [("name",pure $ Text n),("value",pure v)])
+funcall :: ThunkT f -> ThunkT f -> SyntaxT f
+funcall f x = ValList [f,x]
+
+reduce :: MonadReader (Env m) m => SyntaxT m -> ThunkT m
+reduce (ValList (map (>>= reduce) -> (fun:args))) = fun >>= \f -> foldlM call f args
+  where call (Function f) x = f x
+        call _ _ = error "Invalid function call"
+reduce (Dictionary d) = pure $ Dictionary $ fix (\d' -> map (local (d'+) . (>>= reduce)) d)
+reduce a = pure a
+
+list_ :: [a] -> [a]
+list_ = id
+lambda :: MonadReader (Env m) m => SyntaxT Id -> SyntaxT m -> (ThunkT m -> ThunkT m)
+lambda pat e = tryAlt
+  where tryAlt x = x >>= match >>= maybe (pure nil) bind
+          where bind vars = local (compose (_insert<$>list_ vars)) (reduce e)
+                  where _insert (s,v) = insert s (pure v)
+                match = matchPat pat
+matchPat :: Monad f => SyntaxT Id -> (SyntaxT f -> f (Maybe [(String,SyntaxT f)]))
+matchPat (Text re) = pure.matchText
+  where matchText (Text t) | ((a,wh):_) <- match t = pure $ map2 Text (("&",wh):a)
+        matchText _ = zero
+        match = runRegex re
+matchPat (Dictionary d) = matchDict
+  where matchDict (Dictionary d') = 
+          traverse (matches d') (toList pats) <&> map concat.sequence
+        matchDict _ = pure zero
+        pats = (matchPat.yb _Id<$>d)^.keyed
+        matches d' (k,m) = maybe (pure zero) (>>= m) (d'^.at k)
+matchPat (ValList l) = matchList
+  where n = length l
+        matchList (ValList l') | length (take n l') == n =
+          sequence [matchPat p =<< e | p <- yb _Id<$>l | e <- l'] <&> map concat.sequence
+        matchList _ = pure zero
+matchPat _ = pure (pure zero)
+
+lambdaSum :: Monad m => [ThunkT m -> ThunkT m] -> ThunkT m -> ThunkT m
+lambdaSum = foldr combine (const (pure nil))
+  where combine f g = \v -> f v >>= \case
+          ValList [] -> g v
+          x -> pure x
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,69 @@
+Bill and Ted's Public License
+=============================
+
+Everyone is permitted to copy and distribute verbatim or modified
+copies of this license document, and changing it is allowed as long as
+the name of the license is changed.
+
+PREAMBLE
+--------
+
+The “Greater Lunduke License” is inspired, in part, by the wisdom of
+the Two Great Ones, Bill S. Preston, Esq. and Ted “Theodore” Logan.
+Namely that we should all “be excellent to each other”, that being
+“bogus” is “most non-triumphant” and that all dudes should “party on”.
+
+This license applies those concepts in such a way that it is
+applicable to all forms of content, including, but not limited to:
+software, books, music, movies and various works of art.
+
+TERMS AND CONDITIONS
+--------------------
+
+### 1. Be Excellent To Each Other.
+
+The consumer of this work is granted the right to utilize this work in
+conjunction with any mechanism that is capable of utilizing it, in the
+form supplied by the content creator, without limitation as to
+specific hardware or software.
+
+The consumer of this work may make copies of this work (physical or
+otherwise) for backup purposes.
+
+The consumer of this work may lend this work to another individual
+provided that the following two conditions are met :
+  
+  1. the lender no longer utilizes or possesses the work
+  2. the work is not presently lent to another individual
+
+The consumer of this work may sell this work to another individual
+provided that the following two conditions are met :
+
+  1. the seller no longer utilizes or possesses the work 
+  2. once the work is sold, the seller relinquishes all rights and
+      copies of the work to the buyer.
+
+### 2. Don’t Be Bogus.
+
+The consumer of this work shall not redistribute modified, or
+unmodified, copies of this work without explicit written permission
+from the creator of this work.  The only exceptions allowed to this
+rule are the provisions outlined in section 1 of this license
+
+The consumer of this work shall not hold the creator of this work
+liable for anything the consumer does, or does not, do, or the results
+of utilizing this work.
+
+### 3. Party On, Dudes!
+
+The creator of this work provides the work in a form that contains no
+mechanism to disable the utilization of the work after a specific
+date, period of time or number of uses.
+
+If additional works, which are created and wholly owned by the work’s
+creator, are required to utilize this work, those additional works
+must also be made available to the consumer so long as the following
+conditions are met :
+  
+  1. doing so is possible
+  2. doing so does not cause harm to the creator of the work.
diff --git a/definitive-parser.cabal b/definitive-parser.cabal
new file mode 100644
--- /dev/null
+++ b/definitive-parser.cabal
@@ -0,0 +1,19 @@
+name:          definitive-parser
+version:       1.0
+
+synopsis:      A parser combinator library for the Definitive framework
+description:   
+author:        Marc Coiffier
+maintainer:    marc.coiffier@gmail.com
+license:       OtherLicense
+license-file:  LICENSE
+
+build-type:    Simple
+cabal-version: >=1.10
+
+library
+  exposed-modules: Algebra.Parser Data.Syntax Algebra.Parser.Regex Data.Serialize
+  build-depends: base (== 4.6.*), definitive-base (== 1.0.*), containers (== 0.5.*), deepseq (== 1.3.*), array (== 0.5.*), bytestring (== 0.10.*), vector (== 0.10.*), primitive (== 0.5.*), cpu (== 0.1.*), utf8-string (== 0.3.*)
+  default-extensions: TypeSynonymInstances NoMonomorphismRestriction StandaloneDeriving GeneralizedNewtypeDeriving TypeOperators RebindableSyntax FlexibleInstances FlexibleContexts FunctionalDependencies TupleSections MultiParamTypeClasses Rank2Types
+  ghc-options: -Wall -fno-warn-orphans -threaded
+  default-language: Haskell2010
