355 lines
13 KiB
C++
355 lines
13 KiB
C++
#ifndef COMPLEXSUP_H
|
|
#define COMPLEXSUP_H
|
|
|
|
/*****************************************************************************
|
|
* complexSupport.h *
|
|
* *
|
|
* Description: Slightly simplified version of fedex_plus's complexSupport.h.*
|
|
* This version works with the SCL and is used to validate *
|
|
* complex entities (user requests to build them). It does not *
|
|
* contain info for building these structures from a fedex *
|
|
* Express object, as the fedex_plus version. *
|
|
* *
|
|
* Created by: David Rosenfeld *
|
|
* Date: 5/9/97 *
|
|
*****************************************************************************/
|
|
|
|
#include "g4std/iostream"
|
|
#include "g4std/fstream"
|
|
/*
|
|
extern "C"
|
|
{
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
}
|
|
*/
|
|
#include "Str.h"
|
|
|
|
#define FALSE 0
|
|
#define TRUE 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)
|
|
{ StrToLower( nm, name ); }
|
|
EntNode( const char ** ); // given a list, create a
|
|
~EntNode() { if ( next ) delete next; } // linked list of EntNodes
|
|
|
|
operator const char *() { return name; }
|
|
|
|
// Added missing return types to following operator definitions - GC
|
|
|
|
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 ); }
|
|
EntNode &operator= ( EntNode &ent );
|
|
void Name( const char *nm ) { strncpy( name, nm, BUFSIZ-1 ); }
|
|
const char *Name() { return name; }
|
|
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; }
|
|
void sort( EntNode ** );
|
|
|
|
EntNode *next;
|
|
|
|
private:
|
|
MarkType mark;
|
|
char name[BUFSIZ];
|
|
int multSupers; // do I correspond to an entity with >1 supertype?
|
|
EntNode *lastSmaller( EntNode * ); // used by ::sort()
|
|
};
|
|
|
|
class EntList {
|
|
friend class MultList;
|
|
friend class JoinList;
|
|
friend class OrList;
|
|
friend class ComplexList;
|
|
friend class ComplexCollect;
|
|
friend G4std::ostream & operator<< ( G4std::ostream &, EntList & );
|
|
friend G4std::ostream & operator<< ( G4std::ostream &, MultList & );
|
|
|
|
public:
|
|
// Changed order of member initialisations to match correct order - GC
|
|
EntList( JoinType j ) : join(j), next(0), prev(0), viable(UNKNOWN),
|
|
level(0) {}
|
|
virtual ~EntList() {}
|
|
MatchType viableVal() { return viable; }
|
|
virtual void setLevel( int l ) { level = l; }
|
|
virtual int contains( char * ) =0;
|
|
virtual int hit( 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();
|
|
|
|
// 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 *next, *prev;
|
|
|
|
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 G4std::ostream & operator<< ( G4std::ostream &, SimpleList & );
|
|
|
|
public:
|
|
// Changed order of member initialisations to match correct order - GC
|
|
SimpleList( const char *n ) : EntList(SIMPLE), I_marked(NOMARK)
|
|
{ strcpy( name, n ); }
|
|
~SimpleList() {}
|
|
|
|
// Added missing return type - GC
|
|
int operator== ( const char *nm )
|
|
{ return ( strcmp( name, nm ) == 0 ); }
|
|
const char *Name() { return name; }
|
|
int contains( char *nm ) { return *this == nm; }
|
|
int hit( char *nm ) { return *this == nm; }
|
|
MatchType matchNonORs( EntNode * );
|
|
int acceptChoice( EntNode * );
|
|
void unmarkAll( EntNode * );
|
|
void reset() { viable = UNKNOWN; I_marked = NOMARK; }
|
|
|
|
private:
|
|
char name[BUFSIZ]; // 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 G4std::ostream & operator<< ( G4std::ostream &, MultList & );
|
|
|
|
public:
|
|
MultList( JoinType j ) : EntList(j), supertype(0), numchildren(0),
|
|
childList(0) {}
|
|
~MultList();
|
|
void setLevel( int );
|
|
int contains( char * );
|
|
int hit( char * );
|
|
void appendList( EntList * );
|
|
EntList *copyList( EntList * );
|
|
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();
|
|
|
|
protected:
|
|
int supertype; // do I represent a supertype?
|
|
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 ComplexList;
|
|
friend G4std::ostream & operator<< ( G4std::ostream &, ComplexList & );
|
|
|
|
public:
|
|
AndList() : JoinList( AND ) {}
|
|
~AndList() {}
|
|
MatchType matchNonORs( EntNode * );
|
|
MatchType matchORs( EntNode * );
|
|
};
|
|
|
|
class OrList : public MultList {
|
|
public:
|
|
OrList() : MultList( OR ), choice(-1), choiceCount(0) {}
|
|
~OrList() {}
|
|
int hit( 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; 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 G4std::ostream & operator<< ( G4std::ostream &, ComplexList & );
|
|
|
|
public:
|
|
|
|
// Changed 'and' to 'andl'. 'and' is reserved word in the standard - GC
|
|
// Changed order of member initialisations to match correct order - GC
|
|
ComplexList( AndList *andl = NULL ) : list(0), head(andl), next(0),
|
|
abstract(0), dependent(0),
|
|
multSupers(0) {}
|
|
~ComplexList();
|
|
void buildList();
|
|
void remove();
|
|
|
|
// Added missing return types to following operator definitions - GC
|
|
|
|
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 * );
|
|
|
|
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; }
|
|
|
|
private:
|
|
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
|
|
}; // >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() { 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 * ) const;
|
|
|
|
ComplexList *clists;
|
|
|
|
private:
|
|
int count; // # of clist children
|
|
};
|
|
|
|
#endif
|