parse.y

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

Y
787
字号
/* parse.y */

/* Notes on the stacks that have been added.
 * There are two stacks. argStack and varStack.
 * The argStack contains objects of type Argument which you will find in 
 * calc.h.  They contain various bits of information about arguments.
 * The varStack is what is passed to the functions.  It contains pointers
 * to the _actual_ arguments.  This saves much typing when making the wrapper
 * functions. 
 */
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "integer.h"
#include "fun.h"
#include "calc.h"
#include "stack.h"

#define POLYID 'X'
union {
  MPI *mpi;
  POLYI polyi;
} retval;
  

  
 int  rettype; /* 0 for nothing, 1 for MPI, 2 for POLYI, 3 for failure of 
		* function */
 
 int yyparse(void);
 int yylex(void);
 
  
%}

%union {
  MPI *val;  /* actual value */
  POLYI pol;
  Stack argStack;
  MPIA arr;
  Symbol *sym; /* symbol table pointer */
}

%token <val> NUMBER
%token <pol> POL
%token <argStack> ARGSTACK
%token <arr> ANARRAY
%token <sym> ARRAY POLYVAR VAR POLYTERM BLTIN BLTINV BLTINP UNDEF 
%type <val> expr varassign VOID
%type <pol> polyassign polyexpr
%type <arr> arrayassign arraylist
%type <argStack> arguments arglist
%right '=' /*lowest precedence */
%left '+' '-'
%left '*' '/' '%' ','
%right '^' 
%left UNARYMINUS /* highest precedence */
%%
list:
	| list '\n' 
	| list varassign '\n' 
        {  
	  retval.mpi = $2;
	  rettype=RET_MPI;
	}
        | list arrayassign '\n'
        {
	  rettype=RET_MPIA;
	}
        | list expr   '\n' 
        { 
	  
	  retval.mpi = $2;
	  if (!(rettype == FUNC_FAIL)) {
	    PRINTI($2);
	    printf("\n"); 
	  }
	  rettype = RET_MPI;

	}
	| list VOID  '\n' 
        { 
	  rettype=0;
	}
	| list error  '\n' 
        { 
	  yyerrok; 	   
	}
        | list polyexpr '\n' 
        { 
	  retval.polyi=$2;
	  if (!(rettype == FUNC_FAIL)) {
	    PRINTPI($2);
	    printf("\n"); 
	  }
	  rettype=RET_POLY;
	}
        | list polyassign '\n' 
        { 
	  retval.polyi = $2;
	  rettype=RET_POLY;
	};
;
polyassign: POLYVAR '=' polyexpr /* covers case where old variable is 
				  * reassigned */
            {
	      DELETEPI($1->u.sympval);
	      $1->u.sympval=$3;
	      $$ = COPYPI($3);
	    };
          | VAR '=' polyexpr 
            { 
	      if ($1->type == VAR)
		FREEMPI($1->u.symval);
	      $1->u.sympval = $3;
	      $1->type=POLYVAR;
	      $$=COPYPI($3);
	    }
polyexpr: 
          POLYVAR 
          {
	    if ($1->type == UNDEF)
	      execerror("is an undefined variable", $1->name);
	    else if( $1->u.sympval != (POLYI) NULL)
	      $$ = COPYPI($1->u.sympval);
	    else 
	      $$ = (POLYI) NULL;
	  }
        | POLYTERM /* handles the case of just x */
        {
	  MPI *ONE;
	  ONE = ONEI();
	  $$ = NULL;
	  PINSERTPI(1, ONE, &$$, 1);
	  FREEMPI(ONE);
	}
        | expr POLYTERM /*handles the case of cx where c is a constant */
        {
	  $$ = NULL;
	  PINSERTPI(1, $1, &$$, 1);
	  FREEMPI($1);
        }
        | expr POLYTERM "^" expr
          {
	    $$ = NULL;
	    PINSERTPI(CONVERTI($4), $1, &$$,1);
	    FREEMPI($1);
	    FREEMPI($4); 

	  }
        | POLYTERM "^" expr
          {
	    MPI *O;
	    O = ONEI();
	    $$ = NULL;
	    PINSERTPI(CONVERTI($3), O, &$$,1);
	    FREEMPI(O);
	    FREEMPI($3); 
	  }
          | polyassign
          {
	  }
          | polyexpr '+' polyexpr
          {
	    $$ = ADDPI($1,$3);
	    DELETEPI($1);
	    DELETEPI($3);
	  }
/* I may take the following two out later as well */
        | polyexpr '%' polyexpr
        {
	  $$ = MODPI($1,$3);
	  DELETEPI($1);
	  DELETEPI($3);
	    
	}  
        | polyexpr '/' polyexpr
        {
	  $$ = DIVPI($1, $3);
	  DELETEPI($1);
	  DELETEPI($3);
	  } 
	| '-' polyexpr %prec UNARYMINUS 
        {
	  POLYI Z;
	  Z = ZEROPI(); /* returns zero polynomial */
	  $$ = SUBPI(Z, $2);
	  DELETEPI(Z);
	  DELETEPI($2);
	}
        | polyexpr '-' polyexpr
	  {
	    $$ = SUBPI($1, $3);
	    DELETEPI($1);
	    DELETEPI($3);
	  }
	| polyexpr '+' expr
        { 
	  POLYI O, P;
	  O = ONEPI();
	  P = SCALARPI($3, O);
	  $$ = ADDPI($1, P);
	  DELETEPI(O);
	  DELETEPI(P);
	  DELETEPI($1);
	  FREEMPI($3);
	}
	| expr '+' polyexpr
        { 
	  POLYI O, P;
	  O = ONEPI();
	  P = SCALARPI($1, O);
	  $$ = ADDPI($3, P);
	  DELETEPI(O);
	  DELETEPI(P);
	  DELETEPI($3);
	  FREEMPI($1);
	}

	| polyexpr '-' expr
        { 
	  POLYI O, P;
	  O = ONEPI();
	  P = SCALARPI($3, O);
	  $$ = SUBPI($1, P);
	  DELETEPI(O);
	  DELETEPI(P);
	  DELETEPI($1);
	  FREEMPI($3);
	}
	| expr '-' polyexpr
        { 
	  POLYI O, P;
	  O = ONEPI();
	  P = SCALARPI($1, O);
	  $$ = SUBPI(P, $3);
	  DELETEPI(O);
	  DELETEPI(P);
	  DELETEPI($3);
	  FREEMPI($1);
	}
        | expr '*' polyexpr
        {
	  $$ = SCALARPI($1,$3);
	  FREEMPI($1);
	  DELETEPI($3);
	}
	| polyexpr '*' expr 
        {
	  $$ = SCALARPI($3, $1);
	  FREEMPI($3);
	  DELETEPI($1);
	}
        | polyexpr '*' polyexpr
        {
	  $$ = MULTPI($1, $3);
	  DELETEPI($1);
	  DELETEPI($3);
	}
        | polyexpr '^' expr
        {
	  $$ = POWERPI($1, CONVERTI($3));
	  DELETEPI($1);
	  FREEMPI($3);
	}
	| '(' polyexpr ')'		
	{ 
		$$ = $2; 
	}
        | BLTINP arglist
        {
	  Stack varStack;
	  if ((varStack = checkArgs($1))) {
	    $$ = (*($1->u.ptrp))(varStack);
	    stackFree(&varStack);
	  } else {
	    rettype = FUNC_FAIL; /* return failure of function */
	    $$ = NULL;
	  }
	}

/* Note on arrays. To save excessive reallocation an array is
 * initially allocated 11 slots (including zero slot).  However the
 * array size will be set to the value of the first subscript.  This
 * must be remembered when freeing arrays */

arrayassign: ARRAY '[' expr ']' '=' expr 
	   {
	     unsigned n = CONVERTI($3);
	     if ($1->type == UNDEF) {
	       $1->u.symarr = BUILDMPIA();
	       $1->type = ARRAY;
	     }
	     ADD_TO_MPIA($1->u.symarr, $6, n);
	     FREEMPI($3);
	     FREEMPI($6);

	   }
           | ARRAY '[' ']' '=' '{' arraylist
           {
	     if ($1->type != UNDEF) 
	       FREEMPIA($1->u.symarr);
	     $1->u.symarr = $6;
	     $1->type=ARRAY;

           }
arraylist: expr '}'
           {
	     $$ = BUILDMPIA();
	     ADD_TO_MPIA($$, $1, 0);
	     FREEMPI($1);
	   }
           | expr ',' arraylist
           {
	     MPIA_INSERT($3, $1, 0);
	     FREEMPI($1);
	     $$ = $3;
	   };

varassign:	VAR '=' expr
	{
		if($1->type!=UNDEF && $1->u.symval != NULL)
			FREEMPI($1->u.symval);		  
		$1->u.symval=$3;
		if ( $1->u.symval != (MPI *) NULL)
			$$ = COPYI($1->u.symval);
		else
  			$$ = (MPI *) NULL;
		$1->type = VAR; 
	};
expr:	NUMBER	
        {  
	  $$ = $1; 
	}
        | VAR                   
	{
	  if ($1->type == UNDEF)
			execerror("is an undefined variable", $1->name);
		else 
		  $$ = COPYI($1->u.symval);
	}
/* I may remove this.  This allows one to evaluate a polynomial expression
 * simply by placing a set of brackets after the expression and placing
 * a value within it 
 * eg. 3x^4(1) = 3.
*/
        | polyexpr '(' expr ')'  
        {
	  $$ = VALPI($1, $3);
	  FREEMPI($3);
	  DELETEPI($1);
	}
        | POLYVAR '(' expr ')'
        {
	  $$ = VALPI($1->u.sympval, $3);
	  FREEMPI($3);
	}
	| ARRAY '[' expr ']'    
	{
	  int ind;
		if ($1->type == UNDEF)
		{
			FREEMPI($3);
			execerror("[] is an undefined array", $1->name);
		}
		ind = (int)CONVERTI($3);
		if(ind >= $1->u.symarr->size)
		{
			FREEMPI($3);
			execerror("array is too small", $1->name);
		}
		$$ = COPYI($1->u.symarr->A[ind]);
		FREEMPI($3);
	}
	| varassign
        {
	}
	| expr '+' expr	
	{
		 $$ = ADDI($1, $3);
		 FREEMPI($1);
		 FREEMPI($3);
	}
	| expr '-' expr		
	{ 
		$$ = SUBI($1, $3);
		FREEMPI($1);
		FREEMPI($3);
	}
	| expr '*' expr
	{
		$$ = MULTI($1, $3);

⌨️ 快捷键说明

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