/* The lexical analyser */ #include "evalint.h" #include "symbol.h" #include #include #include #include "support.h" /* For predefined constants, eg pi, e */ /* A non-ansi construction ... */ #define SYMCST(cst, val) if (strcmp(symbuf, "cst") == 0) { symbol.type = cste; symbol.cte = (val); } static char *expr; struct _value symbol; enum symbol_type symbol_type; /* Set string to analyse */ void init_symbol(_expr) char *_expr; { expr = _expr; } /* convert an integer string to a double */ /* returns nb of chars converted */ static int cvt_integer(_str, nb) char *_str; double *nb; { register char *str = _str; *nb = 0.0; while (isdigit(*str)) *nb = 10.0 * *nb + (double)(*str++ - '0'); return(str - _str); } /* cvt a double to a nb */ static int cvt_double(_str, nb) char *_str; double *nb; { double val, dec, exponent; register int l; register char *str = _str; if ((l = cvt_integer(str, &val)) == 0) return(0); else { str += l; /* fractional part */ if (*str == '.') { str++; l = cvt_integer(str, &dec); if (l) { str += l; val += dec * pow(10.0, (double)-l); } } /* exponent */ if (toupper(*str) == 'E') { str++; if ((l = cvt_integer(str, &exponent)) == 0) return(0); else { str += l; val *= pow(10.0, exponent); } } *nb = val; return(str - _str); } } /* extract next symbol as a number */ static void advance_number() { double nb; register int l; if ((l = cvt_double(expr, &nb)) == 0) { symbol_type = s_error; } else { symbol_type = s_value; expr += l; symbol.type = cste; symbol.cte = nb; } } /* next symbol is a keyword */ static void advance_var() { static char symbuf[100]; register onefunc *f; symbol_type = s_value; expr = stpsym(expr, symbuf, 100); strlwr(symbuf); f = locate_name(symbuf); if (f) /* this is a predefined function */ { symbol.type = fonc; symbol.fn.func = f->func; } else SYMCST(pi, PI) /* check for pi */ else SYMCST(e, E) /* check for e */ else /* it's a variable */ { symbol.type = var; symbol.vr.name = symbuf; } } /* Read next symbol */ void advance() { expr = stpblk(expr); /* skip blanks */ switch (*expr) { case '\0': symbol_type = s_none; break; case '(': symbol_type = s_left; expr++; break; case ')': symbol_type = s_right; expr++; break; case '+': symbol_type = s_value; symbol.type = op; symbol.opr.op = plus; expr++; break; case '-': symbol_type = s_value; symbol.type = op; symbol.opr.op = minus; expr++; break; case '*': symbol_type = s_value; symbol.type = op; symbol.opr.op = times; expr++; break; case '/': symbol_type = s_value; symbol.type = op; symbol.opr.op = divide; expr++; break; case '^': symbol_type = s_value; symbol.type = op; symbol.opr.op = power; expr++; break; default: if (isdigit(*expr)) advance_number(); else if (isalpha(*expr)) advance_var(); else symbol_type = s_error; break; } }