on master help sign in
Reduce code duplication.
e75fc73Bryan O'Sullivan
Data/Aeson/Parser.hs+33−31
@@ -43,11 +43,7 @@ import qualified Data.HashMap.Strict as H
43-- | Parse a top-level JSON value. This must be either an object or
43-- | Parse a top-level JSON value. This must be either an object or
44-- an array.
44-- an array.
45json :: Parser Value
45json :: Parser Value
46−json = do
47− c <- skipSpace *> satisfy (`B8.elem` "{[")
48− if c == '{'
49− then object_
46+json = json_ object_ array_
50− else array_
51
47
52-- | Parse a top-level JSON value. This must be either an object or
48-- | Parse a top-level JSON value. This must be either an object or
53-- an array.
49-- an array.
@@ -56,43 +52,49 @@ json = do
56-- building up thunks during parsing. Prefer this version if most of
52-- building up thunks during parsing. Prefer this version if most of
57-- the JSON data needs to be accessed.
53-- the JSON data needs to be accessed.
58json' :: Parser Value
54json' :: Parser Value
59−json' = do
55+json' = json_ object_' array_'
56+
57+json_ :: Parser Value -> Parser Value -> Parser Value
58+json_ obj ary = do
60− c <- skipSpace *> satisfy (`B8.elem` "{[")
59+ w <- skipSpace *> A.satisfy (\w -> w == 123 || w == 91)
61− if c == '{'
60+ if w == 123
62− then object_'
61+ then obj
63− else array_'
62+ else ary
63+{-# INLINE json_ #-}
64
64
65object_ :: Parser Value
65object_ :: Parser Value
66−object_ = {-# SCC "object_" #-} do
66+object_ = {-# SCC "object_" #-} Object <$> objectValues value
67− skipSpace
68− let pair = do
69− a <- jstring <* skipSpace
70− b <- char ':' *> skipSpace *> value
71− return (a,b)
72− vals <- ((pair <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char '}'
73− return . Object $ H.fromList vals
74
67
75object_' :: Parser Value
68object_' :: Parser Value
76object_' = {-# SCC "object_'" #-} do
69object_' = {-# SCC "object_'" #-} do
70+ !vals <- objectValues value'
71+ return (Object vals)
72+
73+objectValues :: Parser Value -> Parser (H.HashMap Text Value)
74+objectValues val = do
77 skipSpace
75 skipSpace
78 let pair = do
76 let pair = do
79 a <- jstring <* skipSpace
77 a <- jstring <* skipSpace
80− b <- char ':' *> skipSpace *> value'
78+ b <- char ':' *> skipSpace *> val
81 return (a,b)
79 return (a,b)
82 vals <- ((pair <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char '}'
80 vals <- ((pair <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char '}'
83− return $! Object $ H.fromList vals
81+ return (H.fromList vals)
82+{-# INLINE objectValues #-}
84
83
85array_ :: Parser Value
84array_ :: Parser Value
86−array_ = {-# SCC "array_" #-} do
85+array_ = {-# SCC "array_" #-} Array <$> arrayValues value
87− skipSpace
88− vals <- ((value <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char ']'
89− return . Array $ Vector.fromList vals
90
86
91array_' :: Parser Value
87array_' :: Parser Value
92array_' = {-# SCC "array_'" #-} do
88array_' = {-# SCC "array_'" #-} do
89+ !vals <- arrayValues value'
90+ return (Array vals)
91+
92+arrayValues :: Parser Value -> Parser (Vector Value)
93+arrayValues val = do
93 skipSpace
94 skipSpace
94− vals <- ((value' <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char ']'
95+ vals <- ((val <* skipSpace) `sepBy` (char ',' *> skipSpace)) <* char ']'
95− return $! Array $ Vector.fromList vals
96+ return (Vector.fromList vals)
97+{-# INLINE arrayValues #-}
96
98
97-- | Parse any JSON value. Use 'json' in preference to this function
99-- | Parse any JSON value. Use 'json' in preference to this function
98-- if you are parsing data from an untrusted source.
100-- if you are parsing data from an untrusted source.
@@ -114,21 +116,21 @@ value = most <|> (Number <$> number)
114value' :: Parser Value
116value' :: Parser Value
115value' = most <|> num
117value' = most <|> num
116 where
118 where
117− num = do
118− n <- number
119− return $! Number n
120 most = do
119 most = do
121 c <- satisfy (`B8.elem` "{[\"ftn")
120 c <- satisfy (`B8.elem` "{[\"ftn")
122 case c of
121 case c of
123 '{' -> object_'
122 '{' -> object_'
124 '[' -> array_'
123 '[' -> array_'
125 '"' -> do
124 '"' -> do
126− s <- jstring_
125+ !s <- jstring_
127− return $! String s
126+ return (String s)
128 'f' -> string "alse" *> pure (Bool False)
127 'f' -> string "alse" *> pure (Bool False)
129 't' -> string "rue" *> pure (Bool True)
128 't' -> string "rue" *> pure (Bool True)
130 'n' -> string "ull" *> pure Null
129 'n' -> string "ull" *> pure Null
131 _ -> error "attoparsec panic! the impossible happened!"
130 _ -> error "attoparsec panic! the impossible happened!"
131+ num = do
132+ !n <- number
133+ return (Number n)
132
134
133doubleQuote, backslash :: Word8
135doubleQuote, backslash :: Word8
134doubleQuote = 34
136doubleQuote = 34