on master help sign in
Implement parser for JSON numbers
commit03e214dcaa94c5b08769723e465c221851d0d5ae authorEvan Czaplicki <evancz@users.noreply.github.com> dateTue 23 Jan 2018, 18:42 (9 years ago) parent7434b91
3 files changed+44−3
src/Json/Decode.hs+37−1 src/Json/Decode/Internals.hs+5−2 src/Parse/Primitives/Number.hs+2
src/Json/Decode.hs+37−1
@@ -17,6 +17,7 @@ module Json.Decode
1717
1818
1919import Prelude hiding (length)
20+import qualified Data.ByteString.Char8 as Char8
2021import qualified Data.ByteString.Internal as B
2122import qualified Data.HashMap.Strict as HashMap
2223import qualified Data.Text as Text
@@ -30,6 +31,7 @@ import qualified Parse.Primitives as P
3031import qualified Parse.Primitives.Internals as I
3132import Parse.Primitives.Internals (Parser(..), State(..), noError)
3233import qualified Parse.Primitives.Keyword as Keyword
34+import qualified Parse.Primitives.Number as Number
3335import qualified Parse.Primitives.Symbol as Symbol
3436import qualified Reporting.Error.Syntax as E
3537import qualified Reporting.Region as R
@@ -169,7 +171,41 @@ arrayHelp !length revEntries =
169171
170172number :: Parser Json.Value
171173number =
172− error "TODO"
174+ Parser $ \(State fp offset terminal indent row col ctx) cok cerr _ eerr ->
175+ if offset < terminal then
176+
177+ let
178+ !word = I.unsafeIndex fp offset
179+ !offset1 = offset + 1
180+ in
181+ if word <= 0x39 {- 9 -} && word >= 0x31 {- 1 -} then
182+ case Number.chompInt fp offset1 terminal (fromIntegral (word - 0x30 {- 0 -})) of
183+ Number.Err newOffset problem ->
184+ cerr (E.ParseError row (col + (newOffset - offset)) problem)
185+
186+ Number.OkInt newOffset n ->
187+ let
188+ !newState = State fp newOffset terminal indent row (col + (newOffset - offset)) ctx
189+ in
190+ cok (Json.Integer n) newState noError
191+
192+ Number.OkFloat newOffset ->
193+ let
194+ !length = newOffset - offset
195+ !scientific = read $ Char8.unpack $ B.PS fp offset length
196+ !newState = State fp newOffset terminal indent row (col + length) ctx
197+ in
198+ cok (Json.Float scientific) newState noError
199+
200+ else if word == 0x30 {- 0 -} then
201+ cok (Json.Integer 0) (State fp offset1 terminal indent row (col + 1) ctx) noError
202+
203+ else
204+ eerr noError
205+
206+ else
207+ eerr noError
208+
173209
174210
175211
src/Json/Decode/Internals.hs+5−2
@@ -21,6 +21,7 @@ import Data.Text (Text)
2121import Prelude hiding (fail, map, maybe)
2222
2323import qualified Data.HashMap.Strict as HashMap
24+import qualified Data.Scientific as Sci
2425import qualified Data.Text as Text
2526import qualified Data.Vector as Vector
2627import Data.Vector ((!?))
@@ -35,9 +36,10 @@ data Value
3536 = Array (Vector.Vector Value)
3637 | Object [(Text, Value)] (HashMap.HashMap Text Value)
3738 | String Text
39+ | Integer Int
40+ | Float Sci.Scientific
3841 | TRUE
3942 | FALSE
40− | Integer Int
4143 | NULL
4244
4345
@@ -261,9 +263,10 @@ toEncodeValue value =
261263 Array vector -> E.array (Vector.toList (Vector.map toEncodeValue vector))
262264 Object fields _ -> E.object (fmap (\(k,v) -> (Text.unpack k, toEncodeValue v)) fields)
263265 String txt -> E.text txt
266+ Integer n -> E.int n
267+ Float n -> E.number n
264268 TRUE -> E.bool True
265269 FALSE -> E.bool False
266− Integer n -> E.int n
267270 NULL -> E.null
268271
269272
src/Parse/Primitives/Number.hs+2
@@ -3,6 +3,8 @@
33module Parse.Primitives.Number
44 ( Number(..)
55 , number
6+ , Outcome(..)
7+ , chompInt
68 , chompHex
79 , precedence
810 )