📄 exprnpsr.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* EXPRESSION PARSER MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides routines for parsing expressions. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* Brian L. Donnell *//* *//* Revision History: *//* *//*************************************************************/#define _EXPRNPSR_SOURCE_#include "setup.h"#include <stdio.h>#define _CLIPS_STDIO_#if ANSI_COMPILER#include <stdlib.h>#endif#include <string.h>#include <ctype.h>#include "constant.h"#include "router.h"#include "strngrtr.h"#include "scanner.h"#include "clipsmem.h"#include "argacces.h"#include "prntutil.h"#include "cstrnchk.h"#include "extnfunc.h"#include "exprnpsr.h"#include "modulutl.h"#if DEFRULE_CONSTRUCT#include "network.h"#endif#if DEFGENERIC_CONSTRUCT#include "genrccom.h"#endif#if DEFFUNCTION_CONSTRUCT#include "dffnxfun.h"#endif/****************************************//* GLOBAL INTERNAL VARIABLE DEFINITIONS *//****************************************/#if (! RUN_TIME) globle SAVED_CONTEXTS *svContexts = NULL; globle int ReturnContext; globle int BreakContext;#endif globle BOOLEAN SequenceOpMode = CLIPS_FALSE;#if (! RUN_TIME)/***************************************************//* Function0Parse: Parses a function. Assumes that *//* none of the function has been parsed yet. *//***************************************************/globle struct expr *Function0Parse(logicalName) char *logicalName; { struct token theToken; struct expr *top; /*=================================*/ /* All functions begin with a '('. */ /*=================================*/ GetToken(logicalName,&theToken); if (theToken.type != LPAREN) { SyntaxErrorMessage("function calls"); return(NULL); } /*=================================*/ /* Parse the rest of the function. */ /*=================================*/ top = Function1Parse(logicalName); return(top); }/*******************************************************//* Function1Parse: Parses a function. Assumes that the *//* opening left parenthesis has already been parsed. *//*******************************************************/globle struct expr *Function1Parse(logicalName) char *logicalName; { struct token theToken; struct expr *top; /*========================*/ /* Get the function name. */ /*========================*/ GetToken(logicalName,&theToken); if (theToken.type != SYMBOL) { PrintErrorID("EXPRNPSR",1,CLIPS_TRUE); PrintCLIPS(WERROR,"A function name must be a symbol\n"); return(NULL); } /*=================================*/ /* Parse the rest of the function. */ /*=================================*/ top = Function2Parse(logicalName,ValueToString(theToken.value)); return(top); }/****************************************************//* Function2Parse: Parses a function. Assumes that *//* the opening left parenthesis and function name *//* have already been parsed. *//****************************************************/globle struct expr *Function2Parse(logicalName,name) char *logicalName, *name; { struct FunctionDefinition *theFunction; struct expr *top;#if DEFGENERIC_CONSTRUCT VOID *gfunc;#endif#if DEFFUNCTION_CONSTRUCT VOID *dptr;#endif /*=========================================================*/ /* Module specification cannot be used in a function call. */ /*=========================================================*/ if (FindModuleSeparator(name)) { IllegalModuleSpecifierMessage(); return(NULL); } /*================================*/ /* Has the function been defined? */ /*================================*/ theFunction = FindFunction(name);#if DEFGENERIC_CONSTRUCT gfunc = (VOID *) LookupDefgenericInScope(name);#endif#if DEFFUNCTION_CONSTRUCT if ((theFunction == NULL)#if DEFGENERIC_CONSTRUCT && (gfunc == NULL)#endif ) dptr = (VOID *) LookupDeffunctionInScope(name); else dptr = NULL;#endif /*=============================*/ /* Define top level structure. */ /*=============================*/#if DEFFUNCTION_CONSTRUCT if (dptr != NULL) top = GenConstant(PCALL,dptr); else#endif#if DEFGENERIC_CONSTRUCT if (gfunc != NULL) top = GenConstant(GCALL,gfunc); else#endif if (theFunction != NULL) top = GenConstant(FCALL,theFunction); else { PrintErrorID("EXPRNPSR",3,CLIPS_TRUE); PrintCLIPS(WERROR,"Missing function declaration for "); PrintCLIPS(WERROR,name); PrintCLIPS(WERROR,".\n"); return(NULL); } /*=======================================================*/ /* Check to see if function has its own parsing routine. */ /*=======================================================*/ PushRtnBrkContexts(); ReturnContext = CLIPS_FALSE; BreakContext = CLIPS_FALSE; #if DEFGENERIC_CONSTRUCT || DEFFUNCTION_CONSTRUCT if (top->type == FCALL)#endif { if (theFunction->parser != NULL) { top = (*theFunction->parser)(top,logicalName); PopRtnBrkContexts(); if (top == NULL) return(NULL); if (ReplaceSequenceExpansionOps(top->argList,top,FindFunction("(expansion-call)"), FindFunction("expand$"))) { ReturnExpression(top); return(NULL); } return(top); } } /*========================================*/ /* Default parsing routine for functions. */ /*========================================*/ top = CollectArguments(top,logicalName); PopRtnBrkContexts(); if (top == NULL) return(NULL); if (ReplaceSequenceExpansionOps(top->argList,top,FindFunction("(expansion-call)"), FindFunction("expand$"))) { ReturnExpression(top); return(NULL); } /*============================================================*/ /* If the function call uses the sequence expansion operator, */ /* its arguments cannot be checked until runtime. */ /*============================================================*/ if (top->value == (VOID *) FindFunction("(expansion-call)")) { return(top); } /*============================*/ /* Check for argument errors. */ /*============================*/ if ((top->type == FCALL) && GetStaticConstraintChecking()) { if (CheckExpressionAgainstRestrictions(top,theFunction->restrictions,name)) { ReturnExpression(top); return(NULL); } } #if DEFFUNCTION_CONSTRUCT else if (top->type == PCALL) { if (CheckDeffunctionCall(top->value,CountArguments(top->argList)) == CLIPS_FALSE) { ReturnExpression(top); return(NULL); } }#endif /*========================*/ /* Return the expression. */ /*========================*/ return(top); }/*********************************************************************** NAME : ReplaceSequenceExpansionOps DESCRIPTION : Replaces function calls which have multifield references as arguments into a call to a special function which expands the multifield into single arguments at run-time. Multifield references which are not function arguments are errors INPUTS : 1) The expression 2) The current function call 3) The address of the internal CLIPS function (expansion-call) 4) The address of the CLIPS function expand$ RETURNS : FALSE if OK, TRUE on errors SIDE EFFECTS : Function call expressions modified, if necessary NOTES : Function calls which truly want a multifield to be passed need use only a single-field refernce (i.e. ? instead of $? - the $ is being treated as a special expansion operator) **********************************************************************/globle BOOLEAN ReplaceSequenceExpansionOps(actions,fcallexp,expcall,expmult) EXPRESSION *actions,*fcallexp; VOID *expcall,*expmult; { EXPRESSION *exp; while (actions != NULL) { if ((SequenceOpMode == CLIPS_FALSE) && (actions->type == MF_VARIABLE)) actions->type = SF_VARIABLE; if ((actions->type == MF_VARIABLE) || (actions->type == MF_GBL_VARIABLE) || (actions->value == expmult)) { if ((fcallexp->type != FCALL) ? CLIPS_FALSE : (((struct FunctionDefinition *) fcallexp->value)->sequenceuseok == CLIPS_FALSE)) { PrintErrorID("EXPRNPSR",4,CLIPS_FALSE); PrintCLIPS(WERROR,"$ Sequence operator not a valid argument for "); PrintCLIPS(WERROR,ValueToString(((struct FunctionDefinition *) fcallexp->value)->callFunctionName)); PrintCLIPS(WERROR,".\n"); return(TRUE); } if (fcallexp->value != expcall) { exp = GenConstant(fcallexp->type,fcallexp->value); exp->argList = fcallexp->argList; exp->nextArg = NULL; fcallexp->type = FCALL; fcallexp->value = expcall; fcallexp->argList = exp; } if (actions->value != expmult) { exp = GenConstant(SF_VARIABLE,actions->value); if (actions->type == MF_GBL_VARIABLE) exp->type = GBL_VARIABLE; actions->argList = exp; actions->type = FCALL; actions->value = expmult; } } if (actions->argList != NULL) { if ((actions->type == GCALL) || (actions->type == PCALL) || (actions->type == FCALL)) exp = actions; else exp = fcallexp; if (ReplaceSequenceExpansionOps(actions->argList,exp,expcall,expmult)) return(TRUE); } actions = actions->nextArg; } return(FALSE); } /*************************************************//* PushRtnBrkContexts: Saves the current context *//* for the break/return functions. *//*************************************************/globle VOID PushRtnBrkContexts() { SAVED_CONTEXTS *svtmp; svtmp = get_struct(saved_contexts); svtmp->rtn = ReturnContext; svtmp->brk = BreakContext; svtmp->nxt = svContexts; svContexts = svtmp; } /***************************************************//* PopRtnBrkContexts: Restores the current context *//* for the break/return functions. *//***************************************************/globle VOID PopRtnBrkContexts() { SAVED_CONTEXTS *svtmp; ReturnContext = svContexts->rtn; BreakContext = svContexts->brk; svtmp = svContexts; svContexts = svContexts->nxt; rtn_struct(saved_contexts,svtmp); }/*****************************************************************//* CheckExpressionAgainstRestrictions: Compares the arguments to *//* a function to the set of restrictions for that function to *//* determine if any incompatibilities exist. If so, the value *//* TRUE is returned, otherwise FALSE is returned. *//*****************************************************************/globle int CheckExpressionAgainstRestrictions(theExpression,restrictions,functionName) struct expr *theExpression; char *restrictions; char *functionName; { char theChar[2]; int i = 0, j = 1; int number1, number2; int argCount; char defaultRestriction, argRestriction; struct expr *argPtr; int theRestriction; theChar[0] = '0'; theChar[1] = '\0'; /*============================================*/ /* If there are no restrictions, then there's */ /* no need to check the function. */ /*============================================*/ if (restrictions == NULL) return(CLIPS_FALSE); /*=========================================*/ /* Count the number of function arguments. */ /*=========================================*/ argCount = CountArguments(theExpression->argList); /*======================================*/ /* Get the minimum number of arguments. */ /*======================================*/ theChar[0] = restrictions[i++]; if (isdigit(theChar[0])) { number1 = atoi(theChar); } else if (theChar[0] == '*') { number1 = -1; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -