📄 factbld.c
字号:
/*************************************************************//* FindPatternNode: Looks for a pattern node at a specified *//* level in the pattern network that can be reused (shared) *//* with a pattern field being added to the pattern network. *//*************************************************************/static struct factPatternNode *FindPatternNode(listOfNodes,thePattern, nodeBeforeMatch,endSlot) struct factPatternNode *listOfNodes; struct lhsParseNode *thePattern; struct factPatternNode **nodeBeforeMatch; int endSlot; { *nodeBeforeMatch = NULL; /*==========================================================*/ /* Loop through the nodes at the given level in the pattern */ /* network looking for a node that can be reused (shared)? */ /*==========================================================*/ while (listOfNodes != NULL) { /*==========================================================*/ /* If the type of the pattern node and the expression being */ /* tested by the pattern node are the same as the type and */ /* expression for the pattern field being added, then */ /* return the pattern node because it can be shared with */ /* the pattern field being added. */ /*==========================================================*/ if ((thePattern->type == SF_WILDCARD) || (thePattern->type == SF_VARIABLE)) { if ((listOfNodes->header.singlefieldNode) && (listOfNodes->header.endSlot == endSlot) && (listOfNodes->whichField == thePattern->index) && (listOfNodes->whichSlot == (thePattern->slotNumber - 1)) && IdenticalExpression(listOfNodes->networkTest,thePattern->networkTest)) { return(listOfNodes); } } else if ((thePattern->type == MF_WILDCARD) || (thePattern->type == MF_VARIABLE)) { if ((listOfNodes->header.multifieldNode) && (listOfNodes->header.endSlot == endSlot) && (listOfNodes->leaveFields == thePattern->singleFieldsAfter) && (listOfNodes->whichField == thePattern->index) && (listOfNodes->whichSlot == (thePattern->slotNumber - 1)) && IdenticalExpression(listOfNodes->networkTest,thePattern->networkTest)) { return(listOfNodes); } } /*==================================*/ /* Move on to the next node at this */ /* level in the pattern network. */ /*==================================*/ *nodeBeforeMatch = listOfNodes; listOfNodes = listOfNodes->rightNode; } /*==============================================*/ /* A shareable pattern node could not be found. */ /*==============================================*/ return(NULL); } /*************************************************************//* RemoveUnneededSlots: Removes fact pattern nodes that have *//* no effect on pattern matching. For example, given the *//* following deftemplate and a pattern using it, *//* *//* (deftemplate foo (slot x) (slot y)) *//* *//* (foo (x ?x) (y ?y)) *//* *//* The x and y slot pattern nodes can be discarded since *//* all foo facts will have these two slots in the fact *//* data structure used to store them. *//*************************************************************/static struct lhsParseNode *RemoveUnneededSlots(thePattern) struct lhsParseNode *thePattern; { struct lhsParseNode *tempPattern = thePattern; struct lhsParseNode *lastPattern = NULL, *head = thePattern; struct expr *theTest; while (tempPattern != NULL) { /*=============================================================*/ /* A single field slot that has no pattern network expression */ /* associated with it can be removed (i.e. any value contained */ /* in this slot will satisfy the pattern being matched). */ /*=============================================================*/ if (((tempPattern->type == SF_WILDCARD) || (tempPattern->type == SF_VARIABLE)) && (tempPattern->networkTest == NULL)) { if (lastPattern != NULL) lastPattern->right = tempPattern->right; else head = tempPattern->right; tempPattern->right = NULL; ReturnLHSParseNodes(tempPattern); if (lastPattern != NULL) tempPattern = lastPattern->right; else tempPattern = head; } /*=======================================================*/ /* A multifield variable or wildcard within a multifield */ /* slot can be removed if there are no other multifield */ /* variables or wildcards contained in the same slot */ /* (and the multifield has no expressions which must be */ /* evaluated in the fact pattern network). */ /*=======================================================*/ else if (((tempPattern->type == MF_WILDCARD) || (tempPattern->type == MF_VARIABLE)) && (tempPattern->multifieldSlot == CLIPS_FALSE) && (tempPattern->networkTest == NULL) && (tempPattern->multiFieldsBefore == 0) && (tempPattern->multiFieldsAfter == 0)) { if (lastPattern != NULL) lastPattern->right = tempPattern->right; else head = tempPattern->right; tempPattern->right = NULL; ReturnLHSParseNodes(tempPattern); if (lastPattern != NULL) tempPattern = lastPattern->right; else tempPattern = head; } /*==================================================================*/ /* A multifield wildcard or variable contained in a multifield slot */ /* that contains no other multifield wildcards or variables, but */ /* does have an expression that must be evaluated, can be changed */ /* to a single field pattern node with the same expression. */ /*==================================================================*/ else if (((tempPattern->type == MF_WILDCARD) || (tempPattern->type == MF_VARIABLE)) && (tempPattern->multifieldSlot == CLIPS_FALSE) && (tempPattern->networkTest != NULL) && (tempPattern->multiFieldsBefore == 0) && (tempPattern->multiFieldsAfter == 0)) { tempPattern->type = SF_WILDCARD; lastPattern = tempPattern; tempPattern = tempPattern->right; } /*=========================================================*/ /* If we're dealing with a multifield slot with no slot */ /* restrictions, then treat the multfield slot as a single */ /* field slot, but attach a test which verifies that the */ /* slot contains a zero length multifield value. */ /*=========================================================*/ else if ((tempPattern->type == MF_WILDCARD) && (tempPattern->multifieldSlot == CLIPS_TRUE) && (tempPattern->bottom == NULL)) { tempPattern->type = SF_WILDCARD; tempPattern->networkTest = FactGenCheckZeroLength(tempPattern->slotNumber); tempPattern->multifieldSlot = CLIPS_FALSE; lastPattern = tempPattern; tempPattern = tempPattern->right; } /*===================================================*/ /* Recursively call RemoveUnneededSlots for the slot */ /* restrictions contained within a multifield slot. */ /*===================================================*/ else if ((tempPattern->type == MF_WILDCARD) && (tempPattern->multifieldSlot == CLIPS_TRUE)) { /*=======================================================*/ /* Add an expression to the first pattern restriction in */ /* the multifield slot that determines whether or not */ /* the fact's slot value contains the minimum number of */ /* required fields to satisfy the pattern restrictions */ /* for this slot. The length check is place before any */ /* other tests, so that preceeding checks do not have to */ /* determine if there are enough fields in the slot to */ /* safely retrieve a value. */ /*=======================================================*/ theTest = FactGenCheckLength(tempPattern->bottom); theTest = CombineExpressions(theTest,tempPattern->bottom->networkTest); tempPattern->bottom->networkTest = theTest; /*=========================================================*/ /* Remove any unneeded pattern restrictions from the slot. */ /*=========================================================*/ tempPattern->bottom = RemoveUnneededSlots(tempPattern->bottom); /*===========================================================*/ /* If the slot no longer contains any restrictions, then the */ /* multifield slot can be completely removed. In any case, */ /* move on to the next slot to be examined for removal. */ /*===========================================================*/ if (tempPattern->bottom == NULL) { if (lastPattern != NULL) lastPattern->right = tempPattern->right; else head = tempPattern->right; tempPattern->right = NULL; ReturnLHSParseNodes(tempPattern); if (lastPattern != NULL) tempPattern = lastPattern->right; else tempPattern = head; } else { lastPattern = tempPattern; tempPattern = tempPattern->right; } } /*=======================================================*/ /* If none of the other tests for removing slots or slot */ /* restrictions apply, then move on to the next slot or */ /* slot restriction to be tested. */ /*=======================================================*/ else { lastPattern = tempPattern; tempPattern = tempPattern->right; } } /*======================================*/ /* Return the pattern with unused slots */ /* and slot restrictions removed. */ /*======================================*/ return(head); }/****************************************************//* CreateNewPatternNode: Creates a new pattern node *//* and initializes all of its values. *//****************************************************/static struct factPatternNode *CreateNewPatternNode(thePattern,nodeBeforeMatch, upperLevel,endSlot) struct lhsParseNode *thePattern; struct factPatternNode *nodeBeforeMatch; struct factPatternNode *upperLevel; int endSlot; { struct factPatternNode *newNode; /*========================================*/ /* Create the pattern node and initialize */ /* its slots to the default values. */ /*========================================*/ newNode = get_struct(factPatternNode); newNode->nextLevel = NULL; newNode->rightNode = NULL; newNode->leftNode = NULL; newNode->leaveFields = thePattern->singleFieldsAfter; InitializePatternHeader((struct patternNodeHeader *) &newNode->header); if (thePattern->index > 0) newNode->whichField = thePattern->index; else newNode->whichField = 0; if (thePattern->slotNumber >= 0) newNode->whichSlot = thePattern->slotNumber - 1; else newNode->whichSlot = newNode->whichField; /*=============================================================*/ /* Set the slot values which indicate whether the pattern node */ /* is a single-field, multifield, or end-of-pattern node. */ /*=============================================================*/ if ((thePattern->type == SF_WILDCARD) || (thePattern->type == SF_VARIABLE)) { newNode->header.singlefieldNode = CLIPS_TRUE; } else if ((thePattern->type == MF_WILDCARD) || (thePattern->type == MF_VARIABLE)) { newNode->header.multifieldNode = CLIPS_TRUE; } newNode->header.endSlot = endSlot; /*===========================================================*/ /* Install the expression associated with this pattern node. */ /*===========================================================*/ newNode->networkTest = AddHashedExpression(thePattern->networkTest); /*===============================================*/ /* Set the upper level pointer for the new node. */ /*===============================================*/ newNode->lastLevel = upperLevel; /*======================================================*/ /* If there are no nodes on this level, then attach the */ /* new node to the child pointer of the upper level. */ /*======================================================*/ if (nodeBeforeMatch == NULL) { if (upperLevel == NULL) CurrentDeftemplate->patternNetwork = newNode; else upperLevel->nextLevel = newNode; return(newNode); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -