Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.csd.uwm.edu!cs.utexas.edu!sun-barr!decwrl!megatest!djones From: djones@megatest.UUCP (Dave Jones) Newsgroups: comp.lang.c Subject: Oh noooooo!! Message-ID: <7598@goofy.megatest.UUCP> Date: 6 Sep 89 06:43:48 GMT Organization: Megatest Corporation, San Jose, Ca Lines: 144 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; }