📄 factmch.c
字号:
/*===========================================*/
/* Create a new multifield marker and append */
/* it to the end of the current list. */
/*===========================================*/
newMark = get_struct(theEnv,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;
FactData(theEnv)->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 = (long) 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) ?
TRUE :
(EvaluatePatternExpression(theEnv,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(theEnv,FactData(theEnv)->CurrentPatternFact,FactData(theEnv)->CurrentPatternMarks,thePattern); }
/*=============================================*/
/* Recursively continue pattern matching based */
/* on the multifield binding just generated. */
/*=============================================*/
FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact,
thePattern->nextLevel,0,FactData(theEnv)->CurrentPatternMarks,newMark);
}
/*================================================*/
/* Discard the multifield marker since we've done */
/* all the pattern matching for this binding of */
/* the multifield slot constraint. */
/*================================================*/
rtn_struct(theEnv,multifieldMarker,newMark);
if (endMark != NULL) endMark->next = NULL;
FactData(theEnv)->CurrentPatternMarks = oldMark;
return;
}
/*==============================================*/
/* Perform matching for nodes beneath this one. */
/*==============================================*/
for (repeatCount = (long) (theSlotValue->multifieldLength -
(newMark->startPosition + thePattern->leaveFields));
repeatCount >= 0;
repeatCount--)
{
newMark->endPosition = newMark->startPosition + (repeatCount - 1);
if ((thePattern->networkTest == NULL) ?
TRUE :
(EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest,
(int) thePattern->whichField + offset)))
{
FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact,
thePattern->nextLevel,offset + repeatCount - 1,
FactData(theEnv)->CurrentPatternMarks,newMark);
}
}
/*======================================================*/
/* Get rid of the marker created for a multifield node. */
/*======================================================*/
rtn_struct(theEnv,multifieldMarker,newMark);
if (endMark != NULL) endMark->next = NULL;
FactData(theEnv)->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(
void *theEnv,
int finishedMatching,
struct factPatternNode *thePattern)
{
EvaluationData(theEnv)->EvaluationError = 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 == 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(
void *theEnv,
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(theEnv,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(theEnv,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(theEnv,theMatch,listOfJoins,RHS); }
}
/*****************************************************************/
/* EvaluatePatternExpression: Performs a faster evaluation for */
/* fact pattern network expressions than if EvaluateExpression */
/* were used directly. */
/*****************************************************************/
static int EvaluatePatternExpression(
void *theEnv,
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(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 = EvaluationData(theEnv)->CurrentExpression;
EvaluationData(theEnv)->CurrentExpression = theTest;
rv = FactPNConstant1(theEnv,theTest->value,&theResult);
EvaluationData(theEnv)->CurrentExpression = oldArgument;
return(rv);
/*=============================================*/
/* This primitive compares the value stored in */
/* a multifield slot to a constant for either */
/* equality or inequality. */
/*=============================================*/
case FACT_PN_CONSTANT2:
oldArgument = EvaluationData(theEnv)->CurrentExpression;
EvaluationData(theEnv)->CurrentExpression = theTest;
rv = FactPNConstant2(theEnv,theTest->value,&theResult);
EvaluationData(theEnv)->CurrentExpression = oldArgument;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -