📄 rulelhs.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.22 06/15/04 */
/* */
/* DEFRULE LHS PARSING MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Coordinates parsing of the LHS conditional */
/* elements of a rule. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* */
/*************************************************************/
#define _RULELHS_SOURCE_
#include "setup.h"
#if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <string.h>
#include "agenda.h"
#include "argacces.h"
#include "constant.h"
#include "constrct.h"
#include "constrnt.h"
#include "cstrnchk.h"
#include "envrnmnt.h"
#include "exprnpsr.h"
#include "memalloc.h"
#include "pattern.h"
#include "reorder.h"
#include "router.h"
#include "ruledef.h"
#include "scanner.h"
#include "symbol.h"
#include "rulelhs.h"
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static struct lhsParseNode *RuleBodyParse(void *,char *,struct token *,char *,int *);
static void DeclarationParse(void *,char *,char *,int *);
static struct lhsParseNode *LHSPattern(void *,char *,int,char *,int *,int,
struct token *,char *);
static struct lhsParseNode *ConnectedPatternParse(void *,char *,struct token *,int *);
static struct lhsParseNode *GroupPatterns(void *,char *,int,char *,int *);
static struct lhsParseNode *TestPattern(void *,char *,int *);
static struct lhsParseNode *AssignmentParse(void *,char *,SYMBOL_HN *,int *);
static void TagLHSLogicalNodes(struct lhsParseNode *);
static struct lhsParseNode *SimplePatternParse(void *,char *,struct token *,int *);
static void ParseSalience(void *,char *,char *,int *);
static void ParseAutoFocus(void *,char *,int *);
/*******************************************************************/
/* ParseRuleLHS: Coordinates all the actions necessary for parsing */
/* the LHS of a rule including the reordering of pattern */
/* conditional elements to conform with the KB Rete topology. */
/*******************************************************************/
globle struct lhsParseNode *ParseRuleLHS(
void *theEnv,
char *readSource,
struct token *theToken,
char *ruleName)
{
struct lhsParseNode *theLHS;
int result;
int error = FALSE;
/*========================================*/
/* Initialize salience parsing variables. */
/*========================================*/
PatternData(theEnv)->GlobalSalience = 0;
PatternData(theEnv)->GlobalAutoFocus = FALSE;
PatternData(theEnv)->SalienceExpression = NULL;
/*============================*/
/* Set the indentation depth. */
/*============================*/
SetIndentDepth(theEnv,3);
/*=====================================================*/
/* Get the raw representation for the LHS of the rule. */
/*=====================================================*/
theLHS = RuleBodyParse(theEnv,readSource,theToken,ruleName,&error);
if (error) return(NULL);
/*====================================================*/
/* Reorder the raw representation so that it consists */
/* of at most a single top level OR CE containing one */
/* or more AND CEs. */
/*====================================================*/
theLHS = ReorderPatterns(theEnv,theLHS,&result);
/*================================*/
/* Return the LHS representation. */
/*================================*/
return(theLHS);
}
/*********************************************************/
/* RuleBodyParse: Parses the LHS of a rule, but does not */
/* reorder any of the LHS patterns to conform with the */
/* KB Rete Topology. */
/* */
/* <rule-body> ::= [<declaration>] */
/* <conditional-element>* */
/* => */
/*********************************************************/
static struct lhsParseNode *RuleBodyParse(
void *theEnv,
char *readSource,
struct token *theToken,
char *ruleName,
int *error)
{
struct lhsParseNode *theNode, *otherNodes;
/*=============================*/
/* Set the error return value. */
/*=============================*/
*error = FALSE;
/*==================================================*/
/* If we're already at the separator, "=>", between */
/* the LHS and RHS, then the LHS is empty. */
/*==================================================*/
if ((theToken->type == SYMBOL) ?
(strcmp(ValueToString(theToken->value),"=>") == 0) : FALSE)
{ return(NULL); }
/*===========================================*/
/* Parse the first pattern as a special case */
/* (the declare statement is allowed). */
/*===========================================*/
theNode = LHSPattern(theEnv,readSource,SYMBOL,"=>",error,TRUE,theToken,ruleName);
if (*error == TRUE)
{
ReturnLHSParseNodes(theEnv,theNode);
return(NULL);
}
PPCRAndIndent(theEnv);
/*======================================*/
/* Parse the other patterns in the LHS. */
/*======================================*/
otherNodes = GroupPatterns(theEnv,readSource,SYMBOL,"=>",error);
if (*error == TRUE)
{
ReturnLHSParseNodes(theEnv,theNode);
return(NULL);
}
/*================================================*/
/* Construct the final LHS by combining the first */
/* pattern with the remaining patterns. */
/*================================================*/
if (theNode == NULL)
{ theNode = otherNodes; }
else
{ theNode->bottom = otherNodes; }
/*=======================*/
/* Return the final LHS. */
/*=======================*/
return(theNode);
}
/********************************************************/
/* DeclarationParse: Parses a defrule declaration. */
/* */
/* <declaration> ::= (declare <rule-property>+) */
/* */
/* <rule-property> ::= (salience <integer-expression>) */
/* <rule-property> ::= (auto-focus TRUE | FALSE) */
/********************************************************/
static void DeclarationParse(
void *theEnv,
char *readSource,
char *ruleName,
int *error)
{
struct token theToken;
struct expr *packPtr;
int notDone = TRUE;
int salienceParsed = FALSE, autoFocusParsed = FALSE;
/*===========================*/
/* Next token must be a '('. */
/*===========================*/
SavePPBuffer(theEnv," ");
GetToken(theEnv,readSource,&theToken);
if (theToken.type != LPAREN)
{
SyntaxErrorMessage(theEnv,"declare statement");
*error = TRUE;
return;
}
/*==========================================*/
/* Continue parsing until there are no more */
/* valid rule property declarations. */
/*==========================================*/
while (notDone)
{
/*=============================================*/
/* The name of a rule property must be symbol. */
/*=============================================*/
GetToken(theEnv,readSource,&theToken);
if (theToken.type != SYMBOL)
{
SyntaxErrorMessage(theEnv,"declare statement");
*error = TRUE;
}
/*==============================================*/
/* Parse a salience declaration if encountered. */
/*==============================================*/
else if (strcmp(ValueToString(theToken.value),"salience") == 0)
{
if (salienceParsed)
{
AlreadyParsedErrorMessage(theEnv,"salience declaration",NULL);
*error = TRUE;
}
else
{
ParseSalience(theEnv,readSource,ruleName,error);
salienceParsed = TRUE;
}
}
/*=================================================*/
/* Parse an auto-focus declaration if encountered. */
/* A global flag is used to indicate if the */
/* auto-focus feature for a rule was parsed. */
/*=================================================*/
else if (strcmp(ValueToString(theToken.value),"auto-focus") == 0)
{
if (autoFocusParsed)
{
AlreadyParsedErrorMessage(theEnv,"auto-focus declaration",NULL);
*error = TRUE;
}
else
{
ParseAutoFocus(theEnv,readSource,error);
autoFocusParsed = TRUE;
}
}
/*==========================================*/
/* Otherwise the symbol does not correspond */
/* to a valid rule property. */
/*==========================================*/
else
{
SyntaxErrorMessage(theEnv,"declare statement");
*error = TRUE;
}
/*=====================================*/
/* Return if an error was encountered. */
/*=====================================*/
if (*error)
{
ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
PatternData(theEnv)->SalienceExpression = NULL;
return;
}
/*=======================================*/
/* Both the salience and auto-focus rule */
/* properties are closed with a ')'. */
/*=======================================*/
GetToken(theEnv,readSource,&theToken);
if (theToken.type != RPAREN)
{
PPBackup(theEnv);
SavePPBuffer(theEnv," ");
SavePPBuffer(theEnv,theToken.printForm);
ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
PatternData(theEnv)->SalienceExpression = NULL;
SyntaxErrorMessage(theEnv,"declare statement");
*error = TRUE;
return;
}
/*=============================================*/
/* The declare statement is closed with a ')'. */
/*=============================================*/
GetToken(theEnv,readSource,&theToken);
if (theToken.type == RPAREN) notDone = FALSE;
else if (theToken.type != LPAREN)
{
ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
PatternData(theEnv)->SalienceExpression = NULL;
SyntaxErrorMessage(theEnv,"declare statement");
*error = TRUE;
return;
}
else
{
PPBackup(theEnv);
SavePPBuffer(theEnv," (");
}
}
/*==========================================*/
/* Return the value of the salience through */
/* the global variable SalienceExpression. */
/*==========================================*/
packPtr = PackExpression(theEnv,PatternData(theEnv)->SalienceExpression);
ReturnExpression(theEnv,PatternData(theEnv)->SalienceExpression);
PatternData(theEnv)->SalienceExpression = packPtr;
return;
}
/************************************************************/
/* ParseSalience: Parses the rest of a defrule salience */
/* declaration once the salience keyword has been parsed. */
/************************************************************/
static void ParseSalience(
void *theEnv,
char *readSource,
char *ruleName,
int *error)
{
int salience;
DATA_OBJECT salienceValue;
/*==============================*/
/* Get the salience expression. */
/*==============================*/
SavePPBuffer(theEnv," ");
PatternData(theEnv)->SalienceExpression = ParseAtomOrExpression(theEnv,readSource,NULL);
if (PatternData(theEnv)->SalienceExpression == NULL)
{
*error = TRUE;
return;
}
/*============================================================*/
/* Evaluate the expression and determine if it is an integer. */
/*============================================================*/
SetEvaluationError(theEnv,FALSE);
if (EvaluateExpression(theEnv,PatternData(theEnv)->SalienceExpression,&salienceValue))
{
SalienceInformationError(theEnv,"defrule",ruleName);
*error = TRUE;
return;
}
if (salienceValue.type != INTEGER)
{
SalienceNonIntegerError(theEnv);
*error = TRUE;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -