;csv: refactor amount parsing

This commit is contained in:
Simon Michael 2020-11-05 20:07:26 -10:00
parent dae007a372
commit 4242a8592a

View File

@ -1024,19 +1024,35 @@ getAmount rules record currency p1IsVirtual n =
"\t=> value: " ++ showMixedAmount a -- XXX not sure this is showing all the right info "\t=> value: " ++ showMixedAmount a -- XXX not sure this is showing all the right info
| (f,a) <- fs] | (f,a) <- fs]
-- | Figure out the expected balance (assertion or assignment) specified for posting N,
-- if any (and its parse position).
getBalance :: CsvRules -> CsvRecord -> String -> Int -> Maybe (Amount, GenericSourcePos)
getBalance rules record currency n = do
v <- (fieldval ("balance"++show n)
-- for posting 1, also recognise the old field name
<|> if n==1 then fieldval "balance" else Nothing)
case v of
"" -> Nothing
s -> Just (
parseBalanceAmount rules record currency n s
,nullsourcepos -- parse position to show when assertion fails,
) -- XXX the csv record's line number would be good
where where
-- | Given a non-empty amount string to parse, along with a possibly fieldval = fmap strip . hledgerFieldValue rules record :: HledgerFieldName -> Maybe String
-- non-empty currency symbol to prepend, parse as a hledger amount (as
-- in journal format), or raise an error. -- | Given a non-empty amount string (from CSV) to parse, along with a
-- The CSV rules and record are provided for the error message. -- possibly non-empty currency symbol to prepend,
parseAmount :: CsvRules -> CsvRecord -> String -> String -> MixedAmount -- parse as a hledger MixedAmount (as in journal format), or raise an error.
parseAmount rules record currency amountstr = -- The whole CSV record is provided for the error message.
parseAmount :: CsvRules -> CsvRecord -> String -> String -> MixedAmount
parseAmount rules record currency s =
either mkerror (Mixed . (:[])) $ -- PARTIAL: either mkerror (Mixed . (:[])) $ -- PARTIAL:
runParser (evalStateT (amountp <* eof) nulljournal) "" $ runParser (evalStateT (amountp <* eof) nulljournal) "" $
T.pack $ (currency++) $ simplifySign amountstr T.pack $ (currency++) $ simplifySign s
where where
mkerror e = error' $ unlines mkerror e = error' $ unlines
["error: could not parse \""++amountstr++"\" as an amount" ["error: could not parse \""++s++"\" as an amount"
,showRecord record ,showRecord record
,showRules rules record ,showRules rules record
-- ,"the default-currency is: "++fromMaybe "unspecified" (getDirective "default-currency" rules) -- ,"the default-currency is: "++fromMaybe "unspecified" (getDirective "default-currency" rules)
@ -1046,22 +1062,17 @@ getAmount rules record currency p1IsVirtual n =
++"or add or change your skip rule" ++"or add or change your skip rule"
] ]
-- | Figure out the expected balance (assertion or assignment) specified for posting N, -- XXX unify these
-- if any (and its parse position). -- | Almost but not quite the same as parseAmount.
getBalance :: CsvRules -> CsvRecord -> String -> Int -> Maybe (Amount, GenericSourcePos) -- Given a non-empty amount string (from CSV) to parse, along with a
getBalance rules record currency n = -- possibly non-empty currency symbol to prepend,
(fieldval ("balance"++show n) -- parse as a hledger Amount (as in journal format), or raise an error.
-- for posting 1, also recognise the old field name -- The CSV record and the field's numeric suffix are provided for the error message.
<|> if n==1 then fieldval "balance" else Nothing) parseBalanceAmount :: CsvRules -> CsvRecord -> String -> Int -> String -> Amount
>>= parsebalance currency n . strip parseBalanceAmount rules record currency n s =
where either (mkerror n s) id $
parsebalance currency n s
| null s = Nothing
| otherwise = Just
(either (mkerror n s) id $
runParser (evalStateT (amountp <* eof) nulljournal) "" $ runParser (evalStateT (amountp <* eof) nulljournal) "" $
T.pack $ (currency++) $ simplifySign s T.pack $ (currency++) $ simplifySign s
,nullsourcepos) -- XXX parse position to show when assertion fails,
-- the csv record's line number would be good -- the csv record's line number would be good
where where
mkerror n s e = error' $ unlines mkerror n s e = error' $ unlines
@ -1071,8 +1082,6 @@ getBalance rules record currency n =
-- ,"the default-currency is: "++fromMaybe "unspecified" mdefaultcurrency -- ,"the default-currency is: "++fromMaybe "unspecified" mdefaultcurrency
,"the parse error is: "++customErrorBundlePretty e ,"the parse error is: "++customErrorBundlePretty e
] ]
-- mdefaultcurrency = rule "default-currency"
fieldval = hledgerFieldValue rules record :: HledgerFieldName -> Maybe String
-- | Make a balance assertion for the given amount, with the given parse -- | Make a balance assertion for the given amount, with the given parse
-- position (to be shown in assertion failures), with the assertion type -- position (to be shown in assertion failures), with the assertion type