📄 rulelhs.c
字号:
/*=======================================================*/
/* Salience number must be in the range -10000 to 10000. */
/*=======================================================*/
salience = (int) ValueToLong(salienceValue.value);
if ((salience > MAX_DEFRULE_SALIENCE) || (salience < MIN_DEFRULE_SALIENCE))
{
SalienceRangeError(theEnv,MIN_DEFRULE_SALIENCE,MAX_DEFRULE_SALIENCE);
*error = TRUE;
return;
}
/*==========================================*/
/* If the expression is a constant integer, */
/* don't bother storing the expression. */
/*==========================================*/
if (PatternData(theEnv)->SalienceExpression->type == INTEGER)
{
ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
PatternData(theEnv)->SalienceExpression = NULL;
}
PatternData(theEnv)->GlobalSalience = salience;
}
/**************************************************************/
/* ParseAutoFocus: Parses the rest of a defrule auto-focus */
/* declaration once the auto-focus keyword has been parsed. */
/**************************************************************/
static void ParseAutoFocus(
void *theEnv,
char *readSource,
int *error)
{
struct token theToken;
/*========================================*/
/* The auto-focus value must be a symbol. */
/*========================================*/
SavePPBuffer(theEnv," ");
GetToken(theEnv,readSource,&theToken);
if (theToken.type != SYMBOL)
{
SyntaxErrorMessage(theEnv,"auto-focus statement");
*error = TRUE;
return;
}
/*====================================================*/
/* The auto-focus value must be either TRUE or FALSE. */
/* If a valid value is parsed, then set the value of */
/* the global variable GlobalAutoFocus. */
/*====================================================*/
if (strcmp(ValueToString(theToken.value),"TRUE") == 0)
{ PatternData(theEnv)->GlobalAutoFocus = TRUE; }
else if (strcmp(ValueToString(theToken.value),"FALSE") == 0)
{ PatternData(theEnv)->GlobalAutoFocus = FALSE; }
else
{
SyntaxErrorMessage(theEnv,"auto-focus statement");
*error = TRUE;
}
}
/*****************************************************************/
/* LHSPattern: Parses a single conditional element found on the */
/* LHS of a rule. Conditonal element types include pattern CEs */
/* (which may be assigned to a variable), test CEs, not CEs, */
/* logical CEs, and CEs, and or CEs. */
/* */
/* <conditional-element> ::= <pattern-CE> | */
/* <assigned-pattern-CE> | */
/* <not-CE> | <and-CE> | <or-CE> | */
/* <logical-CE> | <test-CE> | */
/* <forall-CE> | <exists-CE> */
/*****************************************************************/
static struct lhsParseNode *LHSPattern(
void *theEnv,
char *readSource,
int terminator,
char *terminatorString,
int *error,
int allowDeclaration,
struct token *firstToken,
char *ruleName)
{
struct token theToken;
struct lhsParseNode *theNode;
/*=========================================================*/
/* Check to see if the first token has already been read. */
/* This should only occur for the first pattern in a rule. */
/*=========================================================*/
if (firstToken == NULL) GetToken(theEnv,readSource,&theToken);
else CopyToken(&theToken,firstToken);
/*=====================================================*/
/* A left parenthesis begins all CEs and declarations. */
/*=====================================================*/
if (theToken.type == LPAREN)
{
/*================================================*/
/* The first field of a pattern must be a symbol. */
/*================================================*/
GetToken(theEnv,readSource,&theToken);
if (theToken.type != SYMBOL)
{
SyntaxErrorMessage(theEnv,"the first field of a pattern");
*error = TRUE;
return(NULL);
}
/*====================================*/
/* If this is the first CE of a rule, */
/* then a declare statement is valid. */
/*====================================*/
if (allowDeclaration &&
(strcmp(ValueToString(theToken.value),"declare") == 0))
{
if (ruleName == NULL) SystemError(theEnv,"RULELHS",1);
DeclarationParse(theEnv,readSource,ruleName,error);
theNode = NULL;
}
/*==================================*/
/* Otherwise check for a *test* CE. */
/*==================================*/
else if (strcmp(ValueToString(theToken.value),"test") == 0)
{ theNode = TestPattern(theEnv,readSource,error); }
/*============================================*/
/* Otherwise check for an *and*, *or*, *not*, */
/* *logical*, *exists*, or *forall* CE. */
/*============================================*/
else if ((strcmp(ValueToString(theToken.value),"and") == 0) ||
(strcmp(ValueToString(theToken.value),"logical") == 0) ||
(strcmp(ValueToString(theToken.value),"not") == 0) ||
(strcmp(ValueToString(theToken.value),"exists") == 0) ||
(strcmp(ValueToString(theToken.value),"forall") == 0) ||
(strcmp(ValueToString(theToken.value),"or") == 0))
{ theNode = ConnectedPatternParse(theEnv,readSource,&theToken,error); }
/*=================================*/
/* Otherwise parse a *pattern* CE. */
/*=================================*/
else
{ theNode = SimplePatternParse(theEnv,readSource,&theToken,error); }
}
/*=======================================*/
/* Check for a pattern address variable. */
/*=======================================*/
else if (theToken.type == SF_VARIABLE)
{ theNode = AssignmentParse(theEnv,readSource,(SYMBOL_HN *) theToken.value,error); }
/*=================================================*/
/* Check for the group terminator (either a "=>" */
/* separating the LHS from the RHS or a ")" ending */
/* a CE containing other CEs such as an *and* CE). */
/*=================================================*/
else if ((theToken.type == terminator) ?
(strcmp(theToken.printForm,terminatorString) == 0) : FALSE)
{ return(NULL); }
/*====================================*/
/* Otherwise invalid syntax was used. */
/*====================================*/
else
{
SyntaxErrorMessage(theEnv,"defrule");
*error = TRUE;
return(NULL);
}
/*================================*/
/* If an error occurred, free any */
/* allocated data structures. */
/*================================*/
if (*error == TRUE)
{
ReturnLHSParseNodes(theEnv,theNode);
return(NULL);
}
/*=========================*/
/* Return the LHS pattern. */
/*=========================*/
return(theNode);
}
/*********************************************************************/
/* ConnectedPatternParse: Handles parsing of the connected */
/* conditional elements (i.e. those conditional elements that may */
/* contain one or more other conditional elements). The connected */
/* conditional elements include the *and*, *or*, *not*, *logical*, */
/* *exists*, and *forall* CEs. This routine is entered with the */
/* parsing pointing to the name of the connected CE. It is exited */
/* with the parser pointing to the closing right parenthesis of */
/* the connected CE. */
/* */
/* <and-CE> ::= (and <conditional-element>+) */
/* */
/* <or-CE> ::= (or <conditional-element>+) */
/* */
/* <logical-CE> ::= (logical <conditional-element>+) */
/* */
/* <not-CE> ::= (not <conditional-element>) */
/* */
/* <exists-CE> ::= (exists <conditional-element>+) */
/* */
/* <forall-CE> ::= (forall <conditional-element> */
/* <conditional-element>+) */
/*********************************************************************/
static struct lhsParseNode *ConnectedPatternParse(
void *theEnv,
char *readSource,
struct token *theToken,
int *error)
{
unsigned short connectorValue = 0;
struct lhsParseNode *theNode, *tempNode, *theGroup;
char *errorCE = NULL;
int logical = FALSE;
int tempValue;
/*==========================================================*/
/* Use appropriate spacing for pretty printing of the rule. */
/*==========================================================*/
IncrementIndentDepth(theEnv,5);
if (strcmp(ValueToString(theToken->value),"or") == 0)
{
connectorValue = OR_CE;
errorCE = "the or conditional element";
SavePPBuffer(theEnv," ");
}
else if (strcmp(ValueToString(theToken->value),"and") == 0)
{
connectorValue = AND_CE;
errorCE = "the and conditional element";
SavePPBuffer(theEnv," ");
}
else if (strcmp(ValueToString(theToken->value),"not") == 0)
{
connectorValue = NOT_CE;
errorCE = "the not conditional element";
SavePPBuffer(theEnv," ");
}
else if (strcmp(ValueToString(theToken->value),"exists") == 0)
{
connectorValue = EXISTS_CE;
errorCE = "the exists conditional element";
PPCRAndIndent(theEnv);
}
else if (strcmp(ValueToString(theToken->value),"forall") == 0)
{
connectorValue = FORALL_CE;
errorCE = "the forall conditional element";
PPCRAndIndent(theEnv);
}
else if (strcmp(ValueToString(theToken->value),"logical") == 0)
{
connectorValue = AND_CE;
errorCE = "the logical conditional element";
logical = TRUE;
PPCRAndIndent(theEnv);
}
/*=====================================================*/
/* The logical CE cannot be contained within a not CE. */
/*=====================================================*/
if (PatternData(theEnv)->WithinNotCE && logical)
{
PrintErrorID(theEnv,"RULELHS",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"The logical CE cannot be used within a not/exists/forall CE.\n");
*error = TRUE;
return(NULL);
}
/*=====================================================*/
/* Remember if we're currently within a *not* CE and */
/* then check to see if we're entering a new *not* CE. */
/*=====================================================*/
tempValue = PatternData(theEnv)->WithinNotCE;
if ((connectorValue == NOT_CE) ||
(connectorValue == EXISTS_CE) ||
(connectorValue == FORALL_CE))
{ PatternData(theEnv)->WithinNotCE = TRUE; }
/*===========================================*/
/* Parse all of the CEs contained with the */
/* CE. A ) will terminate the end of the CE. */
/*===========================================*/
theGroup = GroupPatterns(theEnv,readSource,RPAREN,")",error);
/*====================================*/
/* Restore the "with a *not* CE" flag */
/* and reset the indentation depth. */
/*====================================*/
PatternData(theEnv)->WithinNotCE = tempValue;
DecrementIndentDepth(theEnv,5);
/*============================================*/
/* If an error occured while parsing, return. */
/*============================================*/
if (*error == TRUE)
{
ReturnLHSParseNodes(theEnv,theGroup);
return(NULL);
}
/*=========================================================*/
/* If we parsed a *logical* CE, then mark the logical flag */
/* for all of the CEs contained within the logical CE. */
/*=========================================================*/
if (logical) TagLHSLogicalNodes(theGroup);
/*=====================================================*/
/* All the connected CEs must contain at least one CE. */
/*=====================================================*/
if (theGroup == NULL)
{
SyntaxErrorMessage(theEnv,errorCE);
*error = TRUE;
return(NULL);
}
/*============================================*/
/* A not CE may not contain more than one CE. */
/*============================================*/
if ((connectorValue == NOT_CE) && (theGroup->bottom != NULL))
{
SyntaxErrorMessage(theEnv,errorCE);
ReturnLHSParseNodes(theEnv,theGroup);
*error = TRUE;
return(NULL);
}
/*============================================*/
/* A forall CE must contain at least two CEs. */
/*============================================*/
if ((connectorValue == FORALL_CE) && (theGroup->bottom == NULL))
{
SyntaxErrorMessage(theEnv,errorCE);
ReturnLHSParseNodes(theEnv,theGroup);
*error = TRUE;
return(NULL);
}
/*========================================================*/
/* Remove an "and" and "or" CE that only contains one CE. */
/*========================================================*/
if (((connectorValue == AND_CE) || (connectorValue == OR_CE)) &&
(theGroup->bottom == NULL))
{
theGroup->logical = logical;
return(theGroup);
}
/*===========================================================*/
/* Create the top most node which connects the CEs together. */
/*===========================================================*/
theNode = GetLHSParseNode(theEnv);
theNode->logical = logical;
/*======================================================*/
/* Attach and/or/not CEs directly to the top most node. */
/*======================================================*/
if ((connectorValue == AND_CE) ||
(connectorValue == OR_CE) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -