caculator.y
%{
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "calc.h"
void yyerror(char* s)
{
fprintf(stderr, "%s/n", s);
}
%}
%union {
double val;
symrec* tptr;
}
%token <val> NUM
%token <tptr> VAR FNCT
%type <val> exp
%right '='
%left '-' '+'
%left '*' '/'
%left NEG
%right '^'
%%
input : /* empty */
| input line
;
line : '/n'
| exp '/n' {printf("/t%.10g/n", $1);}
| error '/n' {yyerrok;}
;
exp : NUM {$$ = $1;}
| VAR {$$ = $1->value.var;}
| VAR '=' exp {$$ = $3; $1->value.var = $3;}
| FNCT '(' exp ')' {$$ = (*($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);}
| '(' exp ')' {$$ = $2;}
;
%%
#include <ctype.h>
#include <stdlib.h>
int yylex(void)
{
int c;
while ((c = getchar()) == ' ' || c == '/t');
if (c == EOF) return 0;
/* Number */
if (c == '.' || isdigit(c)) {
ungetc(c, stdin);
scanf("%lf", &yylval);
return NUM;
}
/* Identifier */
if (isalpha(c)) {
symrec* s;
static char* symbuf = NULL;
static int length = 0;
int i;
if (length == 0) {
length = 40;
symbuf = malloc(length + 1);
}
i = 0;
do {
/* Grow buffer if necessary */
if (i == length) {
length *= 2;
symbuf = realloc(symbuf, length + 1);
}
/* Add character */
symbuf[i++] = c;
/* Get next character */
c = getchar();
} while (c != EOF && isalnum(c));
ungetc(c, stdin);
symbuf[i] = '/0';
s = getsym(symbuf);
if (s == NULL) s = putsym(symbuf, VAR);
yylval.tptr = s;
return s->type;
}
/* Any other character is its own token */
return c;
}
int main(void)
{
init_table();
yyparse();
return EXIT_SUCCESS;
}
struct {
char* fname;
double (*fnct)();
} arith_fncts[] = {
"sin", sin,
"cos", cos,
"tan", tan,
"atan", atan,
"ln", log,
"exp", exp,
"sqrt", sqrt,
0, 0
};
symrec* sym_table = NULL;
void init_table(void)
{
int i;
symrec* ptr;
for (i = 0; arith_fncts[i].fname != NULL; i++) {
ptr = putsym(arith_fncts[i].fname, FNCT);
ptr->value.fnctptr = arith_fncts[i].fnct;
}
}
symrec* putsym(char* sym_name, int sym_type)
{
symrec* ptr;
ptr = malloc(sizeof(symrec));
ptr->name = malloc(strlen(sym_name) + 1);
strcpy(ptr->name, sym_name);
ptr->type = sym_type;
ptr->value.var = 0;
ptr->next = sym_table;
sym_table = ptr;
return ptr;
}
symrec* getsym(char* sym_name)
{
symrec* ptr;
for (ptr = sym_table; ptr != NULL; ptr = ptr->next)
if (strcmp(ptr->name, sym_name) == 0) return ptr;
return NULL;
}
calc.h
#ifndef SEEN_CALC_H
#define SEEN_CALC_H
typedef struct symrec symrec;
struct symrec {
char* name;
int type;
union {
double var;
double (*fnctptr)();
} value;
symrec* next;
};
extern symrec* sym_table;
extern void init_table(void);
extern symrec* putsym(char* sym_name, int sym_type);
extern symrec* getsym(char* sym_name);
#endif
--------------------------
by caculator.y