How can I throw an error in ply-yacc inside a special parse function?

538 Views Asked by At

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?

1

There are 1 best solutions below

0
On

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 for error (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 of SyntaxError 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 call p_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. Raising SyntaxError by-passes the call p_error; while you are free to call p_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.)