Skip to content

Commit b8781e5

Browse files
committed
Added sax-like parsers.
1 parent c0a6233 commit b8781e5

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

Data/JsonStream/Parser.hs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ module Data.JsonStream.Parser (
6767
, filterI
6868
, takeI
6969
, toList
70+
-- * SAX-like parsers
71+
, arrayFound
72+
, objectFound
7073
) where
7174

7275
import Control.Applicative
@@ -222,6 +225,34 @@ array' valparse = Parser $ \tp ->
222225
arrayOf :: Parser a -> Parser a
223226
arrayOf valparse = array' (const valparse)
224227

228+
-- | Generate start/end objects when an element is found, in between run a parser.
229+
-- The inner parser is not run if an array is not found.
230+
elemFound :: Element -> a -> a -> Parser a -> Parser a
231+
elemFound elsearch start end parser = Parser $ moreData handle
232+
where
233+
handle tok el _
234+
| el == elsearch = Yield start (parseAndAppend (callParse parser tok))
235+
handle tok _ _ = callParse ignoreVal tok
236+
237+
parseAndAppend (Failed err) = Failed err
238+
parseAndAppend (Yield v np) = Yield v (parseAndAppend np)
239+
parseAndAppend (MoreData (Parser np, ntp)) = MoreData (Parser (parseAndAppend . np), ntp)
240+
parseAndAppend (Done ctx ntp) = Yield end (Done ctx ntp)
241+
242+
-- | Generate start/end values when an array is found, in between run a parser.
243+
-- The inner parser is not run if an array is not found.
244+
objectFound :: a -> a -> Parser a -> Parser a
245+
objectFound = elemFound ObjectBegin
246+
247+
-- | Generate start/end values when an object is found, in between run a parser.
248+
-- The inner parser is not run if an array is not found.
249+
--
250+
-- > >>> let test = "[[1,2,3],true,[],false,{\"key\":1}]" :: ByteString
251+
-- > >>> parseByteString (arrayOf (arrayFound 10 20 (1 .! integer))) test :: [Int]
252+
-- > [10,2,20,10,20]
253+
arrayFound :: a -> a -> Parser a -> Parser a
254+
arrayFound = elemFound ArrayBegin
255+
225256
-- | Match nith item in an array.
226257
arrayWithIndexOf :: Int -> Parser a -> Parser a
227258
arrayWithIndexOf idx valparse = array' itemFn

test/ParserSpec.hs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,17 @@ specObjComb = describe "Object accesors" $ do
105105
msg = parseLazyByteString parser (BL.fromChunks test) :: [Int]
106106
msg `shouldBe` [1]
107107

108+
it "arrayFound generates events" $ do
109+
let test = ["[[1,2,3],true,[],false,{\"key\":1}]"]
110+
parser = arrayOf (arrayFound 10 20 (1 .! integer))
111+
msg = parseLazyByteString parser (BL.fromChunks test) :: [Int]
112+
msg `shouldBe` [10,2,20,10,20]
113+
114+
it "objectFound generates events" $ do
115+
let test = ["[[1,2,3],true,[],false,{\"key\":1}]"]
116+
parser = arrayOf (objectFound 10 20 ("key" .: integer))
117+
msg = parseLazyByteString parser (BL.fromChunks test) :: [Int]
118+
msg `shouldBe` [10,1,20]
108119

109120
specEdge :: Spec
110121
specEdge = describe "Edge cases" $ do

0 commit comments

Comments
 (0)