📄 rulebld.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* RULE BUILD MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides routines to ntegrates a set of pattern *//* and join tests associated with a rule into the pattern *//* and join networks. The joins are integrated into the *//* join network by routines in this module. The pattern *//* is integrated by calling the external routine *//* associated with the pattern parser that originally *//* parsed the pattern. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//*************************************************************/#define _RULEBLD_SOURCE_#include "setup.h"#if DEFRULE_CONSTRUCT && (! RUN_TIME) && (! BLOAD_ONLY)#include <stdio.h>#define _CLIPS_STDIO_#include "constant.h"#include "clipsmem.h"#include "router.h"#include "watch.h"#include "constrct.h"#include "drive.h"#include "pattern.h"#include "reteutil.h"#include "incrrset.h"#include "rulebld.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if ANSI_COMPILER static struct joinNode *FindShareableJoin(struct joinNode *,VOID *,int,int,int, struct expr *, int,int,int,struct joinNode **); static int TestJoinForReuse(struct joinNode *,int,int,int, struct expr *, int,int,int,struct joinNode **); static struct joinNode *CreateNewJoin(struct expr *, struct joinNode *,VOID *,int,int); static VOID AttachTestCEsToPatternCEs(struct lhsParseNode *); #else static struct joinNode *FindShareableJoin(); static int TestJoinForReuse(); static struct joinNode *CreateNewJoin(); static VOID AttachTestCEsToPatternCEs(); #endif /****************************************************************//* ConstructJoins: Integrates a set of pattern and join tests *//* associated with a rule into the pattern and join networks. *//****************************************************************/globle struct joinNode *ConstructJoins(logicalJoin,theLHS) int logicalJoin; struct lhsParseNode *theLHS; { struct joinNode *lastJoin = NULL; struct patternNodeHeader *lastPattern; int firstJoin = CLIPS_TRUE; int tryToReuse = CLIPS_TRUE; struct joinNode *listOfJoins; struct joinNode *oldJoin; int joinNumber = 1; int isLogical; struct joinNode *nandReconnect[32]; int currentDepth = 1; int lastIteration = CLIPS_FALSE; int rhsType; int endDepth; /*===================================================*/ /* Remove any test CEs from the LHS and attach their */ /* expression to the closest preceeding non-negated */ /* join at the same not/and depth. */ /*===================================================*/ AttachTestCEsToPatternCEs(theLHS); /*=====================================================*/ /* Process each pattern CE in the rule. At this point, */ /* there should be no and/or/not/test CEs in the LHS. */ /*=====================================================*/ while (theLHS != NULL) { if (theLHS->bottom == NULL) lastIteration = CLIPS_TRUE; /*==================================================*/ /* If the pattern is the start of a new not/and CE, */ /* then remember the join to reconnect to after the */ /* join from the right is completed. */ /*==================================================*/ while (theLHS->beginNandDepth > currentDepth) { nandReconnect[currentDepth-1] = lastJoin; currentDepth++; } /*============================================================*/ /* Add the next pattern for this rule to the pattern network. */ /*============================================================*/ rhsType = theLHS->patternType->positionInArray; lastPattern = (*theLHS->patternType->addPatternFunction)(theLHS); /*======================================================*/ /* Determine if the join being added is a logical join. */ /*======================================================*/ if (joinNumber == logicalJoin) isLogical = CLIPS_TRUE; else isLogical = CLIPS_FALSE; /*===============================================*/ /* Get the list of joins which could potentially */ /* be reused in place of the join being added. */ /*===============================================*/ if (firstJoin == CLIPS_TRUE) { listOfJoins = lastPattern->entryJoin; } else { listOfJoins = lastJoin->nextLevel; } /*=======================================================*/ /* Determine if the next join to be added can be shared. */ /*=======================================================*/ endDepth = theLHS->endNandDepth; if ((tryToReuse == CLIPS_TRUE) && ((oldJoin = FindShareableJoin(listOfJoins,(VOID *) lastPattern,firstJoin, (int) theLHS->negated,isLogical, theLHS->networkTest, endDepth,currentDepth, lastIteration,nandReconnect)) != NULL) ) {#if DEBUGGING_FUNCTIONS if ((GetWatchItem("compilations") == CLIPS_TRUE) && GetPrintWhileLoading()) { PrintCLIPS(WDIALOG,"=j"); }#endif lastJoin = oldJoin; } else { tryToReuse = CLIPS_FALSE; lastJoin = CreateNewJoin(theLHS->networkTest, lastJoin,lastPattern, CLIPS_FALSE,(int) theLHS->negated); lastJoin->rhsType = rhsType; } /*==========================================================*/ /* Create any joins from the right needed to handle not/and */ /* CE combinations and connect them to the join network. */ /*==========================================================*/ while (endDepth < currentDepth) { currentDepth--; if (lastJoin->nextLevel == NULL) tryToReuse = CLIPS_FALSE; if (tryToReuse) { #if DEBUGGING_FUNCTIONS if ((GetWatchItem("compilations") == CLIPS_TRUE) && GetPrintWhileLoading()) { PrintCLIPS(WDIALOG,"=j"); }#endif lastJoin = lastJoin->nextLevel; } else { lastJoin = CreateNewJoin(NULL,nandReconnect[currentDepth-1], lastJoin,CLIPS_TRUE,CLIPS_FALSE); } } /*=======================================*/ /* Move on to the next join to be added. */ /*=======================================*/ theLHS = theLHS->bottom; joinNumber++; firstJoin = CLIPS_FALSE; } /*===================================================*/ /* If compilations are being watched, put a carriage */ /* return after all of the =j's and +j's */ /*===================================================*/ #if DEBUGGING_FUNCTIONS if ((GetWatchItem("compilations") == CLIPS_TRUE) && GetPrintWhileLoading()) { PrintCLIPS(WDIALOG,"\n"); }#endif /*=============================*/ /* Return the last join added. */ /*=============================*/ return(lastJoin); } /****************************************************************//* AttachTestCEsToPatternCEs: Attaches the expressions found in *//* test CEs to the closest preceeding pattern CE that is not *//* negated and is at the same not/and depth. *//****************************************************************/static VOID AttachTestCEsToPatternCEs(theLHS) struct lhsParseNode *theLHS; { struct lhsParseNode *lastNode, *trackNode, *tempNode; /*===============================================*/ /* Look at each pattern on the rule's LHS to see */ /* if any test CEs should be attached to it. */ /*===============================================*/ while (theLHS != NULL) { /*==============================================*/ /* If the pattern is negated, then don't bother */ /* looking for any test CEs to attach to it. */ /*==============================================*/ if (theLHS->negated) { trackNode = NULL; } else { lastNode = theLHS; trackNode = theLHS->bottom; } /*=================================================*/ /* Check all of the patterns following the current */ /* pattern to check for test CEs which can be */ /* attached to the current pattern. */ /*=================================================*/ while (trackNode != NULL) { /*=======================================================*/ /* Skip over any CEs that have a higher not/and depth or */ /* are negated since any test CEs found within these CEs */ /* would be attached to another pattern with the same */ /* depth, rather than the current pattern. */ /*=======================================================*/ if ((trackNode->beginNandDepth != theLHS->beginNandDepth) || (trackNode->negated)) { lastNode = trackNode; trackNode = trackNode->bottom; } /*======================================================*/ /* Once a non-negated pattern has been encounted at the */ /* same not/and depth as the current pattern, then stop */ /* because any test CEs following this pattern would be */ /* attached to it rather than the current pattern. */ /*======================================================*/ else if (trackNode->type == PATTERN_CE) { trackNode = NULL; } /*==================================================*/ /* A test CE encountered at the same not/and depth */ /* can be added to the network test expressions for */ /* the currentpattern. */ /*==================================================*/ else if (trackNode->type == TEST_CE) { theLHS->networkTest = CombineExpressions(theLHS->networkTest, trackNode->networkTest); trackNode->networkTest = NULL; tempNode = trackNode->bottom; trackNode->bottom = NULL; lastNode->bottom = tempNode; lastNode->endNandDepth = trackNode->endNandDepth; ReturnLHSParseNodes(trackNode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -