📄 factqpsr.c
字号:
DESCRIPTION : In parsing an fact-set query, this function replaces a constant template name with an actual pointer to the template INPUTS : The expression RETURNS : TRUE if all OK, FALSE if template cannot be found SIDE EFFECTS : The expression type and value are modified if template is found NOTES : Searches current and imported modules for reference ***************************************************/static intBool ReplaceTemplateNameWithReference( void *theEnv, EXPRESSION *theExp) { char *theTemplateName; void *theDeftemplate; int count; if (theExp->type == SYMBOL) { theTemplateName = ValueToString(theExp->value); theDeftemplate = (struct deftemplate *) FindImportedConstruct(theEnv,"deftemplate",NULL,theTemplateName, &count,TRUE,NULL); if (theDeftemplate == NULL) { CantFindItemErrorMessage(theEnv,"deftemplate",theTemplateName); return(FALSE); } if (count > 1) { AmbiguousReferenceErrorMessage(theEnv,"deftemplate",theTemplateName); return(FALSE); } theExp->type = DEFTEMPLATE_PTR; theExp->value = theDeftemplate; } return(TRUE); }/************************************************************* NAME : ParseQueryTestExpression DESCRIPTION : Parses the test-expression for a query INPUTS : 1) The top node of the query expression 2) The logical name of the input RETURNS : TRUE if all OK, FALSE otherwise SIDE EFFECTS : Entire query-expression deleted on errors Nodes allocated for new expression Test shoved in front of class-restrictions on query argument list NOTES : Expects top != NULL *************************************************************/static int ParseQueryTestExpression( void *theEnv, EXPRESSION *top, char *readSource) { EXPRESSION *qtest; int error; struct BindInfo *oldBindList; error = FALSE; oldBindList = GetParsedBindNames(theEnv); SetParsedBindNames(theEnv,NULL); qtest = ArgumentParse(theEnv,readSource,&error); if (error == TRUE) { SetParsedBindNames(theEnv,oldBindList); ReturnExpression(theEnv,top); return(FALSE); } if (qtest == NULL) { SetParsedBindNames(theEnv,oldBindList); SyntaxErrorMessage(theEnv,"fact-set query function"); ReturnExpression(theEnv,top); return(FALSE); } qtest->nextArg = top->argList; top->argList = qtest; if (ParsedBindNamesEmpty(theEnv) == FALSE) { ClearParsedBindNames(theEnv); SetParsedBindNames(theEnv,oldBindList); PrintErrorID(theEnv,"FACTQPSR",2,FALSE); EnvPrintRouter(theEnv,WERROR,"Binds are not allowed in fact-set query in function "); EnvPrintRouter(theEnv,WERROR,ValueToString(ExpressionFunctionCallName(top))); EnvPrintRouter(theEnv,WERROR,".\n"); ReturnExpression(theEnv,top); return(FALSE); } SetParsedBindNames(theEnv,oldBindList); return(TRUE); }/************************************************************* NAME : ParseQueryActionExpression DESCRIPTION : Parses the action-expression for a query INPUTS : 1) The top node of the query expression 2) The logical name of the input 3) List of query parameters RETURNS : TRUE if all OK, FALSE otherwise SIDE EFFECTS : Entire query-expression deleted on errors Nodes allocated for new expression Action shoved in front of template-restrictions and in back of test-expression on query argument list NOTES : Expects top != NULL && top->argList != NULL *************************************************************/static int ParseQueryActionExpression( void *theEnv, EXPRESSION *top, char *readSource, EXPRESSION *factQuerySetVars, struct token *queryInputToken) { EXPRESSION *qaction,*tmpFactSetVars; int error; struct BindInfo *oldBindList,*newBindList,*prev; error = FALSE; oldBindList = GetParsedBindNames(theEnv); SetParsedBindNames(theEnv,NULL); ExpressionData(theEnv)->BreakContext = TRUE; ExpressionData(theEnv)->ReturnContext = ExpressionData(theEnv)->svContexts->rtn; qaction = GroupActions(theEnv,readSource,queryInputToken,TRUE,NULL,FALSE); PPBackup(theEnv); PPBackup(theEnv); SavePPBuffer(theEnv,queryInputToken->printForm); ExpressionData(theEnv)->BreakContext = FALSE; if (error == TRUE) { SetParsedBindNames(theEnv,oldBindList); ReturnExpression(theEnv,top); return(FALSE); } if (qaction == NULL) { SetParsedBindNames(theEnv,oldBindList); SyntaxErrorMessage(theEnv,"fact-set query function"); ReturnExpression(theEnv,top); return(FALSE); } qaction->nextArg = top->argList->nextArg; top->argList->nextArg = qaction; newBindList = GetParsedBindNames(theEnv); prev = NULL; while (newBindList != NULL) { tmpFactSetVars = factQuerySetVars; while (tmpFactSetVars != NULL) { if (tmpFactSetVars->value == (void *) newBindList->name) { ClearParsedBindNames(theEnv); SetParsedBindNames(theEnv,oldBindList); PrintErrorID(theEnv,"FACTQPSR",3,FALSE); EnvPrintRouter(theEnv,WERROR,"Cannot rebind fact-set member variable "); EnvPrintRouter(theEnv,WERROR,ValueToString(tmpFactSetVars->value)); EnvPrintRouter(theEnv,WERROR," in function "); EnvPrintRouter(theEnv,WERROR,ValueToString(ExpressionFunctionCallName(top))); EnvPrintRouter(theEnv,WERROR,".\n"); ReturnExpression(theEnv,top); return(FALSE); } tmpFactSetVars = tmpFactSetVars->nextArg; } prev = newBindList; newBindList = newBindList->next; } if (prev == NULL) { SetParsedBindNames(theEnv,oldBindList); } else { prev->next = oldBindList; } return(TRUE); }/*********************************************************************************** NAME : ReplaceFactVariables DESCRIPTION : Replaces all references to fact-variables within an fact query-function with function calls to query-fact (which references the fact array at run-time) INPUTS : 1) The fact-variable list 2) A boolean expression containing variable references 3) A flag indicating whether to allow slot references of the type <fact-query-variable>:<slot-name> for direct slot access or not 4) Nesting depth of query functions RETURNS : Nothing useful SIDE EFFECTS : If a SF_VARIABLE node is found and is on the list of fact variables, it is replaced with a query-fact function call. NOTES : Other SF_VARIABLE(S) are left alone for replacement by other parsers. This implies that a user may use defgeneric, defrule, and defmessage-handler variables within a query-function where they do not conflict with fact-variable names. ***********************************************************************************/static void ReplaceFactVariables( void *theEnv, EXPRESSION *vlist, EXPRESSION *bexp, int sdirect, int ndepth) { EXPRESSION *eptr; struct FunctionDefinition *rindx_func,*rslot_func; int posn; rindx_func = FindFunction(theEnv,"(query-fact)"); rslot_func = FindFunction(theEnv,"(query-fact-slot)"); while (bexp != NULL) { if (bexp->type == SF_VARIABLE) { eptr = vlist; posn = 0; while ((eptr != NULL) ? (eptr->value != bexp->value) : FALSE) { eptr = eptr->nextArg; posn++; } if (eptr != NULL) { bexp->type = FCALL; bexp->value = (void *) rindx_func; eptr = GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long long) ndepth)); eptr->nextArg = GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long long) posn)); bexp->argList = eptr; } else if (sdirect == TRUE) { ReplaceSlotReference(theEnv,vlist,bexp,rslot_func,ndepth); } } if (bexp->argList != NULL) { if (IsQueryFunction(bexp)) { ReplaceFactVariables(theEnv,vlist,bexp->argList,sdirect,ndepth+1); } else { ReplaceFactVariables(theEnv,vlist,bexp->argList,sdirect,ndepth); } } bexp = bexp->nextArg; } }/************************************************************************* NAME : ReplaceSlotReference DESCRIPTION : Replaces fact-set query function variable references of the form: <fact-variable>:<slot-name> with function calls to get these fact-slots at run time INPUTS : 1) The fact-set variable list 2) The expression containing the variable 3) The address of the fact slot access function 4) Nesting depth of query functions RETURNS : Nothing useful SIDE EFFECTS : If the variable is a slot reference, then it is replaced with the appropriate function-call. NOTES : None *************************************************************************/static void ReplaceSlotReference( void *theEnv, EXPRESSION *vlist, EXPRESSION *theExp, struct FunctionDefinition *func, int ndepth) { size_t len; int posn,oldpp; size_t i; register char *str; EXPRESSION *eptr; struct token itkn; str = ValueToString(theExp->value); len = strlen(str); if (len < 3) return; for (i = len-2 ; i >= 1 ; i--) { if ((str[i] == FACT_SLOT_REF) ? (i >= 1) : FALSE) { eptr = vlist; posn = 0; while (eptr && ((i != strlen(ValueToString(eptr->value))) || strncmp(ValueToString(eptr->value),str, (STD_SIZE) i))) { eptr = eptr->nextArg; posn++; } if (eptr != NULL) { OpenStringSource(theEnv,"query-var",str+i+1,0); oldpp = GetPPBufferStatus(theEnv); SetPPBufferStatus(theEnv,OFF); GetToken(theEnv,"query-var",&itkn); SetPPBufferStatus(theEnv,oldpp); CloseStringSource(theEnv,"query-var"); theExp->type = FCALL; theExp->value = (void *) func; theExp->argList = GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long long) ndepth)); theExp->argList->nextArg = GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long long) posn)); theExp->argList->nextArg->nextArg = GenConstant(theEnv,itkn.type,itkn.value); break; } } } }/******************************************************************** NAME : IsQueryFunction DESCRIPTION : Determines if an expression is a query function call INPUTS : The expression RETURNS : TRUE if query function call, FALSE otherwise SIDE EFFECTS : None NOTES : None ********************************************************************/static int IsQueryFunction( EXPRESSION *theExp) { int (*fptr)(void); if (theExp->type != FCALL) return(FALSE); fptr = (int (*)(void)) ExpressionFunctionPointer(theExp); if (fptr == (int (*)(void)) AnyFacts) return(TRUE); if (fptr == (int (*)(void)) QueryFindFact) return(TRUE); if (fptr == (int (*)(void)) QueryFindAllFacts) return(TRUE); if (fptr == (int (*)(void)) QueryDoForFact) return(TRUE); if (fptr == (int (*)(void)) QueryDoForAllFacts) return(TRUE); if (fptr == (int (*)(void)) DelayedQueryDoForAllFacts) return(TRUE); return(FALSE); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -