#include <ctype.h> // isspace
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
jmp_buf g_env;
double g_vars['z' - 'a' + 1];
const char* g_s;
#define SPACES(s) while(isspace(*s)) ++s;
double statement(); // fwd
void expect(char expected, char c)
{
if (c == expected) return;
printf("Unexpected \'%c\'\n", c);
longjmp(g_env, -1);
}
double term()
{
double ret;
char* tmp;
SPACES(g_s);
if (*g_s >= 'a' && *g_s <= 'z')
return g_vars[*g_s++ - 'a'];
if (*g_s == '(') {
++g_s;
ret = statement();
SPACES(g_s);
expect(')', *g_s++);
return ret;
}
ret = strtod(g_s, &tmp);
if (tmp == g_s) expect('0', *tmp);
g_s = tmp;
return ret;
}
double subexpr()
{
double ret = term();
while (1) {
SPACES(g_s);
if (*g_s == '*') ++g_s, ret *= term();
else if (*g_s == '/') ++g_s, ret /= term();
else return ret;
}
}
double expr()
{
double ret = subexpr();
while(1) {
SPACES(g_s);
if (*g_s == '+') ++g_s, ret += subexpr();
else if (*g_s == '-') ++g_s, ret -= subexpr();
else return ret;
}
}
double assign()
{
const char* tmp;
unsigned idx;
SPACES(g_s);
if (*g_s >= 'a' && *g_s <= 'z') {
tmp = g_s + 1;
SPACES(tmp);
if (*tmp == '=') {
idx = *g_s - 'a';
g_s = tmp + 1;
return g_vars[idx] = assign();
}
}
return expr();
}
double statement()
{
double ret;
while(1) {
ret = assign();
SPACES(g_s);
if (*g_s != ',') return ret;
++g_s;
}
}
int main()
{
char buf[1024];
double ret;
setjmp(g_env);
while(1) {
g_s = gets(buf);
ret = statement();
expect('\0', *g_s);
printf("%g\n", ret);
}
return 0;
}