Non-greedy matching of Word in pyparsing?
<p>I would like to match a word that ends with either <code>_foo</code> or <code>_bar</code>. I wrote this: </p>

<pre><code>identifier = Word(alphanums + '_')
string     = identifier + Suppress('_') + oneOf('foo bar')
</code></pre>

<p>Unfortunately, I realized <code>identifier</code> is greedy and consume all the keyword. </p>

<p>How do I force <code>identifier</code> to be not greedy?</p>

<pre><code>$ string.parseString('a_keyword_foo')
ParseException: Expected "_" (at char 13), (line:1, col:14)
</code></pre>

<p>Some valid keywords:</p>

<pre><code>a_keyword_foo          # ['a_keyword', 'foo']
foo_bar_foo            # ['foo_bar',   'foo']
bar_bar                # ['bar',       'bar']
</code></pre>

<p>Some invalid keywords:</p>

<pre><code>keyword_foo_foobar
2keywords_bar          # The leading number is perhaps another question...
foo _bar 
_foo
</code></pre>

<p>Once you know for what you're looking, you can use <a href="http://pyparsing.wikispaces.com/share/view/1552279" rel="nofollow"><code>pp.SkipTo</code></a>:</p>

<pre><code>In [38]: foo_or_bar = Literal('foo') | Literal('bar')

In [39]: string = SkipTo(Literal('_') + foo_or_bar) + Literal('_') + foo_or_bar

In [42]: string.parseString('frumpy _foo')
Out[42]: (['frumpy ', '_', 'foo'], {})
</code></pre>

<hr>

<p>Unfortunately, you also get this behavior, though:</p>

<pre><code>In [44]: string.parseString('frumpy _foo _foo')
Out[44]: (['frumpy ', '_', 'foo'], {})
</code></pre>

<p>in case the pattern can appear more than once.</p>

<p>The problem is that <code>pyparsing</code> doesn't do lookahead. If you're concerned about the second case too, you'll have to define it as one or more things ending with underscore + foo or bar (as above), and then take the last one.</p>

python pyparsing non-greedy