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

📄 pattern.c

📁 VC嵌入式CLips专家系统,实现战场环境的目标识别
💻 C
📖 第 1 页 / 共 3 页
字号:
     {
      fprintf(fp,"&%s%d_%d[%d],",
                 JoinPrefix(),imageID,
                 (((int) theHeader->entryJoin->bsaveID) / maxIndices) + 1,
                 ((int) theHeader->entryJoin->bsaveID) % maxIndices);
     }

   fprintf(fp,"%d,%d,%d,0,0,%d,%d}",theHeader->singlefieldNode,
                                     theHeader->multifieldNode,
                                     theHeader->stopNode,
                                     theHeader->beginSlot,
                                     theHeader->endSlot);
  }

#endif /* CONSTRUCT_COMPILER && (! RUN_TIME) */

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

/****************************************************************/
/* PostPatternAnalysis: Calls the post analysis routines for    */
/*   each of the pattern parsers to allow additional processing */
/*   by the pattern parser after the variable analysis routines */
/*   have analyzed the LHS patterns.                            */
/****************************************************************/
globle intBool PostPatternAnalysis(
  void *theEnv,
  struct lhsParseNode *theLHS)
  {
   struct lhsParseNode *patternPtr;
   struct patternParser *tempParser;

   for (patternPtr = theLHS; patternPtr != NULL; patternPtr = patternPtr->bottom)
     {
      if ((patternPtr->type == PATTERN_CE) && (patternPtr->patternType != NULL))
        {
         tempParser = patternPtr->patternType;
         if (tempParser->postAnalysisFunction != NULL)
           { if ((*tempParser->postAnalysisFunction)(theEnv,patternPtr)) return(TRUE); }
        }
     }

   return(FALSE);
  }

/******************************************************************/
/* RestrictionParse: Parses a single field within a pattern. This */
/*    field may either be a single field wildcard, a multifield   */
/*    wildcard, a single field variable, a multifield variable,   */
/*    or a series of connected constraints.                       */
/*                                                                */
/* <constraint> ::= ? |                                           */
/*                  $? |                                          */
/*                  <connected-constraint>                        */
/******************************************************************/
struct lhsParseNode *RestrictionParse(
  void *theEnv,
  char *readSource,
  struct token *theToken,
  int multifieldSlot,
  struct symbolHashNode *theSlot,
  short slotNumber,
  CONSTRAINT_RECORD *theConstraints,
  short position)
  {
   struct lhsParseNode *topNode = NULL, *lastNode = NULL, *nextNode;
   int numberOfSingleFields = 0;
   int numberOfMultifields = 0;
   short startPosition = position;
   int error = FALSE;
   CONSTRAINT_RECORD *tempConstraints;

   /*==================================================*/
   /* Keep parsing fields until a right parenthesis is */
   /* encountered. This will either indicate the end   */
   /* of an instance or deftemplate slot or the end of */
   /* an ordered fact.                                 */
   /*==================================================*/

   while (theToken->type != RPAREN)
     {
      /*========================================*/
      /* Look for either a single or multifield */
      /* wildcard or a conjuctive restriction.  */
      /*========================================*/

      if ((theToken->type == SF_WILDCARD) ||
          (theToken->type == MF_WILDCARD))
        {
         nextNode = GetLHSParseNode(theEnv);
         nextNode->type = theToken->type;
         nextNode->negated = FALSE;
         GetToken(theEnv,readSource,theToken);
        }
      else
        {
         nextNode = ConjuctiveRestrictionParse(theEnv,readSource,theToken,&error);
         if (nextNode == NULL)
           {
            ReturnLHSParseNodes(theEnv,topNode);
            return(NULL);
           }
        }

      /*========================================================*/
      /* Fix up the pretty print representation of a multifield */
      /* slot so that the fields don't run together.            */
      /*========================================================*/

      if ((theToken->type != RPAREN) && (multifieldSlot == TRUE))
        {
         PPBackup(theEnv);
         SavePPBuffer(theEnv," ");
         SavePPBuffer(theEnv,theToken->printForm);
        }

      /*========================================*/
      /* Keep track of the number of single and */
      /* multifield restrictions encountered.   */
      /*========================================*/

      if ((nextNode->type == SF_WILDCARD) || (nextNode->type == SF_VARIABLE))
        { numberOfSingleFields++; }
      else
        { numberOfMultifields++; }

      /*===================================*/
      /* Assign the slot name and indices. */
      /*===================================*/

      nextNode->slot = theSlot;
      nextNode->slotNumber = slotNumber;
      nextNode->index = position++;

      /*==============================================*/
      /* If we're not dealing with a multifield slot, */
      /* attach the constraints directly to the node  */
      /* and return.                                  */
      /*==============================================*/

      if (! multifieldSlot)
        {
         if (theConstraints == NULL)
           {
            if (nextNode->type == SF_VARIABLE)
              { nextNode->constraints = GetConstraintRecord(theEnv); }
            else nextNode->constraints = NULL;
           }
         else nextNode->constraints = theConstraints;
         return(nextNode);
        }

      /*====================================================*/
      /* Attach the restriction to the list of restrictions */
      /* already parsed for this slot or ordered fact.      */
      /*====================================================*/

      if (lastNode == NULL) topNode = nextNode;
      else lastNode->right = nextNode;

      lastNode = nextNode;
     }

   /*=====================================================*/
   /* Once we're through parsing, check to make sure that */
   /* a single field slot was given a restriction. If the */
   /* following test fails, then we know we're dealing    */
   /* with a multifield slot.                             */
   /*=====================================================*/

   if ((topNode == NULL) && (! multifieldSlot))
     {
      SyntaxErrorMessage(theEnv,"defrule");
      return(NULL);
     }

   /*===============================================*/
   /* Loop through each of the restrictions in the  */
   /* list of restrictions for the multifield slot. */
   /*===============================================*/

   for (nextNode = topNode; nextNode != NULL; nextNode = nextNode->right)
     {
      /*===================================================*/
      /* Assign a constraint record to each constraint. If */
      /* the slot has an explicit constraint, then copy    */
      /* this and store it with the constraint. Otherwise, */
      /* create a constraint record for a single field     */
      /* constraint and skip the constraint modifications  */
      /* for a multifield constraint.                      */
      /*===================================================*/

      if (theConstraints == NULL)
        {
         if (nextNode->type == SF_VARIABLE)
           { nextNode->constraints = GetConstraintRecord(theEnv); }
         else
           { continue; }
        }
      else
        { nextNode->constraints = CopyConstraintRecord(theEnv,theConstraints); }

      /*==========================================*/
      /* Remove the min and max field constraints */
      /* for the entire slot from the constraint  */
      /* record for this single constraint.       */
      /*==========================================*/

      ReturnExpression(theEnv,nextNode->constraints->minFields);
      ReturnExpression(theEnv,nextNode->constraints->maxFields);
      nextNode->constraints->minFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->NegativeInfinity);
      nextNode->constraints->maxFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->PositiveInfinity);
      nextNode->derivedConstraints = TRUE;

      /*====================================================*/
      /* If we're not dealing with a multifield constraint, */
      /* then no further modifications are needed to the    */
      /* min and max constraints for this constraint.       */
      /*====================================================*/

      if ((nextNode->type != MF_WILDCARD) && (nextNode->type != MF_VARIABLE))
        { continue; }

      /*==========================================================*/
      /* Create a separate constraint record to keep track of the */
      /* cardinality information for this multifield constraint.  */
      /*==========================================================*/

      tempConstraints = GetConstraintRecord(theEnv);
      SetConstraintType(MULTIFIELD,tempConstraints);
      tempConstraints->singlefieldsAllowed = FALSE;
      tempConstraints->multifield = nextNode->constraints;
      nextNode->constraints = tempConstraints;

      /*=====================================================*/
      /* Adjust the min and max field values for this single */
      /* multifield constraint based on the min and max      */
      /* fields for the entire slot and the number of single */
      /* field values contained in the slot.                 */
      /*=====================================================*/

      if (theConstraints->maxFields->value != SymbolData(theEnv)->PositiveInfinity)
        {
         ReturnExpression(theEnv,tempConstraints->maxFields);
         tempConstraints->maxFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,ValueToLong(theConstraints->maxFields->value) - numberOfSingleFields));
        }

      if ((numberOfMultifields == 1) && (theConstraints->minFields->value != SymbolData(theEnv)->NegativeInfinity))
        {
         ReturnExpression(theEnv,tempConstraints->minFields);
         tempConstraints->minFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,ValueToLong(theConstraints->minFields->value) - numberOfSingleFields));
        }
     }

   /*================================================*/
   /* If a multifield slot is being parsed, place a  */
   /* node on top of the list of constraints parsed. */
   /*================================================*/

   if (multifieldSlot)
     {
      nextNode = GetLHSParseNode(theEnv);
      nextNode->type = MF_WILDCARD;
      nextNode->multifieldSlot = TRUE;
      nextNode->bottom = topNode;
      nextNode->slot = theSlot;
      nextNode->slotNumber = slotNumber;
      nextNode->index = startPosition;
      nextNode->constraints = theConstraints;
      topNode = nextNode;
      TallyFieldTypes(topNode->bottom);
     }

   /*=================================*/
   /* Return the list of constraints. */
   /*=================================*/

   return(topNode);
  }

/***************************************************************/
/* TallyFieldTypes: Determines the number of single field and  */
/*   multifield variables and wildcards that appear before and */
/*   after each restriction found in a multifield slot.        */
/***************************************************************/
static void TallyFieldTypes(
  struct lhsParseNode *theRestrictions)
  {
   struct lhsParseNode *tempNode1, *tempNode2, *tempNode3;
   unsigned short totalSingleFields = 0, totalMultiFields = 0;
   unsigned short runningSingleFields = 0, runningMultiFields = 0;

   /*========================================*/
   /* Compute the total number of single and */
   /* multifield variables and wildcards.    */
   /*========================================*/

   for (tempNode1 = theRestrictions; tempNode1 != NULL; tempNode1 = tempNode1->right)
     {
      if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
        { totalSingleFields++; }
      else
        { totalMultiFields++; }
     }

   /*======================================================*/
   /* Loop through each constraint tallying the numbers of */
   /* the variable types before and after along the way.   */
   /*======================================================*/

   for (tempNode1 = theRestrictions; tempNode1 != NULL; tempNode1 = tempNode1->right)
     {
      /*===================================*/
      /* Assign the values to the "binding */
      /* variable" node of the constraint. */
      /*===================================*/

      tempNode1->singleFieldsBefore = runningSingleFields;
      tempNode1->multiFieldsBefore = runningMultiFields;
      tempNode1->withinMultifieldSlot = TRUE;

      if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
        {
         tempNode1->singleFieldsAfter = (unsigned short) (totalSingleFields - (runningSingleFields + 1));
         tempNode1->multiFieldsAfter = (unsigned short) (totalMultiFields - runningMultiFields);
        }
      else
        {
         tempNode1->singleFieldsAfter = (unsigned short) (totalSingleFields - runningSingleFields);
         tempNode1->multiFieldsAfter = (unsigned short) (totalMultiFields - (runningMultiFields + 1));
        }

      /*=====================================================*/
      /* Assign the values to each of the and (&) and or (|) */
      /* connected constraints within the constraint.        */
      /*=====================================================*/

      for (tempNode2 = tempNode1->bottom; tempNode2 != NULL; tempNode2 = tempNode2->bottom)
        {
         for (tempNode3 = tempNode2; tempNode3 != NULL; tempNode3 = tempNode3->right)
           {
            tempNode3->singleFieldsBefore = tempNode1->singleFieldsBefore;
            tempNode3->singleFieldsAfter = tempNode1->singleFieldsAfter;
            tempNode3->multiFieldsBefore = tempNode1->multiFieldsBefore;
            tempNode3->multiFieldsAfter = tempNode1->multiFieldsAfter;
            tempNode3->withinMultifieldSlot = TRUE;
           }
        }

      /*=======================================*/
      /* Calculate the running total of single */
      /* and multifield constraints.           */
      /*=======================================*/

      if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
        { runningSingleFields++; }
      else
        { runningMultiFields++; }
     }
  }

/*******************************************************************/
/* ConjuctiveRestrictionParse: Parses a single constraint field in */
/*   a pattern that is not a single field wildcard, multifield     */
/*   wildcard, or multifield variable. The field may consist of a  */
/*   number of subfields tied together using the & connective      */
/*   constraint and/or the | connective constraint.                */

⌨️ 快捷键说明

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