1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE NamedFieldPuns #-}
3 {-# LANGUAGE OverloadedStrings #-}
4 {-# LANGUAGE ScopedTypeVariables #-}
5 {-# LANGUAGE TupleSections #-}
6 {-# LANGUAGE TypeFamilies #-}
7 module Hcompta.Account.Read where
9 import Control.Applicative ((<$>), (<*))
10 import Control.Monad (Monad(..))
13 import Data.Eq (Eq(..))
14 import Data.Maybe (Maybe(..))
15 import Data.String (fromString)
16 import Data.Typeable ()
17 import Prelude (($), (.))
18 import qualified Text.Parsec as R hiding
31 import Text.Parsec (Stream, ParsecT, (<|>))
33 import qualified Hcompta.Account as Account
34 import Hcompta.Account (Account)
35 import qualified Hcompta.Lib.Regex as Regex
36 import Hcompta.Lib.Regex (Regex)
37 import qualified Hcompta.Lib.Parsec as R
44 -- | Read an 'Account'.
45 account :: Stream s m Char => ParsecT s u m Account
47 R.notFollowedBy $ R.space_horizontal
48 Account.from_List <$> do
49 R.many1_separated section $ R.char section_sep
51 -- | Read an Account.'Account.Name'.
55 section :: Stream s m Char => ParsecT s u m Account.Name
58 R.many1 $ R.try account_name_char
60 account_name_char :: Stream s m Char => ParsecT s u m Char
61 account_name_char = do
64 _ | c == comment_begin -> R.parserZero
65 _ | c == section_sep -> R.parserZero
66 _ | c /= '\t' && R.is_space_horizontal c -> do
67 _ <- R.notFollowedBy $ R.space_horizontal
68 return c <* (R.lookAhead $ R.try $
69 ( R.try (R.char section_sep)
72 _ | not (Data.Char.isSpace c) -> return c
75 -- | Read an Account.'Account.Joker_Name'.
76 joker_section :: Stream s m Char => ParsecT s u m Account.Joker_Name
78 n <- R.option Nothing $ (Just <$> section)
80 Nothing -> R.char section_sep >> (return $ Account.Joker_Any)
81 Just n' -> return $ Account.Joker_Name n'
83 -- | Read an Account.'Account.Joker'.
84 joker :: Stream s m Char => ParsecT s u m Account.Joker
86 R.notFollowedBy $ R.space_horizontal
87 R.many1_separated joker_section $ R.char section_sep
90 regex :: Stream s m Char => ParsecT s u m Regex
92 re <- R.many1 $ R.satisfy (not . R.is_space_horizontal)
95 -- | Read an Account.'Account.Filter'.
96 pattern :: Stream s m Char => ParsecT s u m Account.Pattern
99 [ Account.Pattern_Exact <$> (R.char '=' >> account)
100 , Account.Pattern_Joker <$> (R.char '*' >> joker)
101 , Account.Pattern_Regex <$> (R.option '~' (R.char '~') >> regex)