📄 factmch.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* FACT MATCH MODULE */ /*******************************************************//*************************************************************//* Purpose: Implements the algorithm for pattern matching in *//* the fact pattern network. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//*************************************************************/#define _FACTMCH_SOURCE_#include <stdio.h>#define _CLIPS_STDIO_#include "setup.h"#if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT#include "clipsmem.h"#include "extnfunc.h"#include "router.h"#if INCREMENTAL_RESET#include "incrrset.h"#endif#include "reteutil.h"#include "drive.h"#include "factgen.h"#include "factrete.h"#include "tmpltdef.h"#include "factmch.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if ANSI_COMPILER static BOOLEAN EvaluatePatternExpression(struct factPatternNode *,struct expr *,int); static VOID TraceErrorToJoin(struct factPatternNode *,int); static VOID ProcessFactAlphaMatch(struct fact *,struct multifieldMarker *,struct factPatternNode *); static struct factPatternNode *GetNextFactPatternNode(int,struct factPatternNode *); static int SkipFactPatternNode(struct factPatternNode *); static VOID ProcessMultifieldNode(struct factPatternNode *, struct multifieldMarker *, struct multifieldMarker *,int); static VOID PatternNetErrorMessage(struct factPatternNode *);#else static BOOLEAN EvaluatePatternExpression(); static VOID TraceErrorToJoin(); static VOID ProcessFactAlphaMatch(); static struct factPatternNode *GetNextFactPatternNode(); static int SkipFactPatternNode(); static VOID ProcessMultifieldNode(); static VOID PatternNetErrorMessage();#endif/****************************************//* GLOBAL INTERNAL VARIABLE DEFINITIONS *//****************************************/ globle struct fact *CurrentPatternFact; globle struct multifieldMarker *CurrentPatternMarks;/*************************************************************************//* FactPatternMatch: Implements the core loop for fact pattern matching. *//*************************************************************************/globle VOID FactPatternMatch(theFact,patternPtr,offset,markers,endMark) struct fact *theFact; struct factPatternNode *patternPtr; int offset; struct multifieldMarker *markers, *endMark; { int theSlotField; int offsetSlot; /*=========================================================*/ /* If there's nothing left in the pattern network to match */ /* against, then the current traversal of the pattern */ /* network needs to back up. */ /*=========================================================*/ if (patternPtr == NULL) return; /*=======================================================*/ /* The offsetSlot variable indicates the current offset */ /* within the multifield slot being pattern matched. */ /* (Recall that a multifield wildcard or variable */ /* recursively iterates through all possible bindings.) */ /* Once a new slot starts being pattern matched, the */ /* offset is reset to zero. */ /*=======================================================*/ offsetSlot = patternPtr->whichSlot; /*================================================*/ /* Set up some global parameters for use by the */ /* Rete access functions and general convenience. */ /*================================================*/ CurrentPatternFact = theFact; CurrentPatternMarks = markers; /*============================================*/ /* Loop through each node in pattern network. */ /*============================================*/ while (patternPtr != NULL) { /*=============================================================*/ /* Determine the position of the field we're going to pattern */ /* match. If this routine has been entered recursively because */ /* of multifield wildcards or variables, then add in the */ /* additional offset caused by the values which match these */ /* multifields. This offset may be negative (if for example a */ /* a multifield matched a zero length value). */ /*=============================================================*/ theSlotField = patternPtr->whichField; if (offsetSlot == patternPtr->whichSlot) { theSlotField += offset; } /*===================================*/ /* Determine if we want to skip this */ /* node during an incremental reset. */ /*===================================*/ if (SkipFactPatternNode(patternPtr)) { patternPtr = GetNextFactPatternNode(CLIPS_TRUE,patternPtr); } /*=========================================================*/ /* If this is a single field pattern node, then determine */ /* if the constraints for the node have been satisfied for */ /* the current field in the slot being examined. */ /*=========================================================*/ else if (patternPtr->header.singlefieldNode) { /*==================================================*/ /* If we're at the last slot in the pattern, make */ /* sure the number of fields in the fact correspond */ /* to the number of fields required by the pattern */ /* based on the binding of multifield variables. */ /*==================================================*/ int skipit = CLIPS_FALSE; if (patternPtr->header.endSlot && ((CurrentPatternMarks == NULL) ? CLIPS_FALSE : (CurrentPatternMarks->where.whichSlotNumber == patternPtr->whichSlot)) && (CurrentPatternFact->theProposition.theFields [patternPtr->whichSlot].type == MULTIFIELD)) { if ((patternPtr->leaveFields + theSlotField) != ((struct multifield *) CurrentPatternFact->theProposition.theFields [patternPtr->whichSlot].value)->multifieldLength) { skipit = CLIPS_TRUE; } } if (skipit) { patternPtr = GetNextFactPatternNode(CLIPS_TRUE,patternPtr); } else /*=============================================*/ /* If the constraints are satisified, then ... */ /*=============================================*/ if (EvaluatePatternExpression(patternPtr, patternPtr->networkTest, theSlotField)) { /*=======================================================*/ /* 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 (patternPtr->header.stopNode) { ProcessFactAlphaMatch(theFact,markers,patternPtr); } /*===================================*/ /* Move on to the next pattern node. */ /*===================================*/ patternPtr = GetNextFactPatternNode(CLIPS_FALSE,patternPtr); } /*==============================================*/ /* Otherwise, move on to the next pattern node. */ /*==============================================*/ else { patternPtr = GetNextFactPatternNode(CLIPS_TRUE,patternPtr); } } /*======================================================*/ /* If this is a multifield pattern node, then determine */ /* if the constraints for the node have been satisfied */ /* for the current field in the slot being examined. */ /*======================================================*/ else if (patternPtr->header.multifieldNode) { /*========================================================*/ /* Determine if the multifield pattern node's constraints */ /* are satisfied. If we've traversed to a different slot */ /* than the one we started this routine with, then the */ /* offset into the slot is reset to zero. */ /*========================================================*/ if (offsetSlot == patternPtr->whichSlot) { ProcessMultifieldNode(patternPtr,markers,endMark,offset); } else { ProcessMultifieldNode(patternPtr,markers,endMark,0); } /*===================================================*/ /* Move on to the next pattern node. Since the lower */ /* branches of the pattern network have already been */ /* recursively processed by ProcessMultifieldNode, */ /* we get the next pattern node by treating this */ /* multifield pattern node as if it were a single */ /* field pattern node that failed its constraint. */ /*===================================================*/ patternPtr = GetNextFactPatternNode(CLIPS_TRUE,patternPtr); } } } /**************************************************************//* ProcessMultifieldNode: Handles recursive pattern matching *//* when a multifield wildcard or variable is encountered as *//* a slot constraint. The pattern matching routine is called *//* iteratively for each possible binding of the multifield *//* wildcard or variable. *//**************************************************************/static VOID ProcessMultifieldNode(thePattern,markers,endMark,offset) struct factPatternNode *thePattern; struct multifieldMarker *markers, *endMark; int offset; { struct multifieldMarker *newMark, *oldMark; int repeatCount; struct multifield *theSlotValue; /*========================================*/ /* Get a pointer to the slot value of the */ /* multifield slot being pattern matched. */ /*========================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -