home *** CD-ROM | disk | FTP | other *** search
- /*
- * LSystem.C - methods for classes ProductionSlot, Table and LSystem.
- *
- * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
- * University of Berne, Switzerland
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- */
-
- #include "LSystem.h"
- #include "Options.h"
-
- implementList(TableList, TablePtr);
- implementList(DerivationList, DerivationItemPtr);
-
- //___________________________________________________________ Table Hashing
-
- unsigned int modHash(const char* aString, long arg) {
- return (hash(aString, arg) % HASH_ARRAY_SIZE);
- }
-
- static inline unsigned int rehash(int place) {
- return (place + 17) % HASH_ARRAY_SIZE;
- }
-
- //___________________________________________________________ Production
-
- ProductionSlot::ProductionSlot(Production* p)
- : name(p->name())
- {
- argCount = p->argCount();
-
- productions = new ProductionList(1);
- productions->append(p);
-
- }
-
- ProductionSlot::~ProductionSlot()
- {
- delete productions;
- }
-
- void ProductionSlot::append(Production* p)
- {
- productions->append(p);
- }
-
- int ProductionSlot::match(Production* p) const
- {
- return (name == p->name()) && (argCount == p->argCount());
- }
-
- int ProductionSlot::match(Module* m) const
- {
- return (name == m->name()) && (argCount == m->argCount());
- }
-
- //___________________________________________________________ Table
-
- /*
- * Takes a list of productions and stores them in a hashed array
- * to achieve fast access.
- */
-
- Table::Table(const Name& n, ProductionList* plist)
- : _name(n), productions(plist)
- {
- register long i;
- int hashvalue;
-
- /*
- * Initialize the array.
- */
- for (i=0; i<HASH_ARRAY_SIZE; i++)
- pslots[i] = NULL;
-
- for (i=0; i<plist->count(); i++) {
- hashvalue = plist->item(i)->hashValue();
-
- /*
- * Try to find a slot to store the production; a infinite loop can
- * occur, if we need more than HASH_ARRAY_SIZE ProductionSlots,
- * which will rarely happen!
- */
- while(1) {
- /*
- * No ProductionSlot yet -> instantiate a new one.
- */
- if (pslots[hashvalue] == NULL) {
- pslots[hashvalue] = new ProductionSlot(plist->item(i));
- break;
- }
- /*
- * ProductionSlot is present, but is it the right on for the
- * production.
- */
- else if (pslots[hashvalue]->match(plist->item(i))) {
- pslots[hashvalue]->append(plist->item(i));
- break;
- }
- /*
- * Not lucky yet, try another place.
- */
- else
- hashvalue = rehash(hashvalue);
- }
- }
- }
-
- Table::~Table()
- {
- long i;
-
- for (i=0; i<productions->count(); i++)
- delete productions->item(i);
- delete productions;
-
- for (i=0; i<HASH_ARRAY_SIZE; i++)
- if (pslots[i])
- delete pslots[i];
- }
-
- /*
- * Apply steps-times the productions of the table to the given list of
- * modules.
- */
-
- ModuleList* Table::execute(ModuleList* m, int steps)
- {
- result = new ModuleList(1000);
-
- for (register long i=0; i<m->count(); i++)
- rexecute(m->item(i), steps);
- delete m;
-
- return result;
- }
-
- /*
- * Recursively apply the productions of the table to the given module.
- */
-
- void Table::rexecute(Module* m, int steps)
- {
- ModuleList* r;
- if (steps != 0) // -1 = INFINITY, STOP when 0
- if (r = apply(m)) {
- for (register long i=0; i<r->count(); i++)
- rexecute(r->item(i), steps-1);
- delete m;
- delete r;
- }
- else
- result->append(m);
- else
- result->append(m);
- }
-
- /*
- * Look for a matching production and evaluate the replacement for
- * the module m.
- */
-
- ModuleList* Table::apply(Module* m)
- {
- int hashvalue = m->hashValue();
-
- while(1) {
- /*
- * Is there a production which matches the module name and the
- * number number of arguments of the module m.
- */
- if (pslots[hashvalue])
- if (pslots[hashvalue]->match(m)) {
- /*
- * Yes: bind the actual parameters of the module to the formal
- * ones of the productions stored in the ProductionSlot.
- */
- m->bind();
- break;
- }
- else
- hashvalue = rehash(hashvalue);
- else
- return NULL; // no production could be applied
- }
-
- /*
- * Clone the successor of the first production in the ProductionSlot
- * which condition evaluates to TRUE.
- */
- ProductionList* pl = pslots[hashvalue]->productions;
- for (register long i=0; i<pl->count(); i++)
- if (pl->item(i)->evalCondition())
- return pl->item(i)->cloneSuccessor();
-
- /*
- * No production could be applied.
- */
- return NULL;
- }
-
- ostream& operator<<(ostream& os, const Table& t)
- {
- os << "table " << t._name << '\n';
- for (long i=0; i<t.productions->count(); i++)
- os << " " << *t.productions->item(i);
-
- return os;
- }
-
- //___________________________________________________________ LSystem
-
- ostream& operator<<(ostream& os, const DerivationItem& d)
- {
- os << d.table->name() << '(';
- if (d.steps < 0)
- os << "infinity";
- else
- os << d.steps;
- os << ')';
-
- return os;
- }
-
- LSystem::LSystem(const Name& n, TableList* t, ProdModuleList* a,
- DerivationList* d)
- : name(n), tables(t), axiom(a), derivation(d)
- {}
-
- LSystem::~LSystem()
- {
- long i;
- for (i=0; i<tables->count(); i++)
- delete tables->item(i);
- delete tables;
- for (i=0; i<axiom->count(); i++)
- delete axiom->item(i);
- delete axiom;
- for (i=0; i<derivation->count(); i++)
- delete derivation->item(i);
- delete derivation;
- }
-
- ModuleList* LSystem::execute()
- {
- ModuleList* result;
- DerivationItem* d;
- register long i;
-
- /*
- * Replace the ProdModuleList by a ModuleList -> 0. iteration step.
- */
- result = new ModuleList(axiom->count());
- for (i=0; i<axiom->count(); i++)
- result->append(new Module(axiom->item(i)));
-
- if (!theOptions.quiet) cerr << "\nExecution:\n";
-
- for (i=0; i<derivation->count(); i++) {
- d = derivation->item(i);
- if (!theOptions.quiet) cerr << "\tTable " << *d << '\n';
- result = d->table->execute(result, d->steps);
- }
- if (theOptions.verbose)
- cerr << "\n\n#Modules: " << result->count() << "\n\n";
-
- return result;
- }
-
- ostream& operator<<(ostream& os, const LSystem& lsys)
- {
- os << "lsystem " << lsys.name << "\n\n";
-
- for (long i=0; i<lsys.tables->count(); i++)
- os << *lsys.tables->item(i) << '\n';
-
- os << "Axiom ";
- for (i=0; i<lsys.axiom->count(); i++)
- os << *lsys.axiom->item(i) << ' ';
- os << '\n';
-
- os << "Derivation ";
- for (i=0; i<lsys.derivation->count(); i++)
- os << *lsys.derivation->item(i) << ' ';
- os << '\n';
-
- return os;
- }
-