SORRY - Lepl is no longer being developed.
There's also LEPL - http://www.acooke.org/lepl
Here's a quick solution I wrote during breakfast:
pl6 src: python3
Python 3.1 (r31:73572, Oct 24 2009, 05:39:09)
[GCC 4.4.1 [gcc-4_4-branch revision 150839]] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from lepl import *
>>>
>>> class Alternatives(Node):
... pass
...
>>> class Query(Node):
... pass
...
>>> class Text(Node):
... pass
...
>>> def compile():
... qualifier = Word() & Drop(':') > 'qualifier'
... word = ~Lookahead('OR') & Word()
... phrase = String()
... text = phrase | word
... word_or_phrase = (Optional(qualifier) & text) > Text
... space = Drop(Space()[1:])
... query = word_or_phrase[1:, space] > Query
... separator = Drop(space & 'OR' & space)
... alternatives = query[:, separator] > Alternatives
... return alternatives.string_parser()
...
>>> parser = compile()
>>>
>>> alternatives = parser('all of these words "with this phrase" '
... 'OR that OR this site:within.site '
... 'filetype:ps from:lastweek')[0]
>>>
>>> print(str(alternatives))
Alternatives
+- Query
| +- Text
| | `- 'all'
| +- Text
| | `- 'of'
| +- Text
| | `- 'these'
| +- Text
| | `- 'words'
| `- Text
| `- 'with this phrase'
+- Query
| `- Text
| `- 'that'
`- Query
+- Text
| `- 'this'
+- Text
| +- qualifier 'site'
| `- 'within.site'
+- Text
| +- qualifier 'filetype'
| `- 'ps'
`- Text
+- qualifier 'from'
`- 'lastweek'
>>>
I would argue that LEPL isn't a "toy" - although it's recursive descent, it includes memoisation and trampolining, which help avoid some of the limitations of that approach.
However, it is pure Python, so it's not super-fast, and it's in active development (a new release, 4.0, with quite a few fixes and improvements, is coming relatively soon).