Source

fparsec / Doc / html / users-guide / parsing-alternatives.html

Full commit
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <title>Parsing alternatives</title>
 <link rel="stylesheet" type="text/css" media="all" href="../css/style.css" />
 <link rel="stylesheet" type="text/css" media="screen" href="../css/screen-sidebar.css" />
 <!--[if lt IE 9]>
 <link rel="stylesheet" type="text/css" media="all" href="../css/style-ie.css" />
 <![endif]-->
 <!--[if IE 6]>
 <link rel="stylesheet" type="text/css" media="all" href="../css/style-ie6.css" />
 <![endif]-->
 <link rel="stylesheet" type="text/css" media="print" href="../css/print.css" />
</head>
<body>
 <div id="fixed-layer">
 <div id="fixed-wrapper">
 <div id="sidebar">
  <div id="top-links"><span><a href="http://bitbucket.org/fparsec/main">FParsec @ BitBucket</a> | <a href="https://bitbucket.org/fparsec/main/issues">Report a bug</a> | <a href="mailto:fparsec [at] quanttec.com?subject=FParsec&amp;body=Hello Stephan,%0A%0A[your feedback]">Feedback</a></span></div>
  <div id="nav-tree">
   <table class="nav n1">
    <tbody class="nav-open n1">
     <tr class="nav-entry n1 _1">
      <td class="nav-number n1"></td>
      <td class="nav-title n1"><a href="../index.html">FParsec Documentation</a></td>
     </tr>
     <tr class="nav-subentries n1 _1">
      <td class="nav-subentries-number n1"></td>
      <td class="nav-subentries n1">
       <table class="nav n2">
        <tbody class="nav-before-open n2">
         <tr class="nav-entry n2 _1">
          <td class="nav-number n2"><a href="../about/index.html"><span class="section-number">1</span><span class="nav-space"></span></a></td>
          <td class="nav-title n2"><a href="../about/index.html">About FParsec</a></td>
         </tr>
         <tr class="nav-entry n2 _2">
          <td class="nav-number n2"><a href="../license.html"><span class="section-number">2</span><span class="nav-space"></span></a></td>
          <td class="nav-title n2"><a href="../license.html">License</a></td>
         </tr>
         <tr class="nav-entry n2 _3">
          <td class="nav-number n2">
           <a href="../download-and-installation.html"><span class="section-number">3</span><span class="nav-space"></span></a>
          </td>
          <td class="nav-title n2"><a href="../download-and-installation.html">Download and installation</a></td>
         </tr>
         <tr class="nav-entry n2 _4">
          <td class="nav-number n2"><a href="../tutorial.html"><span class="section-number">4</span><span class="nav-space"></span></a></td>
          <td class="nav-title n2"><a href="../tutorial.html">Tutorial</a></td>
         </tr>
        </tbody>
        <tbody class="nav-open n2">
         <tr class="nav-entry n2 _5">
          <td class="nav-number n2"><a href="index.html"><span class="section-number">5</span><span class="nav-space"></span></a></td>
          <td class="nav-title n2"><a href="index.html">User’s Guide</a></td>
         </tr>
         <tr class="nav-subentries n2 _5">
          <td class="nav-subentries-number n2"></td>
          <td class="nav-subentries n2">
           <table class="nav n3">
            <tbody class="nav-before-open n3">
             <tr class="nav-entry n3 _1">
              <td class="nav-number n3"><a href="parser-functions.html"><span class="section-number">1</span><span class="nav-space"></span></a></td>
              <td class="nav-title n3"><a href="parser-functions.html">Parser functions</a></td>
             </tr>
             <tr class="nav-entry n3 _2">
              <td class="nav-number n3">
               <a href="running-parsers-on-input.html"><span class="section-number">2</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="running-parsers-on-input.html">Running parsers on input</a></td>
             </tr>
             <tr class="nav-entry n3 _3">
              <td class="nav-number n3">
               <a href="internals-of-a-simple-parser-function.html"><span class="section-number">3</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3">
               <a href="internals-of-a-simple-parser-function.html">Internals of a simple <code class="fsharp"><span class="ci">Parser</span></code>
               function</a>
              </td>
             </tr>
             <tr class="nav-entry n3 _4">
              <td class="nav-number n3">
               <a href="applying-parsers-in-sequence.html"><span class="section-number">4</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="applying-parsers-in-sequence.html">Applying parsers in sequence</a></td>
             </tr>
             <tr class="nav-entry n3 _5">
              <td class="nav-number n3"><a href="parsing-sequences.html"><span class="section-number">5</span><span class="nav-space"></span></a></td>
              <td class="nav-title n3"><a href="parsing-sequences.html">Parsing sequences</a></td>
             </tr>
            </tbody>
            <tbody class="nav-open selected n3">
             <tr class="nav-entry selected n3 _6">
              <td class="nav-number selected n3"><a href="#"><span class="section-number">6</span><span class="nav-space"></span></a></td>
              <td class="nav-title selected n3"><a href="#">Parsing alternatives</a></td>
             </tr>
            </tbody>
            <tbody class="nav-after-open n3">
             <tr class="nav-entry n3 _7">
              <td class="nav-number n3">
               <a href="looking-ahead-and-backtracking.html"><span class="section-number">7</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="looking-ahead-and-backtracking.html">Looking ahead and backtracking</a></td>
             </tr>
             <tr class="nav-entry n3 _8">
              <td class="nav-number n3">
               <a href="customizing-error-messages.html"><span class="section-number">8</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="customizing-error-messages.html">Customizing error messages</a></td>
             </tr>
             <tr class="nav-entry n3 _9">
              <td class="nav-number n3">
               <a href="parsing-with-user-state.html"><span class="section-number">9</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="parsing-with-user-state.html">Parsing with user state</a></td>
             </tr>
             <tr class="nav-entry n3 _0">
              <td class="nav-number n3">
               <a href="where-is-the-monad.html"><span class="section-number">10</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="where-is-the-monad.html">Where is the monad?</a></td>
             </tr>
             <tr class="nav-entry n3 _1">
              <td class="nav-number n3">
               <a href="debugging-a-parser.html"><span class="section-number">11</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="debugging-a-parser.html">Debugging a parser</a></td>
             </tr>
             <tr class="nav-entry n3 _2">
              <td class="nav-number n3">
               <a href="performance-optimizations.html"><span class="section-number">12</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="performance-optimizations.html">Performance optimizations</a></td>
             </tr>
             <tr class="nav-entry n3 _3">
              <td class="nav-number n3"><a href="tips-and-tricks.html"><span class="section-number">13</span><span class="nav-space"></span></a></td>
              <td class="nav-title n3"><a href="tips-and-tricks.html">Tips and tricks</a></td>
             </tr>
            </tbody>
           </table>
          </td>
         </tr>
        </tbody>
        <tbody class="nav-after-open n2">
         <tr class="nav-entry n2 _6">
          <td class="nav-number n2"><a href="../reference/index.html"><span class="section-number">6</span><span class="nav-space"></span></a></td>
          <td class="nav-title n2"><a href="../reference/index.html">Reference</a></td>
         </tr>
        </tbody>
       </table>
      </td>
     </tr>
    </tbody>
   </table>
  </div>
  <div id="copyright">
    <span>Copyright © 2012 <a href="../about/contact.html">Stephan Tolksdorf</a></span>
  </div>
 </div>
 </div>
 </div>
 <div id="wrapper">
 <div id="main">
 <div id="main-content">
 <div id="breadcrumbs">
  <span class="breadcrumbs">
   <span id="breadcrumbs-parents"><a href="../index.html">FParsec Documentation</a><span class="breadcrumbs-sep"> > </span><a href="index.html">User’s Guide</a></span><span class="breadcrumbs-sep"> > </span>Parsing alternatives
  </span>
 </div>
 <div class="section s2">
  <h1 class="title h2"><span><span class="section-number">5.6</span> Parsing alternatives</span></h1>
  <div class="intro i2">
   <div class="para _1 lcinp">
    <p>FParsec’s main operator for trying to parse input with alternative parsers is</p>
<pre class="code fsharp"><span class="ck">val</span> <span class="cp">(</span><a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a><span class="cp">)</span><span class="cp">:</span> <a href="../reference/primitives.html#members.Parser"><span class="ci">Parser</span></a><span class="cp">&lt;</span><span class="ctv">'a</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span> <span class="cr">-&gt;</span> <a href="../reference/primitives.html#members.Parser"><span class="ci">Parser</span></a><span class="cp">&lt;</span><span class="ctv">'a</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span> <span class="cr">-&gt;</span> <a href="../reference/primitives.html#members.Parser"><span class="ci">Parser</span></a><span class="cp">&lt;</span><span class="ctv">'a</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span>
</pre>
   </div>
   <div class="para _2">
    <p>
     This operator implements a form of <em>prioritized choice</em>: it only tries to parse input with the second parser if the first parser fails.
    </p>
   </div>
   <div class="para _3 lcinp">
    <p>The following example illustrates this behaviour:</p>
<pre class="code fsharp"><span class="ck">type</span> <span class="ci">Char</span> <span class="cp">=</span> <span class="ci">AsciiChar</span> <span class="ck">of</span> <span class="ci">char</span>
          <span class="cp">|</span> <span class="ci">Char</span> <span class="ck">of</span> <span class="ci">char</span>

<span class="ck">let</span> <a href="../reference/charparsers.html#members.asciiLetter"><span class="ci">asciiLetter</span></a> <span class="cp">=</span> <a href="../reference/charparsers.html#members.asciiLetter"><span class="ci">asciiLetter</span></a> <a href="../reference/primitives.html#members.:124::62::62:"><span class="co">|&gt;&gt;</span></a> <span class="ci">AsciiChar</span>
<span class="ck">let</span> <a href="../reference/charparsers.html#members.letter"><span class="ci">letter</span></a> <span class="cp">=</span> <a href="../reference/charparsers.html#members.letter"><span class="ci">letter</span></a> <a href="../reference/primitives.html#members.:124::62::62:"><span class="co">|&gt;&gt;</span></a> <span class="ci">Char</span>
</pre>
<pre class="code fsharp"><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><a href="../reference/charparsers.html#members.asciiLetter"><span class="ci">asciiLetter</span></a> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <a href="../reference/charparsers.html#members.letter"><span class="ci">letter</span></a><span class="cp">)</span> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;Char,unit&gt; = Success: AsciiChar 'a'
</span><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><a href="../reference/charparsers.html#members.letter"><span class="ci">letter</span></a> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <a href="../reference/charparsers.html#members.asciiLetter"><span class="ci">asciiLetter</span></a><span class="cp">)</span> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;Char,unit&gt; = Success: Char 'a'
</span><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><a href="../reference/charparsers.html#members.asciiLetter"><span class="ci">asciiLetter</span></a> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <a href="../reference/charparsers.html#members.letter"><span class="ci">letter</span></a><span class="cp">)</span> <span class="cs"><span class="cld">"</span>ä<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;Char,unit&gt; = Success: Char 'ä'
</span></pre>
   </div>
   <div class="para _4 lcinp">
    <p>The prioritized choice also implies that FParsec doesn’t enforce a longest‐match rule like in regular expressions:</p>
<pre class="code fsharp"><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="cs"><span class="cld">"</span>ab<span class="crd">"</span></span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>ab<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;string,unit&gt; = Success: "a"
</span></pre>
   </div>
   <div class="para _5">
    <p>
     If you want to accept more than two alternatives, you can either chain multiple <code class="fsharp"><a
     href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a></code> operators, like in <code
     class="fsharp"><span class="ci">p1</span> <a href="../reference/primitives.html#members.:60::124::62:"><span
     class="co">&lt;|&gt;</span></a> <span class="ci">p2</span> <a href="../reference/primitives.html#members.:60::124::62:"><span
     class="co">&lt;|&gt;</span></a> <span class="ci">p3</span></code>, or you can use the <code class="fsharp"><a
     href="../reference/primitives.html#members.choice"><span class="ci">choice</span></a></code> combinator, which accepts a sequence of parsers as
     the argument, like in <code class="fsharp"><a href="../reference/primitives.html#members.choice"><span class="ci">choice</span></a> <span
     class="cp">[</span><span class="ci">p1</span><span class="cp">;</span> <span class="ci">p2</span><span class="cp">;</span> <span
     class="ci">p3</span><span class="cp">]</span></code>. In both cases the argument parsers are tried from left to right until a parser succeeds.
    </p>
   </div>
   <div class="para _6">
    <p>
     A good understanding of the <code class="fsharp"><a href="../reference/primitives.html#members.:60::124::62:"><span
     class="co">&lt;|&gt;</span></a></code> operator is important for productively working with FParsec, so let’s have a look at its implementation:
    </p>
   </div>
   <div class="para _7 lcinp">
<pre class="code fsharp"><span class="ck">let</span> <span class="cp">(</span><a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a><span class="cp">)</span> <span class="cp">(</span><span class="ci">p1</span><span class="cp">:</span> <a href="../reference/primitives.html#members.Parser"><span class="ci">Parser</span></a><span class="cp">&lt;</span><span class="ctv">'a</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span><span class="cp">)</span> <span class="cp">(</span><span class="ci">p2</span><span class="cp">:</span> <a href="../reference/primitives.html#members.Parser"><span class="ci">Parser</span></a><span class="cp">&lt;</span><span class="ctv">'a</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span><span class="cp">)</span> <span class="cp">:</span> <a href="../reference/primitives.html#members.Parser"><span class="ci">Parser</span></a><span class="cp">&lt;</span><span class="ctv">'a</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span> <span class="cp">=</span>
    <span class="ck">fun</span> <span class="ci">stream</span> <span class="cr">-&gt;</span>
        <span class="ck">let</span> <span class="ci">stateTag</span> <span class="cp">=</span> <span class="ci">stream</span><span class="cm">.</span><a href="../reference/charstream.html#CharStream.members.StateTag"><span class="ci">StateTag</span></a>
        <span class="ck">let</span> <span class="ck">mutable</span> <span class="ci">reply</span> <span class="cp">=</span> <span class="ci">p1</span> <span class="ci">stream</span>
        <span class="ck">if</span> <span class="ci">reply</span><span class="cm">.</span><a href="../reference/reply.html#members.Status"><span class="ci">Status</span></a> <span class="co">=</span> <a href="../reference/primitives.html#members.Error"><span class="ci">Error</span></a> <span class="co">&amp;&amp;</span> <span class="ci">stateTag</span> <span class="co">=</span> <span class="ci">stream</span><span class="cm">.</span><a href="../reference/charstream.html#CharStream.members.StateTag"><span class="ci">StateTag</span></a> <span class="ck">then</span>
            <span class="ck">let</span> <span class="ci">error1</span> <span class="cp">=</span> <span class="ci">reply</span><span class="cm">.</span><a href="../reference/reply.html#members.Error"><span class="ci">Error</span></a>
            <span class="ci">reply</span> <span class="co">&lt;-</span> <span class="ci">p2</span> <span class="ci">stream</span>
            <span class="ck">if</span> <span class="ci">stateTag</span> <span class="co">=</span> <span class="ci">stream</span><span class="cm">.</span><a href="../reference/charstream.html#CharStream.members.StateTag"><span class="ci">StateTag</span></a> <span class="ck">then</span>
                <span class="ci">reply</span><span class="cm">.</span><a href="../reference/reply.html#members.Error"><span class="ci">Error</span></a> <span class="co">&lt;-</span> <a href="../reference/error.html#members.mergeErrors"><span class="ci">mergeErrors</span></a> <span class="ci">reply</span><span class="cm">.</span><a href="../reference/reply.html#members.Error"><span class="ci">Error</span></a> <span class="ci">error1</span>
        <span class="ci">reply</span>
</pre>
   </div>
   <div class="para _8">
    <p>
     As you can see, the parser <code class="fsharp"><span class="ci">p1</span> <a href="../reference/primitives.html#members.:60::124::62:"><span
     class="co">&lt;|&gt;</span></a> <span class="ci">p2</span></code> works as follows: First, it applies the parser <code class="fsharp"><span
     class="ci">p1</span></code> to the input stream. If <code class="fsharp"><span class="ci">p1</span></code> succeeds, the reply of <code
     class="fsharp"><span class="ci">p1</span></code> is returned. If <code class="fsharp"><span class="ci">p1</span></code> fails with a non‐fatal
     error (i.e. with the status <code class="fsharp"><a href="../reference/primitives.html#members.Error"><span class="ci">Error</span></a></code>,
     not <code class="fsharp"><a href="../reference/primitives.html#members.FatalError"><span class="ci">FatalError</span></a></code>) and <em>without
     changing the parser state</em>, the parser <code class="fsharp"><span class="ci">p2</span></code> is applied. If <code class="fsharp"><span
     class="ci">p2</span></code> does not change the parser state, the error messages from both parsers are merged. (We compare the <code
     class="fsharp"><a href="../reference/charstream.html#CharStream.members.StateTag"><span class="ci">StateTag</span></a></code> values instead of
     the actual parser states for optimization reasons, see <a href="applying-parsers-in-sequence.html#the-statetag">section 5.4.3</a>.)
    </p>
   </div>
   <div class="para _9">
    <p>
     The most important point to note here is that <code class="fsharp"><span class="ci">p1</span> <a
     href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <span class="ci">p2</span></code> will always
     return with the reply of <code class="fsharp"><span class="ci">p1</span></code> if <code class="fsharp"><span class="ci">p1</span></code> changes
     the parser state, even if <code class="fsharp"><span class="ci">p1</span></code> eventually fails. Remember that the stream position is part of
     the parser state, so if <code class="fsharp"><span class="ci">p1</span></code> fails after consuming input, <code class="fsharp"><span
     class="ci">p2</span></code> will not be applied. Since a parser usually consumes input as soon as it can accept at least one atomic token from
     the input, this means that <code class="fsharp"><span class="ci">p1</span> <a href="../reference/primitives.html#members.:60::124::62:"><span
     class="co">&lt;|&gt;</span></a> <span class="ci">p2</span></code> by default implements backtracking with only a &#x201C;one token
     look‐ahead&#x201D;.
    </p>
   </div>
   <div class="para _0 lcinp">
    <p>Consider the following example:</p>
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">parserA</span> <span class="cp">=</span> <a href="../reference/charparsers.html#members.spaces"><span class="ci">spaces</span></a> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span>
<span class="ck">let</span> <span class="ci">parserB</span> <span class="cp">=</span> <a href="../reference/charparsers.html#members.spaces"><span class="ci">spaces</span></a> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="cs"><span class="cld">"</span>b<span class="crd">"</span></span>
<a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><span class="ci">parserA</span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <span class="ci">parserB</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span> b<span class="crd">"</span></span><span class="cp">;;</span>
</pre>
<pre class="code fsharp"><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><span class="ci">parserA</span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <span class="ci">parserB</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span> b<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;string,unit&gt; = Failure:
Error in Ln: 1 Col: 2
 b
 ^
Expecting: 'a'
</span></pre>
   </div>
   <div class="para _1">
    <p>
     The combined parser fails because <code class="fsharp"><span class="ci">parserA</span></code> fails after consuming the whitespace, so that <code
     class="fsharp"><span class="ci">parserB</span></code> never gets tried.
    </p>
   </div>
   <div class="para _2 lcinp">
    <p>Of course, this simple parser could be easily fixed by factoring out the common prefix:</p>
<pre class="code fsharp"><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><a href="../reference/charparsers.html#members.spaces"><span class="ci">spaces</span></a> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <span class="cp">(</span><a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="cs"><span class="cld">"</span>b<span class="crd">"</span></span><span class="cp">)</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span> b<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;string,unit&gt; = Success: "b"
</span></pre>
   </div>
   <div class="para _3 lcinp">
    <p>
     The restriction of the look‐ahead in <code class="fsharp"><span class="ci">p1</span> <a
     href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <span class="ci">p2</span></code> may strike you
     as odd at first, but it has two big advantages:
    </p>
    <ol class="l1">
     <li class="_1">
      The error reporting is simplified and error messages are easier to understand because terminal errors can only occur at one position at a time.
     </li>
     <li class="_2">
      Parser developers are guided towards more efficient grammar implementations because parsers requiring more than a one token look‐ahead need to
      be explicitly annotated with the <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span
      class="ci">attempt</span></a></code> or <code class="fsharp"><a href="../reference/primitives.html#members.:62::62::63:"><span
      class="co">&gt;&gt;?</span></a></code> combinators (see the <a href="looking-ahead-and-backtracking.html">next chapter</a>).<sup
      class="fn-mark"><a id=":FN:1:B:" href="#:FN:1">[1]</a></sup>
     </li>
    </ol>
   </div>
  </div>
  <div class="fn-list">
   <div class="fn-title">Footnotes:</div>
   <table class="fn">
    <tr class="fn _1">
     <th class="fn _1"><a class="footnote-backlink" id=":FN:1" href="#:FN:1:B:">[1]</a></th>
     <td class="fn _2">
      In case you’re wondering: No, we’re not trying to sell a design limitation as a feature here. In Parsec, the Haskell library on which FParsec’s
      design was originally based, the limited look‐ahead is essential for the library design, because it allows Parsec to exploit Haskell’s laziness
      in order to ensure space efficiency. FParsec has a different implementation in which the limited look‐ahead has <a
      href="../reference/charstream.html#CharStream.remarks.block-wise">no effect on space efficiency</a>. We stick to the limited look‐ahead because
      we think it’s the appropriate default behaviour for a parser combinator library like FParsec. Now, admittedly, if FParsec could automatically
      optimize the implementation of a parser in a way that minimized backtracking, e.g. by automatically left‐factoring grammars, then backtracking
      would be less of a problem and a different default behaviour might become more attractive.
     </td>
    </tr>
   </table>
  </div>
 </div>
 </div>
 </div>
 </div>
</body>
</html>