mirror of
https://github.com/simonmichael/hledger.git
synced 2024-12-26 20:02:27 +03:00
parsing: fix obscured date parse errors with parsec 3; require split
With parsec 3, invalid date errors were not being reported properly. This should be more robust.
This commit is contained in:
parent
6ebb9a3100
commit
ce7e155934
@ -265,6 +265,7 @@ Assumes any text in the parse stream has been lowercased.
|
||||
-}
|
||||
smartdate :: GenParser Char st SmartDate
|
||||
smartdate = do
|
||||
-- XXX maybe obscures date errors ? see ledgerdate
|
||||
(y,m,d) <- choice' [yyyymmdd, ymd, ym, md, y, d, month, mon, today, yesterday, tomorrow, lastthisnextthing]
|
||||
return (y,m,d)
|
||||
|
||||
@ -276,7 +277,8 @@ smartdateonly = do
|
||||
eof
|
||||
return d
|
||||
|
||||
datesepchar = oneOf "/-."
|
||||
datesepchars = "/-."
|
||||
datesepchar = oneOf datesepchars
|
||||
|
||||
validYear, validMonth, validDay :: String -> Bool
|
||||
validYear s = length s >= 4 && isJust (readMay s :: Maybe Int)
|
||||
|
@ -117,6 +117,7 @@ module Hledger.Read.Journal (
|
||||
)
|
||||
where
|
||||
import Control.Monad.Error (ErrorT(..), throwError, catchError)
|
||||
import Data.List.Split (wordsBy)
|
||||
import Text.ParserCombinators.Parsec hiding (parse)
|
||||
#if __GLASGOW_HASKELL__ <= 610
|
||||
import Prelude hiding (readFile, putStr, putStrLn, print, getContents)
|
||||
@ -331,21 +332,27 @@ ledgerTransaction = do
|
||||
Left err -> fail err
|
||||
|
||||
ledgerdate :: GenParser Char JournalContext Day
|
||||
ledgerdate = choice' [ledgerfulldate, ledgerpartialdate] <?> "full or partial date"
|
||||
|
||||
ledgerfulldate :: GenParser Char JournalContext Day
|
||||
ledgerfulldate = do
|
||||
(y,m,d) <- ymd
|
||||
return $ fromGregorian (read y) (read m) (read d)
|
||||
|
||||
-- | Match a partial M/D date in a ledger, and also require that a default
|
||||
-- year directive was previously encountered.
|
||||
ledgerpartialdate :: GenParser Char JournalContext Day
|
||||
ledgerpartialdate = do
|
||||
(_,m,d) <- md
|
||||
y <- getYear
|
||||
when (isNothing y) $ fail "partial date found, but no default year specified"
|
||||
return $ fromGregorian (fromJust y) (read m) (read d)
|
||||
ledgerdate = do
|
||||
-- hacky: try to ensure precise errors for invalid dates
|
||||
-- XXX reported error position is not too good
|
||||
-- pos <- getPosition
|
||||
datestr <- many1 $ choice' [digit, datesepchar]
|
||||
let dateparts = wordsBy (`elem` datesepchars) datestr
|
||||
case dateparts of
|
||||
[y,m,d] -> do
|
||||
failIfInvalidYear y
|
||||
failIfInvalidMonth m
|
||||
failIfInvalidDay d
|
||||
return $ fromGregorian (read y) (read m) (read d)
|
||||
[m,d] -> do
|
||||
y <- getYear
|
||||
case y of Nothing -> fail "partial date found, but no default year specified"
|
||||
Just y' -> do failIfInvalidYear $ show y'
|
||||
failIfInvalidMonth m
|
||||
failIfInvalidDay d
|
||||
return $ fromGregorian y' (read m) (read d)
|
||||
_ -> fail $ "bad date: " ++ datestr
|
||||
<?> "full or partial date"
|
||||
|
||||
ledgerdatetime :: GenParser Char JournalContext LocalTime
|
||||
ledgerdatetime = do
|
||||
|
@ -91,6 +91,7 @@ executable hledger
|
||||
,process
|
||||
,regexpr >= 0.5.1
|
||||
,safe >= 0.2
|
||||
,split == 0.1.*
|
||||
,time
|
||||
,utf8-string >= 0.3
|
||||
|
||||
@ -168,6 +169,7 @@ library
|
||||
,process
|
||||
,regexpr >= 0.5.1
|
||||
,safe >= 0.2
|
||||
,split == 0.1.*
|
||||
,time
|
||||
,utf8-string >= 0.3
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user