lib: fix issue where spaces were allowed as decimal points

- Fixes #749
- Also enabling the tests prepared for #749
This commit is contained in:
Alex Chen 2018-05-20 19:39:40 -06:00 committed by Simon Michael
parent 46aae19a54
commit 676ea912b3
2 changed files with 25 additions and 22 deletions

View File

@ -714,10 +714,12 @@ fromRawNumber suggestedStyle negated raw = (quantity, precision, mdecimalpoint,
-- unpack with a hint if useful -- unpack with a hint if useful
(mseparator, intparts, mdecimalpoint, frac) = (mseparator, intparts, mdecimalpoint, frac) =
case raw of 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) (Just s, [firstGroup, lastGroup], Nothing)
-- if have a decimalHint restrict this assumpion only to a matching separator | s `elem` decimalPointChars && maybe True (`asdecimalcheck` s) suggestedStyle ->
| maybe True (`asdecimalcheck` s) suggestedStyle -> (Nothing, [firstGroup], Just s, lastGroup) (Nothing, [firstGroup], Just s, lastGroup)
(firstSep, digitGroups, Nothing) -> (firstSep, digitGroups, Nothing, []) (firstSep, digitGroups, Nothing) -> (firstSep, digitGroups, Nothing, [])
(firstSep, digitGroups, Just (d, frac)) -> (firstSep, digitGroups, Just d, frac) (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) -- (Just ' ',["1","000"],Nothing)
rawnumberp :: TextParser m ( Maybe Char , [String] , Maybe (Char, String) ) rawnumberp :: TextParser m ( Maybe Char , [String] , Maybe (Char, String) )
rawnumberp = do rawnumberp = do
let sepChars = ['.', ','] -- all allowed punctuation characters
(firstSep, groups) <- option (Nothing, []) $ do (firstSep, groups) <- option (Nothing, []) $ do
leadingDigits <- some digitChar leadingDigits <- some digitChar
option (Nothing, [leadingDigits]) . try $ do option (Nothing, [leadingDigits]) . try $ do
firstSep <- oneOf sepChars <|> whitespaceChar firstSep <- oneOf decimalPointChars <|> whitespaceChar
secondGroup <- some digitChar secondGroup <- some digitChar
otherGroups <- many $ try $ char firstSep *> some digitChar otherGroups <- many $ try $ char firstSep *> some digitChar
return (Just firstSep, leadingDigits : secondGroup : otherGroups) return (Just firstSep, leadingDigits : secondGroup : otherGroups)
let remSepChars = maybe sepChars (`delete` sepChars) firstSep let remSepChars = maybe decimalPointChars (`delete` decimalPointChars) firstSep
modifier modifier
| null groups = fmap Just -- if no digits so far, we require at least some decimals | null groups = fmap Just -- if no digits so far, we require at least some decimals
| otherwise = optional | otherwise = optional
@ -778,11 +778,14 @@ rawnumberp = do
return (lastSep, fromMaybe [] digits) return (lastSep, fromMaybe [] digits)
-- make sure we didn't leading part of mistyped number -- 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) return $ dbg8 "rawnumberp" (firstSep, groups, extraGroup)
<?> "rawnumberp" <?> "rawnumberp"
decimalPointChars :: String
decimalPointChars = ".,"
-- | Parse a unicode char that represents any non-control space char (Zs general category). -- | Parse a unicode char that represents any non-control space char (Zs general category).
whitespaceChar :: TextParser m Char whitespaceChar :: TextParser m Char
whitespaceChar = charCategory Space whitespaceChar = charCategory Space

View File

@ -117,23 +117,23 @@ $ hledger -f- bal -V -N
# 9. Here the amount is parsed as 1. I think (hope) no country uses space # 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. # for decimal point, so we should parse this as 1000.
#< <
#2018-01-01 2018-01-01
# (a) USD1 000 (a) USD1 000
#
#$ hledger -f- reg amt:1 $ hledger -f- reg amt:1
# 10. This commodity directive should complain about a missing decimal point, # 10. This commodity directive should complain about a missing decimal point,
# which we now require. # which we now require.
#< <
#commodity 1 000 USD commodity 1 000 USD
#
#2018-01-01 2018-01-01
# (a) USD1 000 (a) USD1 000
#
#$ hledger -f- bal $ hledger -f- bal
#>2 /decimal point/ >2 /decimal point/
#>=1 >=1
# 11. After a space-grouped amount, a posting comment should parse. # 11. After a space-grouped amount, a posting comment should parse.
< <