📄 reorder.c
字号:
break; } /*==============================*/ /* Two adjacent test CEs within */ /* an and CE can be combined. */ /*==============================*/ else if ((theLHS->type == AND_CE) && (argPtr->type == TEST_CE) && ((argPtr->bottom != NULL) ? argPtr->bottom->type == TEST_CE : CLIPS_FALSE) && (argPtr->beginNandDepth == argPtr->endNandDepth) && (argPtr->endNandDepth == argPtr->bottom->beginNandDepth)) { change = CLIPS_TRUE; *newChange = CLIPS_TRUE; e1 = LHSParseNodesToExpression(argPtr->expression); e2 = LHSParseNodesToExpression(argPtr->bottom->expression); e1 = CombineExpressions(e1,e2); ReturnLHSParseNodes(argPtr->expression); argPtr->expression = ExpressionToLHSParseNodes(e1); ReturnExpression(e1); tempArg = argPtr->bottom; argPtr->bottom = tempArg->bottom; tempArg->bottom = NULL; ReturnLHSParseNodes(tempArg); } /*=====================================*/ /* Replace and CEs containing a single */ /* test CE with just a test CE. */ /*=====================================*/ else if ((theLHS->type == AND_CE) && (argPtr->type == TEST_CE) && (theLHS->right == argPtr) && (argPtr->bottom == NULL)) { change = CLIPS_TRUE; *newChange = CLIPS_TRUE; CopyLHSParseNode(theLHS,argPtr,CLIPS_TRUE); theLHS->right = NULL; ReturnLHSParseNodes(argPtr); break; } /*===================================================*/ /* If no changes are needed, move on to the next CE. */ /*===================================================*/ else { lastArg = argPtr; argPtr = argPtr->bottom; } } } /*===========================*/ /* Return the reordered LHS. */ /*===========================*/ return(theLHS); } /*********************************************************************//* CopyLHSParseNodes: Copies a linked group of conditional elements. *//*********************************************************************/globle struct lhsParseNode *CopyLHSParseNodes(listOfCEs) struct lhsParseNode *listOfCEs; { struct lhsParseNode *newList; if (listOfCEs == NULL) { return(NULL); } newList = get_struct(lhsParseNode); CopyLHSParseNode(newList,listOfCEs,CLIPS_TRUE); newList->right = CopyLHSParseNodes(listOfCEs->right); newList->bottom = CopyLHSParseNodes(listOfCEs->bottom); return(newList); }/**********************************************************//* CopyLHSParseNode: Copies a single conditional element. *//**********************************************************/globle VOID CopyLHSParseNode(dest,src,duplicate) struct lhsParseNode *dest, *src; int duplicate; { dest->type = src->type; dest->value = src->value; dest->negated = src->negated; dest->bindingVariable = src->bindingVariable; dest->withinMultifieldSlot = src->withinMultifieldSlot; dest->multifieldSlot = src->multifieldSlot; dest->multiFieldsBefore = src->multiFieldsBefore; dest->multiFieldsAfter = src->multiFieldsAfter; dest->singleFieldsBefore = src->singleFieldsBefore; dest->singleFieldsAfter = src->singleFieldsAfter; dest->logical = src->logical; dest->userCE = src->userCE; dest->referringNode = src->referringNode; dest->patternType = src->patternType; dest->pattern = src->pattern; dest->index = src->index; dest->slot = src->slot; dest->slotNumber = src->slotNumber; dest->beginNandDepth = src->beginNandDepth; dest->endNandDepth = src->endNandDepth; /*==========================================================*/ /* The duplicate flag controls whether pointers to existing */ /* data structures are used when copying some slots or if */ /* new copies of the data structures are made. */ /*==========================================================*/ if (duplicate) { dest->networkTest = CopyExpression(src->networkTest); if (src->userData == NULL) { dest->userData = NULL; } else if (src->patternType->copyUserDataFunction == NULL) { dest->userData = src->userData; } else { dest->userData = (*src->patternType->copyUserDataFunction)(src->userData); } dest->expression = CopyLHSParseNodes(src->expression); dest->constraints = CopyConstraintRecord(src->constraints); if (dest->constraints != NULL) dest->derivedConstraints = CLIPS_TRUE; else dest->derivedConstraints = CLIPS_FALSE; } else { dest->networkTest = src->networkTest; dest->userData = src->userData; dest->expression = src->expression; dest->derivedConstraints = CLIPS_FALSE; dest->constraints = src->constraints; } }/****************************************************//* GetLHSParseNode: Creates an empty node structure *//* used for building conditional elements. *//****************************************************/globle struct lhsParseNode *GetLHSParseNode() { struct lhsParseNode *newNode; newNode = get_struct(lhsParseNode); newNode->type = UNKNOWN_VALUE; newNode->value = NULL; newNode->negated = CLIPS_FALSE; newNode->bindingVariable = CLIPS_FALSE; newNode->withinMultifieldSlot = CLIPS_FALSE; newNode->multifieldSlot = CLIPS_FALSE; newNode->multiFieldsBefore = 0; newNode->multiFieldsAfter = 0; newNode->singleFieldsBefore = 0; newNode->singleFieldsAfter = 0; newNode->logical = CLIPS_FALSE; newNode->derivedConstraints = CLIPS_FALSE; newNode->userCE = CLIPS_TRUE; newNode->constraints = NULL; newNode->referringNode = NULL; newNode->patternType = NULL; newNode->pattern = -1; newNode->index = -1; newNode->slot = NULL; newNode->slotNumber = -1; newNode->beginNandDepth = 1; newNode->endNandDepth = 1; newNode->userData = NULL; newNode->networkTest = NULL; newNode->expression = NULL; newNode->right = NULL; newNode->bottom = NULL; return(newNode); }/***********************************************************//* ReturnLHSParseNodes: Returns a multiply linked list of *//* lhsParseNode structures to the CLIPS memory manager. *//***********************************************************/globle VOID ReturnLHSParseNodes(waste) struct lhsParseNode *waste; { if (waste != NULL) { ReturnExpression(waste->networkTest); ReturnLHSParseNodes(waste->right); ReturnLHSParseNodes(waste->bottom); ReturnLHSParseNodes(waste->expression); if (waste->derivedConstraints) RemoveConstraint(waste->constraints); if ((waste->userData != NULL) && (waste->patternType->returnUserDataFunction != NULL)) { (*waste->patternType->returnUserDataFunction)(waste->userData); } rtn_struct(lhsParseNode,waste); } }/********************************************************//* ExpressionToLHSParseNodes: Copies an expression into *//* the equivalent lhsParseNode data structures. *//********************************************************/globle struct lhsParseNode *ExpressionToLHSParseNodes(expressionList) struct expr *expressionList; { struct lhsParseNode *newList, *theList; struct FunctionDefinition *theFunction; int i, theRestriction; /*===========================================*/ /* A NULL expression requires no conversion. */ /*===========================================*/ if (expressionList == NULL) return(NULL); /*====================================*/ /* Recursively convert the expression */ /* to lhsParseNode data structures. */ /*====================================*/ newList = GetLHSParseNode(); newList->type = expressionList->type; newList->value = expressionList->value; newList->right = ExpressionToLHSParseNodes(expressionList->nextArg); newList->bottom = ExpressionToLHSParseNodes(expressionList->argList); /*==================================================*/ /* If the expression is a function call, then store */ /* the constraint information for the functions */ /* arguments in the lshParseNode data structures. */ /*==================================================*/ if (newList->type != FCALL) return(newList); theFunction = (struct FunctionDefinition *) newList->value; for (theList = newList->bottom, i = 1; theList != NULL; theList = theList->right, i++) { if (theList->type == SF_VARIABLE) { theRestriction = GetNthRestriction(theFunction,i); theList->constraints = ArgumentTypeToConstraintRecord(theRestriction); theList->derivedConstraints = CLIPS_TRUE; } } /*==================================*/ /* Return the converted expression. */ /*==================================*/ return(newList); } /******************************************************************//* LHSParseNodesToExpression: Copies lhsParseNode data structures *//* into the equivalent expression data structures. *//******************************************************************/globle struct expr *LHSParseNodesToExpression(nodeList) struct lhsParseNode *nodeList; { struct expr *newList; if (nodeList == NULL) { return(NULL); } newList = get_struct(expr); newList->type = (short) nodeList->type; newList->value = nodeList->value; newList->nextArg = LHSParseNodesToExpression(nodeList->right); newList->argList = LHSParseNodesToExpression(nodeList->bottom); return(newList); }/************************************************************//* IncrementNandDepth: Increments the nand depth of a group *//* of CEs. The nand depth is used to indicate the nesting *//* of not/and or not/not CEs which are implemented using *//* joins from the right. A single pattern within a "not" *//* CE does not require a join from the right and its nand *//* depth is normally not increased (except when it's *//* within a not/and or not/not CE. The begin nand depth *//* indicates the current nesting for a CE. The end nand *//* depth indicates the nand depth in the following CE *//* (assuming that the next CE is not the beginning of a *//* new group of nand CEs). All but the last CE in a nand *//* group should have the same begin and end nand depths. *//* Since a single CE can be the last CE of several nand *//* groups, it is possible to have an end nand depth that *//* is more than 1 less than the begin nand depth of the *//* CE. *//************************************************************/static VOID IncrementNandDepth(theLHS,lastCE) struct lhsParseNode *theLHS; int lastCE; { /*======================================*/ /* Loop through each CE in the group of */ /* CEs having its nand depth increased. */ /*======================================*/ for (; theLHS != NULL; theLHS = theLHS->bottom) { /*=========================================================*/ /* Increment the begin nand depth of pattern and test CEs. */ /* The last CE in the original list doesn't have its end */ /* nand depth incremented. All other last CEs in other CEs */ /* entered recursively do have their end depth incremented */ /* (unless the last CE in the recursively entered CE is */ /* the same last CE as contained in the original group */ /* when this function was first entered). */ /*=========================================================*/ if ((theLHS->type == PATTERN_CE) || (theLHS->type == TEST_CE)) { theLHS->beginNandDepth++; if (lastCE == CLIPS_FALSE) theLHS->endNandDepth++; else if (theLHS->bottom != NULL) theLHS->endNandDepth++; } /*==============================================*/ /* Recursively increase the nand depth of other */ /* CEs contained within the CE having its nand */ /* depth increased. */ /*==============================================*/ else if ((theLHS->type == AND_CE) || (theLHS->type == NOT_CE)) { IncrementNandDepth(theLHS->right, (lastCE ? (theLHS->bottom == NULL) : CLIPS_FALSE)); } /*=====================================*/ /* All or CEs should have been removed */ /* from the LHS at this point. */ /*=====================================*/ else if (theLHS->type == OR_CE) { CLIPSSystemError("REORDER",1); } } } /***********************************************************//* CreateInitialPattern: Creates a default pattern used in *//* the LHS of a rule under certain cirmustances (such as *//* when a "not" or "test" CE is the first CE in an "and" *//* CE or when no CEs are specified in the LHS of a rule. *//***********************************************************/static struct lhsParseNode *CreateInitialPattern(theParser) struct patternParser *theParser; { struct lhsParseNode *topNode; /*==========================================*/ /* Create the top most node of the pattern. */ /*==========================================*/ topNode = GetLHSParseNode(); topNode->type = PATTERN_CE; topNode->userCE = CLIPS_FALSE; topNode->bottom = NULL; /*==============================================*/ /* If a pattern type was not supplied, then try */ /* to use the (initial-fact) fact pattern. */ /*==============================================*/ if (theParser == NULL) { theParser = FindPatternParser("facts"); } /*====================================================*/ /* If a pattern type was supplied or the initial fact */ /* pattern is available, create the initial pattern */ /* with one of those in the given order. */ /*====================================================*/ if (theParser != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -