📄 rulecstr.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* RULE CONSTRAINTS MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides routines for detecting constraint *//* conflicts in the LHS and RHS of rules. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//*************************************************************/#define _RULECSTR_SOURCE_#include "setup.h"#if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT#include <stdio.h>#define _CLIPS_STDIO_#include "router.h"#include "reorder.h"#include "cstrnchk.h"#include "cstrnops.h"#include "extnfunc.h"#include "analysis.h"#include "prcdrpsr.h"#include "cstrnutl.h"#include "rulepsr.h"#include "rulecstr.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/ #if ANSI_COMPILER static BOOLEAN CheckForUnmatchableConstraints(struct lhsParseNode *,int); static BOOLEAN MultifieldCardinalityViolation(struct lhsParseNode *); static struct lhsParseNode *UnionVariableConstraints(struct lhsParseNode *, struct lhsParseNode *); static struct lhsParseNode *AddToVariableConstraints(struct lhsParseNode *, struct lhsParseNode *); static VOID ConstraintConflictMessage(struct symbolHashNode *, int,int,struct symbolHashNode *); static BOOLEAN CheckArgumentForConstraintError(struct expr *,struct expr*, int,struct FunctionDefinition *, struct lhsParseNode *);#else static BOOLEAN CheckForUnmatchableConstraints(); static BOOLEAN MultifieldCardinalityViolation(); static struct lhsParseNode *UnionVariableConstraints(); static struct lhsParseNode *AddToVariableConstraints(); static VOID ConstraintConflictMessage(); static BOOLEAN CheckArgumentForConstraintError();#endif /***********************************************************//* CheckForUnmatchableConstraints: Determines if a LHS CE *//* node contains unmatchable constraints. Return TRUE if *//* there are unmatchable constraints, otherwise FALSE. *//***********************************************************/static BOOLEAN CheckForUnmatchableConstraints(theNode,whichCE) struct lhsParseNode *theNode; int whichCE; { if (GetStaticConstraintChecking() == CLIPS_FALSE) return(CLIPS_FALSE); if (UnmatchableConstraint(theNode->constraints)) { ConstraintConflictMessage(theNode->value,whichCE, theNode->index,theNode->slot); return(CLIPS_TRUE); } return(CLIPS_FALSE); }/******************************************************//* ConstraintConflictMessage: Error message used when *//* a constraint restriction for a slot prevents any *//* value from matching the pattern constraint. *//******************************************************/static VOID ConstraintConflictMessage(variableName,thePattern,theField,theSlot) struct symbolHashNode *variableName; int thePattern, theField; struct symbolHashNode *theSlot; { /*=========================*/ /* Print the error header. */ /*=========================*/ PrintErrorID("RULECSTR",1,CLIPS_TRUE); /*======================================================*/ /* Print the variable name (if available) and CE number */ /* for which the constraint violation occurred. */ /*======================================================*/ if (variableName != NULL) { PrintCLIPS(WERROR,"Variable ?"); PrintCLIPS(WERROR,ValueToString(variableName)); PrintCLIPS(WERROR," in CE #"); PrintLongInteger(WERROR,(long int) thePattern); } else { PrintCLIPS(WERROR,"Pattern #"); PrintLongInteger(WERROR,(long int) thePattern); } /*=======================================*/ /* Print the slot name or field position */ /* in which the violation occurred. */ /*=======================================*/ if (theSlot == NULL) { PrintCLIPS(WERROR," field #"); PrintLongInteger(WERROR,(long int) theField); } else { PrintCLIPS(WERROR," slot "); PrintCLIPS(WERROR,ValueToString(theSlot)); } /*======================================*/ /* Print the rest of the error message. */ /*======================================*/ PrintCLIPS(WERROR,"\nhas constraint conflicts which make the pattern unmatchable.\n"); } /***************************************************************//* MultifieldCardinalityViolation: Determines if a cardinality *//* violation has occurred for a LHS CE node. *//***************************************************************/static BOOLEAN MultifieldCardinalityViolation(theNode) struct lhsParseNode *theNode; { struct lhsParseNode *tmpNode; struct expr *tmpMax; long minFields = 0; long maxFields = 0; int positiveInfinity = CLIPS_FALSE; CONSTRAINT_RECORD *newConstraint, *tempConstraint; /*================================*/ /* A single field slot can't have */ /* a cardinality violation. */ /*================================*/ if (theNode->multifieldSlot == CLIPS_FALSE) return(CLIPS_FALSE); /*=============================================*/ /* Determine the minimum and maximum number of */ /* fields the slot could contain based on the */ /* slot constraints found in the pattern. */ /*=============================================*/ for (tmpNode = theNode->bottom; tmpNode != NULL; tmpNode = tmpNode->right) { /*====================================================*/ /* A single field variable increases both the minimum */ /* and maximum number of fields by one. */ /*====================================================*/ if ((tmpNode->type == SF_VARIABLE) || (tmpNode->type == SF_WILDCARD)) { minFields++; maxFields++; } /*=================================================*/ /* Otherwise a multifield wildcard or variable has */ /* been encountered. If it is constrained then use */ /* minimum and maximum number of fields constraint */ /* associated with this LHS node. */ /*=================================================*/ else if (tmpNode->constraints != NULL) { /*=======================================*/ /* The lowest minimum of all the min/max */ /* pairs will be the first in the list. */ /*=======================================*/ if (tmpNode->constraints->minFields->value != NegativeInfinity) { minFields += ValueToLong(tmpNode->constraints->minFields->value); } /*=========================================*/ /* The greatest maximum of all the min/max */ /* pairs will be the last in the list. */ /*=========================================*/ tmpMax = tmpNode->constraints->maxFields; while (tmpMax->nextArg != NULL) tmpMax = tmpMax->nextArg; if (tmpMax->value == PositiveInfinity) { positiveInfinity = CLIPS_TRUE; } else { maxFields += ValueToLong(tmpMax->value); } } /*================================================*/ /* Otherwise an unconstrained multifield wildcard */ /* or variable increases the maximum number of */ /* fields to positive infinity. */ /*================================================*/ else { positiveInfinity = CLIPS_TRUE; } } /*==================================================================*/ /* Create a constraint record for the cardinality of the sum of the */ /* cardinalities of the restrictions inside the multifield slot. */ /*==================================================================*/ if (theNode->constraints == NULL) tempConstraint = GetConstraintRecord(); else tempConstraint = CopyConstraintRecord(theNode->constraints); ReturnExpression(tempConstraint->minFields); ReturnExpression(tempConstraint->maxFields); tempConstraint->minFields = GenConstant(INTEGER,AddLong((long) minFields)); if (positiveInfinity) tempConstraint->maxFields = GenConstant(SYMBOL,PositiveInfinity); else tempConstraint->maxFields = GenConstant(INTEGER,AddLong((long) maxFields)); /*================================================================*/ /* Determine the final cardinality for the multifield slot by */ /* intersecting the cardinality sum of the restrictions within */ /* the multifield slot with the original cardinality of the slot. */ /*================================================================*/ newConstraint = IntersectConstraints(theNode->constraints,tempConstraint); if (theNode->derivedConstraints) RemoveConstraint(theNode->constraints); RemoveConstraint(tempConstraint); theNode->constraints = newConstraint; theNode->derivedConstraints = CLIPS_TRUE; /*===================================================================*/ /* Determine if the final cardinality for the slot can be satisfied. */ /*===================================================================*/ if (GetStaticConstraintChecking() == CLIPS_FALSE) return(CLIPS_FALSE); if (UnmatchableConstraint(newConstraint)) return(CLIPS_TRUE); return(CLIPS_FALSE); } /***************************************************//* ProcessConnectedConstraints: Examines a single *//* connected constraint searching for constraint *//* violations. *//***************************************************/globle BOOLEAN ProcessConnectedConstraints(theNode,multifieldHeader,patternHead) struct lhsParseNode *theNode, *multifieldHeader, *patternHead; { struct constraintRecord *orConstraints = NULL, *andConstraints; struct constraintRecord *tmpConstraints, *rvConstraints; struct lhsParseNode *orNode, *andNode; struct expr *tmpExpr; /*============================================*/ /* Loop through all of the or (|) constraints */ /* found in the connected constraint. */ /*============================================*/ for (orNode = theNode->bottom; orNode != NULL; orNode = orNode->bottom) { /*=================================================*/ /* Intersect all of the &'ed constraints together. */ /*=================================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -