I'm creating a calculator using PLY and I want to be able to stop the parsing when it encounters a division by 0. If I raise an error, it will stop my program, which is not what I want. I want to be able to print an error message and then ignore the rest of the parsed string.
Since I'm in a loop, it will end the parsing and ask again for a new input.
while True:
question = input('>>> ')
try:
answer = parser.parse(question)
if answer is not None:
print(answer)
except EOFError:
break
I have a class (not a parsing rule) for handling numbers and operations between them. If a division by zero occurs it will call the error method, which will just print an error message for now.
def error(self, op, other):
print('Illegal operation "{} {} {}" for {}'.format(self, op, other, type(self).__name__))
Which is fine if there is nothing else after the division, but will be a problem for this: 10/0 - 3 + 2
because the parsing is continuing and multiple errors will be thrown. I want to be able to stop the parsing after the very first error.
I was thinking something like lexer.skip(1)
but for all the string, not just 1 token. Is there a similar method for this ?
Thanks a lot !
If you just want to interrupt the parse and discard the rest of the line being parsed, raise an exception (or let the Python divide by zero exception through). Here, I've created an exception class for calculator errors, so that bugs in the parser code will still result in backtraces. The code not shown is based on examples/calc/calc.py
.
class CalcError(Exception):
def __init__(self, message):
self.message = message
# ...
def p_expression_div(p):
'''expression : expression '/' expression'''
if p[3] == 0:
raise CalcError("Divide by zero")
p[0] = p[1] / p[3]
Then you just need to modify your main loop a bit:
import readline
try:
while True:
question = input('>>> ')
try:
answer = parser.parse(question)
if answer is not None:
print(answer)
except CalcError as e:
print(e.message)
except EOFError:
print()
break