{- Author: Wishnu Prasetya Copyright 2011 Utrecht University The use of this sofware is free under the Modified BSD License. -} {- | This module provides a parser for FITTEST raw-log files. It also defines a data type that abstractly represents such a file. -} module Eu.Fittest.Logging.Compression.RawlogParser( RawLogEntry(..), isParagraph, isSection, strParseRawLog, UTCTimeStamp1970(..) ) where import Text.ParserCombinators.ReadP import Data.Char import Data.Time import System.IO -- | A representation of entries in a raw-log file. We will make it more -- generic than needed so that we can reuse it later. data RawLogEntry timestamp attrib paragraph -- | Section = Section (Maybe timestamp) attrib [RawLogEntry timestamp attrib paragraph] -- | Paragraph | Par paragraph deriving (Eq,Show) isParagraph (Par p) = True isParagraph _ = False isSection s = not (isParagraph s) -- Hashlog literals -- dquote = '\"' sectionStart = "% [RawLogEntry UTCTimeStamp1970 String [String]] strParseRawLog input = runParser parseLog input runParser p s = fst . last $ (readP_to_S p s) parseLog :: ReadP [RawLogEntry UTCTimeStamp1970 String [String]] parseLog = do { skipSpaces ; sections <- endBy (parseSection <++ parseParagraph) skipSpaces ; return sections } parseSection :: ReadP (RawLogEntry (Int,Integer) String [String]) parseSection = do { string sectionStart ; skipSpaces ; time <- option Nothing (do { t <- parseTimeStamp; return (Just t) }) ; skipSpaces ; tag <- parseSectionTag ; skipSpaces ; content <- pSectionPart `manyTill` (string endTok) ; return (Section time tag content) ; } pSectionPart = do { part <- (parseParagraph <++ parseSection) ; skipSpaces ; return part ; } parseSectionTag = do { char dquote ; tag <- pAny `manyTill` char dquote ; return tag ; } parseTimeStamp :: ReadP UTCTimeStamp1970 parseTimeStamp = do { offset <- pInteger ; char ':'; time <- pInteger ; return (fromInteger offset,time) ; } pInteger :: ReadP Integer pInteger = do { sign <- option 1 ((do { char '-' ; return (-1) }) <++ (do { char '+' ; return 1 })) ; s <- munch1 isDigit ; if (sign < 0) then return (- (read s)) else return (read s) } parseParagraph = do { string parStart ; skipSpaces ; sentences <- parseSentence `manyTill` (string endTok) ; return (Par sentences) ; } parseSentence = do { string sentStart ; skipSpaces ; s <- pAny `manyTill` (string sentEnd) ; skipSpaces ; return (dropTrailingSpace s) ; } pAny = satisfy (\_-> True) dropTrailingSpace = reverse . dropWhile isSpace . reverse exPar1 = "%

" exPar2 = "%

%>" exPar3 = "%

%<{ undefined:void }%>%> \n %>" exSec1 = "%" exSec2 = "%" exSec3 = "%" exSec4 = "%" exSec5 = "%" exSec6 = "% %>\n" ++ "% %>\n" ++ "%

%>\n" ++ "%>\n" ++ "%>\n" exLog1 = do { log <- readFile "./Eu/Fittest/Logging/Compression/SampleRawLog1.log" ; return (strParseRawLog log) }