packages feed

profiteur-0.2.0.0: src/Profiteur/Parser.hs

--------------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
module Profiteur.Parser
    ( parseProf
    ) where


--------------------------------------------------------------------------------
import           Control.Applicative              ((<$>))
import           Control.Monad                    (replicateM_)
import           Data.Attoparsec.ByteString       as AP
import           Data.Attoparsec.ByteString.Char8 as AP8
import           Data.Text                        (Text)
import qualified Data.Text                        as T
import qualified Data.Text.Encoding               as T
import qualified Data.Vector                      as V


--------------------------------------------------------------------------------
import           Profiteur.Core


--------------------------------------------------------------------------------
parseProf :: AP.Parser Prof
parseProf = fmap mkProf $ do
    -- Hacky stuff.
    _ <- AP.manyTill AP8.anyChar (AP.try $ AP8.string "COST CENTRE")
    _ <- AP.manyTill AP8.anyChar (AP.try $ AP8.string "COST CENTRE")
    _ <- AP.skipWhile (not . AP8.isEndOfLine)
    _ <- AP8.skipSpace
    parseContCentreNode 0


--------------------------------------------------------------------------------
parseContCentreNode :: Int -> AP.Parser CostCentreNode
parseContCentreNode indent = do
    replicateM_ indent $ AP8.char8 ' '
    canonical <- identifier
    skipHorizontalSpace
    module' <- identifier
    skipHorizontalSpace
    id' <- T.pack . show <$> (AP8.decimal :: AP.Parser Int)

    skipHorizontalSpace
    entries <- AP8.decimal
    skipHorizontalSpace
    individualTime <- AP8.double
    skipHorizontalSpace
    individualAlloc <- AP8.double
    skipHorizontalSpace
    inheritedTime <- AP8.double
    skipHorizontalSpace
    inheritedAlloc <- AP8.double
    skipToEol

    children <- AP.many' $ parseContCentreNode (indent + 1)

    return CostCentreNode
        { ccnName     = Name
            { nCanonical = canonical
            , nModule    = module'
            }
        , ccnId       = id'
        , ccnInfo     = CostCentreInfo
            { cciEntries         = entries
            , cciIndividualTime  = individualTime
            , cciIndividualAlloc = individualAlloc
            , cciInheritedTime   = inheritedTime
            , cciInheritedAlloc  = inheritedAlloc
            }
        , ccnChildren = V.fromList children
        }


--------------------------------------------------------------------------------
identifier :: AP.Parser Text
identifier = T.decodeUtf8 <$> AP8.takeWhile (not . AP8.isSpace)


--------------------------------------------------------------------------------
skipHorizontalSpace :: AP.Parser ()
skipHorizontalSpace = AP.skipWhile AP8.isHorizontalSpace


--------------------------------------------------------------------------------
skipToEol :: AP.Parser ()
skipToEol = do
    AP.skipWhile (not . AP8.isEndOfLine)
    AP8.endOfLine