lib: Re-implement 'includedirectivep' with the new 'ExceptT' layer
- Parse errors encountered in include files are treated as "final" parse errors in the parent file, preventing backtracking and fixing an issue in #853
This commit is contained in:
parent
3e54fc77a4
commit
31d4e930e7
@ -189,6 +189,7 @@ includedirectivep = do
|
||||
void newline
|
||||
|
||||
where
|
||||
getFilePaths :: MonadIO m => SourcePos -> FilePath -> JournalParser m [FilePath]
|
||||
getFilePaths parserpos filename = do
|
||||
curdir <- lift $ expandPath (takeDirectory $ sourceName parserpos) ""
|
||||
`orRethrowIOError` (show parserpos ++ " locating " ++ filename)
|
||||
@ -205,49 +206,41 @@ includedirectivep = do
|
||||
else customFailure $ parseErrorAt parserpos $
|
||||
"No existing files match pattern: " ++ filename
|
||||
|
||||
parseChild :: MonadIO m => SourcePos -> FilePath -> ErroringJournalParser m ()
|
||||
parseChild parentpos filepath = do
|
||||
parentfilestack <- fmap sourceName . statePos <$> getParserState
|
||||
when (filepath `elem` parentfilestack) $ customFailure $
|
||||
parseErrorAt parentpos ("Cyclic include: " ++ filepath)
|
||||
parentj <- get
|
||||
|
||||
childInput <- lift $ readFilePortably filepath
|
||||
`orRethrowIOError` (show parentpos ++ " reading " ++ filepath)
|
||||
let parentfilestack = jincludefilestack parentj
|
||||
when (filepath `elem` parentfilestack) $
|
||||
fail ("Cyclic include: " ++ filepath)
|
||||
|
||||
-- save parent state
|
||||
parentParserState <- getParserState
|
||||
parentj <- get
|
||||
childInput <- lift $ readFilePortably filepath
|
||||
`orRethrowIOError` (show parentpos ++ " reading " ++ filepath)
|
||||
let initChildj = newJournalWithParseStateFrom filepath parentj
|
||||
|
||||
let childj = newJournalWithParseStateFrom parentj
|
||||
let parser = choiceInState
|
||||
[ journalp
|
||||
, timeclockfilep
|
||||
, timedotfilep
|
||||
] -- can't include a csv file yet, that reader is special
|
||||
updatedChildj <- journalAddFile (filepath, childInput) <$>
|
||||
parseIncludeFile parser initChildj filepath childInput
|
||||
|
||||
-- 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
|
||||
-- discard child's parse info, combine other fields
|
||||
put $ updatedChildj <> parentj
|
||||
|
||||
|
||||
newJournalWithParseStateFrom :: Journal -> Journal
|
||||
newJournalWithParseStateFrom j = mempty{
|
||||
jparsedefaultyear = jparsedefaultyear j
|
||||
,jparsedefaultcommodity = jparsedefaultcommodity j
|
||||
,jparseparentaccounts = jparseparentaccounts j
|
||||
,jparsealiases = jparsealiases j
|
||||
,jcommodities = jcommodities j
|
||||
-- ,jparsetransactioncount = jparsetransactioncount j
|
||||
,jparsetimeclockentries = jparsetimeclockentries j
|
||||
}
|
||||
newJournalWithParseStateFrom :: FilePath -> Journal -> Journal
|
||||
newJournalWithParseStateFrom filepath j = mempty{
|
||||
jparsedefaultyear = jparsedefaultyear j
|
||||
,jparsedefaultcommodity = jparsedefaultcommodity j
|
||||
,jparseparentaccounts = jparseparentaccounts j
|
||||
,jparsealiases = jparsealiases j
|
||||
,jcommodities = jcommodities j
|
||||
-- ,jparsetransactioncount = jparsetransactioncount j
|
||||
,jparsetimeclockentries = jparsetimeclockentries j
|
||||
,jincludefilestack = filepath : jincludefilestack j
|
||||
}
|
||||
|
||||
-- | Lift an IO action into the exception monad, rethrowing any IO
|
||||
-- error with the given message prepended.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user