Oh noooooo!!

Dave Jones djones at megatest.UUCP
Wed Sep 6 16:43:48 AEST 1989


Hi. It's me. I've been gone from comp.lang.c for several months now.
(I'll wait for the applause to die down. .. Now. That's better.)
Why the return? Well, as you probably know, the subject of the "goto"
statement comes up here rather often, leading to crazed shouting matches.

Oh nooooooo!!

About a year or two ago, I brazenly stated that I thought the
goto-statement was not necessarily a hanging offense. I was astounded
by the reaction. People posted messages stating flat out that I was
an incompetent programmer, and that software from any company unfortunate
enough ever to have had me on the payroll was suspect at best. They were
adamant; rude, I thought. I pouted.

At the time, I wanted to post an example benign goto, but grepping through the
hundred thousand or so lines of my code which I had on line yielded not one
goto of any kind. Nope, not a goto in the lot. Oh well.

But be of good cheer! I just now produced one, which I will be happy to
share with you.

The following is from a yacc-lookalike program, which I am tentatively
calling "Molly McYacc". It's no deal, Home. I started it three working
days ago, and expect to be finished sometime tonight.  And the goto stays,
thank-you-very-much.



#include "lr1.h"

/**********************************************************************
 * Verify that all nonterminal symbols can derive some string of
 * terminal symbols. If a rule derives the empty string, make particular
 * note of that. We'll use that info when generating follow-sets.
 *
 * All nonterminal symbols initially have their "derives" variable
 * set to "dont_know". That will be changed to one of these, as
 * defined in dict.h:
 *
 *    derives_nothing     This indicates an error in the grammar.
 *    derives_something   Derives some string, but not the empty string.
 *    derives_empty       Derives the empty string.
 */

void
check_derivations()
{
  Hash_iter next;
  Symbol* sym;

  /* Iterate through all symbols. */
  Hash_iter_init(&next, &symbols.table);

  while(sym = (Symbol*)Hash_iter_next(&next))
    if(sym->sym_class == nonterminal) {

      if((sym->is_a.nonterminal.derives = derives(sym)) == derives_nothing)
	error_msg("Symbol %s derives nothing.\n", sym_name(sym->sym_num));

    }
}


static
derives(lsym)
  Symbol* lsym;
{
  
  Queue_iter rule_iter;
  Rule* rule;
  int we_find_it_derives;
  
  if( lsym->is_a.nonterminal.derives != dont_know)  {
    return lsym->is_a.nonterminal.derives;
  }
  
  /* While this invocation of derives() is active, 
   * we will assert that the symbol does not derive anything.
   * Thus we avoid recursive derivations, which need not be
   * considered, and would lead us into unterminated recursion.
   * Non-recursive derivations are unaffected.
   */
  
  lsym->is_a.nonterminal.derives = derives_nothing;
  we_find_it_derives = derives_nothing;
  
  /* Iterate through all the rules that derive this
   * symbol, looking for one which derives something. [sic.]
   * If one derives the empty string, take note.
   */
  Queue_iter_init(&rule_iter, &lsym->is_a.nonterminal.rules);      
  
  while(rule = (Rule*)Queue_iter_next(&rule_iter)) {
    
    /* Iterate through the right-hand-side to see if all symbols
     * there derive something. Notice if they all derive the empty
     * string or not.
     */
    
    Queue_iter rsym_iter;
    Symbol* rsym;
    int all_derive_empty = 1;
    
    Queue_iter_init(&rsym_iter, &rule->rhs);
    
    while(rsym = (Symbol*)Queue_iter_next(&rsym_iter)) {
      if(rsym->sym_class == terminal)
	all_derive_empty = 0;
      else
	switch (derives(rsym)) {
	case derives_nothing:
	  goto next_rule;
	case derives_something:
	  all_derive_empty = 0;
	  break;
	case derives_empty:
	  break;
	}
    }
    
    /* If we get here, all symbols on the rhs are proven
     * to derive something.
     */
    
    if(all_derive_empty) {
      return lsym->is_a.nonterminal.derives = derives_empty;
    }
    else {
      lsym->is_a.nonterminal.derives =
	we_find_it_derives = derives_something;
    }
    
    
  next_rule: continue;
    
  }
  
  
  if( we_find_it_derives == derives_nothing )
    lsym->is_a.nonterminal.derives = dont_know;
  
  return we_find_it_derives;
 
}



More information about the Comp.lang.c mailing list