📄 pattern.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* RULE PATTERN MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides the mechanism for recognizing and *//* parsing the various types of patterns that can be used *//* in the LHS of a rule. In CLIPS 6.0, the only pattern *//* types provided are for deftemplate and instance */ /* patterns. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//*************************************************************/#define _PATTERN_SOURCE_#include "setup.h"#include <stdio.h>#define _CLIPS_STDIO_#if DEFRULE_CONSTRUCT#include "constant.h"#include "clipsmem.h"#include "match.h"#include "reteutil.h"#include "constrnt.h"#include "exprnpsr.h"#include "router.h"#include "cstrnchk.h"#include "cstrnutl.h"#include "rulecmp.h"#include "pattern.h"#define MAX_POSITIONS 8/**************//* STRUCTURES *//**************/struct reservedSymbol { char *theSymbol; char *reservedBy; struct reservedSymbol *next; };/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if (! RUN_TIME) && (! BLOAD_ONLY)#if ANSI_COMPILER static struct lhsParseNode *ConjuctiveRestrictionParse(char *,struct token *,int *); static struct lhsParseNode *LiteralRestrictionParse(char *,struct token *,int *); static int CheckForVariableMixing(struct lhsParseNode *); static VOID TallyFieldTypes(struct lhsParseNode *);#else static struct lhsParseNode *ConjuctiveRestrictionParse(); static struct lhsParseNode *LiteralRestrictionParse(); static int CheckForVariableMixing(); static VOID TallyFieldTypes();#endif#endif/****************************************//* GLOBAL INTERNAL VARIABLE DEFINITIONS *//****************************************/ globle struct patternParser *ListOfPatternParsers = NULL;/***************************************//* LOCAL INTERNAL VARIABLE DEFINITIONS *//***************************************/ static struct patternParser *PatternParserArray[MAX_POSITIONS]; static int nextPosition = 0; static struct reservedSymbol *ListOfReservedPatternSymbols = NULL; /******************************************************************//* AddReservedPatternSymbol: Adds a symbol to the list of symbols *//* that are restricted for use in patterns. For example, the *//* deftemplate construct cannot use the symbol "object", since *//* this needs to be reserved for object patterns. Some symbols, *//* such as "exists" are completely reserved and can not be used *//* to start any type of pattern CE. *//******************************************************************/VOID AddReservedPatternSymbol(theSymbol,reservedBy) char *theSymbol; char *reservedBy; { struct reservedSymbol *newSymbol; newSymbol = get_struct(reservedSymbol); newSymbol->theSymbol = theSymbol; newSymbol->reservedBy = reservedBy; newSymbol->next = ListOfReservedPatternSymbols; ListOfReservedPatternSymbols = newSymbol; } /******************************************************************//* ReservedPatternSymbol: Returns TRUE if the specified symbol is *//* a reserved pattern symbol, otherwise FALSE is returned. If *//* the construct which is trying to use the symbol is the same *//* construct that reserved the symbol, then FALSE is returned. *//******************************************************************/BOOLEAN ReservedPatternSymbol(theSymbol,checkedBy) char *theSymbol; char *checkedBy; { struct reservedSymbol *currentSymbol; for (currentSymbol = ListOfReservedPatternSymbols; currentSymbol != NULL; currentSymbol = currentSymbol->next) { if (strcmp(theSymbol,currentSymbol->theSymbol) == 0) { if ((currentSymbol->reservedBy == NULL) || (checkedBy == NULL)) { return(CLIPS_TRUE); } if (strcmp(checkedBy,currentSymbol->reservedBy) == 0) return(CLIPS_FALSE); return(CLIPS_TRUE); } } return(CLIPS_FALSE); }/********************************************************//* ReservedPatternSymbolErrorMsg: Generic error message *//* for attempting to use a reserved pattern symbol. *//********************************************************/VOID ReservedPatternSymbolErrorMsg(theSymbol,usedFor) char *theSymbol; char *usedFor; { PrintErrorID("PATTERN",1,CLIPS_TRUE); PrintCLIPS(WERROR,"The symbol "); PrintCLIPS(WERROR,theSymbol); PrintCLIPS(WERROR," has special meaning\n"); PrintCLIPS(WERROR,"and may not be used as "); PrintCLIPS(WERROR,usedFor); PrintCLIPS(WERROR,".\n"); } /************************************************************//* GetNextEntity: Utility routine for accessing all of the *//* data entities that can match patterns. Currently facts *//* and instances are the only data entities available. *//************************************************************/globle VOID GetNextPatternEntity(theParser,theEntity) struct patternParser **theParser; struct patternEntity **theEntity; { /*=============================================================*/ /* If the current parser is NULL, then we want to retrieve the */ /* very first data entity. The traversal of entities is done */ /* by entity type (e.g. all facts are traversed followed by */ /* all instances). To get the first entity type to traverse, */ /* the current parser is set to the first parser on the list */ /* of pattern parsers. */ /*=============================================================*/ if (*theParser == NULL) { *theParser = ListOfPatternParsers; *theEntity = NULL; } /*================================================================*/ /* Otherwise try to retrieve the next entity following the entity */ /* returned by the last call to GetNextEntity. If that entity was */ /* the last of its data type, then move on to the next pattern */ /* parser, otherwise return that entity as the next one. */ /*================================================================*/ else if (theEntity != NULL) { *theEntity = (struct patternEntity *) (*(*theParser)->entityType->base.getNextFunction)(*theEntity); if ((*theEntity) != NULL) return; *theParser = (*theParser)->next; } /*===============================================================*/ /* Otherwise, we encountered a situation which should not occur. */ /* Once a NULL entity is returned from GetNextEntity, it should */ /* not be passed back to GetNextEntity. */ /*===============================================================*/ else { CLIPSSystemError("PATTERN",1); ExitCLIPS(4); } /*================================================*/ /* Keep looping through the lists of entities and */ /* pattern parsers until an entity is found. */ /*================================================*/ while ((*theEntity == NULL) && (*theParser != NULL)) { *theEntity = (struct patternEntity *) (*(*theParser)->entityType->base.getNextFunction)(*theEntity); if (*theEntity != NULL) return; *theParser = (*theParser)->next; } return; } /**************************************************************//* DetachPattern: Detaches a pattern from the pattern network *//* by calling the appropriate function for the data type *//* associated with the pattern. *//**************************************************************/VOID DetachPattern(rhsType,theHeader) int rhsType; struct patternNodeHeader *theHeader; { if (PatternParserArray[rhsType] != NULL) { FlushAlphaBetaMemory(theHeader->alphaMemory); (*PatternParserArray[rhsType]->removePatternFunction)(theHeader); } } /**************************************************//* AddPatternParser: Adds a pattern type to the *//* list of pattern parsers used to detect valid *//* patterns in the LHS of a rule. *//**************************************************/globle BOOLEAN AddPatternParser(name,priority,entityType, recognizeFunction,parseFunction, postAnalysisFunction,addPatternFunction,removePatternFunction, genJNConstantFunction,replaceGetJNValueFunction, genGetJNValueFunction,genCompareJNValuesFunction, genPNConstantFunction,replaceGetPNValueFunction, genGetPNValueFunction,genComparePNValuesFunction, returnUserDataFunction,copyUserDataFunction, markIRPatternFunction,incrementalResetFunction, initialPatternFunction, codeReferenceFunction) char *name; int priority; struct patternEntityRecord *entityType;#if ANSI_COMPILER int (*recognizeFunction)(SYMBOL_HN *); struct lhsParseNode *(*parseFunction)(char *,struct token *); int (*postAnalysisFunction)(struct lhsParseNode *); struct patternNodeHeader *(*addPatternFunction)(struct lhsParseNode *); VOID (*removePatternFunction)(struct patternNodeHeader *); struct expr *(*genJNConstantFunction)(struct lhsParseNode *); VOID (*replaceGetJNValueFunction)(struct expr *,struct lhsParseNode *); /* 10 */ struct expr *(*genGetJNValueFunction)(struct lhsParseNode *); struct expr *(*genCompareJNValuesFunction)(struct lhsParseNode *,struct lhsParseNode *); struct expr *(*genPNConstantFunction)(struct lhsParseNode *); VOID (*replaceGetPNValueFunction)(struct expr *,struct lhsParseNode *); struct expr *(*genGetPNValueFunction)(struct lhsParseNode *); struct expr *(*genComparePNValuesFunction)(struct lhsParseNode *,struct lhsParseNode *); VOID (*returnUserDataFunction)(VOID *); VOID *(*copyUserDataFunction)(VOID *); VOID (*markIRPatternFunction)(struct patternNodeHeader *,int); VOID (*incrementalResetFunction)(VOID); struct lhsParseNode *(*initialPatternFunction)(VOID); VOID (*codeReferenceFunction)(VOID *,FILE *,int,int);#else int (*recognizeFunction)(); struct lhsParseNode *(*parseFunction)(); int (*postAnalysisFunction)(); struct patternNodeHeader *(*addPatternFunction)(); VOID (*removePatternFunction)(); struct expr *(*genJNConstantFunction)(); VOID (*replaceGetJNValueFunction)(); struct expr *(*genGetJNValueFunction)(); struct expr *(*genCompareJNValuesFunction)(); struct expr *(*genPNConstantFunction)(); VOID (*replaceGetPNValueFunction)(); struct expr *(*genGetPNValueFunction)(); struct expr *(*genComparePNValuesFunction)(); VOID (*returnUserDataFunction)(); VOID *(*copyUserDataFunction)(); VOID (*markIRPatternFunction)(); VOID (*incrementalResetFunction)(); struct lhsParseNode *(*initialPatternFunction)(); VOID (*codeReferenceFunction)();#endif { struct patternParser *newPtr, *currentPtr, *lastPtr = NULL; /*============================================*/ /* Check to see that the limit for the number */ /* of pattern parsers has not been exceeded. */ /*============================================*/ if (nextPosition >= MAX_POSITIONS) return(CLIPS_FALSE); /*================================*/ /* Create the new pattern parser. */ /*================================*/ newPtr = get_struct(patternParser); newPtr->name = name; newPtr->entityType = entityType; newPtr->recognizeFunction = recognizeFunction; newPtr->parseFunction = parseFunction; newPtr->postAnalysisFunction = postAnalysisFunction; newPtr->addPatternFunction = addPatternFunction; newPtr->removePatternFunction = removePatternFunction; newPtr->genJNConstantFunction = genJNConstantFunction; newPtr->replaceGetJNValueFunction = replaceGetJNValueFunction; newPtr->genGetJNValueFunction = genGetJNValueFunction; newPtr->genCompareJNValuesFunction = genCompareJNValuesFunction; newPtr->genPNConstantFunction = genPNConstantFunction; newPtr->replaceGetPNValueFunction = replaceGetPNValueFunction; newPtr->genGetPNValueFunction = genGetPNValueFunction; newPtr->genComparePNValuesFunction = genComparePNValuesFunction; newPtr->returnUserDataFunction = returnUserDataFunction; newPtr->copyUserDataFunction = copyUserDataFunction; newPtr->markIRPatternFunction = markIRPatternFunction; newPtr->incrementalResetFunction = incrementalResetFunction; newPtr->initialPatternFunction = initialPatternFunction; newPtr->codeReferenceFunction = codeReferenceFunction; newPtr->priority = priority; newPtr->positionInArray = nextPosition; PatternParserArray[nextPosition] = newPtr; nextPosition++; /*================================*/ /* Add the parser to the list of */ /* parsers based on its priority. */ /*================================*/ if (ListOfPatternParsers == NULL) { newPtr->next = NULL; ListOfPatternParsers = newPtr; return(CLIPS_TRUE); } currentPtr = ListOfPatternParsers; while ((currentPtr != NULL) ? (priority < currentPtr->priority) : CLIPS_FALSE) { lastPtr = currentPtr; currentPtr = currentPtr->next; } if (lastPtr == NULL) { newPtr->next = ListOfPatternParsers; ListOfPatternParsers = newPtr; } else { newPtr->next = currentPtr; lastPtr->next = newPtr; } return(CLIPS_TRUE); } /****************************************************//* FindPatternParser: Searches for a pattern parser *//* that can parse a pattern beginning with the *//* specified keyword (e.g. "object"). */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -