parse.y

来自「calc大数库」· Y 代码 · 共 787 行 · 第 1/2 页

Y
787
字号
		FREEMPI($1);
		FREEMPI($3);
	}
	| expr '/' expr		
	{
	        if(($3)->S <= 0)
		{
			FREEMPI($1);
			FREEMPI($3);
			execerror(" divisor <= 0", "");
		}
		$$ = INTI($1, $3);
		FREEMPI($1);
		FREEMPI($3);
	}
	| expr '%' expr		
	{
	        if(($3)->S <= 0)
		{
			FREEMPI($1);
			FREEMPI($3);
			execerror(" divisor <= 0", "");
		}
		$$ = MOD($1, $3);
		FREEMPI($1);
 	        FREEMPI($3);
	}
	| expr '^' expr		
	{ 
		if (($3)->S < 0)
		{
			FREEMPI($1);
			FREEMPI($3);
			execerror("negative exponent", "");
		}
		if (($3)->D > 0)
		{
			FREEMPI($1);
			FREEMPI($3);
			execerror("exponent >= R0", "");
		}
		$$ = POWERI($1, (unsigned int)(CONVERTI($3))); 
 		FREEMPI($1);
		FREEMPI($3);
	}
	| '-' expr %prec UNARYMINUS 
	{
		$$ = MINUSI($2); 
		FREEMPI($2);
	}
	| '(' expr ')'		
	{ 
		$$ = $2; 
	}
        | BLTIN arglist 
        {        
	  Stack varStack;
	  if ((varStack = checkArgs($1))) {
	    $$ = (*($1->u.ptr))(varStack);
	    stackFree(&varStack);
	  } else {
	    $$ = NULL;
	    rettype = FUNC_FAIL;
	  }
	};


VOID:	BLTINV arglist
        {
	  Stack varStack;
	  if ((varStack = checkArgs($1))) {
	    (*($1->u.ptrv))(varStack);
	    stackFree(&varStack);
	  } else {
	    rettype = FUNC_FAIL;
	  }
	}
        | ARRAY '[' ']'
        { 
	  if ($1->type != UNDEF){
	    PRINTIA($1->u.symarr);
	  } else {
	    execerror("undefined array", $1->name );
	  }
	};
         
arglist: '(' ')'
       {
       }
       | '(' arguments
       {
       };


arguments:  expr ')'
         {
	   stackPush(argStack, createArg($1, NUM, 0));
         }
         | polyexpr ')'
         {
	   stackPush(argStack, createArg($1, POLY, 0));
         }
         |  ARRAY '[' ']' ')'
         {
	   if ($1->type != UNDEF) {
	     stackPush(argStack, createArg($1, ARR, 0));
	   } else {
	     execerror("[] is an undefined array", $1->name);
	     rettype = FUNC_FAIL;
	   }
         }
         | '&' ARRAY '[' ']' ')'
         {

	   /* S.Seefried.  Normally one would free an old array if it 
	    * existed.  I have deferred this until I am sure all arguments
	    * on the command line are valid for the function in question.
	    * See checkArgs.  It is here that I free. */
	   if ($2->type != UNDEF)
	     stackPush(argStack, createArg($2, ARRADR, 1));	     
	   else
	     stackPush(argStack, createArg($2, ARRADR, 0));
	   $2->type=ARRAY;
         }
         | '&' VAR ')'
         {

	   if ($2->type != UNDEF) 
	     stackPush(argStack, createArg($2, VARADR, 1));	     
	   else
	     stackPush(argStack, createArg($2, VARADR, 0));
	   $2->type=VAR;
	 }

         | '&' VAR ',' arguments
         {
	   if ($2->type != UNDEF) 
	     stackPush(argStack, createArg($2, VARADR, 1));	     
	   else
	     stackPush(argStack, createArg($2, VARADR, 0));
	   $2->type=VAR;
	 }
         | expr ',' arguments
         {
	   stackPush(argStack, createArg($1, NUM, 0));
         }
         | polyexpr ',' arguments
         {
	   stackPush(argStack, createArg($1, POLY, 0));
         }
         |  ARRAY '[' ']' ',' arguments
         {
	   if ($1->type != UNDEF) {
	     stackPush(argStack, createArg($1, ARR, 0));
	   } else {
	     rettype = FUNC_FAIL;
	   }
         }
         | '&' ARRAY '[' ']' ',' arguments
         {
	   /* S.Seefried.  Normally one would free an old array if it 
	    * existed.  I have deferred this until I am sure all arguments
	    * on the command line are valid for the function in question.
	    * See checkArgs.  It is here that I free. */

	   if ($2->type != UNDEF) 
	     stackPush(argStack, createArg($2, ARRADR, 1));	     
	   else
	     stackPush(argStack, createArg($2, ARRADR, 0));
	   $2->type=ARRAY;
	 };

%%

static char *p;

 static Stack argStack =NULL;


void Parse(s)
char *s;
{
	p = s;
	argStack = stackNew();
	yyparse();
	switch (rettype) {
	case RET_MPI: 
	  FREEMPI(retval.mpi); 
	  break;
	case RET_POLY: 
	  DELETEPI(retval.polyi); 
	  break;

	}
	rettype=RET_NULL; 
	stackFree(&argStack);

	
}
/* Checks if the arguments contained in the source stack match the arguments 
 * of the function whose information is stored in the supplied symbol. 
 * If the arguments match then the function returns a variable stack that 
 * can be sent straight to a wrapper function (see note at top of file)
 * If the arguments do not match then an error message is printed, and the
 * function returns NULL. 
 * Regardless of whether the match is successful or not, all the arguments on
 * the globar variable argStack are popped, leaving an empty stack.
 */

Stack checkArgs(Symbol *s)
{
  Stack varStack=stackNew();
  Stack tmpStack=stackNew();
  int *argTypes = s->argTypes;
  int nArgs=argTypes[0];
  int quitFlag=0;
  int i;
  Argument Arg=NULL;
  for (i=1; ; i++) {
    if (i > nArgs && stackEmpty(argStack))
      break;
    if (!stackEmpty(argStack))
      Arg = stackPop(argStack);
    else 
      quitFlag = 1; /* This means there are too few arguments sent to this
		     * function */

    
    /* oh no! we quit if this is true */
    if (quitFlag == 1 || Arg->type != argTypes[i]) { /* short circuit eval! */
      int j;
      /* pop all entries off argument stack */
      if (!quitFlag) { /* only free these if the reason we are exiting is 
			* that there are too few Arguments */
	freeArg(Arg);
	while (!stackEmpty(argStack)) {
	  Arg = stackPop(argStack);
	  freeArg(Arg); 
	}
      }
      /* pop all entries off stack to be returned 
       * It is helpful that i contains a value one greater than the number
       * of elements on the stack to be returned. */
      while (!stackEmpty(tmpStack)) {
	Arg = stackPop(tmpStack);
	switch(Arg->type) {
	case NUM:
	  FREEMPI(Arg->u.num);
	  break;
	case POLY:
	  DELETEPI(Arg->u.poly);
	  break;
	  /* we do not free arrays, array address or variable addresses */
	}
      }
      
      printf("This function has the format: %s(", s->name);
      if (nArgs > 0) {
	for (j=1;j<=nArgs;j++) {
	  switch(argTypes[j]) {
	  case NUM: 
	    printf("number");
	    break;
	  case VARADR:
	    printf("&var");
	    break;
	  case ARR: 
	    printf("array[]");
	    break;
	  case ARRADR: 
	    printf("&array[]");
	    break;
	  case POLY: 
	    printf("poly");
	    break;
	  }
	  if (j!=nArgs) 
	    printf(", ");
	  else
	    printf(")\n");
	}
      } else 
	printf(")\n");

      stackFree(&tmpStack);
      return NULL;
    }
    stackPush(tmpStack, Arg); /* put it back in the stack. in reverse order */

  }

  while (!stackEmpty(tmpStack)) {
    Arg = stackPop(tmpStack);
    switch(Arg->type) {
    case NUM: 
      stackPush(varStack, Arg->u.num);
      break;
    case VARADR:
      if ( Arg->defined == 1) /* if the variable has previously been assigned.
			       */
	FREEMPI(*(Arg->u.varAdr));
      stackPush(varStack, Arg->u.varAdr);
      break;
    case ARR:
      stackPush(varStack, Arg->u.array);
      break;
    case ARRADR:
      if ( Arg->defined == 1) /* if the variable has previously been assigned.
			       */
	FREEMPIA(*(Arg->u.arrayAdr));

      stackPush(varStack, Arg->u.arrayAdr);
      break;
    case POLY:
      stackPush(varStack, Arg->u.poly);
      break;
    }
  }
  stackFree(&tmpStack);
  return varStack;
}

int yylex()
{
	MPI *Temp;
	char c;
	int typ;

	while ((c = *p++) == ' ' || c == '\t')
		;
	if (c == '\0')
		return 0;
	if (isdigit((int)c))
	{
		yylval.val = CHANGE((USL)(c - '0'));
		while (isdigit((int)*p))
		{
		  Temp = yylval.val;
		  yylval.val = MULT_I(yylval.val, 10L);
		  FREEMPI(Temp);
		  Temp = yylval.val;
		  yylval.val = ADD0_I(yylval.val, (USL)(*p++ - '0'));
		  FREEMPI(Temp);
		}
		return NUMBER;
	}
	p--;
	if ( isalpha((int)c))
	{
		Symbol *s;
		char sbuf[100], *tmp = sbuf;

		do {
			*tmp++ = *p;
			p++;
			c=(*p);
		} while (c && isalnum((int)c));
		*tmp = '\0';
		if(c=='[')
		  typ=ARRAY;
		else if ( (c=='^' && *(tmp-1) == POLYID && (tmp-1) == sbuf ) ||
			  (*(p-1)==POLYID && strlen(sbuf) == 1 )) {
		  return POLYTERM; /* don't want to install this */
		} else
		  typ=VAR;
		s = lookup(sbuf,typ);
		if (s == NULL)
		  s = lookup(sbuf, BLTIN);
		if (s == NULL)
		  s = lookup(sbuf, BLTINV);
		if (s == NULL)
		  s = lookup(sbuf, BLTINP);
		if (s == NULL) 
		  s = lookup(sbuf,POLYVAR);
		if (s == NULL) 
		  s = install(sbuf, UNDEF);
		yylval.sym = s;
		if (s->type == UNDEF) 
		  return(typ);
		else 
		  return (s->type);
		
	}
	p++;
	return (int)c; /* returns +, -, ^, *, / etc */
}

void yyerror(s)
char *s;
{
	warning(s,"");
}

⌨️ 快捷键说明

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