#ifndef COMPLEXSUP_H #define COMPLEXSUP_H #include #include using namespace std; extern "C" { #include #include "classes.h" #include "../express/express.h" #include "../exppp/exppp.h" #include "../express/dict.h" } #define FALSE 0 #define TRUE 1 #define DONT_KNOW -1 #define LISTEND 999 // LISTEND signifies that an OrList has gone beyond its last viable choice // among its children. enum MarkType { NOMARK, ORMARK, MARK }; // MARK is the usual value we'd mark with. If we mark with ORMARK, it means // an OrList marked this node, so we'll know it may become unmarked later if // we try another choice. enum MatchType { UNKNOWN, UNSATISFIED, SATISFIED, MATCHSOME, MATCHALL, NEWCHOICE, NOMORE }; // These are the conditions the EntList::match() functions may return. They // are also the assigned values to EntList::viable. // // UNKNOWN - The default EntList::viable value - before any matching // has been attempted. // UNSATISFIED - EntList had conditions that EntNode did not satisfy (e.g., // EntList specified A AND B while EntNode only contained an // A). // SATISFIED - EntList had no conditions EntNode did not meet. But, // EntList did not match (mark) any nodes of EntNode which // were not already matched. // MATCHSOME - EntList matched some of the nodes in EntNode. // MATCHALL - EntList matched all the nodes in EntNode (complex entity // can be instantiated). // MORECHOICES - Special case - when trying alternate OR paths, this return // value signifies that we have found another choice. // NOMORE - Special case - when trying alternate OR paths, this return // value signifies that no more alternates within this path. enum JoinType { SIMPLE, AND, OR, ANDOR }; class SimpleList; class MultList; class JoinList; class AndOrList; class AndList; class OrList; class ComplexList; class ComplexCollect; class EntNode { friend class SimpleList; friend class AndOrList; friend class AndList; friend class OrList; friend class ComplexList; public: EntNode( const char * nm = "" ) : next( 0 ), mark( NOMARK ), multSupers( 0 ) { strcpy( name, nm ); } EntNode( char *[] ); // given a list, create a linked list of EntNodes ~EntNode() { if( next ) { delete next; } } operator const char * () { return name; } int operator== ( EntNode & ent ) { return ( strcmp( name, ent.name ) == 0 ); } int operator< ( EntNode & ent ) { return ( strcmp( name, ent.name ) < 0 ); } int operator> ( EntNode & ent ) { return ( strcmp( name, ent.name ) > 0 ); } void setmark( MarkType stamp = MARK ) { mark = stamp; } void markAll( MarkType = MARK ); void unmarkAll() { markAll( NOMARK ); } int marked( MarkType base = ORMARK ) { return ( mark >= base ); } int allMarked(); // returns TRUE if all nodes in list are marked int unmarkedCount(); int multSuprs() { return multSupers; } void multSuprs( int j ) { multSupers = j; } EntNode * next; private: MarkType mark; char name[BUFSIZ+1]; int multSupers; // do I correspond to an entity with >1 supertype? }; class EntList { friend class MultList; friend class JoinList; friend class OrList; friend class ComplexList; friend class ComplexCollect; friend ostream & operator<< ( ostream &, EntList & ); friend ostream & operator<< ( ostream &, MultList & ); public: EntList( JoinType j ) : join( j ), prev( 0 ), next( 0 ), viable( UNKNOWN ), level( 0 ) {} virtual ~EntList() {} MatchType viableVal() { return viable; } virtual void setLevel( int l ) { level = l; } virtual int getMaxLevel() { return level; } virtual int contains( const char * ) = 0; virtual int hit( const char * ) = 0; virtual int isDependent( const char * ) = 0; virtual MatchType matchNonORs( EntNode * ) { return UNKNOWN; } virtual int acceptChoice( EntNode * ) = 0; virtual void unmarkAll( EntNode * ) = 0; virtual void reset() { viable = UNKNOWN; } int siblings(); virtual void write( ostream & ) = 0; // write out my contents to stream // List access functions. They access desired children based on their // join or viable values. Below is an incomplete list of possible fns, // but all we need. EntList * firstNot( JoinType ); EntList * nextNot( JoinType j ) { return next->firstNot( j ); } EntList * firstWanted( MatchType ); EntList * nextWanted( MatchType mat ) { return next->firstWanted( mat ); } EntList * lastNot( JoinType ); EntList * prevNot( JoinType j ) { return prev->lastNot( j ); } EntList * lastWanted( MatchType ); EntList * prevWanted( MatchType mat ) { return prev->lastWanted( mat ); } JoinType join; int multiple() { return ( join != SIMPLE ); } EntList * prev, * next; protected: MatchType viable; // How does this EntList match the complex type. Used especially if Ent- // List's parent is an OrList or AndOrList to record if this child is an // acceptable choice or not. For an AndOr, viable children are accepted // right away. For Or, only one is accepted, but we keep track of the // other possible solutions in case we'll want to try them. int level; // How many levels deep are we (main use for printing). }; class SimpleList : public EntList { friend class ComplexList; friend ostream & operator<< ( ostream &, SimpleList & ); public: SimpleList( const char * n ) : EntList( SIMPLE ), I_marked( NOMARK ) { strcpy( name, n ); } ~SimpleList() {} int operator== ( const char * nm ) { return ( strcmp( name, nm ) == 0 ); } const char * Name() { return name; } int contains( const char * nm ) { return *this == nm; } int hit( const char * nm ) { return *this == nm; } int isDependent( const char * ); MatchType matchNonORs( EntNode * ); int acceptChoice( EntNode * ); void unmarkAll( EntNode * ); void reset() { viable = UNKNOWN; I_marked = NOMARK; } void write( ostream & ); private: char name[BUFSIZ+1]; // Name of entity we correspond to. MarkType I_marked; // Did I mark, and with what type of mark. }; class MultList : public EntList { // Supports concepts and functionality common to all the compound list // types, especially AND and ANDOR. friend class ComplexList; friend class ComplexCollect; friend ostream & operator<< ( ostream &, MultList & ); public: MultList( JoinType j ) : EntList( j ), numchildren( 0 ), childList( 0 ) {} ~MultList(); void setLevel( int ); int getMaxLevel(); int contains( const char * ); int hit( const char * ); int isDependent( const char * ); void appendList( EntList * ); EntList * copyList( EntList * ); void processSubExp( Expression, Entity, ComplexCollect * ); void addSimpleAndSubs( Entity, ComplexCollect * ); virtual MatchType matchORs( EntNode * ) = 0; virtual MatchType tryNext( EntNode * ); int childCount() { return numchildren; } // EntList *operator[]( int ); EntList * getChild( int ); EntList * getLast() { return ( getChild( numchildren - 1 ) ); } void unmarkAll( EntNode * ); int prevKnown( EntList * ); void reset(); void write( ostream & ); protected: int numchildren; EntList * childList; // Points to a list of "children" of this EntList. E.g., if join = // AND, it would point to a list of the entity types we are AND'ing. // The children may be SIMPLE EntLists (contain entity names) or may // themselves be And-, Or-, or AndOrLists. }; class JoinList : public MultList { // A specialized MultList, super for subtypes AndOrList and AndList, or // ones which join their multiple children. public: JoinList( JoinType j ) : MultList( j ) {} ~JoinList() {} void setViableVal( EntNode * ); int acceptChoice( EntNode * ); }; class AndOrList : public JoinList { friend class ComplexList; public: AndOrList() : JoinList( ANDOR ) {} ~AndOrList() {} MatchType matchNonORs( EntNode * ); MatchType matchORs( EntNode * ); }; class AndList : public JoinList { friend class MultList; friend class ComplexList; friend ostream & operator<< ( ostream &, ComplexList & ); public: AndList() : JoinList( AND ), supertype( 0 ) {} ~AndList() {} int isDependent( const char * ); MatchType matchNonORs( EntNode * ); MatchType matchORs( EntNode * ); private: int supertype; // do I represent a supertype? }; class OrList : public MultList { public: OrList() : MultList( OR ), choice( -1 ), choice1( -2 ), choiceCount( 0 ) {} ~OrList() {} int hit( const char * ); MatchType matchORs( EntNode * ); MatchType tryNext( EntNode * ); void unmarkAll( EntNode * ); int acceptChoice( EntNode * ); int acceptNextChoice( EntNode * ents ) { choice++; return ( acceptChoice( ents ) ); } void reset() { choice = -1; choice1 = -2; choiceCount = 0; MultList::reset(); } private: int choice, choice1, choiceCount; // Which choice of our childList did we select from this OrList; what's // the first viable choice; and how many choices are there entirely. }; class ComplexList { // Contains the entire list of EntLists which describe the set of // instantiable complex entities defined by an EXPRESS expression. friend class MultList; friend class ComplexCollect; friend ostream & operator<< ( ostream &, ComplexList & ); public: ComplexList( AndList * alist = NULL ) : list( 0 ), head( alist ), next( 0 ), abstract( 0 ), dependent( 0 ), multSupers( 0 ) {} ComplexList( Entity, ComplexCollect * ); ~ComplexList(); void buildList(); void remove(); int operator< ( ComplexList & c ) { return ( strcmp( supertype(), c.supertype() ) < 0 ); } int operator< ( char * name ) { return ( strcmp( supertype(), name ) < 0 ); } int operator== ( char * name ) { return ( strcmp( supertype(), name ) == 0 ); } const char * supertype() { return ( ( SimpleList * )head->childList )->name; } // Based on knowledge that ComplexList always created by ANDing supertype // with subtypes. int toplevel( const char * ); int contains( EntNode * ); int matches( EntNode * ); int isDependent( const char * ); EntNode * list; // List of all entities contained in this complex type, // regardless of how. (Used as a quick way of determining // if this List *may* contain a certain complex type.) AndList * head; ComplexList * next; int Dependent() { return dependent; } void write( ostream & ); int getEntListMaxLevel() { return head->getMaxLevel(); } private: void addSuper( Entity ); void addSubExp( Expression ); void addImplicitSubs( Linked_List, ComplexCollect * ); void addChildren( EntList * ); int hitMultNodes( EntNode * ); int abstract; // is our supertype abstract? int dependent; // is our supertype also a subtype of other supertype(s)? int multSupers; // am I a combo-CList created to test a subtype which has int maxlevel; }; // >1 supertypes? class ComplexCollect { // The collection of all the ComplexLists defined by the current schema. public: ComplexCollect( ComplexList * c = NULL ) : clists( c ) { count = ( c ? 1 : 0 ); } ComplexCollect( Express ); ~ComplexCollect() { delete clists; } void insert( ComplexList * ); void remove( ComplexList * ); // Remove this list but don't delete its hierarchy structure, because // it's used elsewhere. ComplexList * find( char * ); int supports( EntNode * ); int externMapping( const char * ent ) { return ( clists ? clists->isDependent( ent ) : 0 ); } // One of our clists shows that ent will have to be instantiated // using external mapping (see Part 21, sect 11.2.5.1). void write( const char * ); ComplexList * clists; private: int count; // # of clist children }; // Standalone function which can be used to print out the complex info in an // express file (prints out CCollect, CList & EntList instant. statements): void print_complex( ComplexCollect &, const char * ); #endif