From 87c92e9d6eed3cf7a45f9df8da45c3a5689d28e1 Mon Sep 17 00:00:00 2001 From: Tom Hunger Date: Thu, 8 Dec 2016 23:34:46 +0000 Subject: [PATCH] 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. --- Data/GraphQL/Parser.hs | 16 ++++++++++------ graphql.cabal | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Data/GraphQL/Parser.hs b/Data/GraphQL/Parser.hs index 2de09b0..26902d4 100644 --- a/Data/GraphQL/Parser.hs +++ b/Data/GraphQL/Parser.hs @@ -8,14 +8,14 @@ import Control.Applicative ((<|>), empty, many, optional) import Control.Monad (when) import Data.Char (isDigit, isSpace) import Data.Foldable (traverse_) +import Data.Scientific (floatingOrInteger) import Data.Text (Text, append) import Data.Attoparsec.Text ( Parser , () , anyChar - , decimal - , double + , scientific , endOfLine , inClass , many1 @@ -23,7 +23,6 @@ import Data.Attoparsec.Text , option , peekChar , sepBy1 - , signed , takeWhile , takeWhile1 ) @@ -149,9 +148,7 @@ typeCondition = namedType -- explicit types use the `typedValue` parser. value :: Parser Value value = ValueVariable <$> variable - -- TODO: Handle maxBound, Int32 in spec. - <|> ValueInt <$> tok (signed decimal) - <|> ValueFloat <$> tok (signed double) + <|> number <|> ValueBoolean <$> booleanValue <|> ValueString <$> stringValue -- `true` and `false` have been tried before @@ -159,6 +156,13 @@ value = ValueVariable <$> variable <|> ValueList <$> listValue <|> ValueObject <$> objectValue "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 = True <$ tok "true" diff --git a/graphql.cabal b/graphql.cabal index b73e259..d330abd 100644 --- a/graphql.cabal +++ b/graphql.cabal @@ -34,7 +34,8 @@ library attoparsec >= 0.10.4.0, base >= 4.7 && < 5, 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) ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances else