g = Grammar()
g['expr'] = g['addend'] & pRep(pLiteral('+') & g['addend'])
g['addend'] = g['factor'] & pRep(pLiteral('*') & g['factor'])
g['factor'] = g['number'] | g['parenthetic']
g['number'] = reduce(pOr, (pLiteral(c) for c in '0123456789'))
g['parenthetic'] = pLiteral('(') & g['expr'] & pLiteral(')')
"""
### various test results for negative test cases.
### (note the automatic nice error messages, derived
### from grammar element names)
case ''
expected number, found end of stream
r: -1 len: 0 parsed: False
PASS
case '1+'
expected number, found end of stream
r: -1 len: 2 parsed: False
PASS
case '+1'
expected number, found +
r: -1 len: 2 parsed: False
PASS
case '((0)'
expected addend, found (
r: -1 len: 4 parsed: False
PASS
"""