?? analysis.c
字號:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.24 06/05/06 */ /* */ /* ANALYSIS MODULE */ /*******************************************************//*************************************************************//* Purpose: Analyzes LHS patterns to check for semantic *//* errors and to determine variable comparisons and other *//* tests which must be performed either in the pattern or *//* join networks. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//* 6.24: Renamed BOOLEAN macro type to intBool. *//* *//*************************************************************/#define _ANALYSIS_SOURCE_#include "setup.h"#if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT#include <stdio.h>#define _STDIO_INCLUDED_#include "constant.h"#include "symbol.h"#include "memalloc.h"#include "exprnpsr.h"#include "reorder.h"#include "generate.h"#include "pattern.h"#include "router.h"#include "ruledef.h"#include "cstrnchk.h"#include "cstrnutl.h"#include "cstrnops.h"#include "rulecstr.h"#include "modulutl.h"#include "analysis.h"#if DEFGLOBAL_CONSTRUCT#include "globldef.h"#endif/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/ static int GetVariables(void *,struct lhsParseNode *); static intBool UnboundVariablesInPattern(void *,struct lhsParseNode *,int); static int PropagateVariableToNodes(void *, struct lhsParseNode *, int, struct symbolHashNode *, struct lhsParseNode *, int,int,int); static struct lhsParseNode *CheckExpression(void *, struct lhsParseNode *, struct lhsParseNode *, int, struct symbolHashNode *, int); static void VariableReferenceErrorMessage(void *, struct symbolHashNode *, struct lhsParseNode *, int, struct symbolHashNode *, int); static int ProcessField(void *theEnv, struct lhsParseNode *, struct lhsParseNode *, struct lhsParseNode *); static int ProcessVariable(void *, struct lhsParseNode *, struct lhsParseNode *, struct lhsParseNode *); static void VariableMixingErrorMessage(void *,struct symbolHashNode *); static int PropagateVariableDriver(void *, struct lhsParseNode *, struct lhsParseNode *, struct lhsParseNode *, int,struct symbolHashNode *, struct lhsParseNode *, int); static void CombineNandExpressions(void *,struct lhsParseNode *);/******************************************************************//* VariableAnalysis: Propagates variables references to other *//* variables in the LHS and determines if there are any illegal *//* variable references (e.g. referring to an unbound variable). *//* The propagation of variable references simply means all *//* subsequent references of a variable are made to "point" back *//* to the variable being propagated. *//******************************************************************/globle int VariableAnalysis( void *theEnv, struct lhsParseNode *patternPtr) { struct lhsParseNode *rv, *theList, *tempList; int errorFlag = FALSE; struct lhsParseNode *topNode; /* int isNand; */ /*======================================================*/ /* Loop through all of the CEs in the rule to determine */ /* which variables refer to other variables and whether */ /* any semantic errors exist when refering to variables */ /* (such as referring to a variable that was not */ /* previously bound). */ /*======================================================*/ topNode = patternPtr; while (patternPtr != NULL) { /*=========================================================*/ /* If a pattern CE is encountered, propagate any variables */ /* found in the pattern and note any illegal references to */ /* other variables. */ /*=========================================================*/ if (patternPtr->type == PATTERN_CE) { /*====================================================*/ /* Determine if the fact address associated with this */ /* pattern illegally refers to other variables. */ /*====================================================*/ if ((patternPtr->value != NULL) && (patternPtr->referringNode != NULL)) { errorFlag = TRUE; if (patternPtr->referringNode->index == -1) { PrintErrorID(theEnv,"ANALYSIS",1,TRUE); EnvPrintRouter(theEnv,WERROR,"Duplicate pattern-address ?"); EnvPrintRouter(theEnv,WERROR,ValueToString(patternPtr->value)); EnvPrintRouter(theEnv,WERROR," found in CE #"); PrintLongInteger(theEnv,WERROR,(long) patternPtr->whichCE); EnvPrintRouter(theEnv,WERROR,".\n"); } else { PrintErrorID(theEnv,"ANALYSIS",2,TRUE); EnvPrintRouter(theEnv,WERROR,"Pattern-address ?"); EnvPrintRouter(theEnv,WERROR,ValueToString(patternPtr->value)); EnvPrintRouter(theEnv,WERROR," used in CE #"); PrintLongInteger(theEnv,WERROR,(long) patternPtr->whichCE); EnvPrintRouter(theEnv,WERROR," was previously bound within a pattern CE.\n"); } } /*====================================================*/ /* Propagate the pattern and field location of bound */ /* variables found in this pattern to other variables */ /* in the same semantic scope as the bound variable. */ /*====================================================*/ if (GetVariables(theEnv,patternPtr)) return(TRUE); } /*==============================================================*/ /* If a test CE is encountered, make sure that all references */ /* to variables have been previously bound. If they are bound */ /* then replace the references to variables with function calls */ /* to retrieve the variables. */ /*==============================================================*/ else if (patternPtr->type == TEST_CE) { /*=====================================================*/ /* Verify that all variables were referenced properly. */ /*=====================================================*/ rv = CheckExpression(theEnv,patternPtr->expression,NULL,(int) patternPtr->whichCE,NULL,0); /*=========================================================*/ /* Determine the type and value constraints implied by the */ /* expression and propagate these constraints to other */ /* variables in the LHS. For example, the expression */ /* (+ ?x 1) implies that ?x is a number. */ /*=========================================================*/ theList = GetExpressionVarConstraints(theEnv,patternPtr->expression); for (tempList = theList; tempList != NULL; tempList = tempList->right) { if (PropagateVariableDriver(theEnv,patternPtr,patternPtr,NULL,SF_VARIABLE, (SYMBOL_HN *) tempList->value,tempList,FALSE)) { ReturnLHSParseNodes(theEnv,theList); return(TRUE); } } ReturnLHSParseNodes(theEnv,theList); /*========================================================*/ /* If the variables in the expression were all referenced */ /* properly, then create the expression to use in the */ /* join network. */ /*========================================================*/ if (rv != NULL) { errorFlag = TRUE; } else { if (IsNandTest(patternPtr->expression)) { patternPtr->externalNetworkTest = GetvarReplace(theEnv,patternPtr->expression,TRUE); } else { patternPtr->networkTest = GetvarReplace(theEnv,patternPtr->expression,FALSE); } } } /*=====================================================*/ /* Move on to the next pattern in the LHS of the rule. */ /*=====================================================*/ patternPtr = patternPtr->bottom; } /*========================================================*/ /* Collapse all of the expressions that must be evaluated */ /* in a join from the right into the first pattern of the */ /* not/and group. */ /*========================================================*/ CombineNandExpressions(theEnv,topNode); /*==========================================*/ /* Return the error status of the analysis. */ /*==========================================*/ return(errorFlag); }/****************************************************************//* GetVariables: Loops through each field/slot within a pattern *//* and propagates the pattern and field location of bound *//* variables found in the pattern to other variables within *//* the same semantic scope as the bound variables. *//****************************************************************/static int GetVariables( void *theEnv, struct lhsParseNode *thePattern) { struct lhsParseNode *patternHead = thePattern; struct lhsParseNode *multifieldHeader = NULL; /*======================================================*/ /* Loop through all the fields/slots found in a pattern */ /* looking for binding instances of variables. */ /*======================================================*/ while (thePattern != NULL) { /*================================================*/ /* A multifield slot contains a sublist of fields */ /* that must be traversed and checked. */ /*================================================*/ if (thePattern->multifieldSlot) { multifieldHeader = thePattern; thePattern = thePattern->bottom; } /*==================================================*/ /* Propagate the binding occurences of single field */ /* variables, multifield variables, and fact */ /* addresses to other occurences of the variable. */ /* If an error is encountered, return TRUE. */ /*==================================================*/ if (thePattern != NULL) { if ((thePattern->type == SF_VARIABLE) || (thePattern->type == MF_VARIABLE) || ((thePattern->type == PATTERN_CE) && (thePattern->value != NULL))) { if (ProcessVariable(theEnv,thePattern,multifieldHeader,patternHead)) { return(TRUE); } } else { if (ProcessField(theEnv,thePattern,multifieldHeader,patternHead)) { return(TRUE); } } } /*===============================================*/ /* Move on to the next field/slot in the pattern */ /* or to the next field in a multifield slot. */ /*===============================================*/ if (thePattern == NULL) { thePattern = multifieldHeader; } else if ((thePattern->right == NULL) && (multifieldHeader != NULL)) { thePattern = multifieldHeader; multifieldHeader = NULL; } thePattern = thePattern->right; } /*===============================*/ /* Return FALSE to indicate that */ /* no errors were detected. */ /*===============================*/ return(FALSE); }/******************************************************//* ProcessVariable: Processes a single occurence of a *//* variable by propagating references to it. *//******************************************************/static int ProcessVariable( void *theEnv, struct lhsParseNode *thePattern, struct lhsParseNode *multifieldHeader, struct lhsParseNode *patternHead) { int theType; struct symbolHashNode *theVariable; struct constraintRecord *theConstraints; /*=============================================================*/ /* If a pattern address is being propagated, then treat it as */ /* a single field pattern variable and create a constraint */ /* which indicates that is must be a fact or instance address. */ /* This code will have to be modified for new data types which */ /* can match patterns. */ /*=============================================================*/ if (thePattern->type == PATTERN_CE) { theType = SF_VARIABLE; theVariable = (struct symbolHashNode *) thePattern->value; if (thePattern->derivedConstraints) RemoveConstraint(theEnv,thePattern->constraints); theConstraints = GetConstraintRecord(theEnv); thePattern->constraints = theConstraints; thePattern->constraints->anyAllowed = FALSE; thePattern->constraints->instanceAddressesAllowed = TRUE; thePattern->constraints->factAddressesAllowed = TRUE; thePattern->derivedConstraints = TRUE; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -