📄 pattern.c
字号:
{
fprintf(fp,"&%s%d_%d[%d],",
JoinPrefix(),imageID,
(((int) theHeader->entryJoin->bsaveID) / maxIndices) + 1,
((int) theHeader->entryJoin->bsaveID) % maxIndices);
}
fprintf(fp,"%d,%d,%d,0,0,%d,%d}",theHeader->singlefieldNode,
theHeader->multifieldNode,
theHeader->stopNode,
theHeader->beginSlot,
theHeader->endSlot);
}
#endif /* CONSTRUCT_COMPILER && (! RUN_TIME) */
#if (! RUN_TIME) && (! BLOAD_ONLY)
/****************************************************************/
/* PostPatternAnalysis: Calls the post analysis routines for */
/* each of the pattern parsers to allow additional processing */
/* by the pattern parser after the variable analysis routines */
/* have analyzed the LHS patterns. */
/****************************************************************/
globle intBool PostPatternAnalysis(
void *theEnv,
struct lhsParseNode *theLHS)
{
struct lhsParseNode *patternPtr;
struct patternParser *tempParser;
for (patternPtr = theLHS; patternPtr != NULL; patternPtr = patternPtr->bottom)
{
if ((patternPtr->type == PATTERN_CE) && (patternPtr->patternType != NULL))
{
tempParser = patternPtr->patternType;
if (tempParser->postAnalysisFunction != NULL)
{ if ((*tempParser->postAnalysisFunction)(theEnv,patternPtr)) return(TRUE); }
}
}
return(FALSE);
}
/******************************************************************/
/* RestrictionParse: Parses a single field within a pattern. This */
/* field may either be a single field wildcard, a multifield */
/* wildcard, a single field variable, a multifield variable, */
/* or a series of connected constraints. */
/* */
/* <constraint> ::= ? | */
/* $? | */
/* <connected-constraint> */
/******************************************************************/
struct lhsParseNode *RestrictionParse(
void *theEnv,
char *readSource,
struct token *theToken,
int multifieldSlot,
struct symbolHashNode *theSlot,
short slotNumber,
CONSTRAINT_RECORD *theConstraints,
short position)
{
struct lhsParseNode *topNode = NULL, *lastNode = NULL, *nextNode;
int numberOfSingleFields = 0;
int numberOfMultifields = 0;
short startPosition = position;
int error = FALSE;
CONSTRAINT_RECORD *tempConstraints;
/*==================================================*/
/* Keep parsing fields until a right parenthesis is */
/* encountered. This will either indicate the end */
/* of an instance or deftemplate slot or the end of */
/* an ordered fact. */
/*==================================================*/
while (theToken->type != RPAREN)
{
/*========================================*/
/* Look for either a single or multifield */
/* wildcard or a conjuctive restriction. */
/*========================================*/
if ((theToken->type == SF_WILDCARD) ||
(theToken->type == MF_WILDCARD))
{
nextNode = GetLHSParseNode(theEnv);
nextNode->type = theToken->type;
nextNode->negated = FALSE;
GetToken(theEnv,readSource,theToken);
}
else
{
nextNode = ConjuctiveRestrictionParse(theEnv,readSource,theToken,&error);
if (nextNode == NULL)
{
ReturnLHSParseNodes(theEnv,topNode);
return(NULL);
}
}
/*========================================================*/
/* Fix up the pretty print representation of a multifield */
/* slot so that the fields don't run together. */
/*========================================================*/
if ((theToken->type != RPAREN) && (multifieldSlot == TRUE))
{
PPBackup(theEnv);
SavePPBuffer(theEnv," ");
SavePPBuffer(theEnv,theToken->printForm);
}
/*========================================*/
/* Keep track of the number of single and */
/* multifield restrictions encountered. */
/*========================================*/
if ((nextNode->type == SF_WILDCARD) || (nextNode->type == SF_VARIABLE))
{ numberOfSingleFields++; }
else
{ numberOfMultifields++; }
/*===================================*/
/* Assign the slot name and indices. */
/*===================================*/
nextNode->slot = theSlot;
nextNode->slotNumber = slotNumber;
nextNode->index = position++;
/*==============================================*/
/* If we're not dealing with a multifield slot, */
/* attach the constraints directly to the node */
/* and return. */
/*==============================================*/
if (! multifieldSlot)
{
if (theConstraints == NULL)
{
if (nextNode->type == SF_VARIABLE)
{ nextNode->constraints = GetConstraintRecord(theEnv); }
else nextNode->constraints = NULL;
}
else nextNode->constraints = theConstraints;
return(nextNode);
}
/*====================================================*/
/* Attach the restriction to the list of restrictions */
/* already parsed for this slot or ordered fact. */
/*====================================================*/
if (lastNode == NULL) topNode = nextNode;
else lastNode->right = nextNode;
lastNode = nextNode;
}
/*=====================================================*/
/* Once we're through parsing, check to make sure that */
/* a single field slot was given a restriction. If the */
/* following test fails, then we know we're dealing */
/* with a multifield slot. */
/*=====================================================*/
if ((topNode == NULL) && (! multifieldSlot))
{
SyntaxErrorMessage(theEnv,"defrule");
return(NULL);
}
/*===============================================*/
/* Loop through each of the restrictions in the */
/* list of restrictions for the multifield slot. */
/*===============================================*/
for (nextNode = topNode; nextNode != NULL; nextNode = nextNode->right)
{
/*===================================================*/
/* Assign a constraint record to each constraint. If */
/* the slot has an explicit constraint, then copy */
/* this and store it with the constraint. Otherwise, */
/* create a constraint record for a single field */
/* constraint and skip the constraint modifications */
/* for a multifield constraint. */
/*===================================================*/
if (theConstraints == NULL)
{
if (nextNode->type == SF_VARIABLE)
{ nextNode->constraints = GetConstraintRecord(theEnv); }
else
{ continue; }
}
else
{ nextNode->constraints = CopyConstraintRecord(theEnv,theConstraints); }
/*==========================================*/
/* Remove the min and max field constraints */
/* for the entire slot from the constraint */
/* record for this single constraint. */
/*==========================================*/
ReturnExpression(theEnv,nextNode->constraints->minFields);
ReturnExpression(theEnv,nextNode->constraints->maxFields);
nextNode->constraints->minFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->NegativeInfinity);
nextNode->constraints->maxFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->PositiveInfinity);
nextNode->derivedConstraints = TRUE;
/*====================================================*/
/* If we're not dealing with a multifield constraint, */
/* then no further modifications are needed to the */
/* min and max constraints for this constraint. */
/*====================================================*/
if ((nextNode->type != MF_WILDCARD) && (nextNode->type != MF_VARIABLE))
{ continue; }
/*==========================================================*/
/* Create a separate constraint record to keep track of the */
/* cardinality information for this multifield constraint. */
/*==========================================================*/
tempConstraints = GetConstraintRecord(theEnv);
SetConstraintType(MULTIFIELD,tempConstraints);
tempConstraints->singlefieldsAllowed = FALSE;
tempConstraints->multifield = nextNode->constraints;
nextNode->constraints = tempConstraints;
/*=====================================================*/
/* Adjust the min and max field values for this single */
/* multifield constraint based on the min and max */
/* fields for the entire slot and the number of single */
/* field values contained in the slot. */
/*=====================================================*/
if (theConstraints->maxFields->value != SymbolData(theEnv)->PositiveInfinity)
{
ReturnExpression(theEnv,tempConstraints->maxFields);
tempConstraints->maxFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,ValueToLong(theConstraints->maxFields->value) - numberOfSingleFields));
}
if ((numberOfMultifields == 1) && (theConstraints->minFields->value != SymbolData(theEnv)->NegativeInfinity))
{
ReturnExpression(theEnv,tempConstraints->minFields);
tempConstraints->minFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,ValueToLong(theConstraints->minFields->value) - numberOfSingleFields));
}
}
/*================================================*/
/* If a multifield slot is being parsed, place a */
/* node on top of the list of constraints parsed. */
/*================================================*/
if (multifieldSlot)
{
nextNode = GetLHSParseNode(theEnv);
nextNode->type = MF_WILDCARD;
nextNode->multifieldSlot = TRUE;
nextNode->bottom = topNode;
nextNode->slot = theSlot;
nextNode->slotNumber = slotNumber;
nextNode->index = startPosition;
nextNode->constraints = theConstraints;
topNode = nextNode;
TallyFieldTypes(topNode->bottom);
}
/*=================================*/
/* Return the list of constraints. */
/*=================================*/
return(topNode);
}
/***************************************************************/
/* TallyFieldTypes: Determines the number of single field and */
/* multifield variables and wildcards that appear before and */
/* after each restriction found in a multifield slot. */
/***************************************************************/
static void TallyFieldTypes(
struct lhsParseNode *theRestrictions)
{
struct lhsParseNode *tempNode1, *tempNode2, *tempNode3;
unsigned short totalSingleFields = 0, totalMultiFields = 0;
unsigned short runningSingleFields = 0, runningMultiFields = 0;
/*========================================*/
/* Compute the total number of single and */
/* multifield variables and wildcards. */
/*========================================*/
for (tempNode1 = theRestrictions; tempNode1 != NULL; tempNode1 = tempNode1->right)
{
if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
{ totalSingleFields++; }
else
{ totalMultiFields++; }
}
/*======================================================*/
/* Loop through each constraint tallying the numbers of */
/* the variable types before and after along the way. */
/*======================================================*/
for (tempNode1 = theRestrictions; tempNode1 != NULL; tempNode1 = tempNode1->right)
{
/*===================================*/
/* Assign the values to the "binding */
/* variable" node of the constraint. */
/*===================================*/
tempNode1->singleFieldsBefore = runningSingleFields;
tempNode1->multiFieldsBefore = runningMultiFields;
tempNode1->withinMultifieldSlot = TRUE;
if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
{
tempNode1->singleFieldsAfter = (unsigned short) (totalSingleFields - (runningSingleFields + 1));
tempNode1->multiFieldsAfter = (unsigned short) (totalMultiFields - runningMultiFields);
}
else
{
tempNode1->singleFieldsAfter = (unsigned short) (totalSingleFields - runningSingleFields);
tempNode1->multiFieldsAfter = (unsigned short) (totalMultiFields - (runningMultiFields + 1));
}
/*=====================================================*/
/* Assign the values to each of the and (&) and or (|) */
/* connected constraints within the constraint. */
/*=====================================================*/
for (tempNode2 = tempNode1->bottom; tempNode2 != NULL; tempNode2 = tempNode2->bottom)
{
for (tempNode3 = tempNode2; tempNode3 != NULL; tempNode3 = tempNode3->right)
{
tempNode3->singleFieldsBefore = tempNode1->singleFieldsBefore;
tempNode3->singleFieldsAfter = tempNode1->singleFieldsAfter;
tempNode3->multiFieldsBefore = tempNode1->multiFieldsBefore;
tempNode3->multiFieldsAfter = tempNode1->multiFieldsAfter;
tempNode3->withinMultifieldSlot = TRUE;
}
}
/*=======================================*/
/* Calculate the running total of single */
/* and multifield constraints. */
/*=======================================*/
if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD))
{ runningSingleFields++; }
else
{ runningMultiFields++; }
}
}
/*******************************************************************/
/* ConjuctiveRestrictionParse: Parses a single constraint field in */
/* a pattern that is not a single field wildcard, multifield */
/* wildcard, or multifield variable. The field may consist of a */
/* number of subfields tied together using the & connective */
/* constraint and/or the | connective constraint. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -