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 + -
显示快捷键?