Sophie

Sophie

distrib > Fedora > 18 > i386 > by-pkgid > db7a4a658d190b3e658423135710c498 > files > 1077

ghc-darcs-devel-2.8.3-1.fc18.i686.rpm

<?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://code.haskell.org/~malcolm/hscolour/ -->
<title>src/Darcs/Patch/ReadMonads.hs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE BangPatterns #-}</span>
<a name="line-2"></a><span class='hs-comment'>-- | This module defines our parsing monad.  In the past there have been lazy</span>
<a name="line-3"></a><span class='hs-comment'>-- and strict parsers in this module.  Currently we have only the strict</span>
<a name="line-4"></a><span class='hs-comment'>-- variant and it is used for parsing patch files.</span>
<a name="line-5"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Darcs</span><span class='hs-varop'>.</span><span class='hs-conid'>Patch</span><span class='hs-varop'>.</span><span class='hs-conid'>ReadMonads</span> <span class='hs-layout'>(</span><span class='hs-conid'>ParserM</span><span class='hs-layout'>,</span> <span class='hs-conid'>Darcs</span><span class='hs-varop'>.</span><span class='hs-conid'>Patch</span><span class='hs-varop'>.</span><span class='hs-conid'>ReadMonads</span><span class='hs-varop'>.</span><span class='hs-varid'>take</span><span class='hs-layout'>,</span>
<a name="line-6"></a>                        <span class='hs-varid'>parse</span><span class='hs-layout'>,</span> <span class='hs-varid'>parseStrictly</span><span class='hs-layout'>,</span> <span class='hs-varid'>char</span><span class='hs-layout'>,</span> <span class='hs-varid'>int</span><span class='hs-layout'>,</span>
<a name="line-7"></a>                        <span class='hs-varid'>option</span><span class='hs-layout'>,</span> <span class='hs-varid'>choice</span><span class='hs-layout'>,</span> <span class='hs-varid'>skipSpace</span><span class='hs-layout'>,</span> <span class='hs-varid'>skipWhile</span><span class='hs-layout'>,</span> <span class='hs-varid'>string</span><span class='hs-layout'>,</span>
<a name="line-8"></a>                        <span class='hs-varid'>lexChar</span><span class='hs-layout'>,</span> <span class='hs-varid'>lexString</span><span class='hs-layout'>,</span> <span class='hs-varid'>lexEof</span><span class='hs-layout'>,</span> <span class='hs-varid'>takeTillChar</span><span class='hs-layout'>,</span>
<a name="line-9"></a>                        <span class='hs-varid'>myLex'</span><span class='hs-layout'>,</span> <span class='hs-varid'>anyChar</span><span class='hs-layout'>,</span> <span class='hs-varid'>endOfInput</span><span class='hs-layout'>,</span> <span class='hs-varid'>takeTill</span><span class='hs-layout'>,</span>
<a name="line-10"></a>                        <span class='hs-varid'>checkConsumes</span><span class='hs-layout'>,</span>
<a name="line-11"></a>                        <span class='hs-varid'>linesStartingWith</span><span class='hs-layout'>,</span> <span class='hs-varid'>linesStartingWithEndingWith</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-12"></a>
<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>ByteStringUtils</span> <span class='hs-layout'>(</span> <span class='hs-varid'>dropSpace</span><span class='hs-layout'>,</span> <span class='hs-varid'>breakSpace</span><span class='hs-layout'>,</span> <span class='hs-varid'>breakFirstPS</span><span class='hs-layout'>,</span>
<a name="line-14"></a>                         <span class='hs-varid'>readIntPS</span><span class='hs-layout'>,</span> <span class='hs-varid'>breakLastPS</span> <span class='hs-layout'>)</span>
<a name="line-15"></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> <span class='hs-layout'>(</span><span class='hs-varid'>null</span><span class='hs-layout'>,</span> <span class='hs-varid'>drop</span><span class='hs-layout'>,</span> <span class='hs-varid'>length</span><span class='hs-layout'>,</span> <span class='hs-varid'>tail</span><span class='hs-layout'>,</span> <span class='hs-varid'>empty</span><span class='hs-layout'>,</span>
<a name="line-16"></a>                                       <span class='hs-conid'>ByteString</span><span class='hs-layout'>)</span>
<a name="line-17"></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-varop'>.</span><span class='hs-conid'>Char8</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>BC</span> <span class='hs-layout'>(</span> <span class='hs-varid'>uncons</span><span class='hs-layout'>,</span> <span class='hs-varid'>dropWhile</span><span class='hs-layout'>,</span> <span class='hs-varid'>break</span>
<a name="line-18"></a>                                             <span class='hs-layout'>,</span> <span class='hs-varid'>splitAt</span><span class='hs-layout'>,</span> <span class='hs-varid'>length</span><span class='hs-layout'>,</span> <span class='hs-varid'>head</span> <span class='hs-layout'>)</span>
<a name="line-19"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span> <span class='hs-layout'>(</span> <span class='hs-conid'>Alternative</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-conid'>Applicative</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varop'>&lt;$&gt;</span><span class='hs-layout'>)</span> <span class='hs-layout'>)</span>
<a name="line-20"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span> <span class='hs-layout'>(</span> <span class='hs-conid'>MonadPlus</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span> <span class='hs-layout'>)</span>
<a name="line-21"></a>
<a name="line-22"></a><a name="lexChar"></a><span class='hs-comment'>-- | 'lexChar' checks if the next space delimited token from</span>
<a name="line-23"></a><span class='hs-comment'>-- the input stream matches a specific 'Char'.</span>
<a name="line-24"></a><span class='hs-comment'>-- Uses 'Maybe' inside 'ParserM' to handle failed matches, so</span>
<a name="line-25"></a><span class='hs-comment'>-- that it always returns () on success.</span>
<a name="line-26"></a><span class='hs-definition'>lexChar</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-27"></a><span class='hs-definition'>lexChar</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-28"></a>  <span class='hs-varid'>skipSpace</span>
<a name="line-29"></a>  <span class='hs-varid'>char</span> <span class='hs-varid'>c</span>
<a name="line-30"></a>  <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
<a name="line-31"></a>
<a name="line-32"></a><a name="lexString"></a><span class='hs-comment'>-- | 'lexString' fetches the next whitespace delimited token from</span>
<a name="line-33"></a><span class='hs-comment'>-- from the input and checks if it matches the 'ByteString' input.</span>
<a name="line-34"></a><span class='hs-comment'>-- Uses 'Maybe' inside 'ParserM' to handle failed matches, so</span>
<a name="line-35"></a><span class='hs-comment'>-- that it always returns () on success.</span>
<a name="line-36"></a><span class='hs-definition'>lexString</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-37"></a><span class='hs-definition'>lexString</span> <span class='hs-varid'>str</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span>
<a name="line-38"></a>           <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>myLex</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-39"></a>                       <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>xs</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>ys</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>xs</span> <span class='hs-varop'>==</span> <span class='hs-varid'>str</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>()</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>ys</span><span class='hs-layout'>)</span>
<a name="line-40"></a>                       <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span>
<a name="line-41"></a>
<a name="line-42"></a><a name="string"></a><span class='hs-comment'>-- | Only succeeds if the characters in the input exactly match @str@.</span>
<a name="line-43"></a><span class='hs-definition'>string</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-44"></a><span class='hs-definition'>string</span> <span class='hs-varid'>str</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span>
<a name="line-45"></a>        <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>splitAt</span> <span class='hs-layout'>(</span><span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>length</span> <span class='hs-varid'>str</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-46"></a>                  <span class='hs-layout'>(</span><span class='hs-varid'>h</span><span class='hs-layout'>,</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>h</span> <span class='hs-varop'>==</span> <span class='hs-varid'>str</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>()</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>t</span><span class='hs-layout'>)</span>
<a name="line-47"></a>                  <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span>
<a name="line-48"></a>
<a name="line-49"></a><a name="lexEof"></a><span class='hs-comment'>-- | 'lexEof' looks for optional spaces followed by the end of input.</span>
<a name="line-50"></a><span class='hs-comment'>-- Uses 'Maybe' inside 'ParserM' to handle failed matches, so</span>
<a name="line-51"></a><span class='hs-comment'>-- that it always returns () on success.</span>
<a name="line-52"></a><span class='hs-definition'>lexEof</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-53"></a><span class='hs-definition'>lexEof</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span>
<a name="line-54"></a>        <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>if</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>dropSpace</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
<a name="line-55"></a>                <span class='hs-keyword'>then</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>()</span> <span class='hs-conop'>:*:</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>empty</span><span class='hs-layout'>)</span>
<a name="line-56"></a>                <span class='hs-keyword'>else</span> <span class='hs-conid'>Nothing</span>
<a name="line-57"></a>
<a name="line-58"></a><a name="myLex"></a><span class='hs-comment'>-- | 'myLex' drops leading spaces and then breaks the string at the</span>
<a name="line-59"></a><span class='hs-comment'>-- next space.  Returns 'Nothing' when the string is empty after</span>
<a name="line-60"></a><span class='hs-comment'>-- dropping leading spaces, otherwise it returns the first sequence</span>
<a name="line-61"></a><span class='hs-comment'>-- of non-spaces and the remainder of the input.</span>
<a name="line-62"></a><span class='hs-definition'>myLex</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'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-conid'>ParserState</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-63"></a><span class='hs-definition'>myLex</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>let</span> <span class='hs-varid'>s'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>dropSpace</span> <span class='hs-varid'>s</span>
<a name="line-64"></a>           <span class='hs-keyword'>in</span> <span class='hs-keyword'>if</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>null</span> <span class='hs-varid'>s'</span>
<a name="line-65"></a>              <span class='hs-keyword'>then</span> <span class='hs-conid'>Nothing</span>
<a name="line-66"></a>              <span class='hs-keyword'>else</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-varid'>stuple</span> <span class='hs-varop'>$</span> <span class='hs-varid'>breakSpace</span> <span class='hs-varid'>s'</span>
<a name="line-67"></a>
<a name="line-68"></a><a name="myLex'"></a><span class='hs-comment'>-- | Like 'myLex' except that it is in ParserM</span>
<a name="line-69"></a><span class='hs-definition'>myLex'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-70"></a><span class='hs-definition'>myLex'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varid'>myLex</span>
<a name="line-71"></a>
<a name="line-72"></a><a name="anyChar"></a><span class='hs-comment'>-- | Accepts the next character and returns it.  Only fails at end of</span>
<a name="line-73"></a><span class='hs-comment'>-- input.</span>
<a name="line-74"></a><span class='hs-definition'>anyChar</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>Char</span>
<a name="line-75"></a><span class='hs-definition'>anyChar</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>stuple</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>uncons</span> <span class='hs-varid'>s</span>
<a name="line-76"></a>
<a name="line-77"></a><a name="endOfInput"></a><span class='hs-comment'>-- | Only succeeds at end of input, consumes no characters.</span>
<a name="line-78"></a><span class='hs-definition'>endOfInput</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-79"></a><span class='hs-definition'>endOfInput</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>if</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>null</span> <span class='hs-varid'>s</span>
<a name="line-80"></a>                            <span class='hs-keyword'>then</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>()</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
<a name="line-81"></a>                            <span class='hs-keyword'>else</span> <span class='hs-conid'>Nothing</span>
<a name="line-82"></a>
<a name="line-83"></a><a name="char"></a><span class='hs-comment'>-- | Accepts only the specified character.  Consumes a character, if</span>
<a name="line-84"></a><span class='hs-comment'>-- available.</span>
<a name="line-85"></a><span class='hs-definition'>char</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-86"></a><span class='hs-definition'>char</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-87"></a>  <span class='hs-keyword'>case</span> <span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>uncons</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-88"></a>  <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>c'</span><span class='hs-layout'>,</span> <span class='hs-varid'>s'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>c</span> <span class='hs-varop'>==</span> <span class='hs-varid'>c'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>()</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s'</span><span class='hs-layout'>)</span>
<a name="line-89"></a>  <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span>
<a name="line-90"></a>
<a name="line-91"></a><a name="int"></a><span class='hs-comment'>-- | Parse an integer and return it.  Skips leading whitespaces and</span>
<a name="line-92"></a><span class='hs-comment'>-- | uses the efficient ByteString readInt.</span>
<a name="line-93"></a><span class='hs-definition'>int</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>Int</span>
<a name="line-94"></a><span class='hs-definition'>int</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>stuple</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>readIntPS</span> <span class='hs-varid'>s</span>
<a name="line-95"></a>
<a name="line-96"></a><a name="skipSpace"></a><span class='hs-comment'>-- | Discards spaces until a non-space character is encountered.</span>
<a name="line-97"></a><span class='hs-comment'>-- Always succeeds.</span>
<a name="line-98"></a><span class='hs-definition'>skipSpace</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-99"></a><span class='hs-definition'>skipSpace</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>alterInput</span> <span class='hs-varid'>dropSpace</span>
<a name="line-100"></a>
<a name="line-101"></a><a name="skipWhile"></a><span class='hs-comment'>-- | Discards any characters as long as @p@ returns True.  Always</span>
<a name="line-102"></a><span class='hs-comment'>-- | succeeds.</span>
<a name="line-103"></a><span class='hs-definition'>skipWhile</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-104"></a><span class='hs-definition'>skipWhile</span> <span class='hs-varid'>p</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>alterInput</span> <span class='hs-layout'>(</span><span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>dropWhile</span> <span class='hs-varid'>p</span><span class='hs-layout'>)</span>
<a name="line-105"></a>
<a name="line-106"></a><a name="takeTill"></a><span class='hs-comment'>-- | Takes characters while @p@ returns True.  Always succeeds.</span>
<a name="line-107"></a><span class='hs-definition'>takeTill</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-108"></a><span class='hs-definition'>takeTill</span> <span class='hs-varid'>p</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-varid'>stuple</span> <span class='hs-layout'>(</span><span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>break</span> <span class='hs-varid'>p</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
<a name="line-109"></a>
<a name="line-110"></a><a name="takeTillChar"></a><span class='hs-comment'>-- | Equivalent to @takeTill (==c)@, except that it is optimized for</span>
<a name="line-111"></a><span class='hs-comment'>-- | the equality case.</span>
<a name="line-112"></a><span class='hs-definition'>takeTillChar</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-113"></a><span class='hs-definition'>takeTillChar</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-varid'>stuple</span> <span class='hs-layout'>(</span><span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>break</span> <span class='hs-layout'>(</span><span class='hs-varop'>==</span><span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
<a name="line-114"></a>
<a name="line-115"></a><a name="take"></a><span class='hs-comment'>-- | Takes exactly @n@ bytes, or fails.</span>
<a name="line-116"></a><span class='hs-definition'>take</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-117"></a><span class='hs-definition'>take</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>if</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>length</span> <span class='hs-varid'>s</span> <span class='hs-varop'>&gt;=</span> <span class='hs-varid'>n</span>
<a name="line-118"></a>                        <span class='hs-keyword'>then</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>$</span> <span class='hs-varid'>stuple</span> <span class='hs-varop'>$</span> <span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>splitAt</span> <span class='hs-varid'>n</span> <span class='hs-varid'>s</span>
<a name="line-119"></a>                        <span class='hs-keyword'>else</span> <span class='hs-conid'>Nothing</span>
<a name="line-120"></a>
<a name="line-121"></a><a name="linesStartingWith"></a><span class='hs-comment'>-- | This is a highly optimized way to read lines that start with a</span>
<a name="line-122"></a><span class='hs-comment'>-- particular character.  To implement this efficiently we need access</span>
<a name="line-123"></a><span class='hs-comment'>-- to the parser's internal state.  If this is implemented in terms of</span>
<a name="line-124"></a><span class='hs-comment'>-- the other primitives for the parser it requires us to consume one</span>
<a name="line-125"></a><span class='hs-comment'>-- character at a time.  That leads to @(&gt;&gt;=)@ wasting significant</span>
<a name="line-126"></a><span class='hs-comment'>-- time.</span>
<a name="line-127"></a><span class='hs-definition'>linesStartingWith</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</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>
<a name="line-128"></a><span class='hs-definition'>linesStartingWith</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-varid'>linesStartingWith'</span> <span class='hs-varid'>c</span>
<a name="line-129"></a>
<a name="line-130"></a><a name="linesStartingWith'"></a><span class='hs-comment'>-- | Helper function for 'linesStartingWith'.</span>
<a name="line-131"></a><span class='hs-definition'>linesStartingWith'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-conid'>ParserState</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-layout'>)</span>
<a name="line-132"></a><span class='hs-definition'>linesStartingWith'</span> <span class='hs-varid'>c</span> <span class='hs-varid'>thes</span> <span class='hs-keyglyph'>=</span>
<a name="line-133"></a>    <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>lsw</span> <span class='hs-conid'>[]</span> <span class='hs-varid'>thes</span><span class='hs-layout'>)</span>
<a name="line-134"></a>    <span class='hs-keyword'>where</span> <span class='hs-varid'>lsw</span> <span class='hs-varid'>acc</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>null</span> <span class='hs-varid'>s</span> <span class='hs-varop'>||</span> <span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>head</span> <span class='hs-varid'>s</span> <span class='hs-varop'>/=</span> <span class='hs-varid'>c</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>reverse</span> <span class='hs-varid'>acc</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
<a name="line-135"></a>          <span class='hs-varid'>lsw</span> <span class='hs-varid'>acc</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>let</span> <span class='hs-varid'>s'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>tail</span> <span class='hs-varid'>s</span>
<a name="line-136"></a>                  <span class='hs-keyword'>in</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>breakFirstPS</span> <span class='hs-chr'>'\n'</span> <span class='hs-varid'>s'</span> <span class='hs-keyword'>of</span>
<a name="line-137"></a>                     <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>l</span><span class='hs-layout'>,</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>lsw</span> <span class='hs-layout'>(</span><span class='hs-varid'>l</span><span class='hs-conop'>:</span><span class='hs-varid'>acc</span><span class='hs-layout'>)</span> <span class='hs-varid'>r</span>
<a name="line-138"></a>                     <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>reverse</span> <span class='hs-layout'>(</span><span class='hs-varid'>s'</span><span class='hs-conop'>:</span><span class='hs-varid'>acc</span><span class='hs-layout'>)</span> <span class='hs-conop'>:*:</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>empty</span><span class='hs-layout'>)</span>
<a name="line-139"></a>
<a name="line-140"></a><a name="linesStartingWithEndingWith"></a><span class='hs-comment'>-- | This is a highly optimized way to read lines that start with a</span>
<a name="line-141"></a><span class='hs-comment'>-- particular character, and stops when it reaches a particular |</span>
<a name="line-142"></a><span class='hs-comment'>-- character.  See 'linesStartingWith' for details on why this |</span>
<a name="line-143"></a><span class='hs-comment'>-- defined here as a primitive.</span>
<a name="line-144"></a><span class='hs-definition'>linesStartingWithEndingWith</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</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>
<a name="line-145"></a><span class='hs-definition'>linesStartingWithEndingWith</span> <span class='hs-varid'>st</span> <span class='hs-varid'>en</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-varop'>$</span> <span class='hs-varid'>linesStartingWithEndingWith'</span> <span class='hs-varid'>st</span> <span class='hs-varid'>en</span>
<a name="line-146"></a>
<a name="line-147"></a><a name="linesStartingWithEndingWith'"></a><span class='hs-comment'>-- | Helper function for 'linesStartingWithEndingWith'.</span>
<a name="line-148"></a><span class='hs-definition'>linesStartingWithEndingWith'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Char</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-149"></a>                             <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-conid'>ParserState</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-layout'>)</span>
<a name="line-150"></a><span class='hs-definition'>linesStartingWithEndingWith'</span> <span class='hs-varid'>st</span> <span class='hs-varid'>en</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>lswew</span> <span class='hs-varid'>s</span>
<a name="line-151"></a>    <span class='hs-keyword'>where</span>
<a name="line-152"></a>  <span class='hs-varid'>lswew</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>null</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Nothing</span>
<a name="line-153"></a>  <span class='hs-varid'>lswew</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span>
<a name="line-154"></a>    <span class='hs-keyword'>if</span> <span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>head</span> <span class='hs-varid'>x</span> <span class='hs-varop'>==</span> <span class='hs-varid'>en</span>
<a name="line-155"></a>    <span class='hs-keyword'>then</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>[]</span> <span class='hs-conop'>:*:</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>tail</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
<a name="line-156"></a>    <span class='hs-keyword'>else</span> <span class='hs-keyword'>if</span> <span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>head</span> <span class='hs-varid'>x</span> <span class='hs-varop'>/=</span> <span class='hs-varid'>st</span>
<a name="line-157"></a>         <span class='hs-keyword'>then</span> <span class='hs-conid'>Nothing</span>
<a name="line-158"></a>         <span class='hs-keyword'>else</span> <span class='hs-keyword'>case</span> <span class='hs-conid'>BC</span><span class='hs-varop'>.</span><span class='hs-varid'>break</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varop'>==</span><span class='hs-layout'>)</span> <span class='hs-chr'>'\n'</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>tail</span> <span class='hs-varid'>x</span> <span class='hs-keyword'>of</span>
<a name="line-159"></a>              <span class='hs-layout'>(</span><span class='hs-varid'>l</span><span class='hs-layout'>,</span><span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>lswew</span> <span class='hs-varop'>$</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>tail</span> <span class='hs-varid'>r</span> <span class='hs-keyword'>of</span>
<a name="line-160"></a>                       <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>ls</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>r'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varid'>l</span><span class='hs-conop'>:</span><span class='hs-varid'>ls</span><span class='hs-layout'>)</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>r'</span><span class='hs-layout'>)</span>
<a name="line-161"></a>                       <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-162"></a>                           <span class='hs-keyword'>case</span> <span class='hs-varid'>breakLastPS</span> <span class='hs-varid'>en</span> <span class='hs-varid'>l</span> <span class='hs-keyword'>of</span>
<a name="line-163"></a>                           <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>l2</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-164"></a>                               <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>[</span><span class='hs-varid'>l2</span><span class='hs-keyglyph'>]</span> <span class='hs-conop'>:*:</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>drop</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>length</span> <span class='hs-varid'>l2</span><span class='hs-varop'>+</span><span class='hs-num'>2</span><span class='hs-layout'>)</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
<a name="line-165"></a>                           <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span>
<a name="line-166"></a>
<a name="line-167"></a>
<a name="line-168"></a><a name="alterInput"></a><span class='hs-comment'>-- | Applies a function to the input stream and discards the</span>
<a name="line-169"></a><span class='hs-comment'>-- result of the function.</span>
<a name="line-170"></a><span class='hs-definition'>alterInput</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span>
<a name="line-171"></a>            <span class='hs-keyglyph'>=&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-conid'>()</span>
<a name="line-172"></a><span class='hs-definition'>alterInput</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>work</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>()</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>f</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-173"></a>
<a name="line-174"></a><a name="option"></a><span class='hs-comment'>-- | If @p@ fails it returns @x@, otherwise it returns the result of @p@.</span>
<a name="line-175"></a><span class='hs-definition'>option</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Alternative</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>f</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>f</span> <span class='hs-varid'>a</span>
<a name="line-176"></a><span class='hs-definition'>option</span> <span class='hs-varid'>x</span> <span class='hs-varid'>p</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>p</span> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>pure</span> <span class='hs-varid'>x</span>
<a name="line-177"></a>
<a name="line-178"></a><a name="choice"></a><span class='hs-comment'>-- | Attempts each option until one succeeds.</span>
<a name="line-179"></a><span class='hs-definition'>choice</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Alternative</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>f</span> <span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>f</span> <span class='hs-varid'>a</span>
<a name="line-180"></a><span class='hs-definition'>choice</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>foldr</span> <span class='hs-layout'>(</span><span class='hs-varop'>&lt;|&gt;</span><span class='hs-layout'>)</span> <span class='hs-varid'>empty</span>
<a name="line-181"></a>
<a name="line-182"></a><a name="checkConsumes"></a><span class='hs-comment'>-- |Ensure that a parser consumes input when producing a result</span>
<a name="line-183"></a><span class='hs-comment'>-- Causes the initial state of the input stream to be held on to while the</span>
<a name="line-184"></a><span class='hs-comment'>-- parser runs, so use with caution.</span>
<a name="line-185"></a><span class='hs-definition'>checkConsumes</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>m</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-varid'>a</span>
<a name="line-186"></a><span class='hs-definition'>checkConsumes</span> <span class='hs-varid'>parser</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-187"></a>   <span class='hs-varid'>x</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>length</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>peekInput</span>
<a name="line-188"></a>   <span class='hs-varid'>res</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>parser</span>
<a name="line-189"></a>   <span class='hs-varid'>x'</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-varid'>length</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>peekInput</span>
<a name="line-190"></a>   <span class='hs-keyword'>if</span> <span class='hs-varid'>x'</span> <span class='hs-varop'>&lt;</span> <span class='hs-varid'>x</span> <span class='hs-keyword'>then</span> <span class='hs-varid'>return</span> <span class='hs-varid'>res</span> <span class='hs-keyword'>else</span> <span class='hs-varid'>mzero</span>
<a name="line-191"></a>
<a name="line-192"></a><a name="ParserM"></a><span class='hs-keyword'>class</span> <span class='hs-layout'>(</span><span class='hs-conid'>Functor</span> <span class='hs-varid'>m</span><span class='hs-layout'>,</span> <span class='hs-conid'>Applicative</span> <span class='hs-varid'>m</span><span class='hs-layout'>,</span> <span class='hs-conid'>Alternative</span> <span class='hs-varid'>m</span><span class='hs-layout'>,</span> <span class='hs-conid'>Monad</span> <span class='hs-varid'>m</span><span class='hs-layout'>,</span> <span class='hs-conid'>MonadPlus</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>ParserM</span> <span class='hs-varid'>m</span> <span class='hs-keyword'>where</span>
<a name="line-193"></a>    <span class='hs-comment'>-- | Applies a parsing function inside the 'ParserM' monad.</span>
<a name="line-194"></a>    <span class='hs-varid'>work</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-conid'>ParserState</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-varid'>a</span>
<a name="line-195"></a>    <span class='hs-comment'>-- | Applies a parsing function, that can return 'Nothing',</span>
<a name="line-196"></a>    <span class='hs-comment'>-- inside the 'ParserM' monad.</span>
<a name="line-197"></a>    <span class='hs-varid'>maybeWork</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-conid'>ParserState</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>m</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-198"></a>    <span class='hs-comment'>-- | Allows for the inspection of the input that is yet to be parsed.</span>
<a name="line-199"></a>    <span class='hs-varid'>peekInput</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>m</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-200"></a>    <span class='hs-comment'>-- | Run the parser</span>
<a name="line-201"></a>    <span class='hs-varid'>parse</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>m</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</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-202"></a>
<a name="line-203"></a><a name="parseStrictly"></a><span class='hs-comment'>----- Strict Monad -----</span>
<a name="line-204"></a><span class='hs-comment'>-- | 'parseStrictly' applies the parser functions to a string</span>
<a name="line-205"></a><span class='hs-comment'>-- and checks that each parser produced a result as it goes.</span>
<a name="line-206"></a><span class='hs-comment'>-- The strictness is in the 'ParserM' instance for 'SM'.</span>
<a name="line-207"></a><span class='hs-definition'>parseStrictly</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>SM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</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-208"></a><span class='hs-definition'>parseStrictly</span> <span class='hs-layout'>(</span><span class='hs-conid'>SM</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>f</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-209"></a>  <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span>
<a name="line-210"></a>  <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span>
<a name="line-211"></a>
<a name="line-212"></a><a name="ParserState"></a><span class='hs-comment'>-- | ParserState represents the internal state of the parser.  We make it</span>
<a name="line-213"></a><a name="ParserState"></a><span class='hs-comment'>-- strict and specialize it on ByteString.  This is purely to help GHC</span>
<a name="line-214"></a><a name="ParserState"></a><span class='hs-comment'>-- optimize.  If performance were not a concern, it could be replaced</span>
<a name="line-215"></a><a name="ParserState"></a><span class='hs-comment'>-- with @(a, ByteString)@.</span>
<a name="line-216"></a><a name="ParserState"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>ParserState</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-varop'>!</span><span class='hs-varid'>a</span> <span class='hs-conop'>:*:</span> <span class='hs-varop'>!</span><span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-217"></a>
<a name="line-218"></a><a name="stuple"></a><span class='hs-comment'>-- | Convert from a lazy tuple to a strict tuple.</span>
<a name="line-219"></a><span class='hs-definition'>stuple</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ParserState</span> <span class='hs-varid'>a</span>
<a name="line-220"></a><span class='hs-definition'>stuple</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>b</span>
<a name="line-221"></a>
<a name="line-222"></a><a name="SM"></a><span class='hs-comment'>-- | 'SM' is the Strict Monad for parsing.</span>
<a name="line-223"></a><a name="SM"></a><span class='hs-keyword'>newtype</span> <span class='hs-conid'>SM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>SM</span> <span class='hs-layout'>(</span><span class='hs-conid'>B</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-layout'>(</span><span class='hs-conid'>ParserState</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-224"></a>
<a name="line-225"></a><a name="bindSM"></a><span class='hs-definition'>bindSM</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>SM</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>SM</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>SM</span> <span class='hs-varid'>b</span>
<a name="line-226"></a><span class='hs-definition'>bindSM</span> <span class='hs-layout'>(</span><span class='hs-conid'>SM</span> <span class='hs-varid'>m</span><span class='hs-layout'>)</span> <span class='hs-varid'>k</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>SM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>m</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-227"></a>                             <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span>
<a name="line-228"></a>                             <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-229"></a>                               <span class='hs-keyword'>case</span> <span class='hs-varid'>k</span> <span class='hs-varid'>x</span> <span class='hs-keyword'>of</span>
<a name="line-230"></a>                               <span class='hs-conid'>SM</span> <span class='hs-varid'>y</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>y</span> <span class='hs-varid'>s'</span>
<a name="line-231"></a><a name="returnSM"></a><span class='hs-comment'>{-# INLINE bindSM #-}</span>
<a name="line-232"></a><span class='hs-definition'>returnSM</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>SM</span> <span class='hs-varid'>a</span>
<a name="line-233"></a><span class='hs-definition'>returnSM</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>SM</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-234"></a><a name="failSM"></a><span class='hs-comment'>{-# INLINE returnSM #-}</span>
<a name="line-235"></a><span class='hs-definition'>failSM</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>SM</span> <span class='hs-varid'>a</span>
<a name="line-236"></a><span class='hs-definition'>failSM</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>SM</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>\</span><span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span><span class='hs-layout'>)</span>
<a name="line-237"></a><span class='hs-comment'>{-# INLINE failSM #-}</span>
<a name="line-238"></a>
<a name="line-239"></a><a name="instance%20Monad%20SM"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Monad</span> <span class='hs-conid'>SM</span> <span class='hs-keyword'>where</span>
<a name="line-240"></a>    <span class='hs-layout'>(</span><span class='hs-varop'>&gt;&gt;=</span><span class='hs-layout'>)</span>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>bindSM</span>
<a name="line-241"></a>    <span class='hs-varid'>return</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>returnSM</span>
<a name="line-242"></a>    <span class='hs-varid'>fail</span>   <span class='hs-keyglyph'>=</span> <span class='hs-varid'>failSM</span>
<a name="line-243"></a>
<a name="line-244"></a><a name="instance%20ParserM%20SM"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ParserM</span> <span class='hs-conid'>SM</span> <span class='hs-keyword'>where</span>
<a name="line-245"></a>    <span class='hs-varid'>work</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>SM</span> <span class='hs-varid'>f</span>
<a name="line-246"></a>    <span class='hs-varid'>maybeWork</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>SM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>f</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-247"></a>                                  <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>x</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s'</span><span class='hs-layout'>)</span>
<a name="line-248"></a>                                  <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>Nothing</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
<a name="line-249"></a>    <span class='hs-varid'>peekInput</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>SM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-varid'>s</span> <span class='hs-conop'>:*:</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
<a name="line-250"></a>    <span class='hs-varid'>parse</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>parseStrictly</span>
<a name="line-251"></a>
<a name="line-252"></a><a name="instance%20MonadPlus%20SM"></a><span class='hs-comment'>-- The following instances allow us to use more conventional</span>
<a name="line-253"></a><a name="instance%20MonadPlus%20SM"></a><span class='hs-comment'>-- interfaces provided by other parser libraries. The instances are</span>
<a name="line-254"></a><a name="instance%20MonadPlus%20SM"></a><span class='hs-comment'>-- defined using bindSM, returnSM, and failSM to avoid any infinite,</span>
<a name="line-255"></a><a name="instance%20MonadPlus%20SM"></a><span class='hs-comment'>-- or even unneccessary, recursion of instances between between</span>
<a name="line-256"></a><a name="instance%20MonadPlus%20SM"></a><span class='hs-comment'>-- ParserM and Monad.  Other recursive uses will be fine, such as</span>
<a name="line-257"></a><a name="instance%20MonadPlus%20SM"></a><span class='hs-comment'>-- (&lt;|&gt;) = mplus.</span>
<a name="line-258"></a><a name="instance%20MonadPlus%20SM"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>MonadPlus</span> <span class='hs-conid'>SM</span> <span class='hs-keyword'>where</span>
<a name="line-259"></a>  <span class='hs-varid'>mzero</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>failSM</span> <span class='hs-str'>""</span>
<a name="line-260"></a>  <span class='hs-comment'>-- | Over using mplus can lead to space leaks.  It's best to push</span>
<a name="line-261"></a>  <span class='hs-comment'>-- the use of mplus as far down as possible, because until the the</span>
<a name="line-262"></a>  <span class='hs-comment'>-- first parameter completes, we must hold on to the input.</span>
<a name="line-263"></a>  <span class='hs-varid'>mplus</span> <span class='hs-layout'>(</span><span class='hs-conid'>SM</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>SM</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>SM</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-264"></a>    <span class='hs-keyword'>case</span> <span class='hs-varid'>a</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
<a name="line-265"></a>      <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>b</span> <span class='hs-varid'>s</span>
<a name="line-266"></a>      <span class='hs-varid'>r</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>r</span>
<a name="line-267"></a>
<a name="line-268"></a><a name="instance%20Functor%20SM"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Functor</span> <span class='hs-conid'>SM</span> <span class='hs-keyword'>where</span>
<a name="line-269"></a>  <span class='hs-varid'>fmap</span> <span class='hs-varid'>f</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>m</span> <span class='hs-varop'>`bindSM`</span> <span class='hs-layout'>(</span><span class='hs-varid'>returnSM</span> <span class='hs-varop'>.</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span>
<a name="line-270"></a>
<a name="line-271"></a><a name="instance%20Applicative%20SM"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Applicative</span> <span class='hs-conid'>SM</span> <span class='hs-keyword'>where</span>
<a name="line-272"></a>  <span class='hs-varid'>pure</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>returnSM</span>
<a name="line-273"></a>  <span class='hs-varid'>a</span> <span class='hs-varop'>&lt;*&gt;</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span>
<a name="line-274"></a>    <span class='hs-varid'>a</span> <span class='hs-varop'>`bindSM`</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>c</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-275"></a>    <span class='hs-varid'>b</span> <span class='hs-varop'>`bindSM`</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>d</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-276"></a>    <span class='hs-varid'>returnSM</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span> <span class='hs-varid'>d</span><span class='hs-layout'>)</span>
<a name="line-277"></a>
<a name="line-278"></a><a name="instance%20Alternative%20SM"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Alternative</span> <span class='hs-conid'>SM</span> <span class='hs-keyword'>where</span>
<a name="line-279"></a>  <span class='hs-varid'>empty</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>failSM</span> <span class='hs-str'>""</span>
<a name="line-280"></a>  <span class='hs-layout'>(</span><span class='hs-varop'>&lt;|&gt;</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mplus</span>
</pre></body>
</html>