📄 factmch.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.30 10/19/06 */ /* */ /* 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: *//* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 *//* *//* 6.24: Removed INCREMENTAL_RESET compilation flag. *//* *//* Renamed BOOLEAN macro type to intBool. *//* *//* 6.30: Added support for hashed alpha memories. *//* *//*************************************************************/#define _FACTMCH_SOURCE_#include <stdio.h>#define _STDIO_INCLUDED_#include "setup.h"#if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT#include "drive.h"#include "engine.h"#include "envrnmnt.h"#include "extnfunc.h"#include "factgen.h"#include "factrete.h"#include "incrrset.h"#include "memalloc.h"#include "reteutil.h"#include "router.h"#include "sysdep.h"#include "tmpltdef.h"#include "factmch.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/ static intBool EvaluatePatternExpression(void *,struct factPatternNode *,struct expr *); static void TraceErrorToJoin(void *,struct factPatternNode *,int); static void ProcessFactAlphaMatch(void *,struct fact *,struct multifieldMarker *,struct factPatternNode *); static struct factPatternNode *GetNextFactPatternNode(void *,int,struct factPatternNode *); static int SkipFactPatternNode(void *,struct factPatternNode *); static void ProcessMultifieldNode(void *, struct factPatternNode *, struct multifieldMarker *, struct multifieldMarker *,int); static void PatternNetErrorMessage(void *,struct factPatternNode *);/*************************************************************************//* FactPatternMatch: Implements the core loop for fact pattern matching. *//*************************************************************************/globle void FactPatternMatch( void *theEnv, struct fact *theFact, struct factPatternNode *patternPtr, int offset, struct multifieldMarker *markers, struct multifieldMarker *endMark) { int theSlotField; int offsetSlot; DATA_OBJECT theResult; struct factPatternNode *tempPtr; /*=========================================================*/ /* 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. */ /*================================================*/ FactData(theEnv)->CurrentPatternFact = theFact; FactData(theEnv)->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(theEnv,patternPtr)) { patternPtr = GetNextFactPatternNode(theEnv,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 = FALSE; if (patternPtr->header.endSlot && ((FactData(theEnv)->CurrentPatternMarks == NULL) ? FALSE : (FactData(theEnv)->CurrentPatternMarks->where.whichSlotNumber == patternPtr->whichSlot)) && (FactData(theEnv)->CurrentPatternFact->theProposition.theFields [patternPtr->whichSlot].type == MULTIFIELD)) { if ((patternPtr->leaveFields + theSlotField) != (int) ((struct multifield *) FactData(theEnv)->CurrentPatternFact->theProposition.theFields [patternPtr->whichSlot].value)->multifieldLength) { skipit = TRUE; } } if (skipit) { patternPtr = GetNextFactPatternNode(theEnv,TRUE,patternPtr); } else if (patternPtr->header.selector) { if (EvaluatePatternExpression(theEnv,patternPtr,patternPtr->networkTest->nextArg)) { EvaluateExpression(theEnv,patternPtr->networkTest,&theResult); tempPtr = FindHashedPatternNode(theEnv,patternPtr,theResult.type,theResult.value); } else { tempPtr = NULL; } if (tempPtr != NULL) { if (tempPtr->header.stopNode) { ProcessFactAlphaMatch(theEnv,theFact,markers,tempPtr); } patternPtr = GetNextFactPatternNode(theEnv,FALSE,tempPtr); } else { patternPtr = GetNextFactPatternNode(theEnv,TRUE,patternPtr); } } /*=============================================*/ /* If the constraints are satisified, then ... */ /*=============================================*/ else if (EvaluatePatternExpression(theEnv,patternPtr,patternPtr->networkTest)) { /*=======================================================*/ /* 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(theEnv,theFact,markers,patternPtr); } /*===================================*/ /* Move on to the next pattern node. */ /*===================================*/ patternPtr = GetNextFactPatternNode(theEnv,FALSE,patternPtr); } /*==============================================*/ /* Otherwise, move on to the next pattern node. */ /*==============================================*/ else { patternPtr = GetNextFactPatternNode(theEnv,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(theEnv,patternPtr,markers,endMark,offset); } else { ProcessMultifieldNode(theEnv,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(theEnv,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( void *theEnv, struct factPatternNode *thePattern, struct multifieldMarker *markers, struct multifieldMarker *endMark, int offset) { struct multifieldMarker *newMark, *oldMark; int repeatCount; struct multifield *theSlotValue; DATA_OBJECT theResult; struct factPatternNode *tempPtr; intBool success; /*========================================*/ /* Get a pointer to the slot value of the */ /* multifield slot being pattern matched. */ /*========================================*/ theSlotValue = (struct multifield *) FactData(theEnv)->CurrentPatternFact->theProposition.theFields[thePattern->whichSlot].value; /*===============================================*/ /* Save the value of the markers already stored. */ /*===============================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -