packages feed

profiteur-0.3.0.0: src/Profiteur/Parser.hs

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


--------------------------------------------------------------------------------
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


--------------------------------------------------------------------------------
parseFile :: AP.Parser CostCentre
parseFile = 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
    paresCostCentre 0


--------------------------------------------------------------------------------
paresCostCentre :: Int -> AP.Parser CostCentre
paresCostCentre 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' $ paresCostCentre (indent + 1)

    return CostCentre
        { ccName            = canonical
        , ccModule          = module'
        , ccId              = id'
        , ccEntries         = entries
        , ccIndividualTime  = individualTime
        , ccIndividualAlloc = individualAlloc
        , ccInheritedTime   = inheritedTime
        , ccInheritedAlloc  = inheritedAlloc
        , ccChildren        = 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