code: def debug_reduce(self, rule, tokens, parent, last_token_pos):
          
          def fix(c):
              s = str(c)
              last_token_pos = s.find('_')
              if last_token_pos == -1:
                  return s
              else:
                  return s[:last_token_pos]
  
          prefix = ''
          if parent and tokens:
              p_token = tokens[parent]
              if hasattr(p_token, 'linestart') and p_token.linestart:
                  prefix = 'L.%3d: ' % p_token.linestart
              else:
                  prefix = '       '
              if hasattr(p_token, 'offset'):
                  prefix += "%3s" % fix(p_token.offset)
                  if len(rule[1]) > 1:
                      prefix += '-%-3s ' % fix(tokens[last_token_pos-1].offset)
                  else:
                      prefix += '     '
          else:
              prefix = '               '
  
          print("%s%s ::= %s (%d)" % (prefix, rule[0], ' '.join(rule[1]), last_token_pos))
docs: Customized format and print for our kind of tokens
          which gets called in debugging grammar reduce rules