title: Python Lex-Yacc (PLY) Error recovery at the end of input
body: <h2>Problem</h2>
  
  <p>I am trying to implement an error tolerant parser using Python Lex-Yacc (PLY), but I have trouble using error recovery rules at the end of my input string.</p>
  
  <p>How can I recover from an unexpected end of input?</p>
  
  <h2>Example</h2>
  
  <p>This example grammar produces strings of the form <code>A END A END A END A END</code> <code>...</code></p>
  
  <pre class="lang-py prettyprint-override"><code>Statement   : Expressions
  
  Expressions : Expression Expressions
              | 
  
  Expression  : A END
  </code></pre>
  
  <p>I want to perform an error recovery if the END Token was omitted, so stings like <code>A A A END</code> or <code>A A A</code> will be recognized by the parser.</p>
  
  <h2>My approach</h2>
  
  <p>I added an error recovery rule, which allows me to accept input like <code>A A A END</code></p>
  
  <pre class="lang-py prettyprint-override"><code>Expression : A END
             | A error
  </code></pre>
  
  <p>Which allows me to accept the following input:
  <code>A A A END</code></p>
  
  <p>But if the last END token is omitted (<code>A A A</code>), I still get a syntax error and cannot recover.</p>
  
  <hr>
  
  <h1>Sample PLY code</h1>
  
  <pre class="lang-py prettyprint-override"><code>from __future__ import print_function
  
  # Tokens
  tokens = ('A', 'END')
  
  t_A   = r'A'
  t_END = r'END'
  t_ignore = " "
  
  def t_error(t):
      print("Illegal character '%s'" % t.value[0])
      t.lexer.skip(1)
  
  # Build the lexer
  import ply.lex as lex
  lex.lex()
  
  # Rules
  def p_statement_expr(p):
      '''statement : expressions'''
      print("parsed:", p[1])
  
  def p_expressions(p):
      '''expressions : expression expressions'''
      p[0] = [p[1]] + p[2]
  
  def p_expressions_empty(p):
      '''expressions : '''
      p[0] = list()
  
  def p_expression_pharse(p):
      '''expression : A END
                    | A error'''
      p[0] = 'A'
  
  def p_error(p):
      if p:
          print("Syntax error at '%s'" % p.value)
      else:
          print("Syntax error at EOI")
  
  import ply.yacc as yacc
  yacc.yacc()
  
  while 1:
      try:
          s = raw_input('query &gt; ')   # use input() on Python 3
      except EOFError:
          break
      yacc.parse(s)
  </code></pre>