|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 24479 (0x5f9f)
Types: TextFile
Names: »calc.c«
└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
└─⟦this⟧ »cph85dist/stat/src/calc.c«
# line 2 "calc.y"
/* Copyright (c) 1982 Gary Perlman (see Copyright file) */
static char sccsid[] = "@(#) calc.y 5.0 (unix|stat) 2/26/85";
/* PGM(calc, Algebraic Modeling Calculator) */
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <signal.h>
#define FZERO 10e-10
#define fzero(x) (fabs (x) < FZERO)
#define isvarchar(c) (isalnum (c) || (c) == '_')
#ifndef iscntrl
#define iscntrl(a) ((a)>0&&(a)<26)
#endif
#define OPERATOR 1
#define PARSERROR 1
#define MAXVAR 1000
#define UNDEFINED -99999999999.987654321
int Nvar = 0;
char *Varname[MAXVAR];
char *Exprptr;
int Printequation = 1;
char *Prompt = "CALC: ";
int Interactive = 0;
typedef struct exprnode
{
int nodetype; /* NUMBER, OPERATOR, or VARIABLE */
int operator; /* index of var if a variable, else +/-* */
double *value;
struct exprnode *left;
struct exprnode *right;
} ENODE;
ENODE *Expression, *Variable[MAXVAR];
double eval (), answer;
double *constant;
char *malloc ();
char *getline ();
FILE *outfile = stdout;
# define NUMBER 257
# define VARIABLE 258
# define IF 259
# define THEN 260
# define ELSE 261
# define EQ 262
# define NE 263
# define GE 264
# define LE 265
# define UMINUS 266
# define ABS 267
# define EXP 268
# define LOG 269
# define SQRT 270
# define COS 271
# define TAN 272
# define SIN 273
# define ACOS 274
# define ASIN 275
# define ATAN 276
#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
extern int yychar;
extern short yyerrflag;
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif
#ifndef YYSTYPE
#define YYSTYPE int
#endif
YYSTYPE yylval, yyval;
# define YYERRCODE 256
# line 108 "calc.y"
yylex ()
{
extern int yylval;
char tmpvarname[BUFSIZ];
int i;
while (isspace (*Exprptr)) Exprptr++;
if (begins ("acos", Exprptr)) {Exprptr += 4; return (ACOS);}
if (begins ("asin", Exprptr)) {Exprptr += 4; return (ASIN);}
if (begins ("atan", Exprptr)) {Exprptr += 4; return (ATAN);}
if (begins ("cos", Exprptr)) {Exprptr += 3; return (COS);}
if (begins ("sin", Exprptr)) {Exprptr += 3; return (SIN);}
if (begins ("tan", Exprptr)) {Exprptr += 3; return (TAN);}
if (begins ("log", Exprptr)) {Exprptr += 3; return (LOG);}
if (begins ("sqrt", Exprptr)) {Exprptr += 4; return (SQRT);}
if (begins ("exp", Exprptr)) {Exprptr += 3; return (EXP);}
if (begins ("abs", Exprptr)) {Exprptr += 3; return (ABS);}
if (begins ("if", Exprptr)) {Exprptr += 2; return (IF);}
if (begins ("then", Exprptr)) {Exprptr += 4; return (THEN);}
if (begins ("else", Exprptr)) {Exprptr += 4; return (ELSE);}
if (isdigit (*Exprptr) || *Exprptr == '.')
{
constant = (double *) malloc (sizeof (double));
if (constant == NULL)
errorexit ("Out of storage space");
*constant = atof (Exprptr);
yylval = (int) constant;
/* now skip over the number */
while (isdigit (*Exprptr)) Exprptr++;
if (*Exprptr == '.') Exprptr++;
while (isdigit (*Exprptr)) Exprptr++;
if (*Exprptr == 'E' || *Exprptr == 'e')
{
Exprptr++;
if (*Exprptr == '+' || *Exprptr == '-') Exprptr++;
while (isdigit (*Exprptr)) Exprptr++;
}
return (NUMBER);
}
if (isvarchar (*Exprptr))
{
for (i = 0; isvarchar (Exprptr[i]); i++)
tmpvarname[i] = Exprptr[i];
tmpvarname[i] = NULL;
Exprptr += i;
i = 0;
while (i < Nvar && strcmp (tmpvarname, Varname[i])) i++;
if (i == Nvar)
{
Varname[i] = malloc (strlen (tmpvarname) + 1);
if (Varname[i] == NULL)
errorexit ("Out of storage space");
strcpy (Varname[i], tmpvarname);
if (++Nvar == MAXVAR)
errorexit ("Too many variables");
}
yylval = i;
return (VARIABLE);
}
if (begins ("!=", Exprptr)) { Exprptr += 2; return (NE); }
if (begins (">=", Exprptr)) { Exprptr += 2; return (GE); }
if (begins ("<=", Exprptr)) { Exprptr += 2; return (LE); }
if (begins ("==", Exprptr)) { Exprptr += 2; return (EQ); }
if (begins ("**", Exprptr)) { Exprptr += 2; return ('^'); }
return (*Exprptr++);
}
yyerror (msg)
char *msg;
{
fprintf (outfile, "%s:\n", msg);
fprintf (outfile, "Parsing error. ");
fprintf (outfile, "This is left in input: [%s]\n", Exprptr-1);
}
ENODE *
node (datum, datatype, lson, rson)
int datum; /* pointer to a number or an operator */
int datatype; /* NUMBER or VARIABLE or OPERATOR */
ENODE *lson; /* left part of tree */
ENODE *rson; /* right part of tree */
{
ENODE *newnode;
newnode = (ENODE *) malloc (sizeof (ENODE));
if (newnode == NULL)
errorexit ("Out of storage space");
newnode->nodetype = datatype;
if (datatype == OPERATOR || datatype == VARIABLE)
newnode->operator = datum;
else newnode->value = (double *) datum;
newnode->left = lson;
newnode->right = rson;
return (newnode);
}
main (argc, argv) int argc; char *argv[];
{
int i;
signal (SIGINT, SIG_IGN);
if (isatty (0))
{
Interactive = 1;
printf ("Enter expressions after the prompt '%s'\n", Prompt);
printf ("Quit with ^D, get help with ?\n");
}
for (i = 1; i < argc; i++) process (argv[i]);
process ("-");
if (Interactive) printf ("\015 \015");
exit (0);
}
process (filename) char *filename;
{
char exprline[BUFSIZ];
FILE *ioptr;
if (filename == NULL || (filename[0] == '-' && filename[1] == '\0'))
{
ioptr = stdin;
filename = NULL;
}
else if ((ioptr = fopen (filename, "r")) == NULL)
{
fprintf (stderr, "Can't open %s\n", filename);
return;
}
if (filename) fprintf (outfile, "Reading from %s\n", filename);
for (;;)
{
if (ioptr == stdin && Interactive)
fprintf (outfile, Prompt);
if (!getline (exprline, ioptr)) break;
Exprptr = exprline;
while (isspace (*Exprptr)) Exprptr++;
if (!*Exprptr || *Exprptr == '?')
{
if (filename == NULL && Interactive) printmenu ();
continue;
}
if (iscntrl (*Exprptr))
{
control (Exprptr);
continue;
}
if (yyparse() == PARSERROR)
continue;
if (Printequation || ioptr != stdin)
ptree (outfile, Expression);
if (fzero (answer = eval (Expression)))
answer = 0.0;
if (Printequation)
printf (" =");
if (answer == UNDEFINED)
fprintf (outfile, "\tUNDEFINED\n");
else fprintf (outfile, "\t%g\n", answer);
}
if (ioptr != stdin) fclose (ioptr);
}
printmenu ()
{
puts ("Expressions are in standard C syntax (like algebra).");
puts ("The following CTRL characters have special functions:");
puts ("(You may have to precede the character with a ^V)");
puts ("^D end of input to CALC");
puts ("^P toggles the printing of equations");
puts ("^Rfile reads the expressions from the named file");
puts ("^Wfile writes all expressions to the named file");
puts (" If no file is supplied, then print to the screen");
}
#define CTRL_PRINT 16
#define CTRL_READ 18
#define CTRL_WRITE 23
#define CTRL_VAR 22
control (key) char *key;
{
int var;
FILE *saveoutfile;
switch (*key)
{
case CTRL_PRINT: Printequation = !Printequation; return;
case CTRL_READ: while (iscntrl (*key) || isspace (*key)) key++;
process (key);
return;
case CTRL_WRITE:
case CTRL_VAR:
while (*key && (iscntrl (*key) || isspace (*key)))
key++;
if (*key)
{
fprintf (outfile, "Writing to %s\n", key);
saveoutfile = outfile;
if ((outfile = fopen (key, "a")) == NULL)
{
fprintf (stderr, "Can't open %s\n", key);
outfile = saveoutfile;
}
}
for (var = 0; var < Nvar; var++)
{
fprintf (outfile, "%-10s = ", Varname[var]);
if (outfile == stdout)
{
if (fzero (answer = eval (Variable[var])))
answer = 0.0;
if (answer == UNDEFINED)
fprintf (outfile, " UNDEFINED = ");
else
fprintf (outfile, "%10g = ", answer);
}
ptree (outfile, Variable[var]);
fprintf (outfile, "\n");
}
if (*key)
{
fclose (outfile);
outfile = saveoutfile;
}
return;
default: fprintf (stderr, "Unknown control character.\n");
}
}
double
eval (expression) ENODE *expression;
{
double tmp1, tmp2;
if (expression == NULL) return (UNDEFINED);
if (expression->nodetype == VARIABLE)
if (Variable[expression->operator])
return (eval (Variable[expression->operator]));
else return (UNDEFINED);
if (expression->nodetype == NUMBER)
return (*expression->value);
if ((tmp2 = eval (expression->right)) == UNDEFINED) return (UNDEFINED);
switch (expression->operator)
{
case '_': return (-tmp2);
case LOG: if (tmp2 <= FZERO) return (UNDEFINED);
else return (log (tmp2));
case COS: return (cos (tmp2));
case SIN: return (sin (tmp2));
case TAN: return (tan (tmp2));
case ACOS: return (acos (tmp2));
case ASIN: return (asin (tmp2));
case ATAN: return (atan (tmp2));
case EXP: return (exp (tmp2));
case ABS: return (fabs (tmp2));
case SQRT: if (tmp2 < 0.0) return (UNDEFINED);
else return (sqrt (tmp2));
}
if ((tmp1 = eval (expression->left)) == UNDEFINED) return (UNDEFINED);
switch (expression->operator)
{
case '+': return (tmp1 + tmp2);
case '-': return (tmp1 - tmp2);
case '*': return (tmp1 * tmp2);
case '%': if ((int) tmp2 == 0) return (tmp1);
else return ((double) (((int) tmp1) % ((int) tmp2)));
case '/': if (fzero (tmp2)) return (UNDEFINED);
else return (tmp1/tmp2);
case '^': return (pow (tmp1, tmp2));
case '&': return (!fzero (tmp1) && !fzero (tmp2));
case '|': return (!fzero (tmp1) || !fzero (tmp2));
case '!': return (fzero (tmp1) ? 1.0 : 0.0);
case '>': return (tmp1 > tmp2 ? 1.0 : 0.0);
case '<': return (tmp1 < tmp2 ? 1.0 : 0.0);
case EQ : return (fzero (tmp1 - tmp2) ? 1.0 : 0.0);
case NE : return (!fzero (tmp1 - tmp2) ? 1.0 : 0.0);
case LE : return (tmp1 <= tmp2 ? 1.0 : 0.0);
case GE : return (tmp1 >= tmp2 ? 1.0 : 0.0);
case ':': return (0.0); /* dummy return for ? */
case '?':
if (expression->right->operator == ':')
return (!fzero (tmp1)
? eval (expression->right->left)
: eval (expression->right->right));
else if (!fzero (tmp1)) return (eval (expression->right));
else return (UNDEFINED);
default: fprintf (stderr, "Unknown operator '%c' = %d\n",
expression->operator, expression->operator);
return (UNDEFINED);
}
}
ptree (ioptr, expression) ENODE *expression; FILE *ioptr;
{
if (expression == NULL)
return;
if (expression->nodetype == VARIABLE)
{
fprintf (ioptr, "%s", Varname[expression->operator]);
return;
}
else if (expression->nodetype == NUMBER)
{
if (*expression->value == UNDEFINED)
fprintf (ioptr, "UNDEFINED");
else fprintf (ioptr, "%g", *expression->value);
return;
}
switch (expression->operator)
{
case LOG: fprintf (ioptr, "log("); break;
case ABS: fprintf (ioptr, "abs("); break;
case EXP: fprintf (ioptr, "exp("); break;
case SQRT: fprintf (ioptr, "sqrt("); break;
case ATAN: fprintf (ioptr, "atan("); break;
case ASIN: fprintf (ioptr, "asin("); break;
case ACOS: fprintf (ioptr, "acos("); break;
case TAN: fprintf (ioptr, "tan("); break;
case SIN: fprintf (ioptr, "sin("); break;
case COS: fprintf (ioptr, "cos("); break;
case '_' : putc ('-', ioptr);
ptree (ioptr, expression->right); return;
case '?':
fprintf (ioptr, "(if ");
ptree (ioptr, expression->left);
fprintf (ioptr, " then ");
if (expression->right->operator == ':')
{
ptree (ioptr, expression->right->left);
fprintf (ioptr, " else ");
ptree (ioptr, expression->right->right);
}
else ptree (ioptr, expression->right);
putc (')', ioptr);
return;
default: putc ('(', ioptr);
ptree (ioptr, expression->left);
switch (expression->operator)
{
case EQ: fprintf (ioptr, " == "); break;
case NE: fprintf (ioptr, " != "); break;
case GE: fprintf (ioptr, " >= "); break;
case LE: fprintf (ioptr, " <= "); break;
default: fprintf (ioptr, " %c ",expression->operator);
}
}
ptree (ioptr, expression->right);
putc (')', ioptr);
}
/* Suzanne Shouman fixed a bug here. Thanks */
begins (s1, s2) char *s1, *s2;
{
int alphlag = isvarchar (*s1);
while (*s1)
if (*s1++ != *s2++) return (0);
return (alphlag ? !isvarchar(*s2) : 1);
}
checkrecursion (varno, expr)
int varno; /* look for recursion involving this variable */
ENODE *expr; /* look for recursion of varno in this expr */
{
if (expr == NULL) return (0);
if (expr->nodetype == VARIABLE)
{
if (expr->operator == varno) return (1);
if (checkrecursion (varno, Variable[expr->operator])) return (1);
}
return
(
checkrecursion (varno, expr->left)
||
checkrecursion (varno, expr->right)
);
}
char *
getline (line, ioptr) char *line; FILE *ioptr;
{
register int C;
register char *lptr = line;
while ((C = getc (ioptr)) != '\n' && C != ';' && C != EOF)
*lptr++ = C;
if (C == EOF) return (NULL);
while (C != '\n' && C != EOF) C = getc (ioptr);
*lptr = '\0';
return (line);
}
errorexit (string) char *string;
{
fprintf (stderr, "%s\n", string);
control ("\027calc.save");
fprintf (stderr, "Current state saved in calc.save\n");
exit (1);
}
short yyexca[] ={
-1, 1,
0, -1,
-2, 0,
-1, 58,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 12,
-1, 59,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 13,
-1, 60,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 14,
-1, 61,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 15,
-1, 62,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 16,
-1, 63,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 17,
};
# define YYNPROD 36
# define YYLAST 456
short yyact[]={
7, 25, 5, 23, 32, 37, 1, 3, 22, 20,
0, 21, 6, 24, 0, 23, 0, 0, 0, 0,
22, 20, 23, 21, 71, 24, 29, 22, 31, 34,
23, 32, 24, 0, 0, 22, 20, 0, 21, 0,
24, 23, 32, 0, 0, 68, 22, 20, 0, 21,
0, 24, 0, 29, 0, 31, 34, 0, 0, 0,
25, 0, 0, 0, 29, 0, 31, 34, 23, 32,
0, 0, 25, 22, 20, 0, 21, 0, 24, 25,
0, 0, 0, 0, 0, 0, 0, 25, 0, 0,
33, 29, 0, 31, 34, 23, 32, 0, 25, 0,
22, 20, 0, 21, 0, 24, 23, 32, 0, 0,
0, 22, 20, 0, 21, 0, 24, 33, 29, 0,
31, 0, 0, 0, 0, 25, 0, 0, 33, 29,
0, 31, 0, 23, 32, 0, 0, 0, 22, 20,
0, 21, 0, 24, 0, 0, 0, 0, 0, 0,
0, 0, 25, 0, 23, 33, 29, 0, 31, 22,
20, 0, 21, 25, 24, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 29, 0, 31,
0, 0, 33, 0, 0, 0, 0, 0, 0, 0,
25, 0, 0, 33, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 25, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 19, 4, 8, 35, 26, 27,
30, 28, 0, 0, 17, 16, 15, 18, 12, 14,
13, 9, 10, 11, 0, 0, 0, 0, 0, 0,
0, 0, 0, 70, 35, 26, 27, 30, 28, 0,
0, 0, 0, 0, 0, 35, 26, 27, 30, 28,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 35, 26, 27, 30, 28, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 35,
26, 27, 30, 28, 0, 0, 0, 0, 0, 0,
0, 26, 27, 30, 28, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 26, 27,
30, 28, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 26,
27, 30, 28, 2, 0, 0, 0, 36, 0, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 0, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
0, 69, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 72, 73 };
short yypact[]={
-33,-1000, 31, -33, -56, -33, -33, -33, -33, -33,
-33, -33, -33, -33, -33, -33, -33, -33, -33,-1000,
-33, -33, -33, -33, -33, -33, -33, -33, -33, -33,
-33, -33, -33, -33, -33, -33, 4, -33, 31,-1000,
117, -7,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000, -15, -15, -93, -93, -93, -93, -22, -22,
-22, -22, -22, -22, 117, 96, -34, 69,-1000, 31,
-33, -33, 58, 69 };
short yypgo[]={
0, 6, 383 };
short yyr1[]={
0, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2 };
short yyr2[]={
0, 1, 3, 3, 2, 3, 3, 3, 3, 3,
3, 2, 3, 3, 3, 3, 3, 3, 3, 3,
2, 5, 4, 3, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 1, 1 };
short yychk[]={
-1000, -1, -2, 40, 258, 35, 45, 33, 259, 274,
275, 276, 271, 273, 272, 269, 268, 267, 270, 257,
43, 45, 42, 37, 47, 94, 262, 263, 265, 60,
264, 62, 38, 124, 63, 261, -2, 61, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, 41, -2,
260, 58, -2, -2 };
short yydef[]={
0, -2, 1, 0, 34, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 35,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 4, 11,
20, 0, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 5, 6, 7, 8, 9, 10, -2, -2,
-2, -2, -2, -2, 18, 19, 0, 23, 2, 3,
0, 0, 22, 21 };
#ifndef lint
static char yaccpar_sccsid[] = "@(#)yaccpar 4.1 (Berkeley) 2/11/83";
#endif not lint
#
# define YYFLAG -1000
# define YYERROR goto yyerrlab
# define YYACCEPT return(0)
# define YYABORT return(1)
/* parser for yacc output */
#ifdef YYDEBUG
int yydebug = 0; /* 1 for debugging */
#endif
YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
int yychar = -1; /* current input token number */
int yynerrs = 0; /* number of errors */
short yyerrflag = 0; /* error recovery flag */
yyparse() {
short yys[YYMAXDEPTH];
short yyj, yym;
register YYSTYPE *yypvt;
register short yystate, *yyps, yyn;
register YYSTYPE *yypv;
register short *yyxi;
yystate = 0;
yychar = -1;
yynerrs = 0;
yyerrflag = 0;
yyps= &yys[-1];
yypv= &yyv[-1];
yystack: /* put a state and value onto the stack */
#ifdef YYDEBUG
if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar );
#endif
if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
*yyps = yystate;
++yypv;
*yypv = yyval;
yynewstate:
yyn = yypact[yystate];
if( yyn<= YYFLAG ) goto yydefault; /* simple state */
if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
yychar = -1;
yyval = yylval;
yystate = yyn;
if( yyerrflag > 0 ) --yyerrflag;
goto yystack;
}
yydefault:
/* default state action */
if( (yyn=yydef[yystate]) == -2 ) {
if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
/* look through exception table */
for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
while( *(yyxi+=2) >= 0 ){
if( *yyxi == yychar ) break;
}
if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */
}
if( yyn == 0 ){ /* error */
/* error ... attempt to resume parsing */
switch( yyerrflag ){
case 0: /* brand new error */
yyerror( "syntax error" );
yyerrlab:
++yynerrs;
case 1:
case 2: /* incompletely recovered error ... try again */
yyerrflag = 3;
/* find a state where "error" is a legal shift action */
while ( yyps >= yys ) {
yyn = yypact[*yyps] + YYERRCODE;
if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
yystate = yyact[yyn]; /* simulate a shift of "error" */
goto yystack;
}
yyn = yypact[*yyps];
/* the current yyps has no shift onn "error", pop stack */
#ifdef YYDEBUG
if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
#endif
--yyps;
--yypv;
}
/* there is no state on the stack with an error shift ... abort */
yyabort:
return(1);
case 3: /* no shift yet; clobber input char */
#ifdef YYDEBUG
if( yydebug ) printf( "error recovery discards char %d\n", yychar );
#endif
if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
yychar = -1;
goto yynewstate; /* try again in the same state */
}
}
/* reduction by production yyn */
#ifdef YYDEBUG
if( yydebug ) printf("reduce %d\n",yyn);
#endif
yyps -= yyr2[yyn];
yypvt = yypv;
yypv -= yyr2[yyn];
yyval = yypv[1];
yym=yyn;
/* consult goto table to find next state */
yyn = yyr1[yyn];
yyj = yypgo[yyn] + *yyps + 1;
if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
switch(yym){
case 1:
# line 58 "calc.y"
{ Expression = (ENODE *) yypvt[-0];} break;
case 2:
# line 60 "calc.y"
{ yyval = yypvt[-1]; } break;
case 3:
# line 61 "calc.y"
{
if (checkrecursion (yypvt[-2], (ENODE *) yypvt[-0]))
{
fprintf (stderr, "Can't have recursive definitions\n");
Variable[yypvt[-2]] = NULL;
}
else Variable[yypvt[-2]] = (ENODE *) yypvt[-0];
yyval = yypvt[-0];
} break;
case 4:
# line 70 "calc.y"
{ constant = (double *) malloc (sizeof (double));
if (constant == NULL)
errorexit ("Out of storage space");
*constant = eval ((ENODE *) yypvt[-0]);
yyval = (int) node ((int) constant, NUMBER, NULL, NULL); } break;
case 5:
# line 75 "calc.y"
{ yyval = (int) node ('+', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 6:
# line 76 "calc.y"
{ yyval = (int) node ('-', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 7:
# line 77 "calc.y"
{ yyval = (int) node ('*', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 8:
# line 78 "calc.y"
{ yyval = (int) node ('%', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 9:
# line 79 "calc.y"
{ yyval = (int) node ('/', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 10:
# line 80 "calc.y"
{ yyval = (int) node ('^', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 11:
# line 82 "calc.y"
{ yyval = (int) node ('_', OPERATOR, NULL, yypvt[-0]); } break;
case 12:
# line 83 "calc.y"
{ yyval = (int) node (EQ, OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 13:
# line 84 "calc.y"
{ yyval = (int) node (NE, OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 14:
# line 85 "calc.y"
{ yyval = (int) node (LE, OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 15:
# line 86 "calc.y"
{ yyval = (int) node ('<', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 16:
# line 87 "calc.y"
{ yyval = (int) node (GE, OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 17:
# line 88 "calc.y"
{ yyval = (int) node ('>', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 18:
# line 89 "calc.y"
{ yyval = (int) node ('&', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 19:
# line 90 "calc.y"
{ yyval = (int) node ('|', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 20:
# line 91 "calc.y"
{ yyval = (int) node ('!', OPERATOR, NULL, yypvt[-0]); } break;
case 21:
# line 92 "calc.y"
{ yyval = (int) node ('?', OPERATOR, yypvt[-4],
(int) node (':', OPERATOR, yypvt[-2], yypvt[-0])); } break;
case 22:
# line 94 "calc.y"
{ yyval = (int) node ('?', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 23:
# line 95 "calc.y"
{ yyval = (int) node (':', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 24:
# line 96 "calc.y"
{ yyval = (int) node (ACOS, OPERATOR, NULL, yypvt[-0]); } break;
case 25:
# line 97 "calc.y"
{ yyval = (int) node (ASIN, OPERATOR, NULL, yypvt[-0]); } break;
case 26:
# line 98 "calc.y"
{ yyval = (int) node (ATAN, OPERATOR, NULL, yypvt[-0]); } break;
case 27:
# line 99 "calc.y"
{ yyval = (int) node (COS, OPERATOR, NULL, yypvt[-0]); } break;
case 28:
# line 100 "calc.y"
{ yyval = (int) node (SIN, OPERATOR, NULL, yypvt[-0]); } break;
case 29:
# line 101 "calc.y"
{ yyval = (int) node (TAN, OPERATOR, NULL, yypvt[-0]); } break;
case 30:
# line 102 "calc.y"
{ yyval = (int) node (LOG, OPERATOR, NULL, yypvt[-0]); } break;
case 31:
# line 103 "calc.y"
{ yyval = (int) node (EXP, OPERATOR, NULL, yypvt[-0]); } break;
case 32:
# line 104 "calc.y"
{ yyval = (int) node (ABS, OPERATOR, NULL, yypvt[-0]); } break;
case 33:
# line 105 "calc.y"
{ yyval = (int) node (SQRT, OPERATOR, NULL, yypvt[-0]); } break;
case 34:
# line 106 "calc.y"
{ yyval = (int) node (yypvt[-0], VARIABLE, NULL, NULL); } break;
case 35:
# line 107 "calc.y"
{ yyval = (int) node (yypvt[-0], NUMBER, NULL, NULL); } break;
}
goto yystack; /* stack new state and value */
}