📄 factmch.c
字号:
theSlotValue = (struct multifield *) CurrentPatternFact->theProposition.theFields[thePattern->whichSlot].value; /*===============================================*/ /* Save the value of the markers already stored. */ /*===============================================*/ oldMark = markers; /*===========================================*/ /* Create a new multifield marker and append */ /* it to the end of the current list. */ /*===========================================*/ newMark = get_struct(multifieldMarker); newMark->whichField = thePattern->whichField - 1; newMark->where.whichSlotNumber = (short) thePattern->whichSlot; newMark->startPosition = (thePattern->whichField - 1) + offset; newMark->next = NULL; if (endMark == NULL) { markers = newMark; CurrentPatternMarks = markers; } else { endMark->next = newMark; } /*============================================*/ /* Handle a multifield constraint as the last */ /* constraint of a slot as a special case. */ /*============================================*/ if (thePattern->header.endSlot) { newMark->endPosition = theSlotValue->multifieldLength - (thePattern->leaveFields + 1); /*=======================================================*/ /* Make sure the endPosition is never more than less one */ /* less of the startPosition (a multifield containing no */ /* values. */ /*=======================================================*/ if (newMark->endPosition < newMark->startPosition) { newMark->endPosition = newMark->startPosition - 1; } /*===========================================*/ /* Determine if the constraint is satisfied. */ /*===========================================*/ if ((thePattern->networkTest == NULL) ? CLIPS_TRUE : (EvaluatePatternExpression(thePattern,thePattern->networkTest, (int) thePattern->whichField + offset))) { /*=======================================================*/ /* If a leaf pattern node has been successfully reached, */ /* then the pattern has been satisified. Generate an */ /* alpha match to store in the pattern node. */ /*=======================================================*/ if (thePattern->header.stopNode) { ProcessFactAlphaMatch(CurrentPatternFact,CurrentPatternMarks,thePattern); } /*=============================================*/ /* Recursively continue pattern matching based */ /* on the multifield binding just generated. */ /*=============================================*/ FactPatternMatch(CurrentPatternFact, thePattern->nextLevel,0,CurrentPatternMarks,newMark); } /*================================================*/ /* Discard the multifield marker since we've done */ /* all the pattern matching for this binding of */ /* the multifield slot constraint. */ /*================================================*/ rtn_struct(multifieldMarker,newMark); if (endMark != NULL) endMark->next = NULL; CurrentPatternMarks = oldMark; return; } /*==============================================*/ /* Perform matching for nodes beneath this one. */ /*==============================================*/ for (repeatCount = theSlotValue->multifieldLength - (newMark->startPosition + thePattern->leaveFields); repeatCount >= 0; repeatCount--) { newMark->endPosition = newMark->startPosition + (repeatCount - 1); if ((thePattern->networkTest == NULL) ? CLIPS_TRUE : (EvaluatePatternExpression(thePattern,thePattern->networkTest, (int) thePattern->whichField + offset))) { FactPatternMatch(CurrentPatternFact, thePattern->nextLevel,offset + repeatCount - 1, CurrentPatternMarks,newMark); } } /*======================================================*/ /* Get rid of the marker created for a multifield node. */ /*======================================================*/ rtn_struct(multifieldMarker,newMark); if (endMark != NULL) endMark->next = NULL; CurrentPatternMarks = oldMark; } /******************************************************//* GetNextFactPatternNode: Returns the next node in a *//* pattern network tree to be traversed. The next *//* node is computed using a depth first traversal. */ /******************************************************/static struct factPatternNode *GetNextFactPatternNode(finishedMatching,thePattern) int finishedMatching; struct factPatternNode *thePattern; { EvaluationError = CLIPS_FALSE; /*===================================================*/ /* If pattern matching was successful at the current */ /* node in the tree and it's possible to go deeper */ /* into the tree, then move down to the next level. */ /*===================================================*/ if (finishedMatching == CLIPS_FALSE) { if (thePattern->nextLevel != NULL) return(thePattern->nextLevel); } /*================================================*/ /* Keep backing up toward the root of the pattern */ /* network until a side branch can be taken. */ /*================================================*/ while (thePattern->rightNode == NULL) { /*========================================*/ /* Back up to check the next side branch. */ /*========================================*/ thePattern = thePattern->lastLevel; /*======================================*/ /* If we branched up from the root, the */ /* entire tree has been traversed. */ /*======================================*/ if (thePattern == NULL) return(NULL); /*===================================================*/ /* If we branched up to a multifield node, then stop */ /* since these nodes are handled recursively. The */ /* previous call to the pattern matching algorithm */ /* on the stack will handle backing up to the nodes */ /* above the multifield node in the pattern network. */ /*===================================================*/ if (thePattern->header.multifieldNode) return(NULL); } /*==================================*/ /* Move on to the next side branch. */ /*==================================*/ return(thePattern->rightNode); } /*******************************************************//* ProcessFactAlphaMatch: When a fact pattern has been *//* satisfied, this routine creates an alpha match to *//* store in the pattern network and then sends the *//* new alpha match through the join network. *//*******************************************************/static VOID ProcessFactAlphaMatch(theFact,theMarks,thePattern) struct fact *theFact; struct multifieldMarker *theMarks; struct factPatternNode *thePattern; { struct partialMatch *theMatch; struct patternMatch *listOfMatches; struct joinNode *listOfJoins; /*===========================================*/ /* Create the partial match for the pattern. */ /*===========================================*/ theMatch = CreateAlphaMatch(theFact,theMarks,(struct patternNodeHeader *) &thePattern->header); /*=======================================================*/ /* Add the pattern to the list of matches for this fact. */ /*=======================================================*/ listOfMatches = (struct patternMatch *) theFact->list; theFact->list = (VOID *) get_struct(patternMatch); ((struct patternMatch *) theFact->list)->next = listOfMatches; ((struct patternMatch *) theFact->list)->matchingPattern = (struct patternNodeHeader *) thePattern; ((struct patternMatch *) theFact->list)->theMatch = theMatch; /*================================================================*/ /* Send the partial match to the joins connected to this pattern. */ /*================================================================*/ for (listOfJoins = thePattern->header.entryJoin; listOfJoins != NULL; listOfJoins = listOfJoins->rightMatchNode) { NetworkAssert(theMatch,listOfJoins,RHS); } } /*****************************************************************//* EvaluatePatternExpression: Performs a faster evaluation for *//* fact pattern network expressions than if EvaluateExpression *//* were used directly. *//*****************************************************************/static int EvaluatePatternExpression(patternPtr,theTest,thePosition) struct factPatternNode *patternPtr; struct expr *theTest; int thePosition; { DATA_OBJECT theResult; struct expr *oldArgument; int rv; /*=====================================*/ /* A pattern node without a constraint */ /* is always satisfied. */ /*=====================================*/ if (theTest == NULL) return(CLIPS_TRUE); /*======================================*/ /* Evaluate pattern network primitives. */ /*======================================*/ switch(theTest->type) { /*==============================================*/ /* This primitive compares the value stored in */ /* a single field slot to a constant for either */ /* equality or inequality. */ /*==============================================*/ case FACT_PN_CONSTANT1: oldArgument = CurrentExpression; CurrentExpression = theTest; rv = FactPNConstant1(theTest->value,&theResult); CurrentExpression = oldArgument; return(rv); /*=============================================*/ /* This primitive compares the value stored in */ /* a multifield slot to a constant for either */ /* equality or inequality. */ /*=============================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -