@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12-- |
23-- Module : Streamly.Data.Parser
34-- Copyright : (c) 2020 Composewell Technologies
@@ -6,50 +7,24 @@
67-- Stability : pre-release
78-- Portability : GHC
89--
9−-- Fast backtracking parsers with stream fusion and native streaming
10−-- capability. Parsers are just more powerful folds, folds and parsers can be
11−-- interconverted.
10+-- Fast, composable stream consumers with ability to terminate, backtrack and
11+-- fail, supporting stream fusion. Parsers are a natural extension of
12+-- "Streamly.Data.Fold". Parsers and folds can be interconverted.
1213--
13−-- Note that these parsers do not report the error context (e.g. line number or
14−-- column). This may be supported in future.
15−--
16−-- mtl instances are not provided. If the 'Parser' type is the top most layer
17−-- (which should be the case almost always) you can just use 'fromEffect' to
18−-- execute the lower layer monad effects.
19−--
20−-- == Performance Notes
21−--
22−-- This module is designed for fusion, inline the operations in this module for
23−-- fusion to occur, avoid using these operations in recursive calls, avoid
24−-- operations like 'sequence', 'asum' on these parsers. If you need these then
25−-- use the 'ParserK' module instead.
26−--
27−-- The 'Parser' type represents a stream consumer by composing state as data
28−-- which enables stream fusion. Stream fusion generates a tight loop without
29−-- any constructor allocations between the stages, providing C like performance
30−-- for the loop. Stream fusion works when multiple functions are combined in a
31−-- pipeline statically. Therefore, the operations in this module must be
32−-- inlined and must not be used recursively to allow for stream fusion.
33−--
34−-- Using the 'Parser' type parsing operations like 'one', 'splitWith' etc.
35−-- degrade quadratically (O(n^2)) when combined many times. If you need to
36−-- combine these operations, say more than 50 times in a single loop, then you
37−-- should use the continuation style parser type 'ParserK' instead. Also, if
38−-- you need to use these operations in a recursive loop you should use
39−-- 'ParserK' instead.
40−--
41−-- The 'ParserK' type represents a stream consumer by composing function calls,
42−-- therefore, a function call overhead is incurred at each composition. It is
43−-- quite fast in general but may be a few times slower than a fused parser.
44−-- However, it allows for scalable dynamic composition especially parsers can
45−-- be used in recursive calls. Using the 'ParserK' type operations like
46−-- 'splitWith' provide linear (O(n)) performance with respect to the number of
47−-- compositions..
48−--
49−-- 'Parser' and 'ParserK' types can be interconverted.
14+-- Please refer to "Streamly.Internal.Data.Parser" for functions that have
15+-- not yet been released.
5016--
5117module Streamly.Data.Parser
5218 (
19+ -- * Setup
20+ -- | To execute the code examples provided in this module in ghci, please
21+ -- run the following commands first.
22+ --
23+ -- $setup
24+
25+ -- * Overview
26+ -- $overview
27+
5328 -- * Parser Type
5429 Parser
5530
@@ -146,3 +121,57 @@ where
146121
147122import Streamly.Internal.Data.Parser
148123import Prelude hiding (dropWhile, takeWhile, filter)
124+
125+#include "DocTestDataParser.hs"
126+
127+-- $overview
128+--
129+-- Several combinators in this module can be many times faster than CPS based
130+-- parsers because of stream fusion. For example,
131+-- 'Streamly.Internal.Data.Parser.many' combinator in this module is much
132+-- faster than the 'Control.Applicative.many' combinator of
133+-- 'Control.Applicative.Alternative' type class used by CPS based parsers.
134+--
135+-- The use of 'Alternative' type class, in parsers has another drawback.
136+-- Alternative based parsers use plain Haskell lists to collect the results. In
137+-- a strict Monad like IO, the results are necessarily buffered before they can
138+-- be consumed. This may not perform optimally in streaming applications
139+-- processing large amounts of data. Equivalent combinators in this module can
140+-- consume the results of parsing using a 'Fold' or another parser, thus
141+-- providing a scalable and composable consumer.
142+--
143+-- Note that these parsers do not report the error context (e.g. line number or
144+-- column). This may be supported in future.
145+--
146+-- mtl instances are not provided. If the 'Parser' type is the top most layer
147+-- (which should be the case almost always) you can just use 'fromEffect' to
148+-- execute the lower layer monad effects.
149+--
150+-- == Performance Notes
151+--
152+-- The 'Parser' type represents a stream consumer by composing state as data
153+-- which enables stream fusion. Stream fusion generates a tight loop without
154+-- any constructor allocations between the stages, providing C like performance
155+-- for the loop. Stream fusion works when multiple functions are combined in a
156+-- pipeline statically. Therefore, the operations in this module must be
157+-- inlined and must not be used recursively to allow for stream fusion. Note
158+-- that operations like 'sequence', and 'asum' that compose pasrers using
159+-- recursion should be avoided with these parsers. You can use these with the
160+-- 'ParserK' module instead.
161+--
162+-- Using the 'Parser' type, parsing operations like 'one', 'splitWith' etc.
163+-- degrade quadratically (O(n^2)) when combined many times. If you need to
164+-- combine these operations, say more than 8 times in a single loop, then you
165+-- should consider using the continuation style parser type 'ParserK' instead.
166+-- Also, if you need to use these operations in a recursive loop you should use
167+-- 'ParserK' instead.
168+--
169+-- The 'ParserK' type represents a stream consumer by composing function calls,
170+-- therefore, a function call overhead is incurred at each composition. It is
171+-- quite fast in general but may be a few times slower than a fused parser.
172+-- However, it allows for scalable dynamic composition especially parsers can
173+-- be used in recursive calls. Using the 'ParserK' type operations like
174+-- 'splitWith' provide linear (O(n)) performance with respect to the number of
175+-- compositions..
176+--
177+-- 'Parser' and 'ParserK' types can be interconverted.