Parse number as scientific and interpret meaning separately.

The current parser will fail parsing floats because it parses an int,
and then stumbles on the dot.

To fix I interpret the value with the scientific library which already
is a dependency through attoparsec, so we're not introducing any extra
downloads or compiling.

I think this is still subtly wrong because "10.0" will be parsed as
ValueInt, but because input argument ints are allowed to be coerced
into doubles (according to the spec) this is probably acceptable.
This commit is contained in:
Tom Hunger 2016-12-08 23:34:46 +00:00
parent 61f0a06096
commit 87c92e9d6e
2 changed files with 12 additions and 7 deletions

View File

@ -8,14 +8,14 @@ import Control.Applicative ((<|>), empty, many, optional)
import Control.Monad (when) import Control.Monad (when)
import Data.Char (isDigit, isSpace) import Data.Char (isDigit, isSpace)
import Data.Foldable (traverse_) import Data.Foldable (traverse_)
import Data.Scientific (floatingOrInteger)
import Data.Text (Text, append) import Data.Text (Text, append)
import Data.Attoparsec.Text import Data.Attoparsec.Text
( Parser ( Parser
, (<?>) , (<?>)
, anyChar , anyChar
, decimal , scientific
, double
, endOfLine , endOfLine
, inClass , inClass
, many1 , many1
@ -23,7 +23,6 @@ import Data.Attoparsec.Text
, option , option
, peekChar , peekChar
, sepBy1 , sepBy1
, signed
, takeWhile , takeWhile
, takeWhile1 , takeWhile1
) )
@ -149,9 +148,7 @@ typeCondition = namedType
-- explicit types use the `typedValue` parser. -- explicit types use the `typedValue` parser.
value :: Parser Value value :: Parser Value
value = ValueVariable <$> variable value = ValueVariable <$> variable
-- TODO: Handle maxBound, Int32 in spec. <|> number
<|> ValueInt <$> tok (signed decimal)
<|> ValueFloat <$> tok (signed double)
<|> ValueBoolean <$> booleanValue <|> ValueBoolean <$> booleanValue
<|> ValueString <$> stringValue <|> ValueString <$> stringValue
-- `true` and `false` have been tried before -- `true` and `false` have been tried before
@ -159,6 +156,13 @@ value = ValueVariable <$> variable
<|> ValueList <$> listValue <|> ValueList <$> listValue
<|> ValueObject <$> objectValue <|> ValueObject <$> objectValue
<?> "value error!" <?> "value error!"
where
number = do
v <- scientific
case floatingOrInteger v of
Left r -> pure (ValueFloat r)
-- TODO: Handle maxBound, Int32 in spec.
Right i -> pure (ValueInt i)
booleanValue :: Parser Bool booleanValue :: Parser Bool
booleanValue = True <$ tok "true" booleanValue = True <$ tok "true"

View File

@ -34,7 +34,8 @@ library
attoparsec >= 0.10.4.0, attoparsec >= 0.10.4.0,
base >= 4.7 && < 5, base >= 4.7 && < 5,
text >= 0.11.3.1, text >= 0.11.3.1,
unordered-containers >= 0.2.5.0 unordered-containers >= 0.2.5.0,
scientific >=0.3.1 && <0.4
if impl(ghc >= 8.0) if impl(ghc >= 8.0)
ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances
else else