>>> from lepl import *
>>> class Term(Node): pass
>>> class Factor(Node): pass
>>> class Expression(Node): pass
>>> expr = Delayed()
>>> number = Digit()[1:,...] > 'number'
>>> spaces = Drop(Regexp(r'\s*'))
>>> with Separator(spaces):
>>> term = number | '(' & expr & ')' > Term
>>> muldiv = Any('*/') > 'operator'
>>> factor = term & (muldiv & term)[:] > Factor
>>> addsub = Any('+-') > 'operator'
>>> expr += factor & (addsub & factor)[:] > Expression
>>> line = expr & Eos()
>>> parser = line.parse_string
>>> parser('1 + 2 * (3 + 4 - 5)')[0]
Expression
+- Factor
| +- Term
| | `- number '1'
| `- ' '
+- operator '+'
+- ' '
`- Factor
+- Term
| `- number '2'
+- ' '
+- operator '*'
+- ' '
`- Term
+- '('
+- Expression
| +- Factor
| | +- Term
| | | `- number '3'
| | `- ' '
| +- operator '+'
| +- ' '
| +- Factor
| | +- Term
| | | `- number '4'
| | `- ' '
| +- operator '-'
| +- ' '
| `- Factor
| `- Term
| `- number '5'
`- ')'
LEPL combines the simplicity and ease–of–use of a recursive descent parser with scalability (through memoisation) and advanced (but optional) features like lexing, AST generation, offside–rule, robustness to ambiguous and left–recursive grammars, etc. It is written and maintained by Andrew Cooke.