<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Hi,</div><div><br></div><div>I want to parse a rather unstructured log file, skipping blocks I'm not interested in but keeping others. For that purpose, I define "markers" that flag the beginning of interesting chunks. The "skip parser" reads anything until such a marker (using </div><div><br></div><div><font class="Apple-style-span" face="'Lucida Console'">manyTill parseAny (try (lookAhead parseMarker))</font></div><div><br></div><div>and then the relative content parser starts by really consuming this marker string.</div><div><br></div><div>I have a test case demonstrating this principle which works fine, but when I execute the (seemingly!) equivalent "real" code on a piece of a (seemingly!) equivalent "real log file", ghci enters an infinite loop - and I have no idea why...</div><div><br></div><div>I'd be very grateful for any help, as I'm completely stuck here ;-)</div><div><br></div><div>Following are:</div><div><br></div><div>- the test input file</div><div>- the piece of "real logfile"</div><div>- the complete code in one piece (Main.hs), with the test case code in the bottom</div><div><br></div><div>These are the results when I run</div><div><br></div><div>1) the test case:</div><div><br></div><div><font class="Apple-style-span" face="'Lucida Console'">*Main>  readFile "testfile.txt" >>= parseTest parseAll</font></div><div><font class="Apple-style-span" face="'Lucida Console'">["aaa\naaa\n","aaa\naaa\n","aaa\naaa\n"]</font></div><div><br></div><div>2) the main code (endless loop interrupted, with output from debug.trace):</div><div><br></div><div><font class="Apple-style-span" face="'Lucida Console'">parseUntilChunkWFG: ""</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseMaybeChunk: Nothing</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseWFGMarker: Global Wait-For-Graph(WFG) at ddTS[0.3] :</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseUntilChunkWFG: ""</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseMaybeChunk: Nothing</font></div><div><font class="Apple-style-span" face="'Lucida Console'">^CparseWFGMarker: Global Wait-For-Graph(WFG) at ddTS[0.3] :</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseUntilChunkWFG: ""</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseMaybeChunk: Nothing</font></div><div><font class="Apple-style-span" face="'Lucida Console'">Interrupted.</font></div><div><br></div><div><br></div><div>This is the test input file, with vi newline symbols:</div><div><br></div><div>##########################################################################</div><div>this is just some stuff$</div><div>I wanna skip$</div><div>$</div><div>this is, too$</div><div>12[] $</div><div>$</div><div>BEGIN_MARKER$</div><div>aaa$</div><div>aaa$</div><div>$</div><div>this here again I can skip$</div><div>$</div><div>BEGIN_MARKER$</div><div>aaa$</div><div>aaa$</div><div>$</div><div>and then it goes on till the end of the file$</div><div>##########################################################################</div><div><br></div><div><br></div><div>... and this is the real piece (part of, what is important I have 2 chunks of "interesting content"):</div><div><br></div><div><br></div><div>##########################################################################</div><div>  client details:$</div><div>    O/S info: user: oracle, term: pts/2, ospid: 5820$</div><div>    machine: <a href="http://node1.skyrac.com">node1.skyrac.com</a> program: <a href="mailto:sqlplus@node1.skyrac.com">sqlplus@node1.skyrac.com</a> (TNS V1-V3)$</div><div>    application name: <a href="mailto:sqlplus@node1.skyrac.com">sqlplus@node1.skyrac.com</a> (TNS V1-V3), hash value=10026263$</div><div>  current SQL:$</div><div>  insert into test values(2)$</div><div>DUMP LOCAL BLOCKER: initiate state dump for DEADLOCK$</div><div>  possible owner[39.5827] on resource TX-00080011-00000545$</div><div>$</div><div>*** 2014-02-22 08:43:55.554$</div><div>Submitting asynchronized dump request [28]. summary=[ges process stack dump (kjdglblkrdm1)].$</div><div>Global blockers dump end:-----------------------------------$</div><div>Global Wait-For-Graph(WFG) at ddTS[0.3] :$</div><div>BLOCKED 0x83437238 3 wq 2 cvtops x1 TX 0xc0006.0x1c5(ext 0x4,0x0)[27000-0001-00000001] inst 1 $</div><div>BLOCKER 0x83b196a8 3 wq 1 cvtops x28 TX 0xc0006.0x1c5(ext 0x4,0x0)[36000-0002-00000005] inst 2 $</div><div>BLOCKED 0x83437238 3 wq 2 cvtops x1 TX 0x80011.0x545(ext 0x2,0x0)[36000-0002-00000005] inst 2 $</div><div>BLOCKER 0x83b35b10 3 wq 1 cvtops x28 TX 0x80011.0x545(ext 0x2,0x0)[27000-0001-00000001] inst 1 $</div><div>$</div><div>*** 2014-02-22 08:43:56.292$</div><div>* Cancel deadlock victim lockp 0x83437238 $</div><div>DUMP LOCAL BLOCKER: initiate state dump for DEADLOCK$</div><div>  possible owner[39.5827] on resource TX-00080011-00000545$</div><div>$</div><div>*** 2014-02-22 08:43:55.554$</div><div>Submitting asynchronized dump request [28]. summary=[ges process stack dump (kjdglblkrdm1)].$</div><div>Global blockers dump end:-----------------------------------$</div><div>Global Wait-For-Graph(WFG) at ddTS[0.3] :$</div><div>BLOCKED 0x83437238 3 wq 2 cvtops x1 TX 0xc0006.0x1c5(ext 0x4,0x0)[27000-0001-00000001] inst 1$</div><div>BLOCKER 0x83b196a8 3 wq 1 cvtops x28 TX 0xc0006.0x1c5(ext 0x4,0x0)[36000-0002-00000005] inst 2$</div><div>BLOCKED 0x83437238 3 wq 2 cvtops x1 TX 0x80011.0x545(ext 0x2,0x0)[36000-0002-00000005] inst 2$</div><div>BLOCKER 0x83b35b10 3 wq 1 cvtops x28 TX 0x80011.0x545(ext 0x2,0x0)[27000-0001-00000001] inst 1$</div><div>$</div><div>*** 2014-02-22 08:43:56.292$</div><div><br></div><div>##########################################################################</div><div><br></div><div><br></div><div>... and this is the code:</div><div><br></div><div><br></div><div>##########################################################################</div><div><font class="Apple-style-span" face="'Lucida Console'">module Main (</font></div><div><font class="Apple-style-span" face="'Lucida Console'">    main</font></div><div><font class="Apple-style-span" face="'Lucida Console'">) where</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">import System.Environment</font></div><div><font class="Apple-style-span" face="'Lucida Console'">import System.Directory</font></div><div><font class="Apple-style-span" face="'Lucida Console'">import Text.ParserCombinators.Parsec</font></div><div><font class="Apple-style-span" face="'Lucida Console'">import Debug.Trace</font></div><div><font class="Apple-style-span" face="'Lucida Console'">import Numeric</font></div><div><font class="Apple-style-span" face="'Lucida Console'">import Data.Maybe</font></div><div><font class="Apple-style-span" face="'Lucida Console'">import Data.Char</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">main = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --files <- getArgs</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  currDir <- getCurrentDirectory</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --let filepaths = map ((currDir ++ "/") ++)  ["munip1_lmd0_5702.trc", "munip2_lmd0_5966.trc"]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  let filepaths = map ((currDir ++ "/") ++)  ["munip1_lmd0_5702.trc"]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  wfgs <- mapM (\p -> parseFromFile parseChunks p) filepaths</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  print wfgs</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseChunks :: Parser [Chunk]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseChunks = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  chunks <- many1 parseMaybeChunk</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  -- trace ("parseChunks: " ++ (show chunks)) return (catMaybes chunks)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return (catMaybes chunks)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  </font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseMaybeChunk :: Parser (Maybe Chunk)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseMaybeChunk = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  chunk <- try (parseChunkWFG >>= return . Just)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">           <|> try (parseUntilChunkWFG >> return Nothing)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">           <|> (parseTillEOF >> return Nothing)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  trace ("parseMaybeChunk: " ++ show chunk) return chunk</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --return chunk</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseUntilChunkWFG :: Parser [Char]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseUntilChunkWFG = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  skip <- manyTill parseAny (try (lookAhead parseWFGMarker) )</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  trace ("parseUntilChunkWFG: " ++ show skip) return skip</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --return skip</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseAny :: Parser Char</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseAny = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  anyC <- oneOf (['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ "()[]* -:.,/_?@='\n\\")</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --trace ("parseAny: " ++ (show anyC)) return anyC</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return anyC</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseWFGMarker :: Parser [Char]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseWFGMarker = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  marker <- string "Global Wait-For-Graph(WFG) at ddTS[0.3] :\n"</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  trace ("parseWFGMarker: " ++ marker) return marker</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --return marker</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseTillEOF :: Parser [Char]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseTillEOF = do </font></div><div><font class="Apple-style-span" face="'Lucida Console'">  anyCs <- many1 anyChar</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  eof </font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --trace ("parseTillEOF: " ++ anyCs) return anyCs</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return anyCs</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseChunkWFG :: Parser Chunk</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseChunkWFG = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  marker <- string "Global Wait-For-Graph(WFG) at ddTS[0.3] :\n"</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  wfg <- manyTill parseWFGEntry newline</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --trace ("parseChunkWFG: " ++ (show wfg)) return $ ChunkWFG wfg</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return $ ChunkWFG wfg</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseWFGEntry :: Parser WFGEntry</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseWFGEntry = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  role      <- try (string "BLOCKER") <|> string "BLOCKED"</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  skipMany1 (space >> string "0x")</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  lockaddr  <- many1 hexDigit</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  skipMany1 (space >> (many1 digit) >> space >> string "wq" >> space >></font></div><div><font class="Apple-style-span" face="'Lucida Console'">            (many1 digit) >> space >> string "cvtops" >> space >></font></div><div><font class="Apple-style-span" face="'Lucida Console'">            char 'x' >> (many1 digit) >> space)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  restype   <- manyTill upper space</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  skipMany1 (string "0x")</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  id1       <- manyTill hexDigit (string ".0x")</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  id2       <- manyTill hexDigit (string "(ext ")</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  manyTill (digit <|> oneOf ")[]x,-") (string " inst ")</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  instid    <- manyTill digit (space >> newline)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  let wfgEntry = WFGEntry (read role :: Role)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">                          lockaddr</font></div><div><font class="Apple-style-span" face="'Lucida Console'">                          (ResourceId id1 id2 restype)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">                          (read instid)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --trace ("parseWFGEntry: " ++ show wfgEntry) return $ wfgEntry</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  {- trace ("parseWFGEntry: " ++ role ++ " " ++ lockaddr ++ " " ++ restype</font></div><div><font class="Apple-style-span" face="'Lucida Console'">          ++ " " ++ id1 ++ " " ++ id2 ++ " " ++ instid)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">          return $ wfgEntry</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  -}</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return $ wfgEntry</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  </font></div><div><font class="Apple-style-span" face="'Lucida Console'">data Chunk = ChunkWFG WFG</font></div><div><font class="Apple-style-span" face="'Lucida Console'">              deriving (Show, Read)</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">data ResourceId = ResourceId {</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  id1       :: String,</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  id2       :: String,</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  restype   :: String</font></div><div><font class="Apple-style-span" face="'Lucida Console'">} deriving (Show, Read)</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">data WFGEntry = WFGEntry {</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  role      :: Role,</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  lockaddr  :: String,</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  resource  :: ResourceId,</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  instid    :: Int</font></div><div><font class="Apple-style-span" face="'Lucida Console'">} deriving (Show, Read)</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">type WFG = [WFGEntry]</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">data Role = BLOCKED | BLOCKER deriving (Show, Read)</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">------------------- testcase code ---------------------------</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseAll :: Parser [String]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseAll = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  chunks <- many1 parseChunk</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return (catMaybes chunks)</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseChunk :: Parser (Maybe [Char])</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseChunk = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  chunk <- try (parseContent >>= return . Just)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">           <|> try (parseUntilMarker >> return Nothing)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">           <|> (parseTillEOF >> return Nothing)</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --trace ("parseChunk: " ++ show chunk) return chunk</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return chunk</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseUntilMarker :: Parser [Char]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseUntilMarker = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  skip <- manyTill parseAny (try (lookAhead parseMarker) )</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --trace ("parseUntilMarker: " ++ show skip) return skip</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return skip</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseMarker :: Parser [Char]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseMarker = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  marker <- string "BEGIN_MARKER\n"</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --trace ("parseWFGMarker: " ++ marker) return marker</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return marker</font></div><div><font class="Apple-style-span" face="'Lucida Console'"><br></font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseContent :: Parser [Char]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseContent = do</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  marker <- string "BEGIN_MARKER\n"</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  items <- manyTill parseItem newline</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  --trace ("parseContent: " ++ (show items)) return $ concat items</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  return $ concat items</font></div><div><font class="Apple-style-span" face="'Lucida Console'">  </font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseItem  :: Parser [Char]</font></div><div><font class="Apple-style-span" face="'Lucida Console'">parseItem =  string "aaa\n"</font></div><div>##########################################################################</div><div><br></div><div><br></div><div>Many thanks in advance for any hints what might be going on :-)!</div><div>Sigrid</div><div><br></div><div><br></div><div><br></div></body></html>