docs: def check_grammar(self, ok_start_symbols = set(),
                        out=sys.stderr):
          '''
          Check grammar for:
          -  unused left-hand side nonterminals that are neither start symbols
             or listed in ok_start_symbols
          -  unused right-hand side nonterminals, i.e. not tokens
          -  right-recursive rules. These can slow down parsing.
          '''
          warnings = 0
          (lhs, rhs, tokens, right_recursive,
           dup_rhs) = self.check_sets()
          if lhs - ok_start_symbols:
              warnings += 1
              out.write("LHS symbols not used on the RHS:\n")
              out.write("  " + (', '.join(sorted(lhs)) + "\n"))
          if rhs:
              warnings += 1
              out.write("RHS symbols not used on the LHS:\n")
              out.write((', '.join(sorted(rhs))) + "\n" )
          if right_recursive:
              warnings += 1
              out.write("Right recursive rules:\n")
              for rule in sorted(right_recursive):
                  out.write("  %s ::= %s\n" % (rule[0], ' '.join(rule[1])))
                  pass
              pass
          if dup_rhs:
              warnings += 1
              out.write("Nonterminals with the same RHS\n")
              for rhs in sorted(dup_rhs.keys()):
                  out.write("  RHS: %s\n" % ' '.join(rhs))
                  out.write("  LHS: %s\n" % ', '.join(dup_rhs[rhs]))
                  out.write("  ---\n")
                  pass
              pass
          return warnings