From 676ea912b3c03d173f8a03c7e17eb2859f03f96b Mon Sep 17 00:00:00 2001 From: Alex Chen Date: Sun, 20 May 2018 19:39:40 -0600 Subject: [PATCH] lib: fix issue where spaces were allowed as decimal points - Fixes #749 - Also enabling the tests prepared for #749 --- hledger-lib/Hledger/Read/Common.hs | 19 ++++++++------- tests/journal/amounts-and-commodities.test | 28 +++++++++++----------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/hledger-lib/Hledger/Read/Common.hs b/hledger-lib/Hledger/Read/Common.hs index 998bbf016..ab0788197 100644 --- a/hledger-lib/Hledger/Read/Common.hs +++ b/hledger-lib/Hledger/Read/Common.hs @@ -714,10 +714,12 @@ fromRawNumber suggestedStyle negated raw = (quantity, precision, mdecimalpoint, -- unpack with a hint if useful (mseparator, intparts, mdecimalpoint, frac) = case raw of - -- just a single punctuation between two digits groups, assume it's a decimal point + -- If the number consists of exactly two digit groups + -- separated by a valid decimal point character, we assume + -- that the character represents a decimal point. (Just s, [firstGroup, lastGroup], Nothing) - -- if have a decimalHint restrict this assumpion only to a matching separator - | maybe True (`asdecimalcheck` s) suggestedStyle -> (Nothing, [firstGroup], Just s, lastGroup) + | s `elem` decimalPointChars && maybe True (`asdecimalcheck` s) suggestedStyle -> + (Nothing, [firstGroup], Just s, lastGroup) (firstSep, digitGroups, Nothing) -> (firstSep, digitGroups, Nothing, []) (firstSep, digitGroups, Just (d, frac)) -> (firstSep, digitGroups, Just d, frac) @@ -757,17 +759,15 @@ fromRawNumber suggestedStyle negated raw = (quantity, precision, mdecimalpoint, -- (Just ' ',["1","000"],Nothing) rawnumberp :: TextParser m ( Maybe Char , [String] , Maybe (Char, String) ) rawnumberp = do - let sepChars = ['.', ','] -- all allowed punctuation characters - (firstSep, groups) <- option (Nothing, []) $ do leadingDigits <- some digitChar option (Nothing, [leadingDigits]) . try $ do - firstSep <- oneOf sepChars <|> whitespaceChar + firstSep <- oneOf decimalPointChars <|> whitespaceChar secondGroup <- some digitChar otherGroups <- many $ try $ char firstSep *> some digitChar return (Just firstSep, leadingDigits : secondGroup : otherGroups) - let remSepChars = maybe sepChars (`delete` sepChars) firstSep + let remSepChars = maybe decimalPointChars (`delete` decimalPointChars) firstSep modifier | null groups = fmap Just -- if no digits so far, we require at least some decimals | otherwise = optional @@ -778,11 +778,14 @@ rawnumberp = do return (lastSep, fromMaybe [] digits) -- make sure we didn't leading part of mistyped number - notFollowedBy $ oneOf sepChars <|> (whitespaceChar >> digitChar) + notFollowedBy $ oneOf decimalPointChars <|> (whitespaceChar >> digitChar) return $ dbg8 "rawnumberp" (firstSep, groups, extraGroup) "rawnumberp" +decimalPointChars :: String +decimalPointChars = ".," + -- | Parse a unicode char that represents any non-control space char (Zs general category). whitespaceChar :: TextParser m Char whitespaceChar = charCategory Space diff --git a/tests/journal/amounts-and-commodities.test b/tests/journal/amounts-and-commodities.test index 1a6d28897..53af16753 100644 --- a/tests/journal/amounts-and-commodities.test +++ b/tests/journal/amounts-and-commodities.test @@ -117,23 +117,23 @@ $ hledger -f- bal -V -N # 9. Here the amount is parsed as 1. I think (hope) no country uses space # for decimal point, so we should parse this as 1000. -#< -#2018-01-01 -# (a) USD1 000 -# -#$ hledger -f- reg amt:1 +< +2018-01-01 + (a) USD1 000 + +$ hledger -f- reg amt:1 # 10. This commodity directive should complain about a missing decimal point, # which we now require. -#< -#commodity 1 000 USD -# -#2018-01-01 -# (a) USD1 000 -# -#$ hledger -f- bal -#>2 /decimal point/ -#>=1 +< +commodity 1 000 USD + +2018-01-01 + (a) USD1 000 + +$ hledger -f- bal +>2 /decimal point/ +>=1 # 11. After a space-grouped amount, a posting comment should parse. <