Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If you can factor <code>parser1</code> so that is defined like so:</p> <pre><code>parser1 = (try parser2) &lt;|&gt; parser1extra </code></pre> <p>Then the problem becomes a list of <code>parser1extra</code> or <code>parser2</code> that must end in the later. You can code that as:</p> <pre><code>parserList = liftM2 (:) (try parser1extra) parserList &lt;|&gt; liftM2 (:) (try parser2) (option [] parserList) </code></pre> <p>You may or may not need the <code>try</code> calls depending on if those parsers have any prefix overlap.</p> <p>If you don't want the return value to be a list, but instead your AParse datum, then you could re-write it this way:</p> <pre><code>parserList = do a &lt;- try parser1extra prefix a parserList &lt;|&gt; do a &lt;- try parser2 option (AParse [] a) (prefix a parserList) where prefix a p = do (AParse as t) &lt;- p return $ (AParse (a:as) t) </code></pre> <p>Or, a full example:</p> <pre><code>import Control.Monad import Text.ParserCombinators.Parsec parseNum = do { v &lt;- many1 digit; spaces; return v } parseWord = do { v &lt;- many1 letter; spaces; return v } parsePart = parseNum &lt;|&gt; parseWord parsePartListEndingInWord = liftM2 (:) (try parseNum) parsePartListEndingInWord &lt;|&gt; liftM2 (:) (try parseWord) (option [] parsePartListEndingInWord) </code></pre> <p>Actually, the calls to try aren't needed in this case, as <code>parseNum</code> and <code>parseWord</code> match no common prefix. Notice that <code>parsePartListEndingInWord</code> doesn't actually reference <code>parsePart</code>, but instead, the two options that make up <code>parsePart</code>'s definition</p> <hr> <p>(Original answer, solving a somewhat different situation:)</p> <p>How about something like:</p> <pre><code>parserTest = between (char '[') (char ']') $ do p1s &lt;- try parser1 `endBy` char ',' p2 &lt;- parser2 return $ AParse p1s p2 </code></pre> <p>Taking the punctuation out of your parsers and up into parseTest allows you to use the combinators <code>between</code> and <code>endBy</code> to do the work for you. Lastly, the <code>try</code> is there so that if <code>parser1</code> and <code>parser2</code> match a common prefix, <code>endBy</code> will perform the correct full backup to beginning of the common prefix.</p> <p>Depending on your parsers, it is possible that you can leave the punctuation matching inside your sub-parsers, and all you need might be the a <code>try</code> around <code>parser1</code>:</p> <pre><code>parseTest = do parse1 &lt;- many (try parser1) parse2 &lt;- parser2 return AParse parse1 parse2 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload