Source

fparsec / Doc / html / users-guide / looking-ahead-and-backtracking.html

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
<!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>Looking ahead and backtracking</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>
             <tr class="nav-entry n3 _6">
              <td class="nav-number n3">
               <a href="parsing-alternatives.html"><span class="section-number">6</span><span class="nav-space"></span></a>
              </td>
              <td class="nav-title n3"><a href="parsing-alternatives.html">Parsing alternatives</a></td>
             </tr>
            </tbody>
            <tbody class="nav-open selected n3">
             <tr class="nav-entry selected n3 _7">
              <td class="nav-number selected n3"><a href="#"><span class="section-number">7</span><span class="nav-space"></span></a></td>
              <td class="nav-title selected n3"><a href="#">Looking ahead and backtracking</a></td>
             </tr>
             <tr class="nav-subentries selected n3 _7">
              <td class="nav-subentries-number selected n3"></td>
              <td class="nav-subentries selected n3">
               <table class="nav n4">
                <tbody class="nav-before-open n4">
                 <tr class="nav-entry n4 _1">
                  <td class="nav-number n4"><a href="#backtracking"><span class="section-number">1</span><span class="nav-space"></span></a></td>
                  <td class="nav-title n4"><a href="#backtracking">Backtracking</a></td>
                 </tr>
                 <tr class="nav-entry n4 _2">
                  <td class="nav-number n4"><a href="#parser-predicates"><span class="section-number">2</span><span class="nav-space"></span></a></td>
                  <td class="nav-title n4"><a href="#parser-predicates">Parser predicates</a></td>
                 </tr>
                </tbody>
               </table>
              </td>
             </tr>
            </tbody>
            <tbody class="nav-after-open n3">
             <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>Looking ahead and backtracking
  </span>
 </div>
 <div class="section s2">
  <h1 class="title h2"><span><span class="section-number">5.7</span> Looking ahead and backtracking</span></h1>
  <div id="backtracking" class="section s3">
   <h2 class="title h3"><span><span class="section-number">5.7.1</span> Backtracking</span></h2>
   <div class="intro i3">
    <div class="para _1">
     <p>
      Sometimes you need more than the default one token look‐ahead of <code class="fsharp"><a
      href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a></code>, either because it really can’t be
      avoided or because avoiding it would be too inconvenient. In those instances you can use one of the combinators <code class="fsharp"><a
      href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code>, <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a></code>, <code class="fsharp"><a
      href="../reference/primitives.html#members...:62::62::63:"><span class="co">.&gt;&gt;?</span></a></code> or <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62::61::63:"><span class="co">&gt;&gt;=?</span></a></code> to force a parser to backtrack after
      an error.
     </p>
    </div>
    <div class="para _2">
     <p>The <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> combinator</p>
<pre class="code fsharp"><span class="ck">val</span> <a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a><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>
</pre>
     <p>
      takes a parser as the argument and returns a wrapped parser that behaves exactly like the argument, except that if the argument parser fails
      with an output state different from the input state or with a fatal error, the wrapped parser will backtrack to the original input state and
      report a non‐fatal error.
     </p>
    </div>
    <div class="para _3 lcinp">
     <p>
      You can observe the effect of the <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span
      class="ci">attempt</span></a></code> combinator in the following error message:
     </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/primitives.html#members.attempt"><span class="ci">attempt</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.: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><span class="cp">)</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>ac<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: 1
ac
^

The parser backtracked after:
  Error in Ln: 1 Col: 2
  ac
   ^
  Expecting: 'b'
</span></pre>
    </div>
    <div class="para _4">
     <p>
      The next example demonstrates the effect of <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span
      class="ci">attempt</span></a></code> on the choice combinator.
     </p>
    </div>
    <div class="para _5 lcinp">
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">str</span> <span class="ci">s</span> <span class="cp">=</span> <a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="ci">s</span>
<span class="ck">let</span> <span class="ci">ab</span> <span class="cp">=</span> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span> <a href="../reference/primitives.html#members...:62::62:.."><span class="co">.&gt;&gt;.</span></a> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>b<span class="crd">"</span></span>
<span class="ck">let</span> <span class="ci">ac</span> <span class="cp">=</span> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span> <a href="../reference/primitives.html#members...:62::62:.."><span class="co">.&gt;&gt;.</span></a> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>c<span class="crd">"</span></span>
</pre>
    </div>
    <div class="para _6 lcinp">
     <p>
      Without <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> the following
      test produces an error:
     </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><span class="ci">ab</span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <span class="ci">ac</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>ac<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;(string * string),unit&gt; = Failure:
Error in Ln: 1 Col: 2
ac
 ^
Expecting: 'b'
</span></pre>
    </div>
    <div class="para _7 lcinp">
     <p>
      By introducing <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> we allow
      the <code class="fsharp"><a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a></code> combinator to
      recover from the error in the first branch:
     </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><span class="cp">(</span><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a> <span class="ci">ab</span><span class="cp">)</span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <span class="ci">ac</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>ac<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;(string * string),unit&gt; = Success: ("a", "c")
</span></pre>
    </div>
    <div class="para _8">
     <p>
      Sometimes it can be a disadvantage that <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span
      class="ci">attempt</span></a></code> will trigger backtracking after any error returned by the argument parser, no matter how much content the
      parser has consumed. Consider for example a parser like <code class="fsharp"><span class="ci">prefix</span> <a
      href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <span class="ci">expr</span></code>, where <code
      class="fsharp"><span class="ci">expr</span></code> is a parser for a potentially large and deeply nested expression. If you wrap this parser
      with <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> then the wrapped
      parser will not only backtrack if an error occurs within the prefix or directly after the prefix, but also if it occurs anywhere in the
      expression. However, in most cases you only want the parser to backtrack if the error occurs directly after the prefix, not if the error occurs
      deeply inside the expression parser. For situations like this FParsec defines the <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a></code>, <code class="fsharp"><a
      href="../reference/primitives.html#members...:62::62::63:"><span class="co">.&gt;&gt;?</span></a></code>, <code class="fsharp"><a
      href="../reference/primitives.html#members...:62::62:..:63:"><span class="co">.&gt;&gt;.?</span></a></code> and <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62::61::63:"><span class="co">&gt;&gt;=?</span></a></code> operators.
     </p>
    </div>
    <div class="para _9">
     <p>
      The <code class="fsharp"><a href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a></code> combinator
     </p>
<pre class="code fsharp"><span class="ck">val</span> <span class="cp">(</span><a href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&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">'b</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">'b</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span>
</pre>
     <p>
      behaves like the <code class="fsharp"><a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a></code>
      operator, except that <code class="fsharp"><span class="ci">p1</span> <a href="../reference/primitives.html#members.:62::62::63:"><span
      class="co">&gt;&gt;?</span></a> <span class="ci">p2</span></code> will backtrack to the beginning if <code class="fsharp"><span
      class="ci">p2</span></code> fails with a non‐fatal error and without changing the parser state, even if <code class="fsharp"><span
      class="ci">p1</span></code> has changed the parser state. Similarly, <code class="fsharp"><a
      href="../reference/primitives.html#members...:62::62::63:"><span class="co">.&gt;&gt;?</span></a></code>, <code class="fsharp"><a
      href="../reference/primitives.html#members...:62::62:..:63:"><span class="co">.&gt;&gt;.?</span></a></code> and <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62::61::63:"><span class="co">&gt;&gt;=?</span></a></code> behave like <code class="fsharp"><a
      href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a></code>, <code class="fsharp"><a
      href="../reference/primitives.html#members...:62::62:.."><span class="co">.&gt;&gt;.</span></a></code> and <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62::61:"><span class="co">&gt;&gt;=</span></a></code>, except that they will backtrack to the
      beginning if the second parser fails with a non‐fatal error and without changing the parser state
     </p>
    </div>
    <div class="para _0">
     <p>
      The following tests illustrate the differences between backtracking implemented via <code class="fsharp"><a
      href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> and <code class="fsharp"><a
      href="../reference/primitives.html#members...:62::62:..:63:"><span class="co">.&gt;&gt;.?</span></a></code>.
     </p>
    </div>
    <div class="para _1 lcinp">
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">bInBrackets</span> <span class="cp">=</span> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>[<span class="crd">"</span></span> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>b<span class="crd">"</span></span> <a href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>]<span class="crd">"</span></span>
</pre>
    </div>
    <div class="para _2 lcinp">
     <p>
      A test with <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> on the left
      side of <code class="fsharp"><a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a></code>:
     </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><span class="cp">(</span><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a> <span class="cp">(</span><span class="ci">str</span> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span> <a href="../reference/primitives.html#members...:62::62:.."><span class="co">.&gt;&gt;.</span></a> <span class="ci">bInBrackets</span><span class="cp">)</span><span class="cp">)</span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <span class="ci">ac</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>a[B]<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;(string * string),unit&gt; = Failure:
Error in Ln: 1 Col: 2
a[B]
 ^
Expecting: 'c'
</span></pre>
    </div>
    <div class="para _3 lcinp">
     <p>
      A test with <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> on both sides
      of <code class="fsharp"><a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a></code>:
     </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><span class="cp">(</span><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a> <span class="cp">(</span><span class="ci">str</span> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span> <a href="../reference/primitives.html#members...:62::62:.."><span class="co">.&gt;&gt;.</span></a> <span class="ci">bInBrackets</span><span class="cp">)</span><span class="cp">)</span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a> <span class="ci">ac</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>a[B]<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;(string * string),unit&gt; = Failure:
Error in Ln: 1 Col: 1
a[B]
^

The parser backtracked after:
  Error in Ln: 1 Col: 2
  a[B]
   ^
  Expecting: 'c'

The parser backtracked after:
  Error in Ln: 1 Col: 3
  a[B]
    ^
  Expecting: 'b'
</span></pre>
    </div>
    <div class="para _4 lcinp">
     <p>
      A test with <code class="fsharp"><a href="../reference/primitives.html#members...:62::62:..:63:"><span class="co">.&gt;&gt;.?</span></a></code>
      instead of <code class="fsharp"><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> on the left
      side of <code class="fsharp"><a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a></code>:
     </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><span class="ci">str</span> <span class="cs"><span class="cld">"</span>a<span class="crd">"</span></span> <a href="../reference/primitives.html#members...:62::62:..:63:"><span class="co">.&gt;&gt;.?</span></a> <span class="ci">bInBrackets</span> <a href="../reference/primitives.html#members.:60::124::62:"><span class="co">&lt;|&gt;</span></a> <span class="ci">ac</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>a[B]<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;(string * string),unit&gt; = Failure:
Error in Ln: 1 Col: 3
a[B]
  ^
Expecting: 'b'
</span></pre>
    </div>
    <div class="para _5">
     <p>
      You can of course chain multiple of the <code class="fsharp"><a href="../reference/primitives.html#members.:62::62::63:"><span
      class="co">&gt;&gt;?</span></a></code> and <code class="fsharp"><a href="../reference/primitives.html#members...:62::62::63:"><span
      class="co">.&gt;&gt;?</span></a></code> operators to backtrack longer distances, like in <code class="fsharp"><span class="ci">prefix1</span> <a
      href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a> <span class="ci">prefix2</span> <a
      href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a> <span class="ci">p</span> <a
      href="../reference/primitives.html#members...:62::62::63:"><span class="co">.&gt;&gt;?</span></a> <span class="ci">postfix</span></code>.
     </p>
    </div>
    <div class="para _6 lcinp">
     <div class="admonition">
      <div class="admonition-title">Note</div>
      <div class="admonition-body">
       <div class="para _1">
        <p>
         When implementing backtracking parsers you should generally prefer the <code class="fsharp"><a
         href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a></code>, <code class="fsharp"><a
         href="../reference/primitives.html#members...:62::62::63:"><span class="co">.&gt;&gt;?</span></a></code> and <code class="fsharp"><a
         href="../reference/primitives.html#members...:62::62:..:63:"><span class="co">.&gt;&gt;.?</span></a></code> combinators to the <code
         class="fsharp"><a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a></code> combinator, because the
         former combinators offer finer control over the exact backtracking behaviour and hence will often lead to better error reporting. Note
         however that neither can completely replace the other.
        </p>
       </div>
      </div>
     </div>
    </div>
    <div class="para _7">
     <p>
      Backtracking combinators can also be useful when parsing sequences. In the chapter &#x201C;Parsing sequences&#x201D; we briefly discussed the
      following example:
     </p>
    </div>
    <div class="para _8 lcinp">
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">ws</span> <span class="cp">=</span> <a href="../reference/charparsers.html#members.spaces"><span class="ci">spaces</span></a>
<span class="ck">let</span> <span class="ci">str</span> <span class="ci">s</span> <span class="cp">=</span> <a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="ci">s</span>
<span class="ck">let</span> <span class="ci">numberInBrackets</span> <span class="cp">=</span> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>[<span class="crd">"</span></span> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a> <a href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>]<span class="crd">"</span></span> <a href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a> <span class="ci">ws</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/primitives.html#members.many"><span class="ci">many</span></a> <span class="ci">numberInBrackets</span> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>[c]<span class="crd">"</span></span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>[1] [2] [c]<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: 10
[1] [2] [c]
         ^
Expecting: integer number (32-bit, signed)
</span></pre>
    </div>
    <div class="para _9">
     <p>
      The problem here is that the argument parser to <code class="fsharp"><a href="../reference/primitives.html#members.many"><span
      class="ci">many</span></a></code> fails after consuming input if it encounters a bracket that is not followed by a digit. If we decided that
      this is a defect of the parser as opposed to the grammar, we could fix it by simply replacing a <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a></code> with <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a></code>.
     </p>
    </div>
    <div class="para _0 lcinp">
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">numberInBrackets</span> <span class="cp">=</span> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>[<span class="crd">"</span></span> <a href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a> <a href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>]<span class="crd">"</span></span> <a href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a> <span class="ci">ws</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/primitives.html#members.many"><span class="ci">many</span></a> <span class="ci">numberInBrackets</span> <a href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a> <span class="ci">str</span> <span class="cs"><span class="cld">"</span>[c]<span class="crd">"</span></span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>[1] [2] [c]<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;int32 list,unit&gt; = Success: [1; 2]
</span></pre>
    </div>
    <div class="para _1 lcinp">
     <p>
      A similar example is the <code class="fsharp"><a href="../reference/primitives.html#members.sepEndBy1"><span
      class="ci">sepEndBy1</span></a></code> combinator for parsing a sequence of one or more elements separated and optionally ended by a separator.
      If FParsec didn’t provide this combinator, you could define it yourself using <code class="fsharp"><a
      href="../reference/primitives.html#members.many"><span class="ci">many</span></a></code> and <code class="fsharp"><a
      href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a></code>:
     </p>
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">sepEndBy1_</span> <span class="ci">p</span> <span class="ci">sep</span> <span class="cp">=</span>
    <a href="../reference/primitives.html#members.pipe2"><span class="ci">pipe2</span></a> <span class="ci">p</span> <span class="cp">(</span><a href="../reference/primitives.html#members.many"><span class="ci">many</span></a> <span class="cp">(</span><span class="ci">sep</span> <a href="../reference/primitives.html#members.:62::62::63:"><span class="co">&gt;&gt;?</span></a> <span class="ci">p</span><span class="cp">)</span><span class="cp">)</span> <span class="cp">(</span><span class="ck">fun</span> <span class="ci">hd</span> <span class="ci">tl</span> <span class="cr">-&gt;</span> <span class="ci">hd</span><span class="co">::</span><span class="ci">tl</span><span class="cp">)</span> <a href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a> <a href="../reference/primitives.html#members.opt"><span class="ci">opt</span></a> <span class="ci">sep</span>
</pre>
    </div>
    <div class="para _2 lcinp">
     <p>
      The following tests show that our <code class="fsharp"><a href="../reference/primitives.html#members.sepEndBy1"><span
      class="ci">sepEndBy1</span></a></code> replacement works as expected:
     </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><span class="ci">sepEndBy1_</span> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a> <span class="cp">(</span><span class="ci">str</span> <span class="cs"><span class="cld">"</span>;<span class="crd">"</span></span><span class="cp">)</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>1;2;3<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;int32 list,unit&gt; = Success: [1; 2; 3]
</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><span class="ci">sepEndBy1_</span> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a> <span class="cp">(</span><span class="ci">str</span> <span class="cs"><span class="cld">"</span>;<span class="crd">"</span></span><span class="cp">)</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>1;2;3;<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;int32 list,unit&gt; = Success: [1; 2; 3]
</span></pre>
    </div>
    <div class="para _3">
     <p>
      Note however that in contrast to <code class="fsharp"><span class="ci">sepEndBy1_</span></code> the version of <code class="fsharp"><a
      href="../reference/primitives.html#members.sepEndBy1"><span class="ci">sepEndBy1</span></a></code> provided by FParsec doesn’t need to parse the
      separator twice when it terminates a sequence.
     </p>
    </div>
   </div>
  </div>
  <div id="parser-predicates" class="section s3">
   <h2 class="title h3"><span><span class="section-number">5.7.2</span> Parser predicates</span></h2>
   <div class="intro i3">
    <div class="para _1">
     <p>
      The backtracking combinators allow you to &#x201C;look ahead&#x201D; by tentatively parsing input and then backtracking if an error occurs.
      However, they don’t allow you to conditionally parse the input with one parser depending on the success or failure of another parser. This is
      what the following two combinators are for:
     </p>
    </div>
    <div class="para _2 lcinp">
<pre class="code fsharp"><span class="ck">val</span> <a href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a><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="ci">unit</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span>
<span class="ck">val</span> <a href="../reference/primitives.html#members.notFollowedBy"><span class="ci">notFollowedBy</span></a><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="ci">unit</span><span class="cp">,</span><span class="ctv">'u</span><span class="cp">&gt;</span>
</pre>
    </div>
    <div class="para _3">
     <p>
      The parser <code class="fsharp"><a href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a> <span
      class="ci">p</span></code> (<code class="fsharp"><a href="../reference/primitives.html#members.notFollowedBy"><span
      class="ci">notFollowedBy</span></a> <span class="ci">p</span></code>) succeeds <em>without changing the parser state</em> if <code
      class="fsharp"><span class="ci">p</span></code> succeeds (fails) when applied at the current position.
     </p>
    </div>
    <div class="para _4 lcinp">
     <p>For example, both the following parser definitions only parse positive integer literals without a leeding zero:</p>
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">p1</span> <span class="cp">=</span> <a href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a>    <span class="cp">(</span><a href="../reference/charparsers.html#members.satisfy"><span class="ci">satisfy</span></a> <span class="cp">(</span><span class="cp">(</span><span class="co">&lt;&gt;</span><span class="cp">)</span> <span class="cc"><span class="cld">'</span>0<span class="crd">'</span></span><span class="cp">)</span><span class="cp">)</span> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a>
<span class="ck">let</span> <span class="ci">p2</span> <span class="cp">=</span> <a href="../reference/primitives.html#members.notFollowedBy"><span class="ci">notFollowedBy</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>0<span class="crd">"</span></span><span class="cp">)</span>        <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a>
</pre>
    </div>
    <div class="para _5 lcinp">
     <p>
      Both definitions will correctly parse <code class="fsharp"><span class="cs"><span class="cld">"</span>123<span
      class="crd">"</span></span></code> and fail to parse <code class="fsharp"><span class="cs"><span class="cld">"</span>01<span
      class="crd">"</span></span></code>:
     </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="ci">p1</span> <span class="cs"><span class="cld">"</span>123<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;int32,unit&gt; = Success: 123
</span><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="ci">p1</span> <span class="cs"><span class="cld">"</span>01<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;int32,unit&gt; =  Failure:
Error in Ln: 1 Col: 1
01
^
Unknown Error(s)
</span><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="ci">p2</span> <span class="cs"><span class="cld">"</span>123<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;int32,unit&gt; = Success: 123
</span><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="ci">p2</span> <span class="cs"><span class="cld">"</span>01<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;int32,unit&gt; = Failure:
Error in Ln: 1 Col: 1
01
^
Unknown Error(s)
</span></pre>
    </div>
    <div class="para _6">
     <p>
      While both parsers work as expected, the generated error messages aren’t very helpful. The problem is that <code class="fsharp"><a
      href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a></code> and <code class="fsharp"><a
      href="../reference/primitives.html#members.notFollowedBy"><span class="ci">notFollowedBy</span></a></code> can’t generate better error messages,
      because they don’t know what kind of input their argument parsers accept.<sup class="fn-mark"><a id="parser-predicates.:FN:1:B:"
      href="#parser-predicates.:FN:1">[1]</a></sup> To improve the error messages you can either use the &#x201C;labeled&#x201D; combinator variants
      <code class="fsharp"><a href="../reference/primitives.html#members.followedByL"><span class="ci">followedByL</span></a></code> and <code
      class="fsharp"><a href="../reference/primitives.html#members.notFollowedByL"><span class="ci">notFollowedByL</span></a></code> or you could use
      the labelling operator <code class="fsharp"><a href="../reference/primitives.html#members.:60::63::62:"><span
      class="co">&lt;?&gt;</span></a></code> that we will discuss in the next chapter.
     </p>
    </div>
    <div class="para _7">
     <p>For example:</p>
    </div>
    <div class="para _8 lcinp">
<pre class="code fsharp"><span class="cp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><a href="../reference/primitives.html#members.followedByL"><span class="ci">followedByL</span></a> <span class="cp">(</span><a href="../reference/charparsers.html#members.satisfy"><span class="ci">satisfy</span></a> <span class="cp">(</span><span class="cp">(</span><span class="co">&lt;&gt;</span><span class="cp">)</span> <span class="cc"><span class="cld">'</span>0<span class="crd">'</span></span><span class="cp">)</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>positive int w/o leading 0<span class="crd">"</span></span> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a><span class="cp">)</span>
      <span class="cs"><span class="cld">"</span>01<span class="crd">"</span></span><span class="cp">;;</span>
<span class="ck">val</span> <span class="ci">it</span> <span class="cp">:</span> <a href="../reference/charparsers.html#members.ParserResult"><span class="ci">ParserResult</span></a><span class="cp">&lt;</span><span class="ci">int32</span><span class="cp">,</span><span class="ci">unit</span><span class="cp">&gt;</span> <span class="cp">=</span>  <a href="../reference/charparsers.html#members.Failure"><span class="ci">Failure</span></a><span class="cp">:</span>
<a href="../reference/primitives.html#members.Error"><span class="ci">Error</span></a> <span class="ck">in</span> <span class="ci">Ln</span><span class="cp">:</span> <span class="cn">1</span> <span class="ci">Col</span><span class="cp">:</span> <span class="cn">1</span>
<span class="cn">01</span>
<span class="co">^</span>
<span class="ci">Expecting</span><span class="cp">:</span> <span class="ci">positive</span> <span class="ci">int</span> <span class="ci">w</span><span class="co">/</span><span class="ci">o</span> <span class="ci">leading</span> <span class="cn">0</span>

<span class="co">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><a href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a> <span class="cp">(</span><a href="../reference/charparsers.html#members.satisfy"><span class="ci">satisfy</span></a> <span class="cp">(</span><span class="cp">(</span><span class="co">&lt;&gt;</span><span class="cp">)</span> <span class="cc"><span class="cld">'</span>0<span class="crd">'</span></span><span class="cp">)</span><span class="cp">)</span> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a> <a href="../reference/primitives.html#members.:60::63::62:"><span class="co">&lt;?&gt;</span></a> <span class="cs"><span class="cld">"</span>positive int w/o leading 0<span class="crd">"</span></span><span class="cp">)</span>
      <span class="cs"><span class="cld">"</span>01<span class="crd">"</span></span><span class="cp">;;</span>
<span class="ck">val</span> <span class="ci">it</span> <span class="cp">:</span> <a href="../reference/charparsers.html#members.ParserResult"><span class="ci">ParserResult</span></a><span class="cp">&lt;</span><span class="ci">int32</span><span class="cp">,</span><span class="ci">unit</span><span class="cp">&gt;</span> <span class="cp">=</span> <a href="../reference/charparsers.html#members.Failure"><span class="ci">Failure</span></a><span class="cp">:</span>
<a href="../reference/primitives.html#members.Error"><span class="ci">Error</span></a> <span class="ck">in</span> <span class="ci">Ln</span><span class="cp">:</span> <span class="cn">1</span> <span class="ci">Col</span><span class="cp">:</span> <span class="cn">1</span>
<span class="cn">01</span>
<span class="co">^</span>
<span class="ci">Expecting</span><span class="cp">:</span> <span class="ci">positive</span> <span class="ci">int</span> <span class="ci">w</span><span class="co">/</span><span class="ci">o</span> <span class="ci">leading</span> <span class="cn">0</span>

<span class="co">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="cp">(</span><a href="../reference/primitives.html#members.notFollowedByL"><span class="ci">notFollowedByL</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>0<span class="crd">"</span></span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>'0'<span class="crd">"</span></span> <a href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a><span class="cp">)</span> <span class="cs"><span class="cld">"</span>01<span class="crd">"</span></span><span class="cp">;;</span>
<span class="ck">val</span> <span class="ci">it</span> <span class="cp">:</span> <a href="../reference/charparsers.html#members.ParserResult"><span class="ci">ParserResult</span></a><span class="cp">&lt;</span><span class="ci">int32</span><span class="cp">,</span><span class="ci">unit</span><span class="cp">&gt;</span> <span class="cp">=</span> <a href="../reference/charparsers.html#members.Failure"><span class="ci">Failure</span></a><span class="cp">:</span>
<a href="../reference/primitives.html#members.Error"><span class="ci">Error</span></a> <span class="ck">in</span> <span class="ci">Ln</span><span class="cp">:</span> <span class="cn">1</span> <span class="ci">Col</span><span class="cp">:</span> <span class="cn">1</span>
<span class="cn">01</span>
<span class="co">^</span>
<a href="../reference/error.html#interface.Unexpected"><span class="ci">Unexpected</span></a><span class="cp">:</span> <span class="cc"><span class="cld">'</span>0<span class="crd">'</span></span>
</pre>
    </div>
    <div class="para _9">
     <p>
      The parser <code class="fsharp"><a href="../reference/primitives.html#members.notFollowedByL"><span class="ci">notFollowedByL</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>0<span class="crd">"</span></span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>'0'<span
      class="crd">"</span></span></code> from the last example could actually be simplified to <code class="fsharp"><a
      href="../reference/charparsers.html#members.notFollowedByString"><span class="ci">notFollowedByString</span></a> <span class="cs"><span
      class="cld">"</span>0<span class="crd">"</span></span></code>, which uses the specialized parser predicate <code class="fsharp"><a
      href="../reference/charparsers.html#members.notFollowedByString"><span class="ci">notFollowedByString</span></a></code>. In <a
      href="../reference/parser-overview.html#conditional-parsing-and-looking-ahead">table 6.1.9</a> you’ll find an overview of all available parser
      predicates.
     </p>
    </div>
    <div class="para _0">
     <p>
      A frequent application for the <code class="fsharp"><a href="../reference/primitives.html#members.notFollowedBy"><span
      class="ci">notFollowedBy</span></a></code> predicate are sequence parsers similar to <code class="fsharp"><a
      href="../reference/primitives.html#members.many"><span class="ci">many</span></a> <span class="cp">(</span><a
      href="../reference/primitives.html#members.notFollowedBy"><span class="ci">notFollowedBy</span></a> <span class="ci">pEnd</span> <a
      href="../reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <span class="ci">p</span><span
      class="cp">)</span> <a href="../reference/primitives.html#members...:62::62:"><span class="co">.&gt;&gt;</span></a> <span
      class="ci">pEnd</span></code>. If you are writing such a parser, you should check whether you can replace it with an application of one of the
      <a href="../reference/primitives.html#interface.manyTill-parsers"><code class="fsharp"><span class="ci">manyTill</span></code> parsers</a>.
      Please consult the reference for more details.
     </p>
    </div>
    <div class="para _1">
     <p>
      Before we conclude this chapter we want to emphasize that you’re not limited to the built‐in (backtracking) combinators of FParsec. A great
      advantage of FParsec is the simplicity with which you can write custom combinators using the low‐level API.
     </p>
    </div>
    <div class="para _2">
     <p>For example, you could define a combinator that backtracks if the result of the argument parser doesn’t satisfy a predicate function:</p>
    </div>
    <div class="para _3 lcinp">
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">resultSatisfies</span> <span class="ci">predicate</span> <span class="ci">msg</span> <span class="cp">(</span><span class="ci">p</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="ci">_</span><span class="cp">,</span><span class="ci">_</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="ci">_</span><span class="cp">,</span><span class="ci">_</span><span class="cp">&gt;</span> <span class="cp">=</span>
    <span class="ck">let</span> <span class="ci">error</span> <span class="cp">=</span> <a href="../reference/error.html#members.messageError"><span class="ci">messageError</span></a> <span class="ci">msg</span>
    <span class="ck">fun</span> <span class="ci">stream</span> <span class="cr">-&gt;</span>
      <span class="ck">let</span> <span class="ci">state</span> <span class="cp">=</span> <span class="ci">stream</span><span class="cm">.</span><a href="../reference/charstream.html#CharStream_1.members.State"><span class="ci">State</span></a>
      <span class="ck">let</span> <span class="ci">reply</span> <span class="cp">=</span> <span class="ci">p</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">&lt;&gt;</span> <a href="../reference/primitives.html#members.Ok"><span class="ci">Ok</span></a> <span class="co">||</span> <span class="ci">predicate</span> <span class="ci">reply</span><span class="cm">.</span><a href="../reference/reply.html#members.Result"><span class="ci">Result</span></a> <span class="ck">then</span> <span class="ci">reply</span>
      <span class="ck">else</span>
          <span class="ci">stream</span><span class="cm">.</span><a href="../reference/charstream.html#CharStream_1.members.BacktrackTo"><span class="ci">BacktrackTo</span></a><span class="cp">(</span><span class="ci">state</span><span class="cp">)</span> <span class="clc"><span class="cld">//</span> backtrack to beginning</span>
          <a href="../reference/reply.html"><span class="ci">Reply</span></a><span class="cp">(</span><a href="../reference/primitives.html#members.Error"><span class="ci">Error</span></a><span class="cp">,</span> <span class="ci">error</span><span class="cp">)</span>
</pre>
    </div>
    <div class="para _4">
     <p>With this combinator you could conveniently define a parser for positive ints:</p>
    </div>
    <div class="para _5 lcinp">
<pre class="code fsharp"><span class="ck">let</span> <span class="ci">positiveInt</span> <span class="cp">=</span> <a href="../reference/charparsers.html#members.pint32"><span class="ci">pint32</span></a> <span class="co">|&gt;</span> <span class="ci">resultSatisfies</span> <span class="cp">(</span><span class="ck">fun</span> <span class="ci">x</span> <span class="cr">-&gt;</span> <span class="ci">x</span> <span class="co">&gt;</span> <span class="cn">0</span><span class="cp">)</span>
                                            <span class="cs"><span class="cld">"</span>The integer must be positive.<span class="crd">"</span></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="ci">positiveInt</span> <span class="cs"><span class="cld">"</span>1<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">val it : ParserResult&lt;int32,unit&gt; = Success: 1
</span><span class="cmd"><span class="cmdp">&gt;</span> <a href="../reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="ci">positiveInt</span> <span class="cs"><span class="cld">"</span>-1<span class="crd">"</span></span><span class="cp">;;</span></span>
<span class="cout">Error in Ln: 1 Col: 1
-1
^
The integer must be positive.
</span></pre>
    </div>
   </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="parser-predicates.:FN:1" href="#parser-predicates.:FN:1:B:">[1]</a></th>
     <td class="fn _2">
      In the case of <code class="fsharp"><a href="../reference/primitives.html#members.notFollowedBy"><span class="ci">notFollowedBy</span></a> <span
      class="ci">p</span></code> the problem is clear: <code class="fsharp"><a href="../reference/primitives.html#members.notFollowedBy"><span
      class="ci">notFollowedBy</span></a> <span class="ci">p</span></code> fails if <code class="fsharp"><span class="ci">p</span></code> succeeds and
      when <code class="fsharp"><span class="ci">p</span></code> succeeds, <code class="fsharp"><span class="ci">p</span></code> doesn’t generate an
      error message that <code class="fsharp"><a href="../reference/primitives.html#members.notFollowedBy"><span
      class="ci">notFollowedBy</span></a></code> could reuse. In the case of <code class="fsharp"><a
      href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a> <span class="ci">p</span></code> the situation is
      different: <code class="fsharp"><a href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a> <span
      class="ci">p</span></code> fails if <code class="fsharp"><span class="ci">p</span></code> fails, so <code class="fsharp"><a
      href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a></code> could try to reuse the error messages
      generated by <code class="fsharp"><span class="ci">p</span></code>. However, the error messages generated by the argument parser will in
      practice often not suffice to explain what kind of input is expected. So, for reasons of consistency and performance, <code class="fsharp"><a
      href="../reference/primitives.html#members.followedBy"><span class="ci">followedBy</span></a></code> doesn’t even try to reuse the error
      messages generated by the argument parser.
     </td>
    </tr>
   </table>
  </div>
 </div>
 </div>
 </div>
 </div>
</body>
</html>