📄 pattern.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 06/05/06 */
/* */
/* 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 version 6.0, the only pattern */
/* types provided are for deftemplate and instance */
/* patterns. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* */
/* 6.24: Renamed BOOLEAN macro type to intBool. */
/* */
/*************************************************************/
#define _PATTERN_SOURCE_
#include "setup.h"
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <stdlib.h>
#if DEFRULE_CONSTRUCT
#include "constant.h"
#include "constrnt.h"
#include "cstrnchk.h"
#include "cstrnutl.h"
#include "envrnmnt.h"
#include "exprnpsr.h"
#include "match.h"
#include "memalloc.h"
#include "reteutil.h"
#include "router.h"
#include "rulecmp.h"
#include "pattern.h"
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
#if (! RUN_TIME) && (! BLOAD_ONLY)
static struct lhsParseNode *ConjuctiveRestrictionParse(void *,char *,struct token *,int *);
static struct lhsParseNode *LiteralRestrictionParse(void *,char *,struct token *,int *);
static int CheckForVariableMixing(void *,struct lhsParseNode *);
static void TallyFieldTypes(struct lhsParseNode *);
#endif
static void DeallocatePatternData(void *);
/*****************************************************************************/
/* InitializePatterns: Initializes the global data associated with patterns. */
/*****************************************************************************/
globle void InitializePatterns(
void *theEnv)
{
AllocateEnvironmentData(theEnv,PATTERN_DATA,sizeof(struct patternData),DeallocatePatternData);
}
/**************************************************/
/* DeallocatePatternData: Deallocates environment */
/* data for rule pattern registration. */
/**************************************************/
static void DeallocatePatternData(
void *theEnv)
{
struct reservedSymbol *tmpRSPtr, *nextRSPtr;
struct patternParser *tmpPPPtr, *nextPPPtr;
tmpRSPtr = PatternData(theEnv)->ListOfReservedPatternSymbols;
while (tmpRSPtr != NULL)
{
nextRSPtr = tmpRSPtr->next;
rtn_struct(theEnv,reservedSymbol,tmpRSPtr);
tmpRSPtr = nextRSPtr;
}
tmpPPPtr = PatternData(theEnv)->ListOfPatternParsers;
while (tmpPPPtr != NULL)
{
nextPPPtr = tmpPPPtr->next;
rtn_struct(theEnv,patternParser,tmpPPPtr);
tmpPPPtr = nextPPPtr;
}
}
/******************************************************************/
/* 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(
void *theEnv,
char *theSymbol,
char *reservedBy)
{
struct reservedSymbol *newSymbol;
newSymbol = get_struct(theEnv,reservedSymbol);
newSymbol->theSymbol = theSymbol;
newSymbol->reservedBy = reservedBy;
newSymbol->next = PatternData(theEnv)->ListOfReservedPatternSymbols;
PatternData(theEnv)->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. */
/******************************************************************/
intBool ReservedPatternSymbol(
void *theEnv,
char *theSymbol,
char *checkedBy)
{
struct reservedSymbol *currentSymbol;
for (currentSymbol = PatternData(theEnv)->ListOfReservedPatternSymbols;
currentSymbol != NULL;
currentSymbol = currentSymbol->next)
{
if (strcmp(theSymbol,currentSymbol->theSymbol) == 0)
{
if ((currentSymbol->reservedBy == NULL) || (checkedBy == NULL))
{ return(TRUE); }
if (strcmp(checkedBy,currentSymbol->reservedBy) == 0) return(FALSE);
return(TRUE);
}
}
return(FALSE);
}
/********************************************************/
/* ReservedPatternSymbolErrorMsg: Generic error message */
/* for attempting to use a reserved pattern symbol. */
/********************************************************/
void ReservedPatternSymbolErrorMsg(
void *theEnv,
char *theSymbol,
char *usedFor)
{
PrintErrorID(theEnv,"PATTERN",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"The symbol ");
EnvPrintRouter(theEnv,WERROR,theSymbol);
EnvPrintRouter(theEnv,WERROR," has special meaning\n");
EnvPrintRouter(theEnv,WERROR,"and may not be used as ");
EnvPrintRouter(theEnv,WERROR,usedFor);
EnvPrintRouter(theEnv,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(
void *theEnv,
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 = PatternData(theEnv)->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)(theEnv,*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
{
SystemError(theEnv,"PATTERN",1);
EnvExitRouter(theEnv,EXIT_FAILURE);
}
/*================================================*/
/* 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)(theEnv,*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(
void *theEnv,
int rhsType,
struct patternNodeHeader *theHeader)
{
if (PatternData(theEnv)->PatternParserArray[rhsType] != NULL)
{
FlushAlphaBetaMemory(theEnv,theHeader->alphaMemory);
(*PatternData(theEnv)->PatternParserArray[rhsType]->removePatternFunction)(theEnv,theHeader);
}
}
/**************************************************/
/* AddPatternParser: Adds a pattern type to the */
/* list of pattern parsers used to detect valid */
/* patterns in the LHS of a rule. */
/**************************************************/
globle intBool AddPatternParser(
void *theEnv,
struct patternParser *newPtr)
{
struct patternParser *currentPtr, *lastPtr = NULL;
/*============================================*/
/* Check to see that the limit for the number */
/* 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] = 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)
{
return(PatternData(theEnv)->PatternParserArray[rhsType]);
}
#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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -