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