📄 pattern.c
字号:
/* of pattern parsers has not been exceeded. */ /*============================================*/ if (PatternData(theEnv)->NextPosition >= MAX_POSITIONS) return(FALSE); /*================================*/ /* Create the new pattern parser. */ /*================================*/ newPtr->positionInArray = PatternData(theEnv)->NextPosition; PatternData(theEnv)->PatternParserArray[PatternData(theEnv)->NextPosition-1] = newPtr; PatternData(theEnv)->NextPosition++; /*================================*/ /* Add the parser to the list of */ /* parsers based on its priority. */ /*================================*/ if (PatternData(theEnv)->ListOfPatternParsers == NULL) { newPtr->next = NULL; PatternData(theEnv)->ListOfPatternParsers = newPtr; return(TRUE); } currentPtr = PatternData(theEnv)->ListOfPatternParsers; while ((currentPtr != NULL) ? (newPtr->priority < currentPtr->priority) : FALSE) { lastPtr = currentPtr; currentPtr = currentPtr->next; } if (lastPtr == NULL) { newPtr->next = PatternData(theEnv)->ListOfPatternParsers; PatternData(theEnv)->ListOfPatternParsers = newPtr; } else { newPtr->next = currentPtr; lastPtr->next = newPtr; } return(TRUE); }/****************************************************//* FindPatternParser: Searches for a pattern parser *//* that can parse a pattern beginning with the *//* specified keyword (e.g. "object"). *//****************************************************/globle struct patternParser *FindPatternParser( void *theEnv, char *name) { struct patternParser *tempParser; for (tempParser = PatternData(theEnv)->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( void *theEnv, int rhsType) { if (rhsType == 0) return(NULL); return(PatternData(theEnv)->PatternParserArray[rhsType-1]); }#if CONSTRUCT_COMPILER && (! RUN_TIME)/*************************************************************//* PatternNodeHeaderToCode: Writes the C code representation *//* of a patternNodeHeader data structure. *//*************************************************************/globle void PatternNodeHeaderToCode( void *theEnv, 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); } PrintHashedExpressionReference(theEnv,fp,theHeader->rightHash,imageID,maxIndices); fprintf(fp,",%d,%d,%d,0,0,%d,%d,%d}",theHeader->singlefieldNode, theHeader->multifieldNode, theHeader->stopNode, theHeader->beginSlot, theHeader->endSlot, theHeader->selector); }#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; nextNode->exists = 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. */ /*===================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -