home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 4
/
FreshFish_May-June1994.bin
/
bbs
/
mar94
/
os20
/
util
/
mcalc.lha
/
MCalc
/
Source
/
Parser.y
< prev
next >
Wrap
Text File
|
1993-12-31
|
8KB
|
281 lines
%{
/*
Auto: smake MCalc
*/
static void __yy_bcopy(char *from, char *to, int count);
#undef alloca
#define alloca(x) AllocVecPool(ParsePool, x)
#undef malloc
#define malloc(x) AllocVecPool(ParsePool, x)
#undef free
#define free(x) FreeVecPool(ParsePool, x)
#undef YYINITDEPTH
#define YYINITDEPTH 512
#undef _STDC_
#define _STDC_
#undef error
#define error
extern APTR ParsePool;
extern double Value;
extern double XMem, YMem, ZMem;
#define outputr(x) {Value = x;}
#define outputx(x) {Value = XMem = x;}
#define outputy(x) {Value = YMem = x;}
#define outputz(x) {Value = ZMem = x;}
#define errout(x) ;
#define erroutm(x, y) ;
/**********************************************************************/
/* Chars read and read-position */
/**********************************************************************/
extern UWORD PColumn;
extern UWORD PCharRead;
// This is for the wanted angle
extern UWORD IntAngle;
/**********************************************************************/
/* Error-Value */
/**********************************************************************/
UWORD PError;
%}
/**********************************************************************/
/* Possible Return-Value */
/**********************************************************************/
%union
{
double Real;
}
/**********************************************************************/
/* Token which returns Real */
/**********************************************************************/
%token <Real> INT_CONSTANT
%token <Real> X_MEM Y_MEM Z_MEM
/**********************************************************************/
/* Non-Priority functions */
/**********************************************************************/
%token EQU_OP OPEN_OP CLOSE_OP
/**********************************************************************/
/* Set priorities */
/**********************************************************************/
%left AND_OP OR_OP XOR_OP ASL ASR LSL LSR ROL ROR
%left ADD_OP SUB_OP
%left MUL_OP DIV_OP MOD_OP
%left NEG_OP NOT_OP
%left POW
%nonassoc MY_ABS COS SIN TAN ACOS ASIN ATAN EXP LOG LOG10 SQRT SINH COSH TANH FAK COT
/**********************************************************************/
/* Return-Value of my terminal */
/**********************************************************************/
%type <Real> int_expr
%%
/**********************************************************************/
/* Main "sentence" */
/**********************************************************************/
eingabe
: int_expr {outputr($1);}
| X_MEM EQU_OP int_expr {outputx($3);}
| Y_MEM EQU_OP int_expr {outputy($3);}
| Z_MEM EQU_OP int_expr {outputz($3);}
| error
;
/**********************************************************************/
/* Do the grammar */
/**********************************************************************/
int_expr
: OPEN_OP int_expr CLOSE_OP {$$ = $2;}
| int_expr AND_OP int_expr {$$ = (make_ulong($1)) & (make_ulong($3));}
| int_expr OR_OP int_expr {$$ = (make_ulong($1)) | (make_ulong($3));}
| int_expr XOR_OP int_expr {$$ = MyXOR(make_ulong($1),make_ulong($3));}
| int_expr NOT_OP AND_OP int_expr {$$ = MyNAND(make_ulong($1), make_ulong($4));}
| int_expr NOT_OP OR_OP int_expr {$$ = MyNOR(make_ulong($1), make_ulong($4));}
| int_expr NOT_OP XOR_OP int_expr {$$ = MyNXOR(make_ulong($1), make_ulong($4));}
| int_expr ADD_OP int_expr {$$ = $1 + $3;}
| int_expr SUB_OP int_expr {$$ = $1 - $3;}
| int_expr MUL_OP int_expr {$$ = $1 * $3;}
| int_expr DIV_OP int_expr {if($3 == 0.0) {PError = ERR_DIVBY0; yyerror(NULL); } else $$ = $1 / $3;}
| int_expr MOD_OP int_expr {if($3 == 0.0) {PError = ERR_DIVBY0; yyerror(NULL); } else $$ = fmod($1,$3);}
| SUB_OP int_expr %prec NEG_OP {$$ = -$2; }
| NOT_OP int_expr {$$ = (~make_ulong($2)); }
| int_expr ASL int_expr {$$ = (double)MyASL(make_ulong($1),make_ulong($3)); }
| int_expr ASR int_expr {$$ = (double)MyASR(make_ulong($1),make_ulong($3)); }
| int_expr LSL int_expr {$$ = (double)MyLSL(make_ulong($1),make_ulong($3)); }
| int_expr LSR int_expr {$$ = (double)MyLSR(make_ulong($1),make_ulong($3)); }
| int_expr ROL int_expr {$$ = (double)MyROL(make_ulong($1),make_ulong($3)); }
| int_expr ROR int_expr {$$ = (double)MyROR(make_ulong($1),make_ulong($3)); }
| int_expr POW int_expr {$$ = pow($1,$3); }
| SIN int_expr {$$ = sin(calc_angle($2)); }
| COS int_expr {$$ = cos(calc_angle($2)); }
| TAN int_expr {if(!check_angle($2, TAN)) yyerror(NULL); else $$ = tan(calc_angle($2)); }
| ASIN int_expr {if(!check_angle($2, ASIN)) yyerror(NULL); else $$ = asin(calc_angle($2)); }
| ACOS int_expr {if(!check_angle($2, ACOS)) yyerror(NULL); else $$ = acos(calc_angle($2)); }
| ATAN int_expr {if(!check_angle($2, ATAN)) yyerror(NULL); else $$ = atan(calc_angle($2)); }
| COT int_expr {if(!check_angle($2, COT)) yyerror(NULL); else $$ = cot(calc_angle($2)); }
| SINH int_expr {$$ = sinh(calc_angle($2)); }
| COSH int_expr {$$ = cosh(calc_angle($2)); }
| TANH int_expr {if(!check_angle($2, TANH)) yyerror(NULL); else $$ = tanh(calc_angle($2)); }
| EXP int_expr {$$ = exp($2); }
| LOG int_expr {$$ = log($2); }
| LOG10 int_expr {$$ = log10($2); }
| MY_ABS int_expr {$$ = fabs($2); }
| SQRT int_expr {if($2 < 0.0) {PError = ERR_OVERFLOW; yyerror(NULL); } else $$ = sqrt($2);}
| int_expr FAK {if($1 > 170.0) { PError = ERR_OVERFLOW; yyerror(NULL); } else $$ = calc_fak($1);}
| FAK int_expr {if($2 > 170.0) { PError = ERR_OVERFLOW; yyerror(NULL); } else $$ = calc_fak($2);}
| INT_CONSTANT
| X_MEM
| Y_MEM
| Z_MEM
;
%%
/**********************************************************************/
/* Convert a double to a long (the hard way) */
/**********************************************************************/
ULONG make_ulong(double OldVal)
{
char Buffer[26];
ULONG Dummy;
sprintf(Buffer, "%f", OldVal);
stcd_l(Buffer, (LONG *)&Dummy);
return(Dummy);
}
/**********************************************************************/
/* Calculate Fak */
/**********************************************************************/
double calc_fak(double Fak)
{
double RetVal = 1.0, i = 1.0;
while(i <= Fak)
{
RetVal *= i;
i++;
}
return(RetVal);
}
/**********************************************************************/
/* Calculate correct angle value (rad, deg) */
/**********************************************************************/
double calc_angle(double Value)
{
if(IntAngle == ID_DEG)
Value = Value / 180.0 * PI;
return(Value);
}
/**********************************************************************/
/* Check if input is within bounds */
/**********************************************************************/
BOOL check_angle(double Value, int Mode)
{
Value = calc_angle(Value);
switch(Mode)
{
case TAN :
case TANH :
{
if(Value < -(PI / 2) || Value > (PI / 2))
{
PError = ERR_OVERFLOW;
return(FALSE);
}
}
case COT :
{
if(Value < -PI || Value > PI)
{
PError = ERR_OVERFLOW;
return(FALSE);
}
}
case ASIN :
case ACOS :
{
if(Value < -1.0 || Value > 1.0)
{
PError = ERR_OVERFLOW;
return(FALSE);
}
break;
}
case ATAN :
{
if(Value <= -1.0 || Value >= 1.0)
{
PError = ERR_OVERFLOW;
return(FALSE);
}
break;
}
}
return(TRUE);
}
/**********************************************************************/
/* Error-Routine ;) */
/********************************