packages feed

polyparse-1.0: docs/haddock/src/Text/ParserCombinators/PolyStateLazy.html

<pre><font color=Green><u>module</u></font> Text<font color=Cyan>.</font>ParserCombinators<font color=Cyan>.</font>PolyStateLazy
  <font color=Cyan>(</font> <font color=Blue>-- * The Parser datatype.</font>
    <font color=Blue>-- $parser</font>
    Parser<font color=Cyan>(</font>P<font color=Cyan>)</font>	<font color=Blue>-- datatype, instance of: Functor, Monad</font>
  <font color=Cyan>,</font> runParser	<font color=Blue>-- :: Parser s t a -&gt; s -&gt; [t] -&gt; (a, s, [t])</font>
  <font color=Cyan>,</font> failBad	<font color=Blue>-- :: String -&gt; Parser s t a</font>
  <font color=Cyan>,</font> commit	<font color=Blue>-- :: Parser s t a -&gt; Parser s t a</font>
    <font color=Blue>-- * Combinators:</font>
    <font color=Blue>-- ** Primitives</font>
  <font color=Cyan>,</font> next	<font color=Blue>-- :: Parser s t t</font>
  <font color=Cyan>,</font> satisfy	<font color=Blue>-- :: (t-&gt;Bool) -&gt; Parser s t t</font>
  <font color=Cyan>,</font> apply	<font color=Blue>-- :: Parser t (a-&gt;b) -&gt; Parser s t a -&gt; Parser s t b</font>
  <font color=Cyan>,</font> discard	<font color=Blue>-- :: Parser s t a -&gt; Parser s t b -&gt; Parser s t a</font>
    <font color=Blue>-- ** Error-handling</font>
  <font color=Cyan>,</font> adjustErr	<font color=Blue>-- :: Parser s t a -&gt; (String-&gt;String) -&gt; Parser s t a</font>
  <font color=Cyan>,</font> adjustErrBad<font color=Blue>-- :: Parser s t a -&gt; (String-&gt;String) -&gt; Parser s t a</font>
  <font color=Cyan>,</font> indent	<font color=Blue>-- :: Int -&gt; String -&gt; String</font>
    <font color=Blue>-- ** Choices</font>
  <font color=Cyan>,</font> onFail	<font color=Blue>-- :: Parser s t a -&gt; Parser s t a -&gt; Parser s t a</font>
  <font color=Cyan>,</font> oneOf	<font color=Blue>-- :: [Parser s t a] -&gt; Parser s t a</font>
  <font color=Cyan>,</font> oneOf'	<font color=Blue>-- :: [(String, Parser s t a)] -&gt; Parser s t a</font>
  <font color=Cyan>,</font> optional	<font color=Blue>-- :: Parser s t a -&gt; Parser s t (Maybe a)</font>
    <font color=Blue>-- ** Sequences</font>
  <font color=Cyan>,</font> many	<font color=Blue>-- :: Parser s t a -&gt; Parser s t [a]</font>
  <font color=Cyan>,</font> many1	<font color=Blue>-- :: Parser s t a -&gt; Parser s t [a]</font>
  <font color=Cyan>,</font> sepBy	<font color=Blue>-- :: Parser s t a -&gt; Parser s t sep -&gt; Parser s t [a]</font>
  <font color=Cyan>,</font> sepBy1	<font color=Blue>-- :: Parser s t a -&gt; Parser s t sep -&gt; Parser s t [a]</font>
  <font color=Cyan>,</font> bracketSep	<font color=Blue>-- :: Parser s t bra -&gt; Parser s t sep -&gt; Parser s t ket</font>
                <font color=Blue>--    -&gt; Parser s t a -&gt; Parser s t [a]</font>
  <font color=Cyan>,</font> bracket	<font color=Blue>-- :: Parser s t bra -&gt; Parser s t ket -&gt; Parser s t a</font>
                <font color=Blue>--    -&gt; Parser s t a</font>
  <font color=Cyan>,</font> manyFinally	<font color=Blue>-- :: Parser s t a -&gt; Parser s t z -&gt; Parser s t [a]</font>
    <font color=Blue>-- ** State-handling</font>
  <font color=Cyan>,</font> stUpdate	<font color=Blue>-- :: (s-&gt;s) -&gt; Parser s t ()</font>
  <font color=Cyan>,</font> stQuery	<font color=Blue>-- :: (s-&gt;a) -&gt; Parser s t a</font>
  <font color=Cyan>,</font> stGet	<font color=Blue>-- :: Parser s t s</font>
    <font color=Blue>-- ** Re-parsing</font>
  <font color=Cyan>,</font> reparse	<font color=Blue>-- :: [t] -&gt; Parser s t ()</font>
  <font color=Cyan>)</font> <font color=Green><u>where</u></font>

<font color=Cyan>#</font><font color=Green><u>if</u></font> <b><font color=Magenta>__GLASGOW_HASKELL__</font></b>
<font color=Green><u>import</u></font> Control<font color=Cyan>.</font>Exception hiding <font color=Cyan>(</font>bracket<font color=Cyan>)</font>
throwE <font color=Red>::</font> String <font color=Red>-&gt;</font> a
<a name="throwE"></a>throwE msg <font color=Red>=</font> throw <font color=Cyan>(</font>ErrorCall msg<font color=Cyan>)</font>
<font color=Cyan>#</font><font color=Green><u>else</u></font>
throwE <font color=Red>::</font> String <font color=Red>-&gt;</font> a
throwE msg <font color=Red>=</font> error msg
<font color=Cyan>#</font>endif

<font color=Blue>-- $parser</font>
<font color=Blue>-- Parsers do not return explicit failure.  An exception is raised</font>
<font color=Blue>-- instead.  This allows partial results to be returned before a</font>
<font color=Blue>-- full parse is complete.</font>

<font color=Blue>-- | The @Parser@ datatype is a fairly generic parsing monad with error</font>
<font color=Blue>--   reporting and a running state.  It can be used for arbitrary token</font>
<font color=Blue>--   types, not just String input.</font>
<font color=Green><u>newtype</u></font> Parser s t a <font color=Red>=</font> P <font color=Cyan>(</font>s <font color=Red>-&gt;</font> <font color=Red>[</font>t<font color=Red>]</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Either String a<font color=Cyan>,</font> s<font color=Cyan>,</font> <font color=Red>[</font>t<font color=Red>]</font><font color=Cyan>)</font><font color=Cyan>)</font>

<font color=Blue>-- | A return type like Either, that distinguishes not only between</font>
<font color=Blue>--   right and wrong answers, but also had gradations of wrongness.</font>
<font color=Blue>--   Not used in this library.  !!!!!!!!!!!!!!!!!!!!!!!!!!</font>
<a name="EitherE"></a><font color=Green><u>type</u></font> EitherE a b <font color=Red>=</font> Either <font color=Cyan>(</font>Bool<font color=Cyan>,</font>a<font color=Cyan>)</font> b

<font color=Blue>-- | Apply a parser to an initial state and input token sequence.</font>
<font color=Blue>--   The parser cannot return an error value explicitly, so errors</font>
<font color=Blue>--   raise an exception.  Thus, results can be partial (lazily constructed,</font>
<font color=Blue>--   but containing undefined).</font>
runParser <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> s <font color=Red>-&gt;</font> <font color=Red>[</font>t<font color=Red>]</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>a<font color=Cyan>,</font> s<font color=Cyan>,</font> <font color=Red>[</font>t<font color=Red>]</font><font color=Cyan>)</font>
<a name="runParser"></a>runParser <font color=Cyan>(</font>P p<font color=Cyan>)</font> s <font color=Red>=</font>
    <font color=Cyan>(</font><font color=Red>\</font> <font color=Cyan>(</font>e<font color=Cyan>,</font>s<font color=Cyan>,</font>ts<font color=Cyan>)</font><font color=Red>-&gt;</font> <font color=Cyan>(</font><font color=Green><u>case</u></font> e <font color=Green><u>of</u></font> <font color=Cyan>{</font>Left m<font color=Red>-&gt;</font>throwE m<font color=Cyan>;</font> Right x<font color=Red>-&gt;</font>x<font color=Cyan>}</font><font color=Cyan>,</font> s<font color=Cyan>,</font> ts<font color=Cyan>)</font><font color=Cyan>)</font>
    <font color=Cyan>.</font> p s

<font color=Green><u>instance</u></font> Functor <font color=Cyan>(</font>Parser s t<font color=Cyan>)</font> <font color=Green><u>where</u></font>
    fmap f <font color=Cyan>(</font>P p<font color=Cyan>)</font> <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> p s ts <font color=Green><u>of</u></font>
                                <font color=Cyan>(</font>Left msg<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left msg<font color=Cyan>,</font>    s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font>
                                <font color=Cyan>(</font>Right x<font color=Cyan>,</font>  s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Right <font color=Cyan>(</font>f x<font color=Cyan>)</font><font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font><font color=Cyan>)</font>
<font color=Green><u>instance</u></font> Monad <font color=Cyan>(</font>Parser s t<font color=Cyan>)</font> <font color=Green><u>where</u></font>
    return x     <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Cyan>(</font>Right x<font color=Cyan>,</font> s<font color=Cyan>,</font> ts<font color=Cyan>)</font><font color=Cyan>)</font>
    <font color=Cyan>(</font>P f<font color=Cyan>)</font> <font color=Cyan>&gt;&gt;=</font> g  <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> f s ts <font color=Green><u>of</u></font>
                                <font color=Cyan>(</font>Left msg<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left msg<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font>
                                <font color=Cyan>(</font>Right x<font color=Cyan>,</font>  s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>P g'<font color=Cyan>)</font> <font color=Red>=</font> g x
                                                       <font color=Green><u>in</u></font> g' s' ts'<font color=Cyan>)</font>
    fail msg     <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Cyan>(</font>Left msg<font color=Cyan>,</font> s<font color=Cyan>,</font> ts<font color=Cyan>)</font><font color=Cyan>)</font>

<font color=Blue>-- | Simple failure can be corrected, but when a simple fail is not strong</font>
<font color=Blue>--   enough, use failBad for emphasis.  It guarantees parsing will terminate</font>
<font color=Blue>--   with an exception.</font>
failBad <font color=Red>::</font> String <font color=Red>-&gt;</font> Parser s t a
<a name="failBad"></a>failBad msg      <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Cyan>(</font>throwE msg<font color=Cyan>,</font> s<font color=Cyan>,</font> ts<font color=Cyan>)</font><font color=Cyan>)</font>

<font color=Blue>-- | Commit is a way of raising the severity of any errors found within</font>
<font color=Blue>--   its argument.  Used in the middle of a parser definition, it means that</font>
<font color=Blue>--   any operations prior to commitment fail softly, but after commitment,</font>
<font color=Blue>--   they fail hard.</font>
commit <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t a
<a name="commit"></a>commit <font color=Cyan>(</font>P p<font color=Cyan>)</font> <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> p s ts <font color=Green><u>of</u></font>
                            <font color=Cyan>(</font>Left e<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>throwE e<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font>
                            right             <font color=Red>-&gt;</font> right <font color=Cyan>)</font>

<font color=Blue>-- Combinators</font>

<font color=Blue>-- | One token</font>
next <font color=Red>::</font> Parser s t t
<a name="next"></a>next <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> ts <font color=Green><u>of</u></font>
                    <font color=Red>[</font><font color=Red>]</font>  <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left <font color=Magenta>"Ran out of input (EOF)"</font><font color=Cyan>,</font> s<font color=Cyan>,</font> <font color=Red>[</font><font color=Red>]</font><font color=Cyan>)</font>
                    <font color=Cyan>(</font>t<font color=Red><b>:</b></font>ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Right t<font color=Cyan>,</font> s<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Cyan>)</font>

<font color=Blue>-- | One token satifying a predicate</font>
satisfy <font color=Red>::</font> <font color=Cyan>(</font>t<font color=Red>-&gt;</font>Bool<font color=Cyan>)</font> <font color=Red>-&gt;</font> Parser s t t
<a name="satisfy"></a>satisfy p <font color=Red>=</font> <font color=Green><u>do</u></font><font color=Cyan>{</font> x <font color=Red>&lt;-</font> next
              <font color=Cyan>;</font> <font color=Green><u>if</u></font> p x <font color=Green><u>then</u></font> return x <font color=Green><u>else</u></font> fail <font color=Magenta>"Parse.satisfy: failed"</font>
              <font color=Cyan>}</font>

<font color=Green><u>infixl</u></font> <font color=Magenta>3</font> <font color=Cyan>`apply`</font>
<font color=Blue>-- | Apply a parsed function to a parsed value</font>
apply <font color=Red>::</font> Parser s t <font color=Cyan>(</font>a<font color=Red>-&gt;</font>b<font color=Cyan>)</font> <font color=Red>-&gt;</font> Parser s t a <font color=Red>-&gt;</font> Parser s t b
<font color=Blue>--pf `apply` px = do { f &lt;- pf; x &lt;- px; return (f x) }</font>
<font color=Blue>-- Needs to be lazier!  Must not force the argument value too early.</font>
<a name="apply"></a><font color=Cyan>(</font>P pf<font color=Cyan>)</font> <font color=Cyan>`apply`</font> <font color=Cyan>(</font>P px<font color=Cyan>)</font> <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font>
    <font color=Green><u>case</u></font> pf s ts <font color=Green><u>of</u></font>
      <font color=Cyan>(</font>Left msg<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left msg<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font>
      <font color=Cyan>(</font>Right f<font color=Cyan>,</font>  s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>x'<font color=Cyan>,</font>s''<font color=Cyan>,</font>ts''<font color=Cyan>)</font> <font color=Red>=</font> px s' ts'
                                 x <font color=Red>=</font> <font color=Green><u>case</u></font> x' <font color=Green><u>of</u></font>
                                         Right x <font color=Red>-&gt;</font> x
                                         Left e  <font color=Red>-&gt;</font> throwE e
                             <font color=Green><u>in</u></font> <font color=Cyan>(</font>Right <font color=Cyan>(</font>f x<font color=Cyan>)</font><font color=Cyan>,</font> s''<font color=Cyan>,</font> ts''<font color=Cyan>)</font><font color=Cyan>)</font>

<font color=Green><u>infixl</u></font> <font color=Magenta>3</font> <font color=Cyan>`discard`</font>
<font color=Blue>-- | @x `discard` y@ parses both x and y, but discards the result of y</font>
discard <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t b <font color=Red>-&gt;</font> Parser s t a
<a name="discard"></a>px <font color=Cyan>`discard`</font> py <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> x <font color=Red>&lt;-</font> px<font color=Cyan>;</font> <font color=Green><u>_</u></font> <font color=Red>&lt;-</font> py<font color=Cyan>;</font> return x <font color=Cyan>}</font>

<font color=Blue>-- | @p `adjustErr` f@ applies the transformation @f@ to any error message</font>
<font color=Blue>--   generated in @p@, having no effect if @p@ succeeds.</font>
adjustErr <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> <font color=Cyan>(</font>String<font color=Red>-&gt;</font>String<font color=Cyan>)</font> <font color=Red>-&gt;</font> Parser s t a
<a name="adjustErr"></a><font color=Cyan>(</font>P p<font color=Cyan>)</font> <font color=Cyan>`adjustErr`</font> f <font color=Red>=</font>
        P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> p s ts <font color=Green><u>of</u></font>
                     <font color=Cyan>(</font>Left msg<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left <font color=Cyan>(</font>f msg<font color=Cyan>)</font><font color=Cyan>,</font> s<font color=Cyan>,</font> ts'<font color=Cyan>)</font>
                     right               <font color=Red>-&gt;</font> right <font color=Cyan>)</font>

<font color=Blue>-- | @adjustErrBad@ is just like @adjustErr@ except it also raises the</font>
<font color=Blue>--   severity of the error.</font>
adjustErrBad <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> <font color=Cyan>(</font>String<font color=Red>-&gt;</font>String<font color=Cyan>)</font> <font color=Red>-&gt;</font> Parser s t a
<font color=Blue>-- p `adjustErrBad` f = commit (p `adjustErr` f)</font>
<a name="adjustErrBad"></a><font color=Cyan>(</font>P p<font color=Cyan>)</font> <font color=Cyan>`adjustErrBad`</font> f <font color=Red>=</font>
        P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> p s ts <font color=Green><u>of</u></font>
                     <font color=Cyan>(</font>Left msg<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>throwE <font color=Cyan>(</font>f msg<font color=Cyan>)</font><font color=Cyan>,</font> s<font color=Cyan>,</font> ts'<font color=Cyan>)</font>
                     right               <font color=Red>-&gt;</font> right <font color=Cyan>)</font>

<font color=Green><u>infixl</u></font> <font color=Magenta>6</font> <font color=Cyan>`onFail`</font>	<font color=Blue>-- not sure about precedence 6?</font>
<font color=Blue>-- | @p `onFail` q@ means parse p unless p fails in which case parse q instead.</font>
<font color=Blue>--   Can be chained together to give multiple attempts to parse something.</font>
<font color=Blue>--   (Note that q could itself be a failing parser, e.g. to change the error</font>
<font color=Blue>--   message from that defined in p to something different.)</font>
<font color=Blue>--   However, a *severe* failure in p cannot be ignored.</font>
onFail <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t a <font color=Red>-&gt;</font> Parser s t a
<a name="onFail"></a><font color=Cyan>(</font>P p<font color=Cyan>)</font> <font color=Cyan>`onFail`</font> <font color=Cyan>(</font>P q<font color=Cyan>)</font> <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> p s ts <font color=Green><u>of</u></font>
                                    <font color=Cyan>(</font>Left <font color=Green><u>_</u></font><font color=Cyan>,</font> <font color=Green><u>_</u></font><font color=Cyan>,</font> <font color=Green><u>_</u></font><font color=Cyan>)</font> <font color=Red>-&gt;</font> q s ts
                                    right          <font color=Red>-&gt;</font> right <font color=Cyan>)</font>

<font color=Blue>-- | Parse the first alternative in the list that succeeds.</font>
oneOf <font color=Red>::</font> <font color=Red>[</font>Parser s t a<font color=Red>]</font> <font color=Red>-&gt;</font> Parser s t a
<a name="oneOf"></a>oneOf <font color=Red>[</font><font color=Red>]</font>     <font color=Red>=</font> fail <font color=Cyan>(</font><font color=Magenta>"Failed to parse any of the possible choices"</font><font color=Cyan>)</font>
oneOf <font color=Cyan>(</font>p<font color=Red><b>:</b></font>ps<font color=Cyan>)</font> <font color=Red>=</font> p <font color=Cyan>`onFail`</font> oneOf ps

<font color=Blue>-- | Parse the first alternative that succeeds, but if none succeed,</font>
<font color=Blue>--   report only the severe errors, and if none of those, then report</font>
<font color=Blue>--   all the soft errors.</font>
oneOf' <font color=Red>::</font> <font color=Red>[</font><font color=Cyan>(</font>String<font color=Cyan>,</font> Parser s t a<font color=Cyan>)</font><font color=Red>]</font> <font color=Red>-&gt;</font> Parser s t a
<a name="oneOf'"></a>oneOf' ps <font color=Red>=</font> accum <font color=Red>[</font><font color=Red>]</font> ps
    <font color=Green><u>where</u></font> accum errs <font color=Red>[</font><font color=Red>]</font> <font color=Red>=</font>
              <font color=Green><u>case</u></font> errs <font color=Green><u>of</u></font>
                <font color=Red>[</font><font color=Red>]</font> <font color=Red>-&gt;</font> failBad <font color=Cyan>(</font><font color=Magenta>"internal failure in parser (oneOf'):\n"</font>
                              <font color=Cyan>++</font>indent <font color=Magenta>2</font> <font color=Cyan>(</font>show <font color=Cyan>(</font>map fst ps<font color=Cyan>)</font><font color=Cyan>)</font><font color=Cyan>)</font>
                <font color=Red>[</font><font color=Cyan>(</font><font color=Green><u>_</u></font><font color=Cyan>,</font>e<font color=Cyan>)</font><font color=Red>]</font> <font color=Red>-&gt;</font> fail e
                es <font color=Red>-&gt;</font> fail <font color=Cyan>(</font><font color=Magenta>"one of the following failures occurred:\n"</font>
                           <font color=Cyan>++</font>indent <font color=Magenta>2</font> <font color=Cyan>(</font>concatMap showErr <font color=Cyan>(</font>reverse es<font color=Cyan>)</font><font color=Cyan>)</font><font color=Cyan>)</font>
          accum errs <font color=Cyan>(</font><font color=Cyan>(</font>e<font color=Cyan>,</font>P p<font color=Cyan>)</font><font color=Red><b>:</b></font>ps<font color=Cyan>)</font> <font color=Red>=</font>
              P <font color=Cyan>(</font><font color=Red>\</font>u ts<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> p u ts <font color=Green><u>of</u></font>
                           <font color=Cyan>(</font>Left err<font color=Cyan>,</font><font color=Green><u>_</u></font><font color=Cyan>,</font><font color=Green><u>_</u></font><font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Green><u>let</u></font> <font color=Cyan>(</font>P p<font color=Cyan>)</font> <font color=Red>=</font> accum <font color=Cyan>(</font><font color=Cyan>(</font>e<font color=Cyan>,</font>err<font color=Cyan>)</font><font color=Red><b>:</b></font>errs<font color=Cyan>)</font> ps
                                             <font color=Green><u>in</u></font> p u ts
                           right          <font color=Red>-&gt;</font> right <font color=Cyan>)</font>
          showErr <font color=Cyan>(</font>name<font color=Cyan>,</font>err<font color=Cyan>)</font> <font color=Red>=</font> name<font color=Cyan>++</font><font color=Magenta>":\n"</font><font color=Cyan>++</font>indent <font color=Magenta>2</font> err

<font color=Blue>-- | Helper for formatting error messages: indents all lines by a fixed amount.</font>
indent <font color=Red>::</font> Int <font color=Red>-&gt;</font> String <font color=Red>-&gt;</font> String
<a name="indent"></a>indent n <font color=Red>=</font> unlines <font color=Cyan>.</font> map <font color=Cyan>(</font>replicate n <font color=Magenta>' '</font> <font color=Cyan>++</font><font color=Cyan>)</font> <font color=Cyan>.</font> lines

<font color=Blue>-- | 'optional' indicates whether the parser succeeded through the Maybe type.</font>
optional <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t <font color=Cyan>(</font>Maybe a<font color=Cyan>)</font>
<a name="optional"></a>optional p <font color=Red>=</font> fmap Just p <font color=Cyan>`onFail`</font> return Nothing

<font color=Blue>-- | 'many p' parses a list of elements with individual parser p.</font>
<font color=Blue>--   Cannot fail, since an empty list is a valid return value.</font>
many <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t <font color=Red>[</font>a<font color=Red>]</font>
<a name="many"></a>many p <font color=Red>=</font> many1 p <font color=Cyan>`onFail`</font> return <font color=Red>[</font><font color=Red>]</font>

<font color=Blue>-- | Parse a non-empty list of items.</font>
many1 <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t <font color=Red>[</font>a<font color=Red>]</font>
<a name="many1"></a>many1 p <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> x <font color=Red>&lt;-</font> p <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Cyan>(</font><font color=Magenta>"In a sequence:\n"</font><font color=Cyan>++</font><font color=Cyan>)</font><font color=Cyan>.</font> indent <font color=Magenta>2</font><font color=Cyan>)</font>
             <font color=Cyan>;</font> xs <font color=Red>&lt;-</font> many p
             <font color=Cyan>;</font> return <font color=Cyan>(</font>x<font color=Red><b>:</b></font>xs<font color=Cyan>)</font>
             <font color=Cyan>}</font>
<font color=Blue>--       `adjustErr` ("When looking for a non-empty sequence:\n"++)</font>

<font color=Blue>-- | Parse a list of items separated by discarded junk.</font>
sepBy <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t sep <font color=Red>-&gt;</font> Parser s t <font color=Red>[</font>a<font color=Red>]</font>
<a name="sepBy"></a>sepBy p sep <font color=Red>=</font> <font color=Green><u>do</u></font> sepBy1 p sep <font color=Cyan>`onFail`</font> return <font color=Red>[</font><font color=Red>]</font>

<font color=Blue>-- | Parse a non-empty list of items separated by discarded junk.</font>
sepBy1 <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t sep <font color=Red>-&gt;</font> Parser s t <font color=Red>[</font>a<font color=Red>]</font>
<a name="sepBy1"></a>sepBy1 p sep <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> x <font color=Red>&lt;-</font> p
                  <font color=Cyan>;</font> xs <font color=Red>&lt;-</font> many <font color=Cyan>(</font><font color=Green><u>do</u></font> <font color=Cyan>{</font>sep<font color=Cyan>;</font> p<font color=Cyan>}</font><font color=Cyan>)</font>
                  <font color=Cyan>;</font> return <font color=Cyan>(</font>x<font color=Red><b>:</b></font>xs<font color=Cyan>)</font>
                  <font color=Cyan>}</font>
         <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"When looking for a non-empty sequence with separators:\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
 
<font color=Blue>-- | Parse a list of items, discarding the start, end, and separator</font>
<font color=Blue>--   items.</font>
bracketSep <font color=Red>::</font> Parser s t bra <font color=Red>-&gt;</font> Parser s t sep <font color=Red>-&gt;</font> Parser s t ket
              <font color=Red>-&gt;</font> Parser s t a <font color=Red>-&gt;</font> Parser s t <font color=Red>[</font>a<font color=Red>]</font>
<a name="bracketSep"></a>bracketSep open sep close p <font color=Red>=</font>
    <font color=Green><u>do</u></font> <font color=Cyan>{</font> open<font color=Cyan>;</font> close<font color=Cyan>;</font> return <font color=Red>[</font><font color=Red>]</font> <font color=Cyan>}</font>
       <font color=Cyan>`onFail`</font>
    <font color=Green><u>do</u></font> <font color=Cyan>{</font> open    <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Missing opening bracket:\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
       <font color=Cyan>;</font> x <font color=Red>&lt;-</font> p  <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"After first bracket in a group:\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
       <font color=Cyan>;</font> xs <font color=Red>&lt;-</font> many <font color=Cyan>(</font><font color=Green><u>do</u></font> <font color=Cyan>{</font>sep<font color=Cyan>;</font> p<font color=Cyan>}</font><font color=Cyan>)</font>
       <font color=Cyan>;</font> close   <font color=Cyan>`adjustErrBad`</font> <font color=Cyan>(</font><font color=Magenta>"When looking for closing bracket:\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
       <font color=Cyan>;</font> return <font color=Cyan>(</font>x<font color=Red><b>:</b></font>xs<font color=Cyan>)</font>
       <font color=Cyan>}</font>

<font color=Blue>-- | Parse a bracketed item, discarding the brackets.</font>
bracket <font color=Red>::</font> Parser s t bra <font color=Red>-&gt;</font> Parser s t ket <font color=Red>-&gt;</font> Parser s t a <font color=Red>-&gt;</font> Parser s t a
<a name="bracket"></a>bracket open close p <font color=Red>=</font> <font color=Green><u>do</u></font>
    <font color=Green><u>do</u></font> <font color=Cyan>{</font> open    <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Missing opening bracket:\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
       <font color=Cyan>;</font> x <font color=Red>&lt;-</font> p
       <font color=Cyan>;</font> close   <font color=Cyan>`adjustErrBad`</font> <font color=Cyan>(</font><font color=Magenta>"Missing closing bracket:\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
       <font color=Cyan>;</font> return x
       <font color=Cyan>}</font>

<font color=Blue>-- | 'manyFinally e t' parses a possibly-empty sequence of e's,</font>
<font color=Blue>--   terminated by a t.  Any parse failures could be due either to</font>
<font color=Blue>--   a badly-formed terminator or a badly-formed element, so raise</font>
<font color=Blue>--   both possible errors.</font>
manyFinally <font color=Red>::</font> Parser s t a <font color=Red>-&gt;</font> Parser s t z <font color=Red>-&gt;</font> Parser s t <font color=Red>[</font>a<font color=Red>]</font>
<a name="manyFinally"></a>manyFinally pp<font color=Red>@</font><font color=Cyan>(</font>P p<font color=Cyan>)</font> pt<font color=Red>@</font><font color=Cyan>(</font>P t<font color=Cyan>)</font> <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts <font color=Red>-&gt;</font>
    <font color=Green><u>case</u></font> p s ts <font color=Green><u>of</u></font>
        <font color=Cyan>(</font>Left e<font color=Cyan>,</font> <font color=Green><u>_</u></font><font color=Cyan>,</font> <font color=Green><u>_</u></font><font color=Cyan>)</font> <font color=Red>-&gt;</font>
            <font color=Green><u>case</u></font> t s ts <font color=Green><u>of</u></font>
                <font color=Cyan>(</font>Right <font color=Green><u>_</u></font><font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Right <font color=Red>[</font><font color=Red>]</font><font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font>
                <font color=Cyan>(</font>Left e<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font>  <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left e<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font>
        <font color=Cyan>(</font>Right x<font color=Cyan>,</font> s'<font color=Cyan>,</font> ts'<font color=Cyan>)</font> <font color=Red>-&gt;</font>
            <font color=Green><u>let</u></font> <font color=Cyan>(</font>tail<font color=Cyan>,</font>s''<font color=Cyan>,</font>ts''<font color=Cyan>)</font> <font color=Red>=</font> runParser <font color=Cyan>(</font>manyFinally pp pt<font color=Cyan>)</font> s' ts'
            <font color=Green><u>in</u></font> <font color=Cyan>(</font>Right <font color=Cyan>(</font>x<font color=Red><b>:</b></font>tail<font color=Cyan>)</font><font color=Cyan>,</font> s''<font color=Cyan>,</font> ts''<font color=Cyan>)</font> <font color=Cyan>)</font>

<font color=Blue>------------------------------------------------------------------------</font>
<font color=Blue>-- State handling</font>

<font color=Blue>-- | Update the internal state.</font>
stUpdate   <font color=Red>::</font> <font color=Cyan>(</font>s<font color=Red>-&gt;</font>s<font color=Cyan>)</font> <font color=Red>-&gt;</font> Parser s t <font color=Cyan>(</font><font color=Cyan>)</font>
<a name="stUpdate"></a>stUpdate f  <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Cyan>(</font>Right <font color=Cyan>(</font><font color=Cyan>)</font><font color=Cyan>,</font> f s<font color=Cyan>,</font> ts<font color=Cyan>)</font><font color=Cyan>)</font>

<font color=Blue>-- | Query the internal state.</font>
stQuery    <font color=Red>::</font> <font color=Cyan>(</font>s<font color=Red>-&gt;</font>a<font color=Cyan>)</font> <font color=Red>-&gt;</font> Parser s t a
<a name="stQuery"></a>stQuery f   <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Cyan>(</font>Right <font color=Cyan>(</font>f s<font color=Cyan>)</font><font color=Cyan>,</font> s<font color=Cyan>,</font> ts<font color=Cyan>)</font><font color=Cyan>)</font>

<font color=Blue>-- | Deliver the entire internal state.</font>
stGet      <font color=Red>::</font> Parser s t s
<a name="stGet"></a>stGet       <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s ts<font color=Red>-&gt;</font> <font color=Cyan>(</font>Right s<font color=Cyan>,</font> s<font color=Cyan>,</font> ts<font color=Cyan>)</font><font color=Cyan>)</font>

<font color=Blue>------------------------------------------------------------------------</font>
<font color=Blue>-- | Push some tokens back onto the front of the input stream and reparse.</font>
<font color=Blue>--   This is useful e.g. for recursively expanding macros.  When the</font>
<font color=Blue>--   user-parser recognises a macro use, it can lookup the macro</font>
<font color=Blue>--   expansion from the parse state, lex it, and then stuff the</font>
<font color=Blue>--   lexed expansion back down into the parser.</font>
reparse    <font color=Red>::</font> <font color=Red>[</font>t<font color=Red>]</font> <font color=Red>-&gt;</font> Parser s t <font color=Cyan>(</font><font color=Cyan>)</font>
<a name="reparse"></a>reparse ts  <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s inp<font color=Red>-&gt;</font> <font color=Cyan>(</font>Right <font color=Cyan>(</font><font color=Cyan>)</font><font color=Cyan>,</font> s<font color=Cyan>,</font> ts<font color=Cyan>++</font>inp<font color=Cyan>)</font><font color=Cyan>)</font>

<font color=Blue>------------------------------------------------------------------------</font>
</pre>