<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ --> <title>Data/Attoparsec.hs</title> <link type='text/css' rel='stylesheet' href='hscolour.css' /> </head> <body> <pre><a name="line-1"></a><span class='hs-comment'>-- |</span> <a name="line-2"></a><span class='hs-comment'>-- Module : Data.Attoparsec</span> <a name="line-3"></a><span class='hs-comment'>-- Copyright : Bryan O'Sullivan 2007-2010</span> <a name="line-4"></a><span class='hs-comment'>-- License : BSD3</span> <a name="line-5"></a><span class='hs-comment'>-- </span> <a name="line-6"></a><span class='hs-comment'>-- Maintainer : bos@serpentine.com</span> <a name="line-7"></a><span class='hs-comment'>-- Stability : experimental</span> <a name="line-8"></a><span class='hs-comment'>-- Portability : unknown</span> <a name="line-9"></a><span class='hs-comment'>--</span> <a name="line-10"></a><span class='hs-comment'>-- Simple, efficient combinator parsing for 'B.ByteString' strings,</span> <a name="line-11"></a><span class='hs-comment'>-- loosely based on the Parsec library.</span> <a name="line-12"></a> <a name="line-13"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Attoparsec</span> <a name="line-14"></a> <span class='hs-layout'>(</span> <a name="line-15"></a> <span class='hs-comment'>-- * Differences from Parsec</span> <a name="line-16"></a> <span class='hs-comment'>-- $parsec</span> <a name="line-17"></a> <a name="line-18"></a> <span class='hs-comment'>-- * Incremental input</span> <a name="line-19"></a> <span class='hs-comment'>-- $incremental</span> <a name="line-20"></a> <a name="line-21"></a> <span class='hs-comment'>-- * Performance considerations</span> <a name="line-22"></a> <span class='hs-comment'>-- $performance</span> <a name="line-23"></a> <a name="line-24"></a> <span class='hs-comment'>-- * Parser types</span> <a name="line-25"></a> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-conid'>Parser</span> <a name="line-26"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>Result</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span> <a name="line-27"></a> <a name="line-28"></a> <span class='hs-comment'>-- ** Typeclass instances</span> <a name="line-29"></a> <span class='hs-comment'>-- $instances</span> <a name="line-30"></a> <a name="line-31"></a> <span class='hs-comment'>-- * Running parsers</span> <a name="line-32"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>parse</span> <a name="line-33"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>feed</span> <a name="line-34"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>parseOnly</span> <a name="line-35"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>parseWith</span> <a name="line-36"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>parseTest</span> <a name="line-37"></a> <a name="line-38"></a> <span class='hs-comment'>-- ** Result conversion</span> <a name="line-39"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>maybeResult</span> <a name="line-40"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>eitherResult</span> <a name="line-41"></a> <a name="line-42"></a> <span class='hs-comment'>-- * Combinators</span> <a name="line-43"></a> <span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-conid'>I</span><span class='hs-varop'>.<?></span><span class='hs-layout'>)</span> <a name="line-44"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>try</span> <a name="line-45"></a> <span class='hs-layout'>,</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Attoparsec</span><span class='hs-varop'>.</span><span class='hs-conid'>Combinator</span> <a name="line-46"></a> <a name="line-47"></a> <span class='hs-comment'>-- * Parsing individual bytes</span> <a name="line-48"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>word8</span> <a name="line-49"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>anyWord8</span> <a name="line-50"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>notWord8</span> <a name="line-51"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>satisfy</span> <a name="line-52"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>satisfyWith</span> <a name="line-53"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>skip</span> <a name="line-54"></a> <a name="line-55"></a> <span class='hs-comment'>-- ** Byte classes</span> <a name="line-56"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>inClass</span> <a name="line-57"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>notInClass</span> <a name="line-58"></a> <a name="line-59"></a> <span class='hs-comment'>-- * Efficient string handling</span> <a name="line-60"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>string</span> <a name="line-61"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>skipWhile</span> <a name="line-62"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>take</span> <a name="line-63"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>scan</span> <a name="line-64"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>takeWhile</span> <a name="line-65"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>takeWhile1</span> <a name="line-66"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>takeTill</span> <a name="line-67"></a> <a name="line-68"></a> <span class='hs-comment'>-- ** Consume all remaining input</span> <a name="line-69"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>takeByteString</span> <a name="line-70"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>takeLazyByteString</span> <a name="line-71"></a> <a name="line-72"></a> <span class='hs-comment'>-- * State observation and manipulation functions</span> <a name="line-73"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>endOfInput</span> <a name="line-74"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-varid'>atEnd</span> <a name="line-75"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span> <a name="line-76"></a> <a name="line-77"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Attoparsec</span><span class='hs-varop'>.</span><span class='hs-conid'>Combinator</span> <a name="line-78"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Attoparsec</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>I</span> <a name="line-79"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>B</span> <a name="line-80"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Attoparsec</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span> <span class='hs-layout'>(</span><span class='hs-conid'>Result</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-varid'>parse</span><span class='hs-layout'>)</span> <a name="line-81"></a> <a name="line-82"></a><span class='hs-comment'>-- $parsec</span> <a name="line-83"></a><span class='hs-comment'>--</span> <a name="line-84"></a><span class='hs-comment'>-- Compared to Parsec 3, Attoparsec makes several tradeoffs. It is</span> <a name="line-85"></a><span class='hs-comment'>-- not intended for, or ideal for, all possible uses.</span> <a name="line-86"></a><span class='hs-comment'>--</span> <a name="line-87"></a><span class='hs-comment'>-- * While Attoparsec can consume input incrementally, Parsec cannot.</span> <a name="line-88"></a><span class='hs-comment'>-- Incremental input is a huge deal for efficient and secure network</span> <a name="line-89"></a><span class='hs-comment'>-- and system programming, since it gives much more control to users</span> <a name="line-90"></a><span class='hs-comment'>-- of the library over matters such as resource usage and the I/O</span> <a name="line-91"></a><span class='hs-comment'>-- model to use.</span> <a name="line-92"></a><span class='hs-comment'>--</span> <a name="line-93"></a><span class='hs-comment'>-- * Much of the performance advantage of Attoparsec is gained via</span> <a name="line-94"></a><span class='hs-comment'>-- high-performance parsers such as 'I.takeWhile' and 'I.string'.</span> <a name="line-95"></a><span class='hs-comment'>-- If you use complicated combinators that return lists of bytes or</span> <a name="line-96"></a><span class='hs-comment'>-- characters, there is less performance difference between the two</span> <a name="line-97"></a><span class='hs-comment'>-- libraries.</span> <a name="line-98"></a><span class='hs-comment'>--</span> <a name="line-99"></a><span class='hs-comment'>-- * Unlike Parsec 3, Attoparsec does not support being used as a</span> <a name="line-100"></a><span class='hs-comment'>-- monad transformer.</span> <a name="line-101"></a><span class='hs-comment'>--</span> <a name="line-102"></a><span class='hs-comment'>-- * Attoparsec is specialised to deal only with strict 'B.ByteString'</span> <a name="line-103"></a><span class='hs-comment'>-- input. Efficiency concernts rule out both lists and lazy</span> <a name="line-104"></a><span class='hs-comment'>-- bytestrings. The usual use for lazy bytestrings would be to</span> <a name="line-105"></a><span class='hs-comment'>-- allow consumption of very large input without a large footprint.</span> <a name="line-106"></a><span class='hs-comment'>-- For this need, Attoparsec's incremental input provides an</span> <a name="line-107"></a><span class='hs-comment'>-- excellent substitute, with much more control over when input</span> <a name="line-108"></a><span class='hs-comment'>-- takes place. If you must use lazy bytestrings, see the 'Lazy'</span> <a name="line-109"></a><span class='hs-comment'>-- module, which feeds lazy chunks to a regular parser.</span> <a name="line-110"></a><span class='hs-comment'>--</span> <a name="line-111"></a><span class='hs-comment'>-- * Parsec parsers can produce more helpful error messages than</span> <a name="line-112"></a><span class='hs-comment'>-- Attoparsec parsers. This is a matter of focus: Attoparsec avoids</span> <a name="line-113"></a><span class='hs-comment'>-- the extra book-keeping in favour of higher performance.</span> <a name="line-114"></a> <a name="line-115"></a><span class='hs-comment'>-- $incremental</span> <a name="line-116"></a><span class='hs-comment'>--</span> <a name="line-117"></a><span class='hs-comment'>-- Attoparsec supports incremental input, meaning that you can feed it</span> <a name="line-118"></a><span class='hs-comment'>-- a bytestring that represents only part of the expected total amount</span> <a name="line-119"></a><span class='hs-comment'>-- of data to parse. If your parser reaches the end of a fragment of</span> <a name="line-120"></a><span class='hs-comment'>-- input and could consume more input, it will suspend parsing and</span> <a name="line-121"></a><span class='hs-comment'>-- return a 'Partial' continuation.</span> <a name="line-122"></a><span class='hs-comment'>--</span> <a name="line-123"></a><span class='hs-comment'>-- Supplying the 'Partial' continuation with another bytestring will</span> <a name="line-124"></a><span class='hs-comment'>-- resume parsing at the point where it was suspended. You must be</span> <a name="line-125"></a><span class='hs-comment'>-- prepared for the result of the resumed parse to be another</span> <a name="line-126"></a><span class='hs-comment'>-- 'Partial' continuation.</span> <a name="line-127"></a><span class='hs-comment'>--</span> <a name="line-128"></a><span class='hs-comment'>-- To indicate that you have no more input, supply the 'Partial'</span> <a name="line-129"></a><span class='hs-comment'>-- continuation with an empty bytestring.</span> <a name="line-130"></a><span class='hs-comment'>--</span> <a name="line-131"></a><span class='hs-comment'>-- Remember that some parsing combinators will not return a result</span> <a name="line-132"></a><span class='hs-comment'>-- until they reach the end of input. They may thus cause 'Partial'</span> <a name="line-133"></a><span class='hs-comment'>-- results to be returned.</span> <a name="line-134"></a><span class='hs-comment'>--</span> <a name="line-135"></a><span class='hs-comment'>-- If you do not need support for incremental input, consider using</span> <a name="line-136"></a><span class='hs-comment'>-- the 'I.parseOnly' function to run your parser. It will never</span> <a name="line-137"></a><span class='hs-comment'>-- prompt for more input.</span> <a name="line-138"></a> <a name="line-139"></a><span class='hs-comment'>-- $performance</span> <a name="line-140"></a><span class='hs-comment'>--</span> <a name="line-141"></a><span class='hs-comment'>-- If you write an Attoparsec-based parser carefully, it can be</span> <a name="line-142"></a><span class='hs-comment'>-- realistic to expect it to perform within a factor of 2 of a</span> <a name="line-143"></a><span class='hs-comment'>-- hand-rolled C parser (measuring megabytes parsed per second).</span> <a name="line-144"></a><span class='hs-comment'>--</span> <a name="line-145"></a><span class='hs-comment'>-- To actually achieve high performance, there are a few guidelines</span> <a name="line-146"></a><span class='hs-comment'>-- that it is useful to follow.</span> <a name="line-147"></a><span class='hs-comment'>--</span> <a name="line-148"></a><span class='hs-comment'>-- Use the 'B.ByteString'-oriented parsers whenever possible,</span> <a name="line-149"></a><span class='hs-comment'>-- e.g. 'I.takeWhile1' instead of 'many1' 'I.anyWord8'. There is</span> <a name="line-150"></a><span class='hs-comment'>-- about a factor of 100 difference in performance between the two</span> <a name="line-151"></a><span class='hs-comment'>-- kinds of parser.</span> <a name="line-152"></a><span class='hs-comment'>--</span> <a name="line-153"></a><span class='hs-comment'>-- For very simple byte-testing predicates, write them by hand instead</span> <a name="line-154"></a><span class='hs-comment'>-- of using 'I.inClass' or 'I.notInClass'. For instance, both of</span> <a name="line-155"></a><span class='hs-comment'>-- these predicates test for an end-of-line byte, but the first is</span> <a name="line-156"></a><span class='hs-comment'>-- much faster than the second:</span> <a name="line-157"></a><span class='hs-comment'>--</span> <a name="line-158"></a><span class='hs-comment'>-- >endOfLine_fast w = w == 13 || w == 10</span> <a name="line-159"></a><span class='hs-comment'>-- >endOfLine_slow = inClass "\r\n"</span> <a name="line-160"></a><span class='hs-comment'>--</span> <a name="line-161"></a><span class='hs-comment'>-- Make active use of benchmarking and profiling tools to measure,</span> <a name="line-162"></a><span class='hs-comment'>-- find the problems with, and improve the performance of your parser.</span> <a name="line-163"></a> <a name="line-164"></a><span class='hs-comment'>-- $instances</span> <a name="line-165"></a><span class='hs-comment'>--</span> <a name="line-166"></a><span class='hs-comment'>-- The 'I.Parser' type is an instance of the following classes:</span> <a name="line-167"></a><span class='hs-comment'>--</span> <a name="line-168"></a><span class='hs-comment'>-- * 'Monad', where 'fail' throws an exception (i.e. fails) with an</span> <a name="line-169"></a><span class='hs-comment'>-- error message.</span> <a name="line-170"></a><span class='hs-comment'>--</span> <a name="line-171"></a><span class='hs-comment'>-- * 'Functor' and 'Applicative', which follow the usual definitions.</span> <a name="line-172"></a><span class='hs-comment'>--</span> <a name="line-173"></a><span class='hs-comment'>-- * 'MonadPlus', where 'mzero' fails (with no error message) and</span> <a name="line-174"></a><span class='hs-comment'>-- 'mplus' executes the right-hand parser if the left-hand one</span> <a name="line-175"></a><span class='hs-comment'>-- fails.</span> <a name="line-176"></a><span class='hs-comment'>--</span> <a name="line-177"></a><span class='hs-comment'>-- * 'Alternative', which follows 'MonadPlus'.</span> <a name="line-178"></a><span class='hs-comment'>--</span> <a name="line-179"></a><span class='hs-comment'>-- The 'Result' type is an instance of 'Functor', where 'fmap'</span> <a name="line-180"></a><span class='hs-comment'>-- transforms the value in a 'Done' result.</span> <a name="line-181"></a> <a name="line-182"></a><a name="feed"></a><span class='hs-comment'>-- | If a parser has returned a 'Partial' result, supply it with more</span> <a name="line-183"></a><span class='hs-comment'>-- input.</span> <a name="line-184"></a><span class='hs-definition'>feed</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Result</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Result</span> <span class='hs-varid'>r</span> <a name="line-185"></a><span class='hs-definition'>feed</span> <span class='hs-varid'>f</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>Fail</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>f</span> <a name="line-186"></a><span class='hs-definition'>feed</span> <span class='hs-layout'>(</span><span class='hs-conid'>Partial</span> <span class='hs-varid'>k</span><span class='hs-layout'>)</span> <span class='hs-varid'>d</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>k</span> <span class='hs-varid'>d</span> <a name="line-187"></a><span class='hs-definition'>feed</span> <span class='hs-layout'>(</span><span class='hs-conid'>Done</span> <span class='hs-varid'>bs</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varid'>d</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Done</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>append</span> <span class='hs-varid'>bs</span> <span class='hs-varid'>d</span><span class='hs-layout'>)</span> <span class='hs-varid'>r</span> <a name="line-188"></a><span class='hs-comment'>{-# INLINE feed #-}</span> <a name="line-189"></a> <a name="line-190"></a><a name="parseTest"></a><span class='hs-comment'>-- | Run a parser and print its result to standard output.</span> <a name="line-191"></a><span class='hs-definition'>parseTest</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>Show</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=></span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-conid'>Parser</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <a name="line-192"></a><span class='hs-definition'>parseTest</span> <span class='hs-varid'>p</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>print</span> <span class='hs-layout'>(</span><span class='hs-varid'>parse</span> <span class='hs-varid'>p</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <a name="line-193"></a> <a name="line-194"></a><a name="parseWith"></a><span class='hs-comment'>-- | Run a parser with an initial input string, and a monadic action</span> <a name="line-195"></a><span class='hs-comment'>-- that can supply more input if needed.</span> <a name="line-196"></a><span class='hs-definition'>parseWith</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Monad</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=></span> <a name="line-197"></a> <span class='hs-layout'>(</span><span class='hs-varid'>m</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-layout'>)</span> <a name="line-198"></a> <span class='hs-comment'>-- ^ An action that will be executed to provide the parser</span> <a name="line-199"></a> <span class='hs-comment'>-- with more input, if necessary. The action must return an</span> <a name="line-200"></a> <span class='hs-comment'>-- 'B.empty' string when there is no more input available.</span> <a name="line-201"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>I</span><span class='hs-varop'>.</span><span class='hs-conid'>Parser</span> <span class='hs-varid'>a</span> <a name="line-202"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <a name="line-203"></a> <span class='hs-comment'>-- ^ Initial input for the parser.</span> <a name="line-204"></a> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>m</span> <span class='hs-layout'>(</span><span class='hs-conid'>Result</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <a name="line-205"></a><span class='hs-definition'>parseWith</span> <span class='hs-varid'>refill</span> <span class='hs-varid'>p</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>step</span> <span class='hs-varop'>$</span> <span class='hs-varid'>parse</span> <span class='hs-varid'>p</span> <span class='hs-varid'>s</span> <a name="line-206"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>step</span> <span class='hs-layout'>(</span><span class='hs-conid'>Partial</span> <span class='hs-varid'>k</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>step</span> <span class='hs-varop'>.</span> <span class='hs-varid'>k</span><span class='hs-layout'>)</span> <span class='hs-varop'>=<<</span> <span class='hs-varid'>refill</span> <a name="line-207"></a> <span class='hs-varid'>step</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-varid'>r</span> <a name="line-208"></a><span class='hs-comment'>{-# INLINE parseWith #-}</span> <a name="line-209"></a> <a name="line-210"></a><a name="maybeResult"></a><span class='hs-comment'>-- | Convert a 'Result' value to a 'Maybe' value. A 'Partial' result</span> <a name="line-211"></a><span class='hs-comment'>-- is treated as failure.</span> <a name="line-212"></a><span class='hs-definition'>maybeResult</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Result</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>r</span> <a name="line-213"></a><span class='hs-definition'>maybeResult</span> <span class='hs-layout'>(</span><span class='hs-conid'>Done</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Just</span> <span class='hs-varid'>r</span> <a name="line-214"></a><span class='hs-definition'>maybeResult</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Nothing</span> <a name="line-215"></a> <a name="line-216"></a><a name="eitherResult"></a><span class='hs-comment'>-- | Convert a 'Result' value to an 'Either' value. A 'Partial' result</span> <a name="line-217"></a><span class='hs-comment'>-- is treated as failure.</span> <a name="line-218"></a><span class='hs-definition'>eitherResult</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Result</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Either</span> <span class='hs-conid'>String</span> <span class='hs-varid'>r</span> <a name="line-219"></a><span class='hs-definition'>eitherResult</span> <span class='hs-layout'>(</span><span class='hs-conid'>Done</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Right</span> <span class='hs-varid'>r</span> <a name="line-220"></a><span class='hs-definition'>eitherResult</span> <span class='hs-layout'>(</span><span class='hs-conid'>Fail</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>msg</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Left</span> <span class='hs-varid'>msg</span> <a name="line-221"></a><span class='hs-definition'>eitherResult</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Left</span> <span class='hs-str'>"Result: incomplete input"</span> </pre></body> </html>