lib: refactor includedirectivep to avoid "re-parsing"
This commit is contained in:
parent
b034fa7ca9
commit
4a9e418b7a
@ -75,7 +75,7 @@ import Prelude ()
|
||||
import "base-compat-batteries" Prelude.Compat hiding (readFile)
|
||||
import qualified Control.Exception as C
|
||||
import Control.Monad
|
||||
import Control.Monad.Except (ExceptT(..), runExceptT, throwError)
|
||||
import Control.Monad.Except (ExceptT(..))
|
||||
import Control.Monad.State.Strict
|
||||
import qualified Data.Map.Strict as M
|
||||
import Data.Text (Text)
|
||||
@ -190,36 +190,40 @@ includedirectivep :: MonadIO m => ErroringJournalParser m ()
|
||||
includedirectivep = do
|
||||
string "include"
|
||||
lift (skipSome spacenonewline)
|
||||
filename <- lift restofline
|
||||
parentpos <- getPosition
|
||||
parentj <- get
|
||||
filename <- T.unpack <$> takeWhileP Nothing (/= '\n') -- don't consume newline yet
|
||||
|
||||
-- save parent state
|
||||
parentParserState <- getParserState
|
||||
parentj <- get
|
||||
|
||||
let childj = newJournalWithParseStateFrom parentj
|
||||
(ej :: Either String ParsedJournal) <-
|
||||
liftIO $ runExceptT $ do
|
||||
let curdir = takeDirectory (sourceName parentpos)
|
||||
filepath <- expandPath curdir filename `orRethrowIOError` (show parentpos ++ " locating " ++ filename)
|
||||
txt <- readFilePortably filepath `orRethrowIOError` (show parentpos ++ " reading " ++ filepath)
|
||||
(ej1::Either (ParseError Char CustomErr) ParsedJournal) <-
|
||||
runParserT
|
||||
(evalStateT
|
||||
(choiceInState
|
||||
[journalp
|
||||
,timeclockfilep
|
||||
,timedotfilep
|
||||
-- can't include a csv file yet, that reader is special
|
||||
])
|
||||
childj)
|
||||
filepath txt
|
||||
either
|
||||
(throwError
|
||||
. ((show parentpos ++ " in included file " ++ show filename ++ ":\n") ++)
|
||||
. parseErrorPretty)
|
||||
(return . journalAddFile (filepath, txt))
|
||||
ej1
|
||||
case ej of
|
||||
Left e -> throwError e
|
||||
Right childj -> modify' (\parentj -> childj <> parentj)
|
||||
-- discard child's parse info, prepend its (reversed) list data, combine other fields
|
||||
parentpos <- getPosition
|
||||
|
||||
-- read child input
|
||||
let curdir = takeDirectory (sourceName parentpos)
|
||||
filepath <- lift $ expandPath curdir filename `orRethrowIOError` (show parentpos ++ " locating " ++ filename)
|
||||
childInput <- lift $ readFilePortably filepath `orRethrowIOError` (show parentpos ++ " reading " ++ filepath)
|
||||
|
||||
-- set child state
|
||||
setInput childInput
|
||||
pushPosition $ initialPos filepath
|
||||
put childj
|
||||
|
||||
-- parse include file
|
||||
let parsers = [ journalp
|
||||
, timeclockfilep
|
||||
, timedotfilep
|
||||
] -- can't include a csv file yet, that reader is special
|
||||
updatedChildj <- journalAddFile (filepath, childInput) <$>
|
||||
region (withSource childInput) (choiceInState parsers)
|
||||
|
||||
-- restore parent state, prepending the child's parse info
|
||||
setParserState parentParserState
|
||||
put $ updatedChildj <> parentj
|
||||
-- discard child's parse info, prepend its (reversed) list data, combine other fields
|
||||
|
||||
void newline
|
||||
|
||||
|
||||
newJournalWithParseStateFrom :: Journal -> Journal
|
||||
newJournalWithParseStateFrom j = mempty{
|
||||
@ -234,11 +238,12 @@ newJournalWithParseStateFrom j = mempty{
|
||||
|
||||
-- | Lift an IO action into the exception monad, rethrowing any IO
|
||||
-- error with the given message prepended.
|
||||
orRethrowIOError :: IO a -> String -> ExceptT String IO a
|
||||
orRethrowIOError io msg =
|
||||
ExceptT $
|
||||
(Right <$> io)
|
||||
`C.catch` \(e::C.IOException) -> return $ Left $ printf "%s:\n%s" msg (show e)
|
||||
orRethrowIOError :: MonadIO m => IO a -> String -> TextParser m a
|
||||
orRethrowIOError io msg = do
|
||||
eResult <- liftIO $ (Right <$> io) `C.catch` \(e::C.IOException) -> pure $ Left $ printf "%s:\n%s" msg (show e)
|
||||
case eResult of
|
||||
Right res -> pure res
|
||||
Left errMsg -> fail errMsg
|
||||
|
||||
accountdirectivep :: JournalParser m ()
|
||||
accountdirectivep = do
|
||||
|
||||
@ -83,7 +83,7 @@ reader = Reader
|
||||
parse :: InputOpts -> FilePath -> Text -> ExceptT String IO Journal
|
||||
parse = parseAndFinaliseJournal timeclockfilep
|
||||
|
||||
timeclockfilep :: ErroringJournalParser IO ParsedJournal
|
||||
timeclockfilep :: MonadIO m => ErroringJournalParser m ParsedJournal
|
||||
timeclockfilep = do many timeclockitemp
|
||||
eof
|
||||
j@Journal{jparsetimeclockentries=es} <- get
|
||||
|
||||
Loading…
Reference in New Issue
Block a user