diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Petter Bergman
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Petter Bergman nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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/bgmax.cabal b/bgmax.cabal
new file mode 100644
--- /dev/null
+++ b/bgmax.cabal
@@ -0,0 +1,34 @@
+-- Initial bgmax.cabal generated by cabal init.  For further documentation,
+--  see http://haskell.org/cabal/users-guide/
+
+name:                bgmax
+version:             0.1.0.0
+synopsis:            Parse BgMax-files
+homepage:            http://petterbergman.se/bgmax.html
+license:             BSD3
+license-file:        LICENSE
+author:              Petter Bergman
+maintainer:          jon.petter.bergman@gmail.com
+-- copyright:           
+category:            Finance
+build-type:          Simple
+-- extra-source-files:  
+cabal-version:       >=1.10
+description:         
+  A low-level parser for 
+  <http://www.bgc.se/upload/Gemensamt/Trycksaker/Manualer/BG6040.pdf BgMax>
+  -files from <http://www.bgc.se Bankgirocentralen> (BGC).
+  It is able to parse all of the 
+  <http://www.bgc.se/templates/Iframe____3125.aspx example files> from BGC.
+
+library
+  exposed-modules:     Finance.BgMax.TK 
+                       Finance.BgMax.Parser
+  -- other-modules:       
+  other-extensions:    OverloadedStrings
+  build-depends:       base >=4.7 && <4.8,
+                       time >=1.4.2,
+                       bytestring >=0.10.4.0,
+                       attoparsec >=0.12.1.2
+  hs-source-dirs:      src
+  default-language:    Haskell98
diff --git a/src/Finance/BgMax/Parser.hs b/src/Finance/BgMax/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Finance/BgMax/Parser.hs
@@ -0,0 +1,185 @@
+{-# LANGUAGE OverloadedStrings #-}
+{- |
+Module      :  $Header$
+Description :  Parser for the BgMax file format
+Copyright   :  (c) Petter Bergman
+License     :  BSD3
+
+Maintainer  :  jon.petter.bergman@gmail.com
+Stability   :  experimental
+Portability :  non-portable (OverloadedStrings)
+
+This module contains a Parser for the 
+<http://www.bgc.se/upload/Gemensamt/Trycksaker/Manualer/BG6040.pdf BgMax>
+format.
+
+The parser tries to be forgiving with input it doesn't understand.
+-}
+module Finance.BgMax.Parser(parseBgMax) where
+import Finance.BgMax.TK
+import Data.ByteString.Char8(ByteString,dropWhile,reverse,readInt,readInteger,null,replicate)
+import Data.Time(LocalTime(..),Day,TimeOfDay(..),fromGregorian)
+import Data.Char(isSpace)
+import Data.Attoparsec.ByteString.Char8(Parser,take,endOfLine,sepBy,string,skipWhile,notInClass)
+import Prelude hiding (take,dropWhile,reverse,null,replicate)
+import Control.Applicative((<|>),(*>),(<*>),(<$>),(<*))
+import Data.Fixed(Pico)
+
+class N a where
+  readN :: ByteString -> Maybe (a,ByteString)
+
+instance N Int where
+  readN = readInt
+
+instance N Integer where
+  readN = readInteger
+  
+readFullN :: N a => ByteString -> Parser a
+readFullN bs = 
+  case readN bs of
+    Nothing -> fail $ "could not read as Int: " ++ show bs
+    Just (x,bs') | null bs' -> return x
+                 | otherwise -> fail $ "could not read all characters as Int: " ++ show bs'
+
+n' :: N a => ByteString -> Parser a
+n' = readFullN
+
+n :: N a => Int -> Parser a
+n c = take c >>= n'
+
+nhb' :: N a => ByteString -> Parser a
+nhb' = readFullN . dropWhile isSpace
+
+nhb :: N a => Int -> Parser a
+nhb c = take c >>= nhb'
+
+orBlank :: (Int -> Parser a) -> Int -> Parser (Maybe a)
+orBlank p c = (fmap Just $ p c) <|> (string (replicate c ' ') *> (return Nothing))
+
+avb' :: ByteString -> ByteString
+avb' = reverse . dropWhile isSpace . reverse
+
+avb :: Int -> Parser ByteString
+avb = fmap avb' . take
+
+ab' :: ByteString -> ByteString
+ab' = dropWhile isSpace
+
+ab :: Int -> Parser ByteString
+ab = fmap ab' . take
+
+pOrT :: Parser TestMark
+pOrT =
+  "T" *> return T <|>
+  "P" *> return P
+
+parseCurrency :: Parser Currency
+parseCurrency =
+  "EUR" *> return EUR <|>
+  "SEK" *> return SEK
+
+makeReference :: Int -> ByteString -> Parser Reference
+makeReference 0 _ = return Ref0
+makeReference 1 _ = return Ref1
+makeReference 2 bs = fmap Ref2 $ nhb' bs
+makeReference 3 bs = return $ Ref3 $ ab' bs
+makeReference 4 bs = return $ Ref4 $ avb' bs
+makeReference 5 bs = return $ Ref5 $ ab' bs
+makeReference i bs = return $ Ref i bs
+
+parseDepositType :: Parser DepositType
+parseDepositType = "K" *> return K <|>
+                   "D" *> return D <|>
+                   "S" *> return S
+
+parseDay :: Parser Day
+parseDay = fromGregorian <$> n 4 <*> n 2 <*> n 2
+
+parseMicroseconds :: Parser Pico
+parseMicroseconds =
+  do
+    second <- n 2
+    microsecond <- n 6
+    return $ (fromInteger second) + ((fromInteger microsecond) / 1000000)
+
+parseTimeOfDay :: Parser TimeOfDay
+parseTimeOfDay = TimeOfDay <$> n 2 <*> n 2 <*> parseMicroseconds
+
+localTime :: Parser LocalTime
+localTime = LocalTime <$> parseDay <*> parseTimeOfDay
+
+parseTransaction :: Parser Transaction
+parseTransaction = 
+  do
+    sBG <- n 10
+    ref' <- take 25
+    amm <- n 18
+    refCode <- n 1
+    chan <- n 1
+    bglNo <- n 12
+    imag <- n 1
+    ref <- makeReference refCode ref'
+    return $ Transaction sBG ref amm chan bglNo imag
+
+parsePost :: Parser a -> Parser b -> Parser b
+parsePost code make = code *> make <* skipWhile (== ' ')
+
+tk01 :: Parser Post
+tk01 = fmap TK01 $ parsePost "01" $ TK01_t <$> avb 20 <*> n 2 <*> localTime <*> pOrT
+
+tk05 :: Parser Post
+tk05 = fmap TK05 $ parsePost "05" $ TK05_t <$> n 10 <*> orBlank n 10 <*> parseCurrency
+
+tk20 :: Parser Post
+tk20 = fmap TK20 $ parsePost "20" $ TK20_t <$> parseTransaction
+
+tk21 :: Parser Post
+tk21 = fmap TK21 $ parsePost "21" $ TK21_t <$> parseTransaction <*> n 1
+
+tk22 :: Parser Post
+tk22 = fmap TK22 $ parsePost "22" $ TK22_t <$> parseTransaction
+
+tk23 :: Parser Post
+tk23 = fmap TK23 $ parsePost "23" $ TK23_t <$> parseTransaction
+
+tk25 :: Parser Post
+tk25 = fmap TK25 $ parsePost "25" $ TK25_t <$> ab 50
+
+tk26 :: Parser Post
+tk26 = fmap TK26 $ parsePost "26" $ TK26_t <$> avb 35 <*> avb 35
+
+tk27 :: Parser Post
+tk27 = fmap TK27 $ parsePost "27" $ TK27_t <$> avb 35 <*> avb 9
+
+tk28 :: Parser Post
+tk28 = fmap TK28 $ parsePost "28" $ TK28_t <$> avb 35 <*> avb 35 <*> avb 2
+
+tk29 :: Parser Post
+tk29 = fmap TK29 $ parsePost "29" $ TK29_t <$> n 12
+
+tk15 :: Parser Post
+tk15 = fmap TK15 $ parsePost "15" $ TK15_t <$> n 35 <*> parseDay <*> n 5 <*> n 18 <*> parseCurrency <*> n 8 <*> orBlank (const parseDepositType) 1
+
+tk70 :: Parser Post
+tk70 = fmap TK70 $ parsePost "70" $ TK70_t <$> n 8 <*> n 8 <*> n 8 <*> n 8
+
+tk :: Parser Post
+tk = (TK <$> n 2) <* skipWhile (notInClass "\n\r")
+
+-- | Parser for BgMax posts.
+parseBgMax :: Parser [Post]
+parseBgMax = sepBy go endOfLine 
+  where go = tk01 <|> 
+             tk05 <|> 
+             tk20 <|> 
+             tk21 <|> 
+             tk22 <|> 
+             tk23 <|> 
+             tk25 <|>
+             tk26 <|>
+             tk27 <|>
+             tk28 <|>
+             tk29 <|>
+             tk15 <|> 
+             tk70 <|>
+             tk
diff --git a/src/Finance/BgMax/TK.hs b/src/Finance/BgMax/TK.hs
new file mode 100644
--- /dev/null
+++ b/src/Finance/BgMax/TK.hs
@@ -0,0 +1,185 @@
+{- |
+Module      :  $Header$
+Description :  Datatypes for the BgMax file format
+Copyright   :  (c) Petter Bergman
+License     :  BSD3
+
+Maintainer  :  jon.petter.bergman@gmail.com
+Stability   :  experimental
+Portability :  portable
+
+This module contain data definitions for the different types of "Posts" or 
+"Transaction Codes" that may occur in a BgMax file, as well as auxiliary
+data types. 
+
+The datatypes should map in a straightforward way to the 
+documentation from <http://www.bgc.se/upload/Gemensamt/Trycksaker/Manualer/BG6040.pdf Bankgirocentralen>.
+-}
+module Finance.BgMax.TK where
+import Data.Time(LocalTime(..),Day)
+import Data.ByteString(ByteString)
+
+-- | Testmark
+data TestMark = 
+    T -- ^ Test file  
+  | P -- ^ Production file 
+  deriving Show
+
+-- | BankGirot currently only supports EUR and SEK
+data Currency = EUR | SEK deriving Show
+
+-- | Reference.
+--   The references correspond to the reference codes defined in
+--   <http://www.bgc.se/upload/Gemensamt/Trycksaker/Manualer/BG6040.pdf the BgMax documentation>.
+data Reference = 
+  -- | No reference.
+    Ref0
+  -- | No reference. 
+  | Ref1 
+  -- | Reference is correct OCR-no.
+  | Ref2 Integer
+  -- | One or more references.
+  | Ref3 ByteString
+  -- | One reference.
+  | Ref4 ByteString
+  -- | Incorrect reference.
+  | Ref5 ByteString
+  -- | Reserved for future use.
+  | Ref Int ByteString 
+  deriving Show
+
+-- | Deposit type.
+--   Deposit type according to bank agreement.
+data DepositType = K | D | S deriving Show
+
+-- | Transaction type reused in TK 20,21,22,23.
+data Transaction = 
+  Transaction {
+    senderBG :: Integer,
+    reference :: Reference,
+    ammount :: Integer,
+    -- | See the BGC documentation for the meaning of payment channel code.
+    paymentChannel :: Int,
+    bcgNo :: Integer,
+    -- | See the BGC documentation for the meaning of the image mark.
+    imageMark :: Int } 
+    deriving Show
+
+-- | Start post.
+data TK01_t =
+  TK01_t {
+    layoutName :: ByteString,
+    layoutVersion :: Int,
+    timeStamp :: LocalTime,
+    testMark :: TestMark } 
+    deriving Show
+
+-- | Opening post.
+data TK05_t =
+  TK05_t {
+    recipientBG :: Integer,
+    recipientPG :: Maybe Integer,
+    currency :: Currency } 
+    deriving Show
+
+-- | Payment post.
+data TK20_t =
+  TK20_t {
+    payment :: Transaction } 
+    deriving Show
+
+-- | Deduction post.
+data TK21_t =
+  TK21_t {
+    deduction :: Transaction,
+    -- | See the BGC documentation for the meaning of the deduction code.
+    deductionCode :: Int } 
+    deriving Show
+
+-- | Extra reference post.
+data TK22_t =
+  TK22_t {
+    positiveReference :: Transaction } 
+    deriving Show
+
+-- | Extra reference post (negative ammount).
+data TK23_t =
+  TK23_t {
+    negativeReference :: Transaction } 
+    deriving Show
+
+-- | Information post.
+data TK25_t =
+  TK25_t {
+    information :: ByteString } 
+    deriving Show
+
+-- | Name post.
+data TK26_t =
+  TK26_t {
+    name :: ByteString,
+    extraName :: ByteString } 
+    deriving Show
+
+-- | Address 1 post.
+data TK27_t =
+  TK27_t {
+    address :: ByteString,
+    zipCode :: ByteString } 
+    deriving Show
+
+-- | Address 2 post.
+data TK28_t =
+  TK28_t {
+    city :: ByteString,
+    country :: ByteString,
+    countryCode :: ByteString } 
+    deriving Show
+
+-- | Organisation-number post.
+data TK29_t = 
+  TK29_t {
+    orgNo :: Integer } 
+    deriving Show
+
+-- | Deposit post.
+data TK15_t =
+  TK15_t {
+    recipientAccount :: Integer,
+    paymentDate :: Day,
+    depositNo :: Int,
+    depositAmmount :: Integer,
+    depositCurrency :: Currency,
+    paymentDeductionCount :: Int,
+    depositType :: Maybe DepositType } 
+    deriving Show
+
+-- | End post
+data TK70_t =
+  TK70_t {
+    paymentsCount :: Int,
+    deductionsCount :: Int,
+    extraReferenceCount :: Int,
+    depositCount :: Int } 
+    deriving Show
+
+-- | Sum type for posts.
+data Post =
+    TK01 TK01_t
+  | TK05 TK05_t
+  | TK20 TK20_t
+  | TK21 TK21_t
+  | TK22 TK22_t
+  | TK23 TK23_t
+  | TK25 TK25_t
+  | TK26 TK26_t
+  | TK27 TK27_t
+  | TK28 TK28_t
+  | TK29 TK29_t
+  | TK15 TK15_t
+  | TK70 TK70_t
+  -- | The BGC documentation states that implementations should ignore posts 
+  --   they don't understand, they will be instead be recorded using this 
+  --   constructor.
+  | TK Int 
+  deriving Show
