⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inherpsr.c

📁 VC嵌入式CLips专家系统,实现战场环境的目标识别
💻 C
📖 第 1 页 / 共 3 页
字号:
   /*******************************************************/
   /*      "C" Language Integrated Production System      */
   /*                                                     */
   /*               CLIPS Version 6.20  01/31/02          */
   /*                                                     */
   /*             MULTIPLE INHERITANCE PARSER MODULE      */
   /*******************************************************/

/**************************************************************/
/* Purpose: Parsing Routines for Multiple Inheritance         */
/*                                                            */
/* Principal Programmer(s):                                   */
/*      Brian L. Donnell                                      */
/*                                                            */
/* Contributing Programmer(s):                                */
/*                                                            */
/* Revision History:                                          */
/*                                                            */
/**************************************************************/

/* =========================================
   *****************************************
               EXTERNAL DEFINITIONS
   =========================================
   ***************************************** */
#include "setup.h"

#if OBJECT_SYSTEM && (! BLOAD_ONLY) && (! RUN_TIME)

#include "classcom.h"
#include "classfun.h"
#include "envrnmnt.h"
#include "memalloc.h"
#include "modulutl.h"
#include "router.h"
#include "scanner.h"

#define _INHERPSR_SOURCE_
#include "inherpsr.h"

/* =========================================
   *****************************************
               MACROS AND TYPES
   =========================================
   ***************************************** */
typedef struct partialOrder PARTIAL_ORDER;
typedef struct successor SUCCESSOR;

struct partialOrder
  {
   DEFCLASS *cls;
   unsigned pre;
   SUCCESSOR *suc;
   struct partialOrder *nxt;
  };

struct successor
  {
   PARTIAL_ORDER *po;
   struct successor *nxt;
  };

/* =========================================
   *****************************************
      INTERNALLY VISIBLE FUNCTION HEADERS
   =========================================
   ***************************************** */

static PARTIAL_ORDER *InitializePartialOrderTable(void *,PARTIAL_ORDER *,PACKED_CLASS_LINKS *);
static void RecordPartialOrders(void *,PARTIAL_ORDER *,DEFCLASS *,PACKED_CLASS_LINKS *,unsigned);
static PARTIAL_ORDER *FindPartialOrder(PARTIAL_ORDER *,DEFCLASS *);
static void PrintPartialOrderLoop(void *,PARTIAL_ORDER *);
static void PrintClassLinks(void *,char *,char *,CLASS_LINK *);

/* =========================================
   *****************************************
          EXTERNALLY VISIBLE FUNCTIONS
   =========================================
   ***************************************** */

/**************************************************************
  NAME         : ParseSuperclasses
  DESCRIPTION  : Parses the (is-a <superclass>+) portion of
                 the (defclass ...) construct and returns
                 a list of direct superclasses.  The
                 class "standard-class" is the precedence list
                 for classes with no direct superclasses.
                 The final precedence list (not calculated here)
                 will have the class in question first followed
                 by the merged precedence lists of its direct
                 superclasses.
  INPUTS       : 1) The logical name of the input source
                 2) The symbolic name of the new class
  RETURNS      : The address of the superclass list
                  or NULL if there was an error
  SIDE EFFECTS : None
  NOTES        : Assumes "(defclass <name> [<comment>] ("
                 has already been scanned.

                 All superclasses must be defined before
                 their subclasses.  Duplicates in the (is-a
                 ...) list are are not allowed (a class may only
                 inherits from a superclass once).

                 This routine also checks the class-precedence
                 lists of each of the direct superclasses for
                 an occurrence of the new class - i.e. cycles!
                 This can only happen when a class is redefined
                 (a new class cannot have an unspecified
                 superclass).

                 This routine allocates the space for the list
 ***************************************************************/
globle PACKED_CLASS_LINKS *ParseSuperclasses(
  void *theEnv,
  char *readSource,
  SYMBOL_HN *newClassName)
  {
   CLASS_LINK *clink = NULL,*cbot = NULL,*ctmp;
   DEFCLASS *sclass;
   PACKED_CLASS_LINKS *plinks;

   if (GetType(DefclassData(theEnv)->ObjectParseToken) != LPAREN)
     {
      SyntaxErrorMessage(theEnv,"defclass inheritance");
      return(NULL);
     }
   GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
   if ((GetType(DefclassData(theEnv)->ObjectParseToken) != SYMBOL) ? TRUE :
       (DefclassData(theEnv)->ObjectParseToken.value != (void *) DefclassData(theEnv)->ISA_SYMBOL))
     {
      SyntaxErrorMessage(theEnv,"defclass inheritance");
      return(NULL);
     }
   SavePPBuffer(theEnv," ");
   GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
   while (GetType(DefclassData(theEnv)->ObjectParseToken) != RPAREN)
     {
      if (GetType(DefclassData(theEnv)->ObjectParseToken) != SYMBOL)
        {
         SyntaxErrorMessage(theEnv,"defclass");
         goto SuperclassParseError;
        }
      if (FindModuleSeparator(ValueToString(newClassName)))
        {
         IllegalModuleSpecifierMessage(theEnv);
         goto SuperclassParseError;
        }
      if (GetValue(DefclassData(theEnv)->ObjectParseToken) == (void *) newClassName)
        {
         PrintErrorID(theEnv,"INHERPSR",1,FALSE);
         EnvPrintRouter(theEnv,WERROR,"A class may not have itself as a superclass.\n");
         goto SuperclassParseError;
        }
      for (ctmp = clink ; ctmp != NULL ; ctmp = ctmp->nxt)
        {
         if (GetValue(DefclassData(theEnv)->ObjectParseToken) == (void *) ctmp->cls->header.name)
           {
            PrintErrorID(theEnv,"INHERPSR",2,FALSE);
            EnvPrintRouter(theEnv,WERROR,"A class may inherit from a superclass only once.\n");
            goto SuperclassParseError;
           }
        }
      sclass = LookupDefclassInScope(theEnv,ValueToString(GetValue(DefclassData(theEnv)->ObjectParseToken)));
      if (sclass == NULL)
        {
         PrintErrorID(theEnv,"INHERPSR",3,FALSE);
         EnvPrintRouter(theEnv,WERROR,"A class must be defined after all its superclasses.\n");
         goto SuperclassParseError;
        }
      if ((sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_NAME]) ||
          (sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_ADDRESS]) ||
          (sclass == DefclassData(theEnv)->PrimitiveClassMap[INSTANCE_NAME]->directSuperclasses.classArray[0]))
        {
         PrintErrorID(theEnv,"INHERPSR",6,FALSE);
         EnvPrintRouter(theEnv,WERROR,"A user-defined class cannot be a subclass of ");
         EnvPrintRouter(theEnv,WERROR,EnvGetDefclassName(theEnv,(void *) sclass));
         EnvPrintRouter(theEnv,WERROR,".\n");
         goto SuperclassParseError;
        }
      ctmp = get_struct(theEnv,classLink);
      ctmp->cls = sclass;
      if (clink == NULL)
        clink = ctmp;
      else
        cbot->nxt = ctmp;
      ctmp->nxt = NULL;
      cbot = ctmp;

      SavePPBuffer(theEnv," ");
      GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
     }
   if (clink == NULL)
     {
      PrintErrorID(theEnv,"INHERPSR",4,FALSE);
      EnvPrintRouter(theEnv,WERROR,"Must have at least one superclass.\n");
      return(NULL);
     }
   PPBackup(theEnv);
   PPBackup(theEnv);
   SavePPBuffer(theEnv,")");
   plinks = get_struct(theEnv,packedClassLinks);
   PackClassLinks(theEnv,plinks,clink);
   return(plinks);

SuperclassParseError:
   DeleteClassLinks(theEnv,clink);
   return(NULL);
  }

/***************************************************************************
  NAME         : FindPrecedenceList
  DESCRIPTION  : A complete class precedence list is obtained from the
                 list of direct superclasses as follows :

                 Each class and its direct superclasses are recursively
                 entered in order to a list called the partial order table.
                 A class is only entered once.  The order reflects a pre-order
                 depth-first traversal of the classes, and this order will be
                 followed as closely as possible to preserve the "family"
                 heuristic when constructing the class precedence list.

                 Attached to each node is a count indicating the number of
                 classes which must precede this class and a list of classes
                 which must succeed this class (attached via the suc field and
                 linked via nxt fields).  These predecessor counts
                 and successor lists indicate the partial orderings given
                 by the rules of multiple inheritance for the classes:
                 1) a class must precede all its superclasses, and 2) a
                 class determines the precedence of its immediate superclasses.

                 For example, the following class definitions

                 (defclass A (is-a USER))
                 (defclass B (is-a USER))
                 (defclass C (is-a A B))

                 would give the following partial orders:

                 C < A          by Rule 1
                 C < B          by Rule 1
                 A < B          by Rule 2
                 B < USER       by Rule 1
                 A < USER       by Rule 1
                 USER < OBJECT  by Rule 1

                 In turn, these partial orders would be recorded in a
                 sequence table:

                                     C     A      USER    OBJECT    B
                 Predecessor Count   0     1       2        1       2
                 Successor List     A,B  B,USER  OBJECT   <NIL>    USER

                 To generate a precedence list for C, we pick the first
                 class with a predecessor count of 0, append it to the
                 precedence list, and decrement the counts of all its
                 successors.  We continue scanning for a 0 from where
                 we left off.  If we ever scan completely through the
                 table without finding a 0, then we know there is an
                 error.

                 Shown below is the table above after each class is
                 entered onto the precedence list:

                 Precedence list: C
                                     A      USER    OBJECT    B
                 Predecessor Count   0       2        1       1
                 Successor List     B,USER  OBJECT   <NIL>    USER

                 Precedence list: C A
                                    USER    OBJECT    B
                 Predecessor Count   1        1       0
                 Successor List     OBJECT   <NIL>   USER

                 Precedence list: C A B
                                    USER    OBJECT
                 Predecessor Count   0        1
                 Successor List     OBJECT   <NIL>

                 Precedence list: C A B USER

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -