tsparse 0.2.0.0 → 0.4.0.0
raw patch · 2 files changed
+83/−44 lines, 2 files
Files
- TsParse.hs +82/−43
- tsparse.cabal +1/−1
TsParse.hs view
@@ -26,6 +26,7 @@ -- ** Basic types Dollars , Shares+ , TxnType -- ** Transaction Detail By Source , BySource(..)@@ -36,6 +37,7 @@ , BySourcePosting(..) -- ** Transaction Detail By Fund+ , FundName , ByFund(..) , ByFundBeginningBal(..) , ByFundGainLoss(..)@@ -98,7 +100,7 @@ genDollars = D.Decimal <$> pure 2 <*> genMantissa newtype DollarsRen = DollarsRen { unDollarsRen :: Rendered Dollars }- deriving (Eq, Show)+ deriving (Eq, Ord, Show) instance Arbitrary DollarsRen where arbitrary = do@@ -110,7 +112,7 @@ genShares = D.Decimal <$> pure 4 <*> genMantissa newtype SharesRen = SharesRen { unSharesRen :: Rendered Dollars }- deriving (Eq, Show)+ deriving (Eq, Ord, Show) instance Arbitrary SharesRen where arbitrary = do@@ -140,7 +142,7 @@ data Rendered a = Rendered { ast :: a , rendering :: String- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) genWord :: Gen (Rendered String)@@ -165,7 +167,7 @@ return $ Rendered (map ast ws) withSpaces newtype WordsRen = WordsRen { unWordsRen :: Rendered [String] }- deriving (Eq, Show)+ deriving (Eq, Ord, Show) instance Arbitrary WordsRen where arbitrary = WordsRen <$> genWords@@ -175,6 +177,16 @@ #endif +dollarSign :: Parser ()+dollarSign = () <$ optional (P.char '$')++space :: Parser ()+space = () <$ optional (P.char ' ')++digits :: Parser String+digits = fmap (filter (/= ',')) (P.many1 (P.oneOf "0123456789,"))+ <?> "digits"+ -- | Parses a single decimal value. Recognizes negative signs. Strips -- out dollar signs and commas. --@@ -183,16 +195,18 @@ -- consumes the entire string if there is one. decimal :: Parser D.Decimal decimal = do- ws <- fmap (map (filter (not . (`elem` "$, ")))) words- (isNeg, num) <- case ws of- [] -> fail "empty string, cannot parse decimal"- x:[] -> return (False, x)- x:y:[] -> if x == "-"- then return (True, y)- else fail "could not parse decimal: too many words"- _ -> fail "could not parse decimal, too many words"- dec <- case readMaybe num of- Nothing -> fail $ "could not parse decimal: " ++ num+ dollarSign+ maybeNeg <- optional (P.char '-')+ let isNeg = maybe False (const True) maybeNeg+ dollarSign+ space+ dollarSign+ whole <- digits+ _ <- P.char '.'+ frac <- digits+ let numStr = whole ++ "." ++ frac+ dec <- case readMaybe (whole ++ "." ++ frac) of+ Nothing -> fail $ "could not parse decimal: " ++ numStr Just r -> return r return $ if isNeg then negate dec else dec @@ -202,7 +216,7 @@ prop_Decimal = testRendered decimal . unDecimalRen newtype DecimalRen = DecimalRen { unDecimalRen :: Rendered D.Decimal }- deriving (Eq, Show)+ deriving (Eq, Ord, Show) instance Arbitrary DecimalRen where arbitrary = do@@ -274,7 +288,7 @@ c -> c newtype DayRen = DayRen { unDayRen :: Rendered T.Day }- deriving (Eq, Show)+ deriving (Eq, Ord, Show) instance Arbitrary DayRen where arbitrary =@@ -300,8 +314,7 @@ _ -> fail $ "could not read string: " ++ s columnBreak :: Parser ()-columnBreak- = () <$ P.char ' ' <* P.char ' ' <* P.many (P.char ' ')+columnBreak = () <$ P.many (P.char ' ') class Pretty a where@@ -319,22 +332,27 @@ instance Pretty T.Day where pretty = Y.text . show +-- | A list of words that indicates the transaction type. Each string+-- in this list will not have any spaces in it.+type TxnType = [String]+ data BySourcePosting = BySourcePosting { bspPayrollOffice :: String , bspPostingDate :: T.Day- , bspTxnType :: [String]+ , bspTxnType :: TxnType , bspTraditional :: Dollars , bspRoth :: Dollars , bspAutomatic :: Dollars , bspMatching :: Dollars , bspTotal :: Dollars- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) #ifdef test + data RenTxnBySource = RenTxnBySource { unRenTxnBySource :: Rendered BySourcePosting }- deriving (Eq, Show)+ deriving (Eq, Ord, Show) instance Arbitrary RenTxnBySource where@@ -350,11 +368,16 @@ let rAst = BySourcePosting (ast rPayroll) (ast rPostingDate) (ast rTxnType) (ast rTrad) (ast rRoth) (ast rAuto) (ast rMatch) (ast rTot)- ren <- columns [ rendering rPayroll, rendering rPostingDate,- rendering rTxnType,- rendering rTrad,- rendering rRoth, rendering rAuto,- rendering rMatch, rendering rTot ]+ clmns = [ return $ rendering rPayroll , columnSpaceOne+ , return $ rendering rPostingDate , columnSpaceOne+ , return $ rendering rTxnType , columnSpaceTwo+ , return $ rendering rTrad , columnSpaceOne+ , return $ rendering rRoth , columnSpaceOne+ , return $ rendering rAuto , columnSpaceOne+ , return $ rendering rMatch , columnSpaceOne+ , return $ rendering rTot+ ]+ ren <- fmap concat . sequence $ clmns leader <- fmap (flip replicate ' ') Q.arbitrarySizedIntegral return . RenTxnBySource $ Rendered rAst (leader ++ ren ++ "\n") @@ -364,13 +387,20 @@ genInterleaved :: Gen a -> [a] -> Gen [a] genInterleaved g = sequence . intersperse g . map return -columnSpacer :: Gen String-columnSpacer = fmap (f . abs) Q.arbitrarySizedIntegral+-- | Generates at least two spaces.+columnSpaceTwo :: Gen String+columnSpaceTwo = fmap (f . abs) Q.arbitrarySizedIntegral where f i = " " ++ replicate i ' ' +-- | Generates at least one space.+columnSpaceOne :: Gen String+columnSpaceOne = fmap (f . abs) Q.arbitrarySizedIntegral+ where+ f i = " " ++ replicate i ' '+ columns :: [String] -> Gen String-columns = fmap concat . genInterleaved columnSpacer+columns = fmap concat . genInterleaved columnSpaceTwo #endif@@ -424,7 +454,7 @@ , bssAuto :: Dollars , bssMatching :: Dollars , bssTotal :: Dollars- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) #ifdef test @@ -509,7 +539,7 @@ newtype FundNameRen = FundNameRen { unFundNameRen :: Rendered [String] }- deriving (Eq, Show)+ deriving (Eq, Ord, Show) instance Arbitrary FundNameRen where arbitrary = do@@ -532,7 +562,7 @@ , bfpTotal :: Dollars , bfpSharePrice :: Dollars , bfpNumShares :: Shares- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) #ifdef test @@ -548,10 +578,15 @@ leader <- fmap (flip replicate ' ') Q.arbitrarySizedIntegral let rAst = ByFundPosting (ast rdy) (ast rty) (ast rtrad) (ast rroth) (ast rtot) (ast rpri) (ast rsha)- ren <- columns [ rendering rdy,- rendering rty,- rendering rtrad, rendering rroth,- rendering rtot, rendering rpri, rendering rsha ]+ let clmns = [ return $ rendering rdy , columnSpaceOne+ , return $ rendering rty , columnSpaceTwo+ , return $ rendering rtrad , columnSpaceOne+ , return $ rendering rroth , columnSpaceOne+ , return $ rendering rtot , columnSpaceOne+ , return $ rendering rpri , columnSpaceOne+ , return $ rendering rsha+ ]+ ren <- fmap concat . sequence $ clmns return $ Rendered rAst (leader ++ ren ++ "\n") prop_txnByFund :: QP.Property@@ -595,7 +630,7 @@ { bfbbSharePrice :: Dollars , bfbbNumShares :: Shares , bfbbDollarBalance :: Dollars- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) #ifdef test @@ -640,7 +675,7 @@ -- FUND@ section. data ByFundGainLoss = ByFundGainLoss { bfglDollarBalance :: Dollars }- deriving (Eq, Show)+ deriving (Eq, Ord, Show) #ifdef test @@ -675,7 +710,7 @@ { bfebSharePrice :: Dollars , bfebNumShares :: Shares , bfebDollarBalance :: Dollars- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) #ifdef test @@ -722,7 +757,7 @@ , bsTxns :: [BySourcePosting] , bsGainLoss :: BySourceGainLoss , bsEndingBal :: BySourceEndingBal- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) #ifdef test @@ -865,15 +900,19 @@ <?> "transactions by source summary") return $ BySource begBal txns gainLoss endBal +-- | The name of a fund, eg @C Fund@. This is a list of words; each+-- word will not contain any spaces.+type FundName = [String]+ -- | A single fund in the @YOUR TRANSACTION DETAIL BY FUND@ section -- (e.g. the @G Fund@, @L 2040 Fund@, etc.) data ByFund = ByFund- { bfFundName :: [String]+ { bfFundName :: FundName , bfBeginningBal :: ByFundBeginningBal , bfPostings :: [ByFundPosting] , bfGainLoss :: ByFundGainLoss , bfEndingBal :: ByFundEndingBal- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) #ifdef test @@ -980,7 +1019,7 @@ data TspStatement = TspStatement { tspDetailBySource :: BySource , tspDetailByFund :: [ByFund]- } deriving (Eq, Show)+ } deriving (Eq, Ord, Show) instance Pretty TspStatement where pretty x = Y.vcat
tsparse.cabal view
@@ -4,7 +4,7 @@ -- The name of the package. name: tsparse -version: 0.2.0.0+version: 0.4.0.0 -- A short (one-line) description of the package. synopsis: Parses U.S. federal Thrift Savings Plan PDF quarterly statements