/* tokeniser.c
* geg, a GTK+ Equation Grapher
* David Bryant 1998
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <string.h>
#include <math.h>
#include "tokeniser.h"
#include "localfunctions.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */
#ifndef M_E
#define M_E 2.7182818284590452354
#endif /* M_E */
#define NUMBER(c) (((c) >= '0') && ((c) <= '9'))
typedef struct {
char *string; /* the identifier string in the equation */
gint type; /* eg NUM, FUN */
double value; /* used if it is a number or a constant */
Func func; /* the address of the unary function to call */
} token_db;
static gint compare(token_db *a, gchar *b);
/* these must be in descending order of string length */
static token_db tokens[] =
{ { "arcsin", FUN, 0, asin },
{ "arccos", FUN, 0, acos },
{ "arctan", FUN, 0, atan },
{ "arccsc", FUN, 0, l_acsc },
{ "arcsec", FUN, 0, l_asec },
{ "arccot", FUN, 0, l_acot },
{ "asin", FUN, 0, asin },
{ "acos", FUN, 0, acos },
{ "atan", FUN, 0, atan },
{ "acsc", FUN, 0, l_acsc },
{ "asec", FUN, 0, l_asec },
{ "acot", FUN, 0, l_acot },
{ "sinc", FUN, 0, l_sinc },
{ "sinh", FUN, 0, sinh },
{ "cosh", FUN, 0, cosh },
{ "tanh", FUN, 0, tanh },
{ "cbrt", FUN, 0, l_cbrt },
{ "sqrt", FUN, 0, sqrt },
{ "sin", FUN, 0, sin, },
{ "cos", FUN, 0, cos, },
{ "tan", FUN, 0, tan, },
{ "csc", FUN, 0, l_csc, },
{ "sec", FUN, 0, l_sec, },
{ "cot", FUN, 0, l_cot, },
{ "log", FUN, 0, log10 },
{ "abs", FUN, 0, fabs },
{ "ln", FUN, 0, log },
{ "pi", NUM, M_PI, NULL },
{ "u", FUN, 0, l_u },
{ "e", NUM, M_E, NULL },
{ "+", ADD, 0, NULL },
{ "-", SUB, 0, NULL },
{ "*", MUL, 0, NULL },
{ "/", DIV, 0, NULL },
{ "^", POW, 0, NULL },
{ "[", LSB, 0, NULL },
{ "]", RSB, 0, NULL },
{ "{", LCB, 0, NULL },
{ "}", RCB, 0, NULL },
{ "(", LB, 0, NULL },
{ ")", RB, 0, NULL },
{ "x", X, 0, NULL },
{ "", EOE, 0, NULL } };
/* compare, */
static gint
compare(token_db *a, gchar *b)
{
if((*a->string == '\0') ^ (*b == '\0'))
return(0);
else
return(!strncasecmp(a->string, b, strlen(a->string)));
}
/* make_token_list, this function builds a token list out of the equation
*/
token_list *
make_token_list(gchar *equation)
{
gint i;
token_list *list;
list = (token_list *)g_new(token_list, 1);
/* skip any whitespace */
while(*equation == ' ')
equation++;
/* check for the token in the token database */
for(i = 0; i < (sizeof(tokens) / sizeof(token_db)); i++) {
if(compare(&tokens[i], equation))
{
list->type = tokens[i].type;
list->value = tokens[i].value;
list->func = tokens[i].func;
equation += strlen(tokens[i].string);
if(list->type != EOE)
list->next = make_token_list(equation);
else
list->next = NULL;
return(list);
}
}
/* if it wasn't in the token database, it's either a number, or the token */
/* can't be recognised and is therefore an error */
if(NUMBER(*equation)) {
list->type = NUM;
list->value = 0;
while(NUMBER(*equation)) {
list->value = list->value * 10 + *equation++ - '0';
}
if(*equation == '.') { /* a real number */
equation++;
i = 0; /* use i to count the decimal places */
while(NUMBER(*equation))
list->value += (*equation++ - '0') * pow(10, --i);
}
list->next = make_token_list(equation);
return(list);
}
else { /* it's an error .. */
list->type = ERROR;
list->value = 0;
list->next = NULL;
return(list);
}
}
/* free_list, a recursive list freeing algorithm
*/
void free_list(token_list *list)
{
if(list->next != NULL)
free_list(list->next);
g_free(list);
}
syntax highlighted by Code2HTML, v. 0.9.1