packages feed

polyparse-1.1: docs/haddock/src/Text/ParserCombinators/Poly/Base.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<pre><a name="(line1)"></a><font color=Green><u>module</u></font> Text<font color=Cyan>.</font>ParserCombinators<font color=Cyan>.</font>Poly<font color=Cyan>.</font>Base
<a name="(line2)"></a>  <font color=Cyan>(</font> <font color=Blue>-- * The PolyParse class</font>
<a name="(line3)"></a>    PolyParse<font color=Cyan>(</font><font color=Red>..</font><font color=Cyan>)</font>	<font color=Blue>-- class of all monadic two-level-error parsers</font>
<a name="(line4)"></a>
<a name="(line5)"></a>    <font color=Blue>-- * Combinators general to all parser types.</font>
<a name="(line6)"></a>    <font color=Blue>-- ** Simple combinators</font>
<a name="(line7)"></a>  <font color=Cyan>,</font> discard	<font color=Blue>-- :: PolyParse p =&gt; p a -&gt; p b -&gt; p a</font>
<a name="(line8)"></a>    <font color=Blue>-- ** Error-handling</font>
<a name="(line9)"></a>  <font color=Cyan>,</font> failBad	<font color=Blue>-- :: PolyParse p =&gt; String -&gt; p a</font>
<a name="(line10)"></a>  <font color=Cyan>,</font> adjustErrBad<font color=Blue>-- :: PolyParse p =&gt; p a -&gt; (String-&gt;String) -&gt; p a</font>
<a name="(line11)"></a>  <font color=Cyan>,</font> indent	<font color=Blue>-- :: Int -&gt; String -&gt; String</font>
<a name="(line12)"></a>    <font color=Blue>-- ** Choices</font>
<a name="(line13)"></a>  <font color=Cyan>,</font> oneOf	<font color=Blue>-- :: PolyParse p =&gt; [p a] -&gt; p a</font>
<a name="(line14)"></a>  <font color=Cyan>,</font> optional	<font color=Blue>-- :: PolyParse p =&gt; p a -&gt; p (Maybe a)</font>
<a name="(line15)"></a>    <font color=Blue>-- ** Sequences</font>
<a name="(line16)"></a>  <font color=Cyan>,</font> exactly	<font color=Blue>-- :: PolyParse p =&gt; Int -&gt; p a -&gt; p [a]</font>
<a name="(line17)"></a>  <font color=Cyan>,</font> many	<font color=Blue>-- :: PolyParse p =&gt; p a -&gt; p [a]</font>
<a name="(line18)"></a>  <font color=Cyan>,</font> many1	<font color=Blue>-- :: PolyParse p =&gt; p a -&gt; p [a]</font>
<a name="(line19)"></a>  <font color=Cyan>,</font> sepBy	<font color=Blue>-- :: PolyParse p =&gt; p a -&gt; p sep -&gt; p [a]</font>
<a name="(line20)"></a>  <font color=Cyan>,</font> sepBy1	<font color=Blue>-- :: PolyParse p =&gt; p a -&gt; p sep -&gt; p [a]</font>
<a name="(line21)"></a>  <font color=Cyan>,</font> bracketSep	<font color=Blue>-- :: PolyParse p =&gt; p bra -&gt; p sep -&gt; p ket -&gt; p a -&gt; p [a]</font>
<a name="(line22)"></a>  <font color=Cyan>,</font> bracket	<font color=Blue>-- :: PolyParse p =&gt; p bra -&gt; p ket -&gt; p a -&gt; p a</font>
<a name="(line23)"></a>  <font color=Cyan>,</font> manyFinally <font color=Blue>-- :: PolyParse p =&gt; p a -&gt; p z -&gt; p [a]</font>
<a name="(line24)"></a>  <font color=Cyan>)</font> <font color=Green><u>where</u></font>
<a name="(line25)"></a>
<a name="(line26)"></a><a name="PolyParse"></a><font color=Blue>-- | The @PolyParse@ class is an abstraction over all the current</font>
<a name="(line27)"></a><a name="PolyParse"></a><font color=Blue>--   concrete representations of monadic parser combinators in this</font>
<a name="(line28)"></a><a name="PolyParse"></a><font color=Blue>--   package.  The common feature is two-level error-handling.</font>
<a name="(line29)"></a><a name="PolyParse"></a><font color=Blue>--   Some primitives must be implemented specific to each parser type</font>
<a name="(line30)"></a><a name="PolyParse"></a><font color=Blue>--   (e.g. depending on whether the parser has a running state, or</font>
<a name="(line31)"></a><a name="PolyParse"></a><font color=Blue>--   whether it is lazy).  But given those primitives, large numbers of</font>
<a name="(line32)"></a><a name="PolyParse"></a><font color=Blue>--   combinators do not depend any further on the internal structure of</font>
<a name="(line33)"></a><a name="PolyParse"></a><font color=Blue>--   the particular parser.</font>
<a name="(line34)"></a><a name="PolyParse"></a><font color=Blue>--</font>
<a name="(line35)"></a><a name="PolyParse"></a><font color=Blue>--   There are two additional basic combinators that we expect to be implemented</font>
<a name="(line36)"></a><a name="PolyParse"></a><font color=Blue>--   afresh for every concrete type, but which (for technical reasons)</font>
<a name="(line37)"></a><a name="PolyParse"></a><font color=Blue>--   cannot be class methods.  They are @next@ and @satisfy@.</font>
<a name="(line38)"></a><a name="PolyParse"></a><font color=Green><u>class</u></font> <font color=Cyan>(</font>Functor p<font color=Cyan>,</font> Monad p<font color=Cyan>)</font> <font color=Red>=&gt;</font> PolyParse p <font color=Green><u>where</u></font>
<a name="(line39)"></a>    <font color=Blue>-- | Commit is a way of raising the severity of any errors found within</font>
<a name="(line40)"></a>    <font color=Blue>--   its argument.  Used in the middle of a parser definition, it means that</font>
<a name="(line41)"></a>    <font color=Blue>--   any operations prior to commitment fail softly, but after commitment,</font>
<a name="(line42)"></a>    <font color=Blue>--   they fail hard.</font>
<a name="(line43)"></a>    commit    <font color=Red>::</font> p a <font color=Red>-&gt;</font> p a
<a name="(line44)"></a>    <font color=Blue>-- | @p `adjustErr` f@ applies the transformation @f@ to any error message</font>
<a name="(line45)"></a>    <font color=Blue>--   generated in @p@, having no effect if @p@ succeeds.</font>
<a name="(line46)"></a>    adjustErr <font color=Red>::</font> p 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> p a
<a name="(line47)"></a>    <font color=Blue>-- | @p `onFail` q@ means parse p, unless p fails, in which case</font>
<a name="(line48)"></a>    <font color=Blue>--   parse q instead.</font>
<a name="(line49)"></a>    <font color=Blue>--   Can be chained together to give multiple attempts to parse something.</font>
<a name="(line50)"></a>    <font color=Blue>--   (Note that q could itself be a failing parser, e.g. to change the error</font>
<a name="(line51)"></a>    <font color=Blue>--   message from that defined in p to something different.)</font>
<a name="(line52)"></a>    <font color=Blue>--   However, a severe failure in p cannot be ignored.</font>
<a name="(line53)"></a>    onFail    <font color=Red>::</font> p a <font color=Red>-&gt;</font> p a <font color=Red>-&gt;</font> p a
<a name="(line54)"></a>    <font color=Blue>-- | Parse the first alternative that succeeds, but if none succeed,</font>
<a name="(line55)"></a>    <font color=Blue>--   report only the severe errors, and if none of those, then report</font>
<a name="(line56)"></a>    <font color=Blue>--   all the soft errors.</font>
<a name="(line57)"></a>    oneOf'    <font color=Red>::</font> <font color=Red>[</font><font color=Cyan>(</font>String<font color=Cyan>,</font> p a<font color=Cyan>)</font><font color=Red>]</font> <font color=Red>-&gt;</font> p a
<a name="(line58)"></a>    <font color=Blue>-- | Apply a parsed function to a parsed value.</font>
<a name="(line59)"></a>    <font color=Blue>--   Rather like ordinary function application lifted into parsers.</font>
<a name="(line60)"></a>    apply     <font color=Red>::</font> p <font color=Cyan>(</font>a<font color=Red>-&gt;</font>b<font color=Cyan>)</font> <font color=Red>-&gt;</font> p a <font color=Red>-&gt;</font> p b
<a name="(line61)"></a>    pf <font color=Cyan>`apply`</font> px <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> f <font color=Red>&lt;-</font> pf<font color=Cyan>;</font> x <font color=Red>&lt;-</font> px<font color=Cyan>;</font> return <font color=Cyan>(</font>f x<font color=Cyan>)</font> <font color=Cyan>}</font>
<a name="(line62)"></a>      <font color=Blue>-- note: the Poly.Lazy variants override this defn with a lazier one.</font>
<a name="(line63)"></a>
<a name="(line64)"></a><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>
<a name="(line65)"></a><font color=Green><u>infixl</u></font> <font color=Magenta>3</font> <font color=Cyan>`apply`</font>
<a name="(line66)"></a><font color=Green><u>infixl</u></font> <font color=Magenta>3</font> <font color=Cyan>`discard`</font>
<a name="(line67)"></a>
<a name="(line68)"></a><font color=Blue>{-
<a name="(line69)"></a>-- Combinators we expect most concrete parser types to implement.
<a name="(line70)"></a>--   For technical reasons, they cannot be class members.
<a name="(line71)"></a>
<a name="(line72)"></a>-- | Yield the next token
<a name="(line73)"></a>next      :: PolyParse p =&gt; p t
<a name="(line74)"></a>  --  where t is constrained to be the input token type
<a name="(line75)"></a>
<a name="(line76)"></a>-- | One token satisfying a predicate.
<a name="(line77)"></a>satisfy :: PolyParse p =&gt; (t-&gt;Bool) -&gt; p t t
<a name="(line78)"></a>satisfy p = do{ x &lt;- next
<a name="(line79)"></a>              ; if p x then return x else fail "Parse.satisfy: failed"
<a name="(line80)"></a>              }
<a name="(line81)"></a>  -- note: must be re-defined for each implementation because
<a name="(line82)"></a>  --       its type cannot be expressed otherwise.
<a name="(line83)"></a>-}</font>
<a name="(line84)"></a>
<a name="(line85)"></a><a name="failBad"></a><font color=Blue>-- | When a simple fail is not strong enough, use failBad for emphasis.</font>
<a name="(line86)"></a><font color=Blue>--   An emphasised (severe) error cannot be overridden by choice</font>
<a name="(line87)"></a><font color=Blue>--   operators.</font>
<a name="(line88)"></a>failBad <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> String <font color=Red>-&gt;</font> p a
<a name="(line89)"></a>failBad e <font color=Red>=</font> commit <font color=Cyan>(</font>fail e<font color=Cyan>)</font>
<a name="(line90)"></a>
<a name="(line91)"></a><a name="discard"></a><font color=Blue>-- | @x `discard` y@ parses both x and y, but discards the result of y.</font>
<a name="(line92)"></a><font color=Blue>--   Rather like @const@ lifted into parsers.</font>
<a name="(line93)"></a>discard <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p a <font color=Red>-&gt;</font> p b <font color=Red>-&gt;</font> p a
<a name="(line94)"></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> return <font color=Cyan>(</font>const x<font color=Cyan>)</font> <font color=Cyan>`apply`</font> py<font color=Cyan>;</font> <font color=Cyan>}</font>
<a name="(line95)"></a>
<a name="(line96)"></a><a name="adjustErrBad"></a><font color=Blue>-- | @adjustErrBad@ is just like @adjustErr@ except it also raises the</font>
<a name="(line97)"></a><font color=Blue>--   severity of the error.</font>
<a name="(line98)"></a>adjustErrBad <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p 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> p a
<a name="(line99)"></a><a name="adjustErrBad"></a>p <font color=Cyan>`adjustErrBad`</font> f <font color=Red>=</font> commit <font color=Cyan>(</font>p <font color=Cyan>`adjustErr`</font> f<font color=Cyan>)</font>
<a name="(line100)"></a>
<a name="(line101)"></a><a name="oneOf"></a><font color=Blue>-- | Parse the first alternative in the list that succeeds.</font>
<a name="(line102)"></a>oneOf <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> <font color=Red>[</font>p a<font color=Red>]</font> <font color=Red>-&gt;</font> p a
<a name="(line103)"></a>oneOf []     <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>
<a name="(line104)"></a>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
<a name="(line105)"></a><font color=Blue>--oneOf :: Show t =&gt; [Parser t a] -&gt; Parser t a</font>
<a name="(line106)"></a><font color=Blue>--oneOf []     = do { n &lt;- next</font>
<a name="(line107)"></a><font color=Blue>--                  ; fail ("failed to parse any of the possible choices"</font>
<a name="(line108)"></a><font color=Blue>--                         ++"\n  next token is "++show n)</font>
<a name="(line109)"></a><font color=Blue>--                  }</font>
<a name="(line110)"></a><font color=Blue>--oneOf (p:ps) = p `onFail` oneOf ps</font>
<a name="(line111)"></a>
<a name="(line112)"></a><a name="indent"></a><font color=Blue>-- | Helper for formatting error messages: indents all lines by a fixed amount.</font>
<a name="(line113)"></a>indent <font color=Red>::</font> Int <font color=Red>-&gt;</font> String <font color=Red>-&gt;</font> String
<a name="(line114)"></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
<a name="(line115)"></a>
<a name="(line116)"></a><a name="optional"></a><font color=Blue>-- | 'optional' indicates whether the parser succeeded through the Maybe type.</font>
<a name="(line117)"></a>optional <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p a <font color=Red>-&gt;</font> p <font color=Cyan>(</font>Maybe a<font color=Cyan>)</font>
<a name="(line118)"></a>optional p <font color=Red>=</font> fmap Just p <font color=Cyan>`onFail`</font> return Nothing
<a name="(line119)"></a>
<a name="(line120)"></a><a name="exactly"></a><font color=Blue>-- | 'exactly n p' parses precisely n items, using the parser p, in sequence.</font>
<a name="(line121)"></a>exactly <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> Int <font color=Red>-&gt;</font> p a <font color=Red>-&gt;</font> p <font color=Red>[</font>a<font color=Red>]</font>
<a name="(line122)"></a>exactly <font color=Magenta>0</font> p <font color=Red>=</font> return []
<a name="(line123)"></a>exactly n p <font color=Red>=</font> return <font color=Cyan>(</font><font color=Red><b>:</b></font><font color=Cyan>)</font> <font color=Cyan>`apply`</font>  <font color=Cyan>(</font>p <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Cyan>(</font><font color=Magenta>"When expecting exactly "</font>
<a name="(line124)"></a>                                                    <font color=Cyan>++</font>show n<font color=Cyan>++</font><font color=Magenta>" more items"</font><font color=Cyan>)</font><font color=Cyan>++</font><font color=Cyan>)</font><font color=Cyan>)</font>
<a name="(line125)"></a>                         <font color=Cyan>`apply`</font>  exactly <font color=Cyan>(</font>n<font color=Blue>-</font><font color=Magenta>1</font><font color=Cyan>)</font> p
<a name="(line126)"></a>
<a name="(line127)"></a><a name="many"></a><font color=Blue>-- | 'many p' parses a list of elements with individual parser p.</font>
<a name="(line128)"></a><font color=Blue>--   Cannot fail, since an empty list is a valid return value.</font>
<a name="(line129)"></a>many <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p a <font color=Red>-&gt;</font> p <font color=Red>[</font>a<font color=Red>]</font>
<a name="(line130)"></a>many p <font color=Red>=</font> many1 p <font color=Cyan>`onFail`</font> return []
<a name="(line131)"></a>
<a name="(line132)"></a><a name="many1"></a><font color=Blue>-- | Parse a non-empty list of items.</font>
<a name="(line133)"></a>many1 <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p a <font color=Red>-&gt;</font> p <font color=Red>[</font>a<font color=Red>]</font>
<a name="(line134)"></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>
<a name="(line135)"></a>             <font color=Cyan>;</font> return <font color=Cyan>(</font>x<font color=Red><b>:</b></font><font color=Cyan>)</font> <font color=Cyan>`apply`</font> many p
<a name="(line136)"></a>             <font color=Cyan>}</font>
<a name="(line137)"></a><font color=Blue>--       `adjustErr` ("When looking for a non-empty sequence:\n\t"++)</font>
<a name="(line138)"></a>
<a name="(line139)"></a><a name="sepBy"></a><font color=Blue>-- | Parse a list of items separated by discarded junk.</font>
<a name="(line140)"></a>sepBy <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p a <font color=Red>-&gt;</font> p sep <font color=Red>-&gt;</font> p <font color=Red>[</font>a<font color=Red>]</font>
<a name="(line141)"></a>sepBy p sep <font color=Red>=</font> <font color=Green><u>do</u></font> sepBy1 p sep <font color=Cyan>`onFail`</font> return []
<a name="(line142)"></a>
<a name="(line143)"></a><a name="sepBy1"></a><font color=Blue>-- | Parse a non-empty list of items separated by discarded junk.</font>
<a name="(line144)"></a>sepBy1 <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p a <font color=Red>-&gt;</font> p sep <font color=Red>-&gt;</font> p <font color=Red>[</font>a<font color=Red>]</font>
<a name="(line145)"></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
<a name="(line146)"></a>                  <font color=Cyan>;</font> return <font color=Cyan>(</font>x<font color=Red><b>:</b></font><font color=Cyan>)</font> <font color=Cyan>`apply`</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>
<a name="(line147)"></a>                  <font color=Cyan>}</font>
<a name="(line148)"></a>         <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"When looking for a non-empty sequence with separators:\n\t"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line149)"></a> 
<a name="(line150)"></a><a name="bracketSep"></a><font color=Blue>-- | Parse a list of items, discarding the start, end, and separator</font>
<a name="(line151)"></a><font color=Blue>--   items.</font>
<a name="(line152)"></a>bracketSep <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p bra <font color=Red>-&gt;</font> p sep <font color=Red>-&gt;</font> p ket <font color=Red>-&gt;</font> p a <font color=Red>-&gt;</font> p <font color=Red>[</font>a<font color=Red>]</font>
<a name="(line153)"></a>bracketSep open sep close p <font color=Red>=</font>
<a name="(line154)"></a>    <font color=Green><u>do</u></font> <font color=Cyan>{</font> open<font color=Cyan>;</font> close<font color=Cyan>;</font> return [] <font color=Cyan>}</font>
<a name="(line155)"></a>       <font color=Cyan>`onFail`</font>
<a name="(line156)"></a>    <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\t"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line157)"></a>       <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\t"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line158)"></a>       <font color=Cyan>;</font> return <font color=Cyan>(</font>x<font color=Red><b>:</b></font><font color=Cyan>)</font>
<a name="(line159)"></a>           <font color=Cyan>`apply`</font> manyFinally <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>
<a name="(line160)"></a>              <font color=Cyan>(</font>close <font color=Cyan>`adjustErrBad`</font> <font color=Cyan>(</font><font color=Magenta>"When looking for closing bracket:\n\t"</font><font color=Cyan>++</font><font color=Cyan>)</font><font color=Cyan>)</font>
<a name="(line161)"></a>       <font color=Cyan>}</font>
<a name="(line162)"></a>
<a name="(line163)"></a><a name="bracket"></a><font color=Blue>-- | Parse a bracketed item, discarding the brackets.</font>
<a name="(line164)"></a>bracket <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p bra <font color=Red>-&gt;</font> p ket <font color=Red>-&gt;</font> p a <font color=Red>-&gt;</font> p a
<a name="(line165)"></a>bracket open close p <font color=Red>=</font> <font color=Green><u>do</u></font>
<a name="(line166)"></a>    <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\t"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line167)"></a>       <font color=Cyan>;</font> p <font color=Cyan>`discard`</font> <font color=Cyan>(</font>close <font color=Cyan>`adjustErrBad`</font> <font color=Cyan>(</font><font color=Magenta>"Missing closing bracket:\n\t"</font><font color=Cyan>++</font><font color=Cyan>)</font><font color=Cyan>)</font>
<a name="(line168)"></a>       <font color=Cyan>}</font>
<a name="(line169)"></a>
<a name="(line170)"></a><a name="manyFinally"></a><font color=Blue>-- | 'manyFinally e t' parses a possibly-empty sequence of e's,</font>
<a name="(line171)"></a><font color=Blue>--   terminated by a t.  The final t is discarded.  Any parse failures</font>
<a name="(line172)"></a><font color=Blue>--   could be due either to a badly-formed terminator or a badly-formed</font>
<a name="(line173)"></a><font color=Blue>--   element, so it raises both possible errors.</font>
<a name="(line174)"></a>manyFinally <font color=Red>::</font> PolyParse p <font color=Red>=&gt;</font> p a <font color=Red>-&gt;</font> p z <font color=Red>-&gt;</font> p <font color=Red>[</font>a<font color=Red>]</font>
<a name="(line175)"></a>manyFinally p t <font color=Red>=</font>
<a name="(line176)"></a>    <font color=Cyan>(</font>many p <font color=Cyan>`discard`</font> t<font color=Cyan>)</font>
<a name="(line177)"></a>      <font color=Cyan>`onFail`</font>
<a name="(line178)"></a>    oneOf' <font color=Red>[</font> <font color=Cyan>(</font><font color=Magenta>"sequence terminator"</font><font color=Cyan>,</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> t<font color=Cyan>;</font> return [] <font color=Cyan>}</font> <font color=Cyan>)</font>
<a name="(line179)"></a>           <font color=Cyan>,</font> <font color=Cyan>(</font><font color=Magenta>"item in a sequence"</font><font color=Cyan>,</font>  <font color=Green><u>do</u></font> <font color=Cyan>{</font> p<font color=Cyan>;</font> return [] <font color=Cyan>}</font> <font color=Cyan>)</font>
<a name="(line180)"></a>           <font color=Red>]</font>
<a name="(line181)"></a><font color=Blue>{-
<a name="(line182)"></a>manyFinally p t =
<a name="(line183)"></a>    do { xs &lt;- many p
<a name="(line184)"></a>       ; oneOf' [ ("sequence terminator", do { t; return () } )
<a name="(line185)"></a>                , ("item in a sequence",  do { p; return () } )
<a name="(line186)"></a>                ]
<a name="(line187)"></a>       ; return xs
<a name="(line188)"></a>       }
<a name="(line189)"></a>-}</font>
<a name="(line190)"></a><font color=Blue>------------------------------------------------------------------------</font>
</pre>
</html>