1 #ifndef COMPLEXSUP_H
2 #define COMPLEXSUP_H
3 
4 #include <iostream>
5 #include <fstream>
6 using namespace std;
7 
8 extern "C"
9 {
10 #include <string.h>
11 #include "classes.h"
12 #include "../express/express.h"
13 #include "../exppp/exppp.h"
14 #include "../express/dict.h"
15 }
16 
17 #define FALSE      0
18 #define TRUE       1
19 #define DONT_KNOW -1
20 #define LISTEND  999
21 // LISTEND signifies that an OrList has gone beyond its last viable choice
22 // among its children.
23 
24 enum MarkType {
25     NOMARK, ORMARK, MARK
26 };
27 // MARK is the usual value we'd mark with.  If we mark with ORMARK, it means
28 // an OrList marked this node, so we'll know it may become unmarked later if
29 // we try another choice.
30 
31 enum MatchType {
32     UNKNOWN, UNSATISFIED, SATISFIED, MATCHSOME, MATCHALL, NEWCHOICE, NOMORE
33 };
34 // These are the conditions the EntList::match() functions may return.  They
35 // are also the assigned values to EntList::viable.
36 //
37 //    UNKNOWN     - The default EntList::viable value - before any matching
38 //                  has been attempted.
39 //    UNSATISFIED - EntList had conditions that EntNode did not satisfy (e.g.,
40 //                  EntList specified A AND B while EntNode only contained an
41 //                  A).
42 //    SATISFIED   - EntList had no conditions EntNode did not meet.  But,
43 //                  EntList did not match (mark) any nodes of EntNode which
44 //                  were not already matched.
45 //    MATCHSOME   - EntList matched some of the nodes in EntNode.
46 //    MATCHALL    - EntList matched all the nodes in EntNode (complex entity
47 //                  can be instantiated).
48 //    MORECHOICES - Special case - when trying alternate OR paths, this return
49 //                  value signifies that we have found another choice.
50 //    NOMORE      - Special case - when trying alternate OR paths, this return
51 //                  value signifies that no more alternates within this path.
52 
53 enum JoinType {
54     SIMPLE, AND, OR, ANDOR
55 };
56 
57 class SimpleList;
58 class MultList;
59 class JoinList;
60 class AndOrList;
61 class AndList;
62 class OrList;
63 class ComplexList;
64 class ComplexCollect;
65 
66 class EntNode {
67         friend class SimpleList;
68         friend class AndOrList;
69         friend class AndList;
70         friend class OrList;
71         friend class ComplexList;
72 
73     public:
74         EntNode( const char * nm = "" ) : next( 0 ), mark( NOMARK ),
75             multSupers( 0 ) {
76             strcpy( name, nm );
77         }
78         EntNode( char *[] );  // given a list, create a linked list of EntNodes
~EntNode()79         ~EntNode() {
80             if( next ) {
81                 delete next;
82             }
83         }
84         operator const char * () {
85             return name;
86         }
87         int operator== ( EntNode & ent ) {
88             return ( strcmp( name, ent.name ) == 0 );
89         }
90         int operator< ( EntNode & ent ) {
91             return ( strcmp( name, ent.name ) < 0 );
92         }
93         int operator> ( EntNode & ent ) {
94             return ( strcmp( name, ent.name ) > 0 );
95         }
96         void setmark( MarkType stamp = MARK ) {
97             mark = stamp;
98         }
99         void markAll( MarkType = MARK );
unmarkAll()100         void unmarkAll() {
101             markAll( NOMARK );
102         }
103         int marked( MarkType base = ORMARK ) {
104             return ( mark >= base );
105         }
106         int allMarked();  // returns TRUE if all nodes in list are marked
107         int unmarkedCount();
multSuprs()108         int multSuprs() {
109             return multSupers;
110         }
multSuprs(int j)111         void multSuprs( int j ) {
112             multSupers = j;
113         }
114 
115         EntNode * next;
116 
117     private:
118         MarkType mark;
119         char name[BUFSIZ];
120         int multSupers;  // do I correspond to an entity with >1 supertype?
121 };
122 
123 class EntList {
124         friend class MultList;
125         friend class JoinList;
126         friend class OrList;
127         friend class ComplexList;
128         friend class ComplexCollect;
129         friend ostream & operator<< ( ostream &, EntList & );
130         friend ostream & operator<< ( ostream &, MultList & );
131 
132     public:
EntList(JoinType j)133         EntList( JoinType j ) : join( j ), prev( 0 ), next( 0 ), viable( UNKNOWN ),
134             level( 0 ) {}
~EntList()135         virtual ~EntList() {}
viableVal()136         MatchType viableVal() {
137             return viable;
138         }
setLevel(int l)139         virtual void setLevel( int l ) {
140             level = l;
141         }
getMaxLevel()142         virtual int getMaxLevel() {
143             return level;
144         }
145         virtual int contains( const char * ) = 0;
146         virtual int hit( const char * ) = 0;
147         virtual int isDependent( const char * ) = 0;
matchNonORs(EntNode *)148         virtual MatchType matchNonORs( EntNode * ) {
149             return UNKNOWN;
150         }
151         virtual int acceptChoice( EntNode * ) = 0;
152         virtual void unmarkAll( EntNode * ) = 0;
reset()153         virtual void reset() {
154             viable = UNKNOWN;
155         }
156         int siblings();
157         virtual void write( ostream & ) = 0;
158         // write out my contents to stream
159 
160         // List access functions.  They access desired children based on their
161         // join or viable values.  Below is an incomplete list of possible fns,
162         // but all we need.
163         EntList * firstNot( JoinType );
nextNot(JoinType j)164         EntList * nextNot( JoinType j ) {
165             return next->firstNot( j );
166         }
167         EntList * firstWanted( MatchType );
nextWanted(MatchType mat)168         EntList * nextWanted( MatchType mat ) {
169             return next->firstWanted( mat );
170         }
171         EntList * lastNot( JoinType );
prevNot(JoinType j)172         EntList * prevNot( JoinType j ) {
173             return prev->lastNot( j );
174         }
175         EntList * lastWanted( MatchType );
prevWanted(MatchType mat)176         EntList * prevWanted( MatchType mat ) {
177             return prev->lastWanted( mat );
178         }
179 
180         JoinType join;
multiple()181         int multiple() {
182             return ( join != SIMPLE );
183         }
184         EntList * prev, * next;
185 
186     protected:
187         MatchType viable;
188         // How does this EntList match the complex type.  Used especially if Ent-
189         // List's parent is an OrList or AndOrList to record if this child is an
190         // acceptable choice or not.  For an AndOr, viable children are accepted
191         // right away.  For Or, only one is accepted, but we keep track of the
192         // other possible solutions in case we'll want to try them.
193         int level;  // How many levels deep are we (main use for printing).
194 };
195 
196 class SimpleList : public EntList {
197         friend class ComplexList;
198         friend ostream & operator<< ( ostream &, SimpleList & );
199 
200     public:
SimpleList(const char * n)201         SimpleList( const char * n ) : EntList( SIMPLE ), I_marked( NOMARK ) {
202             strcpy( name, n );
203         }
~SimpleList()204         ~SimpleList() {}
205         int operator== ( const char * nm ) {
206             return ( strcmp( name, nm ) == 0 );
207         }
Name()208         const char * Name() {
209             return name;
210         }
contains(const char * nm)211         int contains( const char * nm ) {
212             return *this == nm;
213         }
hit(const char * nm)214         int hit( const char * nm ) {
215             return *this == nm;
216         }
217         int isDependent( const char * );
218         MatchType matchNonORs( EntNode * );
219         int acceptChoice( EntNode * );
220         void unmarkAll( EntNode * );
reset()221         void reset() {
222             viable = UNKNOWN;
223             I_marked = NOMARK;
224         }
225         void write( ostream & );
226 
227     private:
228         char name[BUFSIZ];    // Name of entity we correspond to.
229         MarkType I_marked; // Did I mark, and with what type of mark.
230 };
231 
232 class MultList : public EntList {
233         // Supports concepts and functionality common to all the compound list
234         // types, especially AND and ANDOR.
235 
236         friend class ComplexList;
237         friend class ComplexCollect;
238         friend ostream & operator<< ( ostream &, MultList & );
239 
240     public:
MultList(JoinType j)241         MultList( JoinType j ) : EntList( j ), numchildren( 0 ), childList( 0 ) {}
242         ~MultList();
243         void setLevel( int );
244         int getMaxLevel();
245         int contains( const char * );
246         int hit( const char * );
247         int isDependent( const char * );
248         void appendList( EntList * );
249         EntList * copyList( EntList * );
250         void processSubExp( Expression, Entity, ComplexCollect * );
251         void addSimpleAndSubs( Entity, ComplexCollect * );
252         virtual MatchType matchORs( EntNode * ) = 0;
253         virtual MatchType tryNext( EntNode * );
254 
childCount()255         int childCount() {
256             return numchildren;
257         }
258 //  EntList *operator[]( int );
259         EntList * getChild( int );
getLast()260         EntList * getLast() {
261             return ( getChild( numchildren - 1 ) );
262         }
263         void unmarkAll( EntNode * );
264         int prevKnown( EntList * );
265         void reset();
266         void write( ostream & );
267 
268     protected:
269         int numchildren;
270         EntList * childList;
271         // Points to a list of "children" of this EntList.  E.g., if join =
272         // AND, it would point to a list of the entity types we are AND'ing.
273         // The children may be SIMPLE EntLists (contain entity names) or may
274         // themselves be And-, Or-, or AndOrLists.
275 };
276 
277 class JoinList : public MultList {
278         // A specialized MultList, super for subtypes AndOrList and AndList, or
279         // ones which join their multiple children.
280     public:
JoinList(JoinType j)281         JoinList( JoinType j ) : MultList( j ) {}
~JoinList()282         ~JoinList() {}
283         void setViableVal( EntNode * );
284         int acceptChoice( EntNode * );
285 };
286 
287 class AndOrList : public JoinList {
288         friend class ComplexList;
289 
290     public:
AndOrList()291         AndOrList() : JoinList( ANDOR ) {}
~AndOrList()292         ~AndOrList() {}
293         MatchType matchNonORs( EntNode * );
294         MatchType matchORs( EntNode * );
295 };
296 
297 class AndList : public JoinList {
298         friend class MultList;
299         friend class ComplexList;
300         friend ostream & operator<< ( ostream &, ComplexList & );
301 
302     public:
AndList()303         AndList() : JoinList( AND ), supertype( 0 ) {}
~AndList()304         ~AndList() {}
305         int isDependent( const char * );
306         MatchType matchNonORs( EntNode * );
307         MatchType matchORs( EntNode * );
308 
309     private:
310         int supertype;  // do I represent a supertype?
311 };
312 
313 class OrList : public MultList {
314     public:
OrList()315         OrList() : MultList( OR ), choice( -1 ), choice1( -2 ), choiceCount( 0 ) {}
~OrList()316         ~OrList() {}
317         int hit( const char * );
318         MatchType matchORs( EntNode * );
319         MatchType tryNext( EntNode * );
320         void unmarkAll( EntNode * );
321         int acceptChoice( EntNode * );
acceptNextChoice(EntNode * ents)322         int acceptNextChoice( EntNode * ents ) {
323             choice++;
324             return ( acceptChoice( ents ) );
325         }
reset()326         void reset() {
327             choice = -1;
328             choice1 = -2;
329             choiceCount = 0;
330             MultList::reset();
331         }
332 
333     private:
334         int choice, choice1, choiceCount;
335         // Which choice of our childList did we select from this OrList; what's
336         // the first viable choice; and how many choices are there entirely.
337 };
338 
339 class ComplexList {
340         // Contains the entire list of EntLists which describe the set of
341         // instantiable complex entities defined by an EXPRESS expression.
342 
343         friend class MultList;
344         friend class ComplexCollect;
345         friend ostream & operator<< ( ostream &, ComplexList & );
346 
347     public:
348         ComplexList( AndList * alist = NULL ) : list( 0 ), head( alist ), next( 0 ),
349             abstract( 0 ), dependent( 0 ),
350             multSupers( 0 ) {}
351         ComplexList( Entity, ComplexCollect * );
352         ~ComplexList();
353         void buildList();
354         void remove();
355         int operator< ( ComplexList & c ) {
356             return ( strcmp( supertype(), c.supertype() ) < 0 );
357         }
358         int operator< ( char * name ) {
359             return ( strcmp( supertype(), name ) < 0 );
360         }
361         int operator== ( char * name ) {
362             return ( strcmp( supertype(), name ) == 0 );
363         }
supertype()364         const char * supertype() {
365             return ( ( SimpleList * )head->childList )->name;
366         }
367         // Based on knowledge that ComplexList always created by ANDing supertype
368         // with subtypes.
369         int toplevel( const char * );
370         int contains( EntNode * );
371         int matches( EntNode * );
372         int isDependent( const char * );
373 
374         EntNode * list; // List of all entities contained in this complex type,
375         // regardless of how.  (Used as a quick way of determining
376         // if this List *may* contain a certain complex type.)
377         AndList * head;
378         ComplexList * next;
Dependent()379         int Dependent() {
380             return dependent;
381         }
382         void write( ostream & );
getEntListMaxLevel()383         int getEntListMaxLevel() {
384             return head->getMaxLevel();
385         }
386 
387     private:
388         void addSuper( Entity );
389         void addSubExp( Expression );
390         void addImplicitSubs( Linked_List, ComplexCollect * );
391         void addChildren( EntList * );
392         int hitMultNodes( EntNode * );
393         int abstract;   // is our supertype abstract?
394         int dependent;  // is our supertype also a subtype of other supertype(s)?
395         int multSupers; // am I a combo-CList created to test a subtype which has
396         int maxlevel;
397 };                  // >1 supertypes?
398 
399 class ComplexCollect {
400         // The collection of all the ComplexLists defined by the current schema.
401     public:
clists(c)402         ComplexCollect( ComplexList * c = NULL ) : clists( c ) {
403             count = ( c ? 1 : 0 );
404         }
405         ComplexCollect( Express );
~ComplexCollect()406         ~ComplexCollect() {
407             delete clists;
408         }
409         void insert( ComplexList * );
410         void remove( ComplexList * );
411         // Remove this list but don't delete its hierarchy structure, because
412         // it's used elsewhere.
413         ComplexList * find( char * );
414         int supports( EntNode * );
externMapping(const char * ent)415         bool externMapping( const char * ent ) {
416             return ( clists ? clists->isDependent( ent ) : 0 );
417         }
418         // One of our clists shows that ent will have to be instantiated
419         // using external mapping (see Part 21, sect 11.2.5.1).
420         void write( const char * );
421 
422         ComplexList * clists;
423 
424     private:
425         int count;  // # of clist children
426 };
427 
428 // Standalone function which can be used to print out the complex info in an
429 // express file (prints out CCollect, CList & EntList instant. statements):
430 void print_complex( ComplexCollect &, const char * );
431 
432 #endif
433