forked from enlightenment/equate
184 lines
3.6 KiB
Plaintext
184 lines
3.6 KiB
Plaintext
%{
|
|
#include <math.h> /* For math functions, cos(), sin(), etc. */
|
|
#include "calc.h"
|
|
#include "Equate.h"
|
|
|
|
#define YYERROR_VERBOSE
|
|
|
|
void
|
|
yyerror (const char *s);
|
|
int
|
|
yylex();
|
|
|
|
double _result;
|
|
char tmp[BUFLEN];
|
|
|
|
%}
|
|
%union {
|
|
double val; /* For returning numbers. */
|
|
symrec *tptr; /* For returning symbol-table pointers */
|
|
}
|
|
|
|
%token <val> NUM /* Simple double precision number */
|
|
%token <tptr> VAR FNCT /* Variable and Function */
|
|
%type <val> exp
|
|
|
|
%token OBRAK
|
|
%token CBRAK
|
|
|
|
%right '='
|
|
%left '-' '+'
|
|
%left '*' '/'
|
|
%left NEG /* Negation--unary minus */
|
|
%right '^' /* Exponentiation */
|
|
|
|
/* Grammar follows */
|
|
|
|
%%
|
|
|
|
input: /* empty string */
|
|
| exp { E(2, "result:\t%.10g\n", $1); _result = $1;}
|
|
;
|
|
|
|
exp: NUM { $$ = $1; }
|
|
| VAR { $$ = $1->value.var; }
|
|
| VAR '=' exp { $$ = $3; $1->value.var = $3; }
|
|
| FNCT OBRAK exp CBRAK { $$ = (*($1->value.fnctptr))($3); }
|
|
| exp '+' exp { $$ = $1 + $3; }
|
|
| exp '-' exp { $$ = $1 - $3; }
|
|
| exp '*' exp { $$ = $1 * $3; }
|
|
| exp '/' exp { $$ = $1 / $3; }
|
|
| '-' exp %prec NEG { $$ = -$2; }
|
|
| exp '^' exp { $$ = pow ($1, $3); }
|
|
| OBRAK exp CBRAK { $$ = $2; }
|
|
;
|
|
/* End of grammar */
|
|
%%
|
|
#include "calc_lex.c"
|
|
|
|
static Eina_Bool yyerror_found;
|
|
|
|
void
|
|
yyerror(const char *s)
|
|
{ /* Called by yyparse on error */
|
|
yyerror_found = EINA_TRUE;
|
|
printf("%s\n", s);
|
|
}
|
|
|
|
double
|
|
yyresult(void)
|
|
{
|
|
return _result;
|
|
}
|
|
|
|
void
|
|
equate_clear(void)
|
|
{
|
|
yyerror_found = EINA_FALSE;
|
|
yy_scan_string("0");
|
|
yyparse();
|
|
tmp[0] = '\0';
|
|
}
|
|
|
|
int
|
|
equate_append(char *str)
|
|
{
|
|
int len, slen, ret;
|
|
|
|
ret = 0;
|
|
if (tmp[0] == '\0') {
|
|
if ((*str == '+') || (*str == '-') || (*str == '*') || (*str == '/')) {
|
|
sprintf(tmp, "%.10g", _result);
|
|
ret = 1;
|
|
}
|
|
}
|
|
len = strlen(tmp);
|
|
slen = strlen(str);
|
|
memcpy(&tmp[len], str, slen);
|
|
tmp[len + slen] = '\0';
|
|
|
|
return ret;
|
|
}
|
|
|
|
double
|
|
equate_eval(void)
|
|
{
|
|
|
|
yy_scan_string(tmp);
|
|
yyparse();
|
|
|
|
tmp[0] = '\0';
|
|
return yyresult();
|
|
}
|
|
|
|
Eina_Bool
|
|
equate_ok(void)
|
|
{
|
|
return !yyerror_found;
|
|
}
|
|
|
|
const char *
|
|
equate_string_get(void)
|
|
{
|
|
return(tmp);
|
|
}
|
|
|
|
struct init {
|
|
char *fname;
|
|
double (*fnct) (double);
|
|
};
|
|
|
|
struct init arith_fncts[] = {
|
|
"sin", sin,
|
|
"cos", cos,
|
|
"tan", tan,
|
|
"ln", log,
|
|
"exp", exp,
|
|
"sqrt", sqrt,
|
|
0, 0
|
|
};
|
|
|
|
/* The symbol table: a chain of `struct symrec'. */
|
|
symrec *sym_table = (symrec *) 0;
|
|
|
|
/* Put arithmetic functions in table. */
|
|
void
|
|
math_init(void)
|
|
{
|
|
int i;
|
|
symrec *ptr;
|
|
|
|
for (i = 0; arith_fncts[i].fname != 0; i++) {
|
|
ptr = putsym(arith_fncts[i].fname, FNCT);
|
|
ptr->value.fnctptr = arith_fncts[i].fnct;
|
|
}
|
|
|
|
tmp[0] = '\0';
|
|
}
|
|
|
|
symrec *
|
|
putsym(const char *sym_name, int sym_type)
|
|
{
|
|
symrec *ptr;
|
|
|
|
ptr = (symrec *) malloc(sizeof(symrec));
|
|
ptr->name = (char *) malloc(strlen(sym_name) + 1);
|
|
strcpy(ptr->name, sym_name);
|
|
ptr->type = sym_type;
|
|
ptr->value.var = 0; /* set value to 0 even if fctn. */
|
|
ptr->next = (struct symrec *) sym_table;
|
|
sym_table = ptr;
|
|
return ptr;
|
|
}
|
|
|
|
symrec *
|
|
getsym(const char *sym_name)
|
|
{
|
|
symrec *ptr;
|
|
|
|
for (ptr = sym_table; ptr != (symrec *) 0; ptr = (symrec *) ptr->next)
|
|
if (strcmp(ptr->name, sym_name) == 0)
|
|
return ptr;
|
|
return 0;
|
|
}
|