Parse one or more expressions with helpful errors
<p>I'm using grako (a PEG parser generator library for python) to parse a simple declarative language where a document can contain one or more protocols.</p>

<p>Originally, I had the root rule for document written as:</p>

<p><code>document = {protocol}+ ;</code></p>

<p>This appropriately returns a list of protocols, but only gives helpful errors if a syntax error is in the first protocol. Otherwise, it silently discards the invalid protocol and everything after it.</p>

<p>I have also tried a few variations on:</p>

<pre><code>document = protocol document | $ ;
</code></pre>

<p>But this doesn't result in a list if there's only one protocol, and doesn't give helpful error messages either, saying only <code>no available options: (...) document</code> if any of the protocols contains an error.</p>

<p>How do I write a rule that does both of the following?:</p>

<ol>
<li>Always returns a list, even if there's only one protocol</li>
<li>Displays helpful error messages about the unsuccessful match, instead of just saying it's an invalid document or silently dropping the damaged protocol</li>
</ol>

<p>This is the solution:</p>

<pre><code>document = {protocol ~ }+ $ ;
</code></pre>

<p>If you don't add the <code>$</code> for the parser to see the end of file, the parse will succeed with one or more <em>protocol</em>, even if there are more to parse.</p>

<p>Adding the <em>cut</em> expression (<code>~</code>) makes the parser commit to what was parsed in the closest option/choice in the parse (a closure is an option of <code>X = a X|();</code>). Additional <em>cut</em> expressions within what's parsed by <code>protocol</code> will make the error messages be closer to the expected points of failure in the input.</p>

python parsing ebnf peg grako