I am working with library ply to make a parser for commands. Code is
def p_expr(v):
'expr : token'
... # action with token, set expr value and return
??? raise error ??? # yacc must stop parse and call p_error
def p_error(p):
print('Error!')
How to raise error?
Note that Ply does not "stop the parse" when a syntax error is encountered. It tries to do error recovery, if the grammar was built with error recovery, and as a last resort it restarts the parse as though the input had been deleted up to that point. To see this, try typing
1+2 error 3+4
into the calculator example in the Ply distribution. It will print an error message forerror
(because it's expecting an operator) and then restart the parse, so that it prints 7.If you want the parser to stop when it finds an error, you'll need to raise an exception from
p_error
. It's generally best to define your own exception class for this sort of thing. Avoid the use ofSyntaxError
because Ply handles that specially in certain cases, as we'll see below.Usually, just stopping the parser is not really what you want to do -- if you don't want to try error recovery, you should normally at least do something like throw away the rest of the input line before restarting the parse.
If you do just want to stop the parser and you raise an exception in p_error to accomplish that, then the best way to signal your own error from a parser action is to call
p_error
with the current token.If you want to trigger Ply's normal error recovery procedure, you an raise
SyntaxError
from a parser action. However, as the manual indicates, this does not callp_error
, so you'll have to do that yourself before raising the error.If you do panic mode recovery in
p_error
, then you're might be out-of-luck with custom error detection. RaisingSyntaxError
by-passes the callp_error
; while you are free to callp_error
yourself, there is no mechanism to pass a new token back to the parser. (Panic mode recovery is not an optimal error recovery technique, and it is not always necessary to return a replacement token. So this paragraph might not apply.)