📄 factmch.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 05/17/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. */
/* */
/*************************************************************/
#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 "tmpltdef.h"
#include "factmch.h"
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static intBool EvaluatePatternExpression(void *,struct factPatternNode *,struct expr *,int);
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;
/*=========================================================*/
/* 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 the constraints are satisified, then ... */
/*=============================================*/
if (EvaluatePatternExpression(theEnv,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(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;
/*========================================*/
/* 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. */
/*===============================================*/
oldMark = markers;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -