on master help sign in
Implement parser for JSON numbers
03e214dEvan Czaplicki
src/Json/Decode.hs+37−1
@@ -17,6 +17,7 @@ module Json.Decode
17
17
18
18
19import Prelude hiding (length)
19import Prelude hiding (length)
20+import qualified Data.ByteString.Char8 as Char8
20import qualified Data.ByteString.Internal as B
21import qualified Data.ByteString.Internal as B
21import qualified Data.HashMap.Strict as HashMap
22import qualified Data.HashMap.Strict as HashMap
22import qualified Data.Text as Text
23import qualified Data.Text as Text
@@ -30,6 +31,7 @@ import qualified Parse.Primitives as P
30import qualified Parse.Primitives.Internals as I
31import qualified Parse.Primitives.Internals as I
31import Parse.Primitives.Internals (Parser(..), State(..), noError)
32import Parse.Primitives.Internals (Parser(..), State(..), noError)
32import qualified Parse.Primitives.Keyword as Keyword
33import qualified Parse.Primitives.Keyword as Keyword
34+import qualified Parse.Primitives.Number as Number
33import qualified Parse.Primitives.Symbol as Symbol
35import qualified Parse.Primitives.Symbol as Symbol
34import qualified Reporting.Error.Syntax as E
36import qualified Reporting.Error.Syntax as E
35import qualified Reporting.Region as R
37import qualified Reporting.Region as R
@@ -169,7 +171,41 @@ arrayHelp !length revEntries =
169
171
170number :: Parser Json.Value
172number :: Parser Json.Value
171number =
173number =
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+
173
209
174
210
175
211
src/Json/Decode/Internals.hs+5−2
@@ -21,6 +21,7 @@ import Data.Text (Text)
21import Prelude hiding (fail, map, maybe)
21import Prelude hiding (fail, map, maybe)
22
22
23import qualified Data.HashMap.Strict as HashMap
23import qualified Data.HashMap.Strict as HashMap
24+import qualified Data.Scientific as Sci
24import qualified Data.Text as Text
25import qualified Data.Text as Text
25import qualified Data.Vector as Vector
26import qualified Data.Vector as Vector
26import Data.Vector ((!?))
27import Data.Vector ((!?))
@@ -35,9 +36,10 @@ data Value
35 = Array (Vector.Vector Value)
36 = Array (Vector.Vector Value)
36 | Object [(Text, Value)] (HashMap.HashMap Text Value)
37 | Object [(Text, Value)] (HashMap.HashMap Text Value)
37 | String Text
38 | String Text
39+ | Integer Int
40+ | Float Sci.Scientific
38 | TRUE
41 | TRUE
39 | FALSE
42 | FALSE
40− | Integer Int
41 | NULL
43 | NULL
42
44
43
45
@@ -261,9 +263,10 @@ toEncodeValue value =
261 Array vector -> E.array (Vector.toList (Vector.map toEncodeValue vector))
263 Array vector -> E.array (Vector.toList (Vector.map toEncodeValue vector))
262 Object fields _ -> E.object (fmap (\(k,v) -> (Text.unpack k, toEncodeValue v)) fields)
264 Object fields _ -> E.object (fmap (\(k,v) -> (Text.unpack k, toEncodeValue v)) fields)
263 String txt -> E.text txt
265 String txt -> E.text txt
266+ Integer n -> E.int n
267+ Float n -> E.number n
264 TRUE -> E.bool True
268 TRUE -> E.bool True
265 FALSE -> E.bool False
269 FALSE -> E.bool False
266− Integer n -> E.int n
267 NULL -> E.null
270 NULL -> E.null
268
271
269
272
src/Parse/Primitives/Number.hs+2
@@ -3,6 +3,8 @@
3module Parse.Primitives.Number
3module Parse.Primitives.Number
4 ( Number(..)
4 ( Number(..)
5 , number
5 , number
6+ , Outcome(..)
7+ , chompInt
6 , chompHex
8 , chompHex
7 , precedence
9 , precedence
8 )
10 )