⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exprnpsr.c

📁 clips源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
   /*******************************************************/   /*      "C" Language Integrated Production System      */   /*                                                     */   /*             CLIPS Version 6.24  06/05/06            */   /*                                                     */   /*              EXPRESSION PARSER MODULE               */   /*******************************************************//*************************************************************//* Purpose: Provides routines for parsing expressions.       *//*                                                           *//* Principal Programmer(s):                                  *//*      Gary D. Riley                                        *//*                                                           *//* Contributing Programmer(s):                               *//*      Brian L. Donnell                                     *//*                                                           *//* Revision History:                                         *//*      6.23: Changed name of variable exp to theExp         *//*            because of Unix compiler warnings of shadowed  *//*            definitions.                                   *//*                                                           *//*      6.24: Renamed BOOLEAN macro type to intBool.         *//*                                                           *//*      6.30: Module specifier can be used within an         *//*            expression to refer to a deffunction or        *//*            defgeneric exported by the specified module,   *//*            but not necessarily imported by the current    *//*            module.                                        *//*************************************************************/#define _EXPRNPSR_SOURCE_#include "setup.h"#include <stdio.h>#define _STDIO_INCLUDED_#include <stdlib.h>#include <string.h>#include <ctype.h>#include "constant.h"#include "envrnmnt.h"#include "router.h"#include "strngrtr.h"#include "scanner.h"#include "memalloc.h"#include "argacces.h"#include "prntutil.h"#include "cstrnchk.h"#include "extnfunc.h"#include "exprnpsr.h"#include "modulutl.h"#include "prcdrfun.h"#if DEFRULE_CONSTRUCT#include "network.h"#endif#if DEFGENERIC_CONSTRUCT#include "genrccom.h"#endif#if DEFFUNCTION_CONSTRUCT#include "dffnxfun.h"#endif#if (! RUN_TIME)/***************************************************//* Function0Parse: Parses a function. Assumes that *//*   none of the function has been parsed yet.     *//***************************************************/globle struct expr *Function0Parse(  void *theEnv,  char *logicalName)  {   struct token theToken;   struct expr *top;   /*=================================*/   /* All functions begin with a '('. */   /*=================================*/   GetToken(theEnv,logicalName,&theToken);   if (theToken.type != LPAREN)     {      SyntaxErrorMessage(theEnv,"function calls");      return(NULL);     }   /*=================================*/   /* Parse the rest of the function. */   /*=================================*/   top = Function1Parse(theEnv,logicalName);   return(top);  }/*******************************************************//* Function1Parse: Parses a function. Assumes that the *//*   opening left parenthesis has already been parsed. *//*******************************************************/globle struct expr *Function1Parse(  void *theEnv,  char *logicalName)  {   struct token theToken;   struct expr *top;   /*========================*/   /* Get the function name. */   /*========================*/   GetToken(theEnv,logicalName,&theToken);   if (theToken.type != SYMBOL)     {      PrintErrorID(theEnv,"EXPRNPSR",1,TRUE);      EnvPrintRouter(theEnv,WERROR,"A function name must be a symbol\n");      return(NULL);     }   /*=================================*/   /* Parse the rest of the function. */   /*=================================*/   top = Function2Parse(theEnv,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(  void *theEnv,  char *logicalName,  char *name)  {   struct FunctionDefinition *theFunction;   struct expr *top;   int moduleSpecified = FALSE;   unsigned position;   struct symbolHashNode *moduleName, *constructName;#if DEFGENERIC_CONSTRUCT   void *gfunc;#endif#if DEFFUNCTION_CONSTRUCT   void *dptr;#endif   /*=========================================================*/   /* Module specification cannot be used in a function call. */   /*=========================================================*/   if ((position = FindModuleSeparator(name)) != FALSE)     {       moduleName = ExtractModuleName(theEnv,position,name);      constructName = ExtractConstructName(theEnv,position,name);      moduleSpecified = TRUE;      }   /*================================*/   /* Has the function been defined? */   /*================================*/   theFunction = FindFunction(theEnv,name);#if DEFGENERIC_CONSTRUCT   if (moduleSpecified)     {       if (ConstructExported(theEnv,"defgeneric",moduleName,constructName) ||          EnvGetCurrentModule(theEnv) == EnvFindDefmodule(theEnv,ValueToString(moduleName)))        { gfunc = (void *) EnvFindDefgeneric(theEnv,name); }      else        { gfunc = NULL; }     }   else     { gfunc = (void *) LookupDefgenericInScope(theEnv,name); }#endif#if DEFFUNCTION_CONSTRUCT   if ((theFunction == NULL)#if DEFGENERIC_CONSTRUCT        && (gfunc == NULL)#endif     )     if (moduleSpecified)       {         if (ConstructExported(theEnv,"deffunction",moduleName,constructName) ||            EnvGetCurrentModule(theEnv) == EnvFindDefmodule(theEnv,ValueToString(moduleName)))          { dptr = (void *) EnvFindDeffunction(theEnv,name); }        else          { dptr = NULL; }       }     else       { dptr = (void *) LookupDeffunctionInScope(theEnv,name); }   else     dptr = NULL;#endif   /*=============================*/   /* Define top level structure. */   /*=============================*/#if DEFFUNCTION_CONSTRUCT   if (dptr != NULL)     top = GenConstant(theEnv,PCALL,dptr);   else#endif#if DEFGENERIC_CONSTRUCT   if (gfunc != NULL)     top = GenConstant(theEnv,GCALL,gfunc);   else#endif   if (theFunction != NULL)     top = GenConstant(theEnv,FCALL,theFunction);   else     {      PrintErrorID(theEnv,"EXPRNPSR",3,TRUE);      EnvPrintRouter(theEnv,WERROR,"Missing function declaration for ");      EnvPrintRouter(theEnv,WERROR,name);      EnvPrintRouter(theEnv,WERROR,".\n");      return(NULL);     }   /*=======================================================*/   /* Check to see if function has its own parsing routine. */   /*=======================================================*/   PushRtnBrkContexts(theEnv);   ExpressionData(theEnv)->ReturnContext = FALSE;   ExpressionData(theEnv)->BreakContext = FALSE;#if DEFGENERIC_CONSTRUCT || DEFFUNCTION_CONSTRUCT   if (top->type == FCALL)#endif     {      if (theFunction->parser != NULL)        {         top = (*theFunction->parser)(theEnv,top,logicalName);         PopRtnBrkContexts(theEnv);         if (top == NULL) return(NULL);         if (ReplaceSequenceExpansionOps(theEnv,top->argList,top,FindFunction(theEnv,"(expansion-call)"),                                         FindFunction(theEnv,"expand$")))           {            ReturnExpression(theEnv,top);            return(NULL);           }         return(top);        }     }   /*========================================*/   /* Default parsing routine for functions. */   /*========================================*/   top = CollectArguments(theEnv,top,logicalName);   PopRtnBrkContexts(theEnv);   if (top == NULL) return(NULL);   if (ReplaceSequenceExpansionOps(theEnv,top->argList,top,FindFunction(theEnv,"(expansion-call)"),                                    FindFunction(theEnv,"expand$")))     {      ReturnExpression(theEnv,top);      return(NULL);     }   /*============================================================*/   /* If the function call uses the sequence expansion operator, */   /* its arguments cannot be checked until runtime.             */   /*============================================================*/   if (top->value == (void *) FindFunction(theEnv,"(expansion-call)"))     { return(top); }   /*============================*/   /* Check for argument errors. */   /*============================*/   if ((top->type == FCALL) && EnvGetStaticConstraintChecking(theEnv))     {      if (CheckExpressionAgainstRestrictions(theEnv,top,theFunction->restrictions,name))        {         ReturnExpression(theEnv,top);         return(NULL);        }     }#if DEFFUNCTION_CONSTRUCT   else if (top->type == PCALL)     {      if (CheckDeffunctionCall(theEnv,top->value,CountArguments(top->argList)) == FALSE)        {         ReturnExpression(theEnv,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 H/L function                    (expansion-call)                 4) The address of the H/L 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 intBool ReplaceSequenceExpansionOps(  void *theEnv,  EXPRESSION *actions,  EXPRESSION *fcallexp,  void *expcall,  void *expmult)  {   EXPRESSION *theExp;   while (actions != NULL)     {      if ((ExpressionData(theEnv)->SequenceOpMode == 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) ? FALSE :             (((struct FunctionDefinition *) fcallexp->value)->sequenceuseok == FALSE))           {            PrintErrorID(theEnv,"EXPRNPSR",4,FALSE);            EnvPrintRouter(theEnv,WERROR,"$ Sequence operator not a valid argument for ");            EnvPrintRouter(theEnv,WERROR,ValueToString(((struct FunctionDefinition *)                              fcallexp->value)->callFunctionName));            EnvPrintRouter(theEnv,WERROR,".\n");            return(TRUE);           }         if (fcallexp->value != expcall)           {            theExp = GenConstant(theEnv,fcallexp->type,fcallexp->value);            theExp->argList = fcallexp->argList;            theExp->nextArg = NULL;            fcallexp->type = FCALL;            fcallexp->value = expcall;            fcallexp->argList = theExp;           }         if (actions->value != expmult)           {            theExp = GenConstant(theEnv,SF_VARIABLE,actions->value);            if (actions->type == MF_GBL_VARIABLE)              theExp->type = GBL_VARIABLE;            actions->argList = theExp;            actions->type = FCALL;            actions->value = expmult;           }        }      if (actions->argList != NULL)        {         if ((actions->type == GCALL) ||             (actions->type == PCALL) ||             (actions->type == FCALL))           theExp = actions;         else           theExp = fcallexp;         if (ReplaceSequenceExpansionOps(theEnv,actions->argList,theExp,expcall,expmult))           return(TRUE);        }      actions = actions->nextArg;     }   return(FALSE);  }/*************************************************//* PushRtnBrkContexts: Saves the current context *//*   for the break/return functions.             *//*************************************************/globle void PushRtnBrkContexts(  void *theEnv)  {   SAVED_CONTEXTS *svtmp;   svtmp = get_struct(theEnv,saved_contexts);   svtmp->rtn = ExpressionData(theEnv)->ReturnContext;   svtmp->brk = ExpressionData(theEnv)->BreakContext;   svtmp->nxt = ExpressionData(theEnv)->svContexts;   ExpressionData(theEnv)->svContexts = svtmp;  }/***************************************************//* PopRtnBrkContexts: Restores the current context *//*   for the break/return functions.               *//***************************************************/globle void PopRtnBrkContexts(  void *theEnv)  {   SAVED_CONTEXTS *svtmp;   ExpressionData(theEnv)->ReturnContext = ExpressionData(theEnv)->svContexts->rtn;   ExpressionData(theEnv)->BreakContext = ExpressionData(theEnv)->svContexts->brk;   svtmp = ExpressionData(theEnv)->svContexts;   ExpressionData(theEnv)->svContexts = ExpressionData(theEnv)->svContexts->nxt;   rtn_struct(theEnv,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(  void *theEnv,  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(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     { return(FALSE); }   /*======================================*/   /* Get the maximum number of arguments. */   /*======================================*/   theChar[0] = restrictions[i++];   if (isdigit(theChar[0]))     { number2 = atoi(theChar); }   else if (theChar[0] == '*')     { number2 = 10000; }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -