📄 pattern.c
字号:
/****************************************************/globle struct patternParser *FindPatternParser(name) char *name; { struct patternParser *tempParser; for (tempParser = ListOfPatternParsers; tempParser != NULL; tempParser = tempParser->next) { if (strcmp(tempParser->name,name) == 0) return(tempParser); } return(NULL); }/******************************************************//* GetPatternParser: Returns a pointer to the pattern *//* parser for the specified data entity. *//******************************************************/struct patternParser *GetPatternParser(rhsType) int rhsType; { return(PatternParserArray[rhsType]); }#if CONSTRUCT_COMPILER && (! RUN_TIME)/*************************************************************//* PatternNodeHeaderToCode: Writes the C code representation *//* of a patternNodeHeader data structure. *//*************************************************************/globle VOID PatternNodeHeaderToCode(fp,theHeader,imageID,maxIndices) FILE *fp; struct patternNodeHeader *theHeader; int imageID; int maxIndices; { fprintf(fp,"{NULL,NULL,"); if (theHeader->entryJoin == NULL) { fprintf(fp,"NULL,"); } else { 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 BOOLEAN PostPatternAnalysis(theLHS) 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)(patternPtr)) return(CLIPS_TRUE); } } } return(CLIPS_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(readSource,theToken,multifieldSlot, theSlot,slotNumber,theConstraints, position) char *readSource; struct token *theToken; int multifieldSlot; struct symbolHashNode *theSlot; int slotNumber; CONSTRAINT_RECORD *theConstraints; int position; { struct lhsParseNode *topNode = NULL, *lastNode = NULL, *nextNode; int numberOfSingleFields = 0; int numberOfMultifields = 0; int startPosition = position; int error = CLIPS_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(); nextNode->type = theToken->type; nextNode->negated = CLIPS_FALSE; GetToken(readSource,theToken); } else { nextNode = ConjuctiveRestrictionParse(readSource,theToken,&error); if (nextNode == NULL) { ReturnLHSParseNodes(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 == CLIPS_TRUE)) { PPBackup(); SavePPBuffer(" "); SavePPBuffer(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(); } 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("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(); } else { continue; } } else { nextNode->constraints = CopyConstraintRecord(theConstraints); } /*==========================================*/ /* Remove the min and max field constraints */ /* for the entire slot from the constraint */ /* record for this single constraint. */ /*==========================================*/ ReturnExpression(nextNode->constraints->minFields); ReturnExpression(nextNode->constraints->maxFields); nextNode->constraints->minFields = GenConstant(SYMBOL,NegativeInfinity); nextNode->constraints->maxFields = GenConstant(SYMBOL,PositiveInfinity); nextNode->derivedConstraints = CLIPS_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(); SetConstraintType(MULTIFIELD,tempConstraints); tempConstraints->singlefieldsAllowed = CLIPS_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 != PositiveInfinity) { ReturnExpression(tempConstraints->maxFields); tempConstraints->maxFields = GenConstant(INTEGER,AddLong(ValueToLong(theConstraints->maxFields->value) - numberOfSingleFields)); } if ((numberOfMultifields == 1) && (theConstraints->minFields->value != NegativeInfinity)) { ReturnExpression(tempConstraints->minFields); tempConstraints->minFields = GenConstant(INTEGER,AddLong(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(); nextNode->type = MF_WILDCARD; nextNode->multifieldSlot = CLIPS_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(theRestrictions) struct lhsParseNode *theRestrictions; { struct lhsParseNode *tempNode1, *tempNode2, *tempNode3; int totalSingleFields = 0, totalMultiFields = 0; int 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 = CLIPS_TRUE; if ((tempNode1->type == SF_VARIABLE) || (tempNode1->type == SF_WILDCARD)) { tempNode1->singleFieldsAfter = totalSingleFields - (runningSingleFields + 1); tempNode1->multiFieldsAfter = totalMultiFields - runningMultiFields; } else { tempNode1->singleFieldsAfter = totalSingleFields - runningSingleFields; tempNode1->multiFieldsAfter = 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -