packages feed

polyparse-1.1: docs/haddock/src/Text/Parse.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>Parse
<a name="(line2)"></a>  <font color=Cyan>(</font> <font color=Blue>-- * The Parse class is a replacement for the standard Read class. </font>
<a name="(line3)"></a>    <font color=Blue>-- $parser</font>
<a name="(line4)"></a>    TextParser	<font color=Blue>-- synonym for Parser Char, i.e. string input, no state</font>
<a name="(line5)"></a>  <font color=Cyan>,</font> Parse<font color=Cyan>(</font><font color=Red>..</font><font color=Cyan>)</font>	<font color=Blue>-- instances: (), (a,b), (a,b,c), Maybe a, Either a, [a],</font>
<a name="(line6)"></a>		<font color=Blue>--            Int, Integer, Float, Double, Char, Bool</font>
<a name="(line7)"></a>  <font color=Cyan>,</font> parseByRead	<font color=Blue>-- :: Read a =&gt; String -&gt; TextParser a</font>
<a name="(line8)"></a>    <font color=Blue>-- ** Combinators specific to string input, lexed haskell-style</font>
<a name="(line9)"></a>  <font color=Cyan>,</font> word	<font color=Blue>-- :: TextParser String</font>
<a name="(line10)"></a>  <font color=Cyan>,</font> isWord	<font color=Blue>-- :: String -&gt; TextParser ()</font>
<a name="(line11)"></a>  <font color=Cyan>,</font> optionalParens	<font color=Blue>-- :: TextParser a -&gt; TextParser a</font>
<a name="(line12)"></a>  <font color=Cyan>,</font> field	<font color=Blue>-- :: Parse a =&gt; String -&gt; TextParser a</font>
<a name="(line13)"></a>  <font color=Cyan>,</font> constructors<font color=Blue>-- :: [(String,TextParser a)] -&gt; TextParser a</font>
<a name="(line14)"></a>  <font color=Cyan>,</font> enumeration <font color=Blue>-- :: Show a =&gt; String -&gt; [a] -&gt; TextParser a</font>
<a name="(line15)"></a>    <font color=Blue>-- ** Re-export all the more general combinators from Poly too</font>
<a name="(line16)"></a>  <font color=Cyan>,</font> <font color=Green><u>module</u></font> Text<font color=Cyan>.</font>ParserCombinators<font color=Cyan>.</font>Poly
<a name="(line17)"></a>  <font color=Cyan>)</font> <font color=Green><u>where</u></font>
<a name="(line18)"></a>
<a name="(line19)"></a><font color=Green><u>import</u></font> Char <font color=Cyan>(</font>isSpace<font color=Cyan>)</font>
<a name="(line20)"></a><font color=Green><u>import</u></font> List <font color=Cyan>(</font>intersperse<font color=Cyan>)</font>
<a name="(line21)"></a><font color=Green><u>import</u></font> Text<font color=Cyan>.</font>ParserCombinators<font color=Cyan>.</font>Poly
<a name="(line22)"></a>
<a name="(line23)"></a><font color=Blue>------------------------------------------------------------------------</font>
<a name="(line24)"></a><font color=Blue>-- $parser</font>
<a name="(line25)"></a><font color=Blue>-- The Parse class is a replacement for the standard Read class.  It is a</font>
<a name="(line26)"></a><font color=Blue>-- specialisation of the (poly) Parser monad for String input.</font>
<a name="(line27)"></a><font color=Blue>-- There are instances defined for all Prelude types.</font>
<a name="(line28)"></a><font color=Blue>-- For user-defined types, you can write your own instance, or use</font>
<a name="(line29)"></a><font color=Blue>-- DrIFT to generate them automatically, e.g. {-! derive : Parse !-}</font>
<a name="(line30)"></a>
<a name="(line31)"></a><a name="TextParser"></a><font color=Blue>-- | A synonym for Parser Char, i.e. string input (no state)</font>
<a name="(line32)"></a><a name="TextParser"></a><font color=Green><u>type</u></font> TextParser a <font color=Red>=</font> Parser Char a
<a name="(line33)"></a>
<a name="(line34)"></a><a name="Parse"></a><font color=Blue>-- | The class @Parse@ is a replacement for @Read@, operating over String input.</font>
<a name="(line35)"></a><a name="Parse"></a><font color=Blue>--   Essentially, it permits better error messages for why something failed to</font>
<a name="(line36)"></a><a name="Parse"></a><font color=Blue>--   parse.  It is rather important that @parse@ can read back exactly what</font>
<a name="(line37)"></a><a name="Parse"></a><font color=Blue>--   is generated by the corresponding instance of @show@.  To apply a parser</font>
<a name="(line38)"></a><a name="Parse"></a><font color=Blue>--   to some text, use @runParser@.</font>
<a name="(line39)"></a><a name="Parse"></a><font color=Green><u>class</u></font> Parse a <font color=Green><u>where</u></font>
<a name="(line40)"></a>    parse     <font color=Red>::</font> TextParser a
<a name="(line41)"></a>    parseList <font color=Red>::</font> TextParser <font color=Red>[</font>a<font color=Red>]</font>	<font color=Blue>-- only to distinguish [] and ""</font>
<a name="(line42)"></a>    parseList  <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> isWord <font color=Magenta>"[]"</font><font color=Cyan>;</font> return [] <font color=Cyan>}</font>
<a name="(line43)"></a>                   <font color=Cyan>`onFail`</font>
<a name="(line44)"></a>                 <font color=Green><u>do</u></font> <font color=Cyan>{</font> isWord <font color=Magenta>"["</font><font color=Cyan>;</font> isWord <font color=Magenta>"]"</font><font color=Cyan>;</font> return [] <font color=Cyan>}</font>
<a name="(line45)"></a>                   <font color=Cyan>`onFail`</font>
<a name="(line46)"></a>                 bracketSep <font color=Cyan>(</font>isWord <font color=Magenta>"["</font><font color=Cyan>)</font> <font color=Cyan>(</font>isWord <font color=Magenta>","</font><font color=Cyan>)</font> <font color=Cyan>(</font>isWord <font color=Magenta>"]"</font><font color=Cyan>)</font> parse
<a name="(line47)"></a>                   <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Expected a list, but\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line48)"></a>
<a name="(line49)"></a><a name="parseByRead"></a><font color=Blue>-- | If there already exists a Read instance for a type, then we can make</font>
<a name="(line50)"></a><font color=Blue>--   a Parser for it, but with only poor error-reporting.</font>
<a name="(line51)"></a>parseByRead <font color=Red>::</font> Read a <font color=Red>=&gt;</font> String <font color=Red>-&gt;</font> TextParser a
<a name="(line52)"></a>parseByRead name <font color=Red>=</font>
<a name="(line53)"></a>    P <font color=Cyan>(</font><font color=Red>\</font>s<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> reads s <font color=Green><u>of</u></font>
<a name="(line54)"></a>                []       <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left <font color=Cyan>(</font>False<font color=Cyan>,</font><font color=Magenta>"no parse, expected a "</font><font color=Cyan>++</font>name<font color=Cyan>)</font><font color=Cyan>,</font> s<font color=Cyan>)</font>
<a name="(line55)"></a>                <font color=Red>[</font><font color=Cyan>(</font>a<font color=Cyan>,</font>s'<font color=Cyan>)</font><font color=Red>]</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Right a<font color=Cyan>,</font> s'<font color=Cyan>)</font>
<a name="(line56)"></a>                <font color=Green><u>_</u></font>        <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left <font color=Cyan>(</font>False<font color=Cyan>,</font><font color=Magenta>"ambiguous parse, expected a "</font><font color=Cyan>++</font>name<font color=Cyan>)</font><font color=Cyan>,</font> s<font color=Cyan>)</font>
<a name="(line57)"></a>      <font color=Cyan>)</font>
<a name="(line58)"></a>
<a name="(line59)"></a><a name="word"></a><font color=Blue>-- | One lexical chunk (Haskell-style lexing).</font>
<a name="(line60)"></a>word <font color=Red>::</font> TextParser String
<a name="(line61)"></a>word <font color=Red>=</font> P <font color=Cyan>(</font><font color=Red>\</font>s<font color=Red>-&gt;</font> <font color=Green><u>case</u></font> lex s <font color=Green><u>of</u></font>
<a name="(line62)"></a>                   []         <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left <font color=Cyan>(</font>False<font color=Cyan>,</font><font color=Magenta>"no input? (impossible)"</font><font color=Cyan>)</font><font color=Cyan>,</font> s<font color=Cyan>)</font>
<a name="(line63)"></a>                   <font color=Red>[</font><font color=Cyan>(</font><font color=Magenta>""</font><font color=Cyan>,</font>s'<font color=Cyan>)</font><font color=Red>]</font>  <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left <font color=Cyan>(</font>False<font color=Cyan>,</font><font color=Magenta>"no input?"</font><font color=Cyan>)</font><font color=Cyan>,</font> s'<font color=Cyan>)</font>
<a name="(line64)"></a>                   <font color=Cyan>(</font><font color=Cyan>(</font>x<font color=Cyan>,</font>s'<font color=Cyan>)</font><font color=Red><b>:</b></font><font color=Green><u>_</u></font><font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Right x<font color=Cyan>,</font> s'<font color=Cyan>)</font> <font color=Cyan>)</font>
<a name="(line65)"></a>
<a name="(line66)"></a><a name="isWord"></a><font color=Blue>-- | Ensure that the next input word is the given string.  (Note the input</font>
<a name="(line67)"></a><font color=Blue>--   is lexed as haskell, so wordbreaks at spaces, symbols, etc.)</font>
<a name="(line68)"></a>isWord <font color=Red>::</font> String <font color=Red>-&gt;</font> TextParser String
<a name="(line69)"></a>isWord w <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> w' <font color=Red>&lt;-</font> word
<a name="(line70)"></a>              <font color=Cyan>;</font> <font color=Green><u>if</u></font> w'<font color=Cyan>==</font>w <font color=Green><u>then</u></font> return w <font color=Green><u>else</u></font> fail <font color=Cyan>(</font><font color=Magenta>"expected "</font><font color=Cyan>++</font>w<font color=Cyan>++</font><font color=Magenta>" got "</font><font color=Cyan>++</font>w'<font color=Cyan>)</font>
<a name="(line71)"></a>              <font color=Cyan>}</font>
<a name="(line72)"></a>
<a name="(line73)"></a><a name="optionalParens"></a><font color=Blue>-- | Allow true string parens around an item.</font>
<a name="(line74)"></a>optionalParens <font color=Red>::</font> TextParser a <font color=Red>-&gt;</font> TextParser a
<a name="(line75)"></a>optionalParens p <font color=Red>=</font> bracket <font color=Cyan>(</font>isWord <font color=Magenta>"("</font><font color=Cyan>)</font> <font color=Cyan>(</font>isWord <font color=Magenta>")"</font><font color=Cyan>)</font> p <font color=Cyan>`onFail`</font> p
<a name="(line76)"></a>
<a name="(line77)"></a><a name="field"></a><font color=Blue>-- | Deal with named field syntax.  The string argument is the field name,</font>
<a name="(line78)"></a><font color=Blue>--   and the parser returns the value of the field.</font>
<a name="(line79)"></a>field <font color=Red>::</font> Parse a <font color=Red>=&gt;</font> String <font color=Red>-&gt;</font> TextParser a
<a name="(line80)"></a>field name <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> isWord name<font color=Cyan>;</font> commit <font color=Cyan>$</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> isWord <font color=Magenta>"="</font><font color=Cyan>;</font> parse <font color=Cyan>}</font> <font color=Cyan>}</font>
<a name="(line81)"></a>
<a name="(line82)"></a><a name="constructors"></a><font color=Blue>-- | Parse one of a bunch of alternative constructors.  In the list argument,</font>
<a name="(line83)"></a><font color=Blue>--   the first element of the pair is the constructor name, and</font>
<a name="(line84)"></a><font color=Blue>--   the second is the parser for the rest of the value.  The first matching</font>
<a name="(line85)"></a><font color=Blue>--   parse is returned.</font>
<a name="(line86)"></a>constructors <font color=Red>::</font> <font color=Red>[</font><font color=Cyan>(</font>String<font color=Cyan>,</font>TextParser a<font color=Cyan>)</font><font color=Red>]</font> <font color=Red>-&gt;</font> TextParser a
<a name="(line87)"></a>constructors cs <font color=Red>=</font> oneOf' <font color=Cyan>(</font>map cons cs<font color=Cyan>)</font>
<a name="(line88)"></a>    <font color=Green><u>where</u></font> cons <font color=Cyan>(</font>name<font color=Cyan>,</font>p<font color=Cyan>)</font> <font color=Red>=</font>
<a name="(line89)"></a>               <font color=Cyan>(</font> name
<a name="(line90)"></a>               <font color=Cyan>,</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> isWord name
<a name="(line91)"></a>                    <font color=Cyan>;</font> p <font color=Cyan>`adjustErrBad`</font> <font color=Cyan>(</font><font color=Cyan>(</font><font color=Magenta>"got constructor, but within "</font>
<a name="(line92)"></a>                                        <font color=Cyan>++</font>name<font color=Cyan>++</font><font color=Magenta>",\n"</font><font color=Cyan>)</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line93)"></a>                    <font color=Cyan>}</font>
<a name="(line94)"></a>               <font color=Cyan>)</font>
<a name="(line95)"></a>
<a name="(line96)"></a><a name="enumeration"></a><font color=Blue>-- | Parse one of the given nullary constructors (an enumeration).</font>
<a name="(line97)"></a><font color=Blue>--   The string argument is the name of the type, and the list argument</font>
<a name="(line98)"></a><font color=Blue>--   should contain all of the possible enumeration values.</font>
<a name="(line99)"></a>enumeration <font color=Red>::</font> <font color=Cyan>(</font>Show a<font color=Cyan>)</font> <font color=Red>=&gt;</font> String <font color=Red>-&gt;</font> <font color=Red>[</font>a<font color=Red>]</font> <font color=Red>-&gt;</font> TextParser a
<a name="(line100)"></a>enumeration typ cs <font color=Red>=</font> oneOf <font color=Cyan>(</font>map <font color=Cyan>(</font><font color=Red>\</font>c<font color=Red>-&gt;</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> isWord <font color=Cyan>(</font>show c<font color=Cyan>)</font><font color=Cyan>;</font> return c <font color=Cyan>}</font><font color=Cyan>)</font> cs<font color=Cyan>)</font>
<a name="(line101)"></a>                         <font color=Cyan>`adjustErr`</font>
<a name="(line102)"></a>                     <font color=Cyan>(</font><font color=Cyan>++</font><font color=Cyan>(</font><font color=Magenta>"\n  expected "</font><font color=Cyan>++</font>typ<font color=Cyan>++</font><font color=Magenta>" value ("</font><font color=Cyan>++</font>e<font color=Cyan>++</font><font color=Magenta>")"</font><font color=Cyan>)</font><font color=Cyan>)</font>
<a name="(line103)"></a>    <font color=Green><u>where</u></font> e <font color=Red>=</font> concat <font color=Cyan>(</font>intersperse <font color=Magenta>", "</font> <font color=Cyan>(</font>map show <font color=Cyan>(</font>init cs<font color=Cyan>)</font><font color=Cyan>)</font><font color=Cyan>)</font>
<a name="(line104)"></a>              <font color=Cyan>++</font> <font color=Magenta>", or "</font> <font color=Cyan>++</font> show <font color=Cyan>(</font>last cs<font color=Cyan>)</font>
<a name="(line105)"></a>
<a name="(line106)"></a><font color=Blue>------------------------------------------------------------------------</font>
<a name="(line107)"></a><font color=Blue>-- Instances for all the Standard Prelude types.</font>
<a name="(line108)"></a>
<a name="(line109)"></a><font color=Blue>-- Basic types</font>
<a name="(line110)"></a><font color=Green><u>instance</u></font> Parse Int <font color=Green><u>where</u></font>
<a name="(line111)"></a>    parse <font color=Red>=</font> parseByRead <font color=Magenta>"Int"</font>
<a name="(line112)"></a><font color=Green><u>instance</u></font> Parse Integer <font color=Green><u>where</u></font>
<a name="(line113)"></a>    parse <font color=Red>=</font> parseByRead <font color=Magenta>"Integer"</font>
<a name="(line114)"></a><font color=Green><u>instance</u></font> Parse Float <font color=Green><u>where</u></font>
<a name="(line115)"></a>    parse <font color=Red>=</font> parseByRead <font color=Magenta>"Float"</font>
<a name="(line116)"></a><font color=Green><u>instance</u></font> Parse Double <font color=Green><u>where</u></font>
<a name="(line117)"></a>    parse <font color=Red>=</font> parseByRead <font color=Magenta>"Double"</font>
<a name="(line118)"></a><font color=Green><u>instance</u></font> Parse Char <font color=Green><u>where</u></font>
<a name="(line119)"></a>    parse <font color=Red>=</font> parseByRead <font color=Magenta>"Char"</font>
<a name="(line120)"></a> <font color=Blue>-- parseList = bracket (isWord "\"") (satisfy (=='"'))</font>
<a name="(line121)"></a> <font color=Blue>--                     (many (satisfy (/='"')))</font>
<a name="(line122)"></a>	<font color=Blue>-- not totally correct for strings...</font>
<a name="(line123)"></a>    parseList <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> w <font color=Red>&lt;-</font> word<font color=Cyan>;</font> <font color=Green><u>if</u></font> head w <font color=Cyan>==</font> <font color=Magenta>'"'</font> <font color=Green><u>then</u></font> return <font color=Cyan>(</font>init <font color=Cyan>(</font>tail w<font color=Cyan>)</font><font color=Cyan>)</font>
<a name="(line124)"></a>                                <font color=Green><u>else</u></font> fail <font color=Magenta>"not a string"</font> <font color=Cyan>}</font>
<a name="(line125)"></a>
<a name="(line126)"></a><font color=Green><u>instance</u></font> Parse Bool <font color=Green><u>where</u></font>
<a name="(line127)"></a>    parse <font color=Red>=</font> enumeration <font color=Magenta>"Bool"</font> <font color=Red>[</font>False<font color=Cyan>,</font>True<font color=Red>]</font>
<a name="(line128)"></a>
<a name="(line129)"></a><font color=Green><u>instance</u></font> Parse Ordering <font color=Green><u>where</u></font>
<a name="(line130)"></a>    parse <font color=Red>=</font> enumeration <font color=Magenta>"Ordering"</font> <font color=Red>[</font>LT<font color=Cyan>,</font>EQ<font color=Cyan>,</font>GT<font color=Red>]</font>
<a name="(line131)"></a>
<a name="(line132)"></a><font color=Blue>-- Structural types</font>
<a name="(line133)"></a><font color=Green><u>instance</u></font> Parse () <font color=Green><u>where</u></font>
<a name="(line134)"></a>    parse <font color=Red>=</font> P p
<a name="(line135)"></a>      <font color=Green><u>where</u></font> p []       <font color=Red>=</font> <font color=Cyan>(</font>Left <font color=Cyan>(</font>False<font color=Cyan>,</font><font color=Magenta>"no input: expected a ()"</font><font color=Cyan>)</font><font color=Cyan>,</font> []<font color=Cyan>)</font>
<a name="(line136)"></a>            p <font color=Cyan>(</font><font color=Magenta>'('</font><font color=Red><b>:</b></font>cs<font color=Cyan>)</font> <font color=Red>=</font> <font color=Green><u>case</u></font> dropWhile isSpace cs <font color=Green><u>of</u></font>
<a name="(line137)"></a>                             <font color=Cyan>(</font><font color=Magenta>')'</font><font color=Red><b>:</b></font>s<font color=Cyan>)</font> <font color=Red>-&gt;</font> <font color=Cyan>(</font>Right ()<font color=Cyan>,</font> s<font color=Cyan>)</font>
<a name="(line138)"></a>                             <font color=Green><u>_</u></font>       <font color=Red>-&gt;</font> <font color=Cyan>(</font>Left <font color=Cyan>(</font>False<font color=Cyan>,</font><font color=Magenta>"Expected ) after ("</font><font color=Cyan>)</font><font color=Cyan>,</font> cs<font color=Cyan>)</font>
<a name="(line139)"></a>            p <font color=Cyan>(</font>c<font color=Red><b>:</b></font>cs<font color=Cyan>)</font> <font color=Red>|</font> isSpace c <font color=Red>=</font> p cs
<a name="(line140)"></a>                     <font color=Red>|</font> otherwise <font color=Red>=</font> <font color=Cyan>(</font> Left <font color=Cyan>(</font>False<font color=Cyan>,</font><font color=Magenta>"Expected a (), got "</font><font color=Cyan>++</font>show c<font color=Cyan>)</font>
<a name="(line141)"></a>                                     <font color=Cyan>,</font> <font color=Cyan>(</font>c<font color=Red><b>:</b></font>cs<font color=Cyan>)</font><font color=Cyan>)</font>
<a name="(line142)"></a>
<a name="(line143)"></a><font color=Green><u>instance</u></font> <font color=Cyan>(</font>Parse a<font color=Cyan>,</font> Parse b<font color=Cyan>)</font> <font color=Red>=&gt;</font> Parse <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>)</font> <font color=Green><u>where</u></font>
<a name="(line144)"></a>    parse <font color=Red>=</font> <font color=Green><u>do</u></font><font color=Cyan>{</font> isWord <font color=Magenta>"("</font> <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Opening a 2-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line145)"></a>              <font color=Cyan>;</font> x <font color=Red>&lt;-</font> parse <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"In 1st item of a 2-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line146)"></a>              <font color=Cyan>;</font> isWord <font color=Magenta>","</font> <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Separating a 2-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line147)"></a>              <font color=Cyan>;</font> y <font color=Red>&lt;-</font> parse <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"In 2nd item of a 2-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line148)"></a>              <font color=Cyan>;</font> isWord <font color=Magenta>")"</font> <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Closing a 2-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line149)"></a>              <font color=Cyan>;</font> return <font color=Cyan>(</font>x<font color=Cyan>,</font>y<font color=Cyan>)</font> <font color=Cyan>}</font>
<a name="(line150)"></a>
<a name="(line151)"></a><font color=Green><u>instance</u></font> <font color=Cyan>(</font>Parse a<font color=Cyan>,</font> Parse b<font color=Cyan>,</font> Parse c<font color=Cyan>)</font> <font color=Red>=&gt;</font> Parse <font color=Cyan>(</font>a<font color=Cyan>,</font>b<font color=Cyan>,</font>c<font color=Cyan>)</font> <font color=Green><u>where</u></font>
<a name="(line152)"></a>    parse <font color=Red>=</font> <font color=Green><u>do</u></font><font color=Cyan>{</font> isWord <font color=Magenta>"("</font> <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Opening a 3-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line153)"></a>              <font color=Cyan>;</font> x <font color=Red>&lt;-</font> parse <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"In 1st item of a 3-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line154)"></a>              <font color=Cyan>;</font> isWord <font color=Magenta>","</font> <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Separating(1) a 3-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line155)"></a>              <font color=Cyan>;</font> y <font color=Red>&lt;-</font> parse <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"In 2nd item of a 3-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line156)"></a>              <font color=Cyan>;</font> isWord <font color=Magenta>","</font> <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Separating(2) a 3-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line157)"></a>              <font color=Cyan>;</font> z <font color=Red>&lt;-</font> parse <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"In 3rd item of a 3-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line158)"></a>              <font color=Cyan>;</font> isWord <font color=Magenta>")"</font> <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Magenta>"Closing a 3-tuple\n"</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line159)"></a>              <font color=Cyan>;</font> return <font color=Cyan>(</font>x<font color=Cyan>,</font>y<font color=Cyan>,</font>z<font color=Cyan>)</font> <font color=Cyan>}</font>
<a name="(line160)"></a>
<a name="(line161)"></a><font color=Green><u>instance</u></font> Parse a <font color=Red>=&gt;</font> Parse <font color=Cyan>(</font>Maybe a<font color=Cyan>)</font> <font color=Green><u>where</u></font>
<a name="(line162)"></a>    parse <font color=Red>=</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> isWord <font color=Magenta>"Nothing"</font><font color=Cyan>;</font> return Nothing <font color=Cyan>}</font>
<a name="(line163)"></a>              <font color=Cyan>`onFail`</font>
<a name="(line164)"></a>            <font color=Green><u>do</u></font> <font color=Cyan>{</font> isWord <font color=Magenta>"Just"</font>
<a name="(line165)"></a>               <font color=Cyan>;</font> fmap Just <font color=Cyan>$</font> optionalParens parse
<a name="(line166)"></a>                     <font color=Cyan>`adjustErrBad`</font> <font color=Cyan>(</font><font color=Magenta>"but within Just, "</font><font color=Cyan>++</font><font color=Cyan>)</font>
<a name="(line167)"></a>               <font color=Cyan>}</font>
<a name="(line168)"></a>              <font color=Cyan>`adjustErr`</font> <font color=Cyan>(</font><font color=Cyan>(</font><font color=Magenta>"expected a Maybe (Just or Nothing)\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="(line169)"></a>
<a name="(line170)"></a><font color=Green><u>instance</u></font> <font color=Cyan>(</font>Parse a<font color=Cyan>,</font> Parse b<font color=Cyan>)</font> <font color=Red>=&gt;</font> Parse <font color=Cyan>(</font>Either a b<font color=Cyan>)</font> <font color=Green><u>where</u></font>
<a name="(line171)"></a>    parse <font color=Red>=</font> constructors <font color=Red>[</font> <font color=Cyan>(</font><font color=Magenta>"Left"</font><font color=Cyan>,</font>  <font color=Green><u>do</u></font> <font color=Cyan>{</font> fmap Left  <font color=Cyan>$</font> optionalParens parse <font color=Cyan>}</font> <font color=Cyan>)</font>
<a name="(line172)"></a>                         <font color=Cyan>,</font> <font color=Cyan>(</font><font color=Magenta>"Right"</font><font color=Cyan>,</font> <font color=Green><u>do</u></font> <font color=Cyan>{</font> fmap Right <font color=Cyan>$</font> optionalParens parse <font color=Cyan>}</font> <font color=Cyan>)</font>
<a name="(line173)"></a>                         <font color=Red>]</font>
<a name="(line174)"></a>
<a name="(line175)"></a><font color=Green><u>instance</u></font> Parse a <font color=Red>=&gt;</font> Parse <font color=Red>[</font>a<font color=Red>]</font> <font color=Green><u>where</u></font>
<a name="(line176)"></a>    parse <font color=Red>=</font> parseList
<a name="(line177)"></a>
<a name="(line178)"></a><font color=Blue>------------------------------------------------------------------------</font>
</pre>
</html>