📄 analysis.c
字号:
{ theNode = theNode->bottom; } } /*========================================================*/ /* Return FALSE to indicate that no errors were detected. */ /*========================================================*/ return(CLIPS_FALSE); }/*************************************************************//* UnboundVariablesInPattern: Verifies that variables within *//* a slot/field have been referenced properly (i.e. that *//* variables have been previously bound if they are not a *//* binding occurrence). *//*************************************************************/static BOOLEAN UnboundVariablesInPattern(theSlot,pattern) struct lhsParseNode *theSlot; int pattern; { struct lhsParseNode *andField; struct lhsParseNode *rv; int result; struct lhsParseNode *orField; struct symbolHashNode *slotName; CONSTRAINT_RECORD *theConstraints; int theField; /*===================================================*/ /* If a multifield slot is being checked, then check */ /* each of the fields grouped with the multifield. */ /*===================================================*/ if (theSlot->multifieldSlot) { theSlot = theSlot->bottom; while (theSlot != NULL) { if (UnboundVariablesInPattern(theSlot,pattern)) { return(CLIPS_TRUE); } theSlot = theSlot->right; } return(CLIPS_FALSE); } /*=======================*/ /* Check a single field. */ /*=======================*/ slotName = theSlot->slot; theField = theSlot->index; theConstraints = theSlot->constraints; /*===========================================*/ /* Loop through each of the '|' constraints. */ /*===========================================*/ for (orField = theSlot->bottom; orField != NULL; orField = orField->bottom) { /*===========================================*/ /* Loop through each of the fields connected */ /* by the '&' within the '|' constraint. */ /*===========================================*/ for (andField = orField; andField != NULL; andField = andField->right) { /*=======================================================*/ /* If this is not a binding occurence of a variable and */ /* there is no previous binding occurence of a variable, */ /* then generate an error message for a variable that is */ /* referred to but not bound. */ /*=======================================================*/ if (((andField->type == SF_VARIABLE) || (andField->type == MF_VARIABLE)) && (andField->referringNode == NULL)) { VariableReferenceErrorMessage((SYMBOL_HN *) andField->value,NULL,pattern, slotName,theField); return(CLIPS_TRUE); } /*==============================================*/ /* Check predicate and return value constraints */ /* to insure that all variables used within the */ /* constraint have been previously bound. */ /*==============================================*/ else if ((andField->type == PREDICATE_CONSTRAINT) || (andField->type == RETURN_VALUE_CONSTRAINT)) { rv = CheckExpression(andField->expression,NULL,pattern,slotName,theField); if (rv != NULL) return(CLIPS_TRUE); } /*========================================================*/ /* If static constraint checking is being performed, then */ /* determine if constant values have violated the set of */ /* derived constraints for the slot/field (based on the */ /* deftemplate definition and propagated constraints). */ /*========================================================*/ else if (((andField->type == INTEGER) || (andField->type == FLOAT) || (andField->type == SYMBOL) || (andField->type == STRING) || (andField->type == INSTANCE_NAME)) && GetStaticConstraintChecking()) { result = ConstraintCheckValue(andField->type,andField->value,theConstraints); if (result != NO_VIOLATION) { ConstraintViolationErrorMessage("A literal restriction value", NULL,CLIPS_FALSE,pattern, slotName,theField,result, theConstraints,CLIPS_TRUE); return(CLIPS_TRUE); } } } } /*===============================*/ /* Return FALSE to indicate that */ /* no errors were detected. */ /*===============================*/ return(CLIPS_FALSE); }/******************************************************************//* CheckExpression: Verifies that variables within an expression *//* have been referenced properly. All variables within an *//* expression must have been previously bound. *//******************************************************************/static struct lhsParseNode *CheckExpression(exprPtr,lastOne,whichCE,slotName,theField) struct lhsParseNode *exprPtr, *lastOne; int whichCE; struct symbolHashNode *slotName; int theField; { struct lhsParseNode *rv; int i = 1; while (exprPtr != NULL) { /*===============================================================*/ /* Check that single field variables contained in the expression */ /* were previously defined in the LHS. Also check to see if the */ /* variable has unmatchable constraints. */ /*===============================================================*/ if (exprPtr->type == SF_VARIABLE) { if (exprPtr->referringNode == NULL) { VariableReferenceErrorMessage((SYMBOL_HN *) exprPtr->value,lastOne, whichCE,slotName,theField); return(exprPtr); } else if ((UnmatchableConstraint(exprPtr->constraints)) && GetStaticConstraintChecking()) { ConstraintReferenceErrorMessage((SYMBOL_HN *) exprPtr->value,lastOne,i, whichCE,slotName,theField); return(exprPtr); } } /*==================================================*/ /* Check that multifield variables contained in the */ /* expression were previously defined in the LHS. */ /*==================================================*/ else if ((exprPtr->type == MF_VARIABLE) && (exprPtr->referringNode == NULL)) { VariableReferenceErrorMessage((SYMBOL_HN *) exprPtr->value,lastOne, whichCE,slotName,theField); return(exprPtr); } /*=====================================================*/ /* Check that global variables are referenced properly */ /* (i.e. if you reference a global variable, it must */ /* already be defined by a defglobal construct). */ /*=====================================================*/#if DEFGLOBAL_CONSTRUCT else if (exprPtr->type == GBL_VARIABLE) { int count; if (FindImportedConstruct("defglobal",NULL,ValueToString(exprPtr->value), &count,CLIPS_TRUE,NULL) == NULL) { VariableReferenceErrorMessage((SYMBOL_HN *) exprPtr->value,lastOne, whichCE,slotName,theField); return(exprPtr); } }#endif /*============================================*/ /* Recursively check other function calls to */ /* insure variables are referenced correctly. */ /*============================================*/ else if (((exprPtr->type == FCALL)#if DEFGENERIC_CONSTRUCT || (exprPtr->type == GCALL)#endif#if DEFFUNCTION_CONSTRUCT || (exprPtr->type == PCALL)#endif ) && (exprPtr->bottom != NULL)) { if ((rv = CheckExpression(exprPtr->bottom,exprPtr,whichCE,slotName,theField)) != NULL) { return(rv); } } /*=============================================*/ /* Move on to the next part of the expression. */ /*=============================================*/ i++; exprPtr = exprPtr->right; } /*================================================*/ /* Return NULL to indicate no error was detected. */ /*================================================*/ return(NULL); } /********************************************************//* VariableReferenceErrorMessage: Generic error message *//* for referencing a variable before it is defined. *//********************************************************/static VOID VariableReferenceErrorMessage(theVariable,theExpression,whichCE,slotName,theField) struct symbolHashNode *theVariable; struct lhsParseNode *theExpression; int whichCE; struct symbolHashNode *slotName; int theField; { struct expr *temprv; /*=============================*/ /* Print the error message ID. */ /*=============================*/ PrintErrorID("ANALYSIS",4,CLIPS_TRUE); /*=================================*/ /* Print the name of the variable. */ /*=================================*/ PrintCLIPS(WERROR,"Variable ?"); PrintCLIPS(WERROR,ValueToString(theVariable)); PrintCLIPS(WERROR," "); /*=================================================*/ /* If the variable was found inside an expression, */ /* then print the expression. */ /*=================================================*/ if (theExpression != NULL) { temprv = LHSParseNodesToExpression(theExpression); ReturnExpression(temprv->nextArg); temprv->nextArg = NULL; PrintCLIPS(WERROR,"found in the expression "); PrintExpression(WERROR,temprv); PrintCLIPS(WERROR,"\n"); ReturnExpression(temprv); } /*====================================================*/ /* Print the CE in which the variable was referenced. */ /*====================================================*/ PrintCLIPS(WERROR,"was referenced in CE #"); PrintLongInteger(WERROR,(long int) whichCE); /*=====================================*/ /* Identify the slot or field in which */ /* the variable was found. */ /*=====================================*/ if (slotName == NULL) { if (theField > 0) { PrintCLIPS(WERROR," field #"); PrintLongInteger(WERROR,(long int) theField); } } else { PrintCLIPS(WERROR," slot "); PrintCLIPS(WERROR,ValueToString(slotName)); } PrintCLIPS(WERROR," before being defined.\n"); } /************************************************************//* VariableMixingErrorMessage: Prints the error message for *//* the illegal mixing of single and multifield variables *//* on the LHS of a rule. *//************************************************************/static VOID VariableMixingErrorMessage(theVariable) struct symbolHashNode *theVariable; { PrintErrorID("ANALYSIS",3,CLIPS_TRUE); PrintCLIPS(WERROR,"Variable ?"); PrintCLIPS(WERROR,ValueToString(theVariable)); PrintCLIPS(WERROR," is used as both a single and multifield variable in the LHS\n"); }#endif /* (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -