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

📄 pattern.c

📁 VC嵌入式CLips专家系统,实现战场环境的目标识别
💻 C
📖 第 1 页 / 共 3 页
字号:
/*                                                                 */
/* <connected-constraint>                                          */
/*            ::= <single-constraint> |                            */
/*                <single-constraint> & <connected-constraint> |   */
/*                <single-constraint> | <connected-constraint>     */
/*******************************************************************/
static struct lhsParseNode *ConjuctiveRestrictionParse(
  void *theEnv,
  char *readSource,
  struct token *theToken,
  int *error)
  {
   struct lhsParseNode *bindNode;
   struct lhsParseNode *theNode, *nextOr, *nextAnd;
   int connectorType;

   /*=====================================*/
   /* Get the first node and determine if */
   /* it is a binding variable.           */
   /*=====================================*/

   theNode = LiteralRestrictionParse(theEnv,readSource,theToken,error);

   if (*error == TRUE)
     { return(NULL); }

   GetToken(theEnv,readSource,theToken);

   if (((theNode->type == SF_VARIABLE) || (theNode->type == MF_VARIABLE)) &&
       (theNode->negated == FALSE) &&
       (theToken->type != OR_CONSTRAINT))
     {
      theNode->bindingVariable = TRUE;
      bindNode = theNode;
      nextOr = NULL;
      nextAnd = NULL;
     }
   else
     {
      bindNode = GetLHSParseNode(theEnv);
      if (theNode->type == MF_VARIABLE) bindNode->type = MF_WILDCARD;
      else bindNode->type = SF_WILDCARD;
      bindNode->negated = FALSE;
      bindNode->bottom = theNode;
      nextOr = theNode;
      nextAnd = theNode;
     }

   /*===================================*/
   /* Process the connected constraints */
   /* within the constraint             */
   /*===================================*/

   while ((theToken->type == OR_CONSTRAINT) || (theToken->type == AND_CONSTRAINT))
     {
      /*==========================*/
      /* Get the next constraint. */
      /*==========================*/

      connectorType = theToken->type;

      GetToken(theEnv,readSource,theToken);
      theNode = LiteralRestrictionParse(theEnv,readSource,theToken,error);

      if (*error == TRUE)
        {
         ReturnLHSParseNodes(theEnv,bindNode);
         return(NULL);
        }

      /*=======================================*/
      /* Attach the new constraint to the list */
      /* of constraints for this field.        */
      /*=======================================*/

      if (connectorType == OR_CONSTRAINT)
        {
         if (nextOr == NULL)
           { bindNode->bottom = theNode; }
         else
           { nextOr->bottom = theNode; }
         nextOr = theNode;
         nextAnd = theNode;
        }
      else if (connectorType == AND_CONSTRAINT)
        {
         if (nextAnd == NULL)
           {
            bindNode->bottom = theNode;
            nextOr = theNode;
           }
         else
           { nextAnd->right = theNode; }
         nextAnd = theNode;
        }
      else
        {
         SystemError(theEnv,"RULEPSR",1);
         EnvExitRouter(theEnv,EXIT_FAILURE);
        }

      /*==================================================*/
      /* Determine if any more restrictions are connected */
      /* to the current list of restrictions.             */
      /*==================================================*/

      GetToken(theEnv,readSource,theToken);
     }

   /*==========================================*/
   /* Check for illegal mixing of single and   */
   /* multifield values within the constraint. */
   /*==========================================*/

   if (CheckForVariableMixing(theEnv,bindNode))
     {
      *error = TRUE;
      ReturnLHSParseNodes(theEnv,bindNode);
      return(NULL);
     }

   /*========================*/
   /* Return the constraint. */
   /*========================*/

   return(bindNode);
  }

/*****************************************************/
/* CheckForVariableMixing: Checks a field constraint */
/*   to determine if single and multifield variables */
/*   are illegally mixed within it.                  */
/*****************************************************/
static int CheckForVariableMixing(
  void *theEnv,
  struct lhsParseNode *theRestriction)
  {
   struct lhsParseNode *tempRestriction;
   CONSTRAINT_RECORD *theConstraint;
   int multifield = FALSE;
   int singlefield = FALSE;
   int constant = FALSE;
   int singleReturnValue = FALSE;
   int multiReturnValue = FALSE;

   /*================================================*/
   /* If the constraint contains a binding variable, */
   /* determine whether it is a single field or      */
   /* multifield variable.                           */
   /*================================================*/

   if (theRestriction->type == SF_VARIABLE) singlefield = TRUE;
   else if (theRestriction->type == MF_VARIABLE) multifield = TRUE;

   /*===========================================*/
   /* Loop through each of the or (|) connected */
   /* constraints within the constraint.        */
   /*===========================================*/

   for (theRestriction = theRestriction->bottom;
        theRestriction != NULL;
        theRestriction = theRestriction->bottom)
     {
      /*============================================*/
      /* Loop through each of the and (&) connected */
      /* constraints within the or (|) constraint.  */
      /*============================================*/

      for (tempRestriction = theRestriction;
           tempRestriction != NULL;
           tempRestriction = tempRestriction->right)
        {
         /*=====================================================*/
         /* Determine if the constraint contains a single field */
         /* variable, multifield variable, constant (a single   */
         /* field), a return value constraint of a function     */
         /* returning a single field value, or a return value   */
         /* constraint of a function returning a multifield     */
         /* value.                                              */
         /*=====================================================*/

         if (tempRestriction->type == SF_VARIABLE) singlefield = TRUE;
         else if (tempRestriction->type == MF_VARIABLE) multifield = TRUE;
         else if (ConstantType(tempRestriction->type)) constant = TRUE;
         else if (tempRestriction->type == RETURN_VALUE_CONSTRAINT)
           {
            theConstraint = FunctionCallToConstraintRecord(theEnv,tempRestriction->expression->value);
            if (theConstraint->anyAllowed) { /* Do nothing. */ }
            else if (theConstraint->multifieldsAllowed) multiReturnValue = TRUE;
            else singleReturnValue = TRUE;
            RemoveConstraint(theEnv,theConstraint);
           }
        }
     }

   /*================================================================*/
   /* Using a single field value (a single field variable, constant, */
   /* or function returning a single field value) together with a    */
   /* multifield value (a multifield variable or function returning  */
   /* a multifield value) is illegal. Return TRUE if this occurs.    */
   /*================================================================*/

   if ((singlefield || constant || singleReturnValue) &&
       (multifield || multiReturnValue))

     {
      PrintErrorID(theEnv,"PATTERN",2,TRUE);
      EnvPrintRouter(theEnv,WERROR,"Single and multifield constraints cannot be mixed in a field constraint\n");
      return(TRUE);
     }

   /*=======================================*/
   /* Otherwise return FALSE to indicate no */
   /* illegal variable mixing was detected. */
   /*=======================================*/

   return(FALSE);
  }

/***********************************************************/
/* LiteralRestrictionParse: Parses a single constraint.    */
/*   The constraint may be a literal constraint, a         */
/*   predicate constraint, a return value constraint, or a */
/*   variable constraint. The constraints may also be      */
/*   negated using the ~ connective constraint.            */
/*                                                         */
/* <single-constraint>     ::= <term> | ~<term>            */
/*                                                         */
/*  <term>                 ::= <constant> |                */
/*                             <single-field-variable> |   */
/*                             <multi-field-variable> |    */
/*                             :<function-call> |          */
/*                             =<function-call>            */
/***********************************************************/
static struct lhsParseNode *LiteralRestrictionParse(
  void *theEnv,
  char *readSource,
  struct token *theToken,
  int *error)
  {
   struct lhsParseNode *topNode;
   struct expr *theExpression;

   /*============================================*/
   /* Create a node to represent the constraint. */
   /*============================================*/

   topNode = GetLHSParseNode(theEnv);

   /*=================================================*/
   /* Determine if the constraint has a '~' preceding */
   /* it. If it  does, then the field is negated      */
   /* (e.g. ~red means "not the constant red."        */
   /*=================================================*/

   if (theToken->type == NOT_CONSTRAINT)
     {
      GetToken(theEnv,readSource,theToken);
      topNode->negated = TRUE;
     }
   else
     { topNode->negated = FALSE; }

   /*===========================================*/
   /* Determine if the constraint is one of the */
   /* recognized types. These are ?variables,   */
   /* symbols, strings, numbers, :(expression), */
   /* and =(expression).                        */
   /*===========================================*/

   topNode->type = theToken->type;

   /*============================================*/
   /* Any symbol is valid, but an = signifies a  */
   /* return value constraint and an : signifies */
   /* a predicate constraint.                    */
   /*============================================*/

   if (theToken->type == SYMBOL)
     {
      /*==============================*/
      /* If the symbol is an =, parse */
      /* a return value constraint.   */
      /*==============================*/

      if (strcmp(ValueToString(theToken->value),"=") == 0)
        {
         theExpression = Function0Parse(theEnv,readSource);
         if (theExpression == NULL)
           {
            *error = TRUE;
            ReturnLHSParseNodes(theEnv,topNode);
            return(NULL);
           }
         topNode->type = RETURN_VALUE_CONSTRAINT;
         topNode->expression = ExpressionToLHSParseNodes(theEnv,theExpression);
         ReturnExpression(theEnv,theExpression);
        }

      /*=============================*/
      /* If the symbol is a :, parse */
      /* a predicate constraint.     */
      /*=============================*/

      else if (strcmp(ValueToString(theToken->value),":") == 0)
        {
         theExpression = Function0Parse(theEnv,readSource);
         if (theExpression == NULL)
           {
            *error = TRUE;
            ReturnLHSParseNodes(theEnv,topNode);
            return(NULL);
           }
         topNode->type = PREDICATE_CONSTRAINT;
         topNode->expression = ExpressionToLHSParseNodes(theEnv,theExpression);
         ReturnExpression(theEnv,theExpression);
        }

      /*==============================================*/
      /* Otherwise, treat the constraint as a symbol. */
      /*==============================================*/

      else
        { topNode->value = theToken->value; }
     }

   /*=====================================================*/
   /* Single and multifield variables and float, integer, */
   /* string, and instance name constants are also valid. */
   /*=====================================================*/

   else if ((theToken->type == SF_VARIABLE)  ||
            (theToken->type == MF_VARIABLE)  ||
            (theToken->type == FLOAT) ||
            (theToken->type == INTEGER) ||
            (theToken->type == STRING) ||
            (theToken->type == INSTANCE_NAME))
     { topNode->value = theToken->value; }

   /*===========================*/
   /* Anything else is invalid. */
   /*===========================*/

   else
     {
      SyntaxErrorMessage(theEnv,"defrule");
      *error = TRUE;
      ReturnLHSParseNodes(theEnv,topNode);
      return(NULL);
     }

   /*===============================*/
   /* Return the parsed constraint. */
   /*===============================*/

   return(topNode);
  }

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

#endif /* DEFRULE_CONSTRUCT */




⌨️ 快捷键说明

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