sheets

a simple spread sheet software
Log | Files | Refs

expr.c (3618B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <ctype.h>
      4 #include <math.h>
      5 #include <string.h>
      6 
      7 #include "sheets.h"
      8 
      9 /*
     10 EXPR := VALUE
     11 | VALUE POSTFIX
     12 | '(' EXPR ')'
     13 
     14 VALUE := NUM
     15 | LOC
     16 
     17 POSTFIX := OP EXPR
     18 OP := '+' | '-' | '*' | '/' | '^'
     19 lOC := '[' NUM ',' NUM ']'
     20 */
     21 
     22 #define TODO(s) fprintf(stderr, "TODO:%d: %s\n", __LINE__, s); exit(1);
     23  
     24 typedef struct expr expr; 
     25 typedef struct value value;  /* for recursive case */
     26 typedef struct postfix postfix;
     27 
     28 typedef enum exprType {
     29 	VALUE,
     30 	POSTFIX,	
     31 	NESTED,
     32 } exprType;
     33 
     34 typedef enum valueType {
     35 	NUM,
     36 	LOC,
     37 } valueType;
     38 
     39 typedef struct loc {
     40         int x, y;
     41 } loc;
     42 
     43 typedef struct expr {
     44 	char *expr;
     45 	exprType t;
     46 	union {
     47 		expr *nested;
     48 		struct {
     49 			value *value;
     50 			postfix *postfix;
     51 		};
     52 	};
     53 } expr;
     54 
     55 typedef struct postfix {
     56 	char op;
     57 	expr *expr;
     58 } postfix;
     59 
     60 typedef struct value {
     61 	valueType t;
     62 	union {
     63 		int num;
     64 		loc *loc;
     65 	};
     66 } value;
     67 
     68 char isop(char c) {
     69         switch (c) {
     70                 case '+':
     71                 case '-':
     72                 case '*':
     73                 case '/':
     74                 case '^':
     75                         return c;
     76         }
     77         return 0;
     78 }
     79 
     80 char *in;
     81 char *Pin;
     82 
     83 void consumeleading(char c) {
     84 loop:
     85 	if (*in == c) {
     86 		in++;
     87 		goto loop;
     88 	}
     89 }
     90 
     91 expr *parseExpr(); 
     92 
     93 loc *parseLoc() {
     94 	consumeleading(' ');
     95 	loc *l = malloc(sizeof(loc));
     96 	if (*in == '[') {
     97 		int i;
     98 		sscanf(in, "[%d,%d]%n", &l->x, &l->y, &i);
     99 		if (i != 0) { 
    100 			in += i;
    101 			return l;
    102 		}
    103 		TODO("ERROR");
    104 	} 
    105 	return NULL;
    106 }
    107 
    108 postfix *parsePostfix() {
    109 	consumeleading(' ');
    110 	postfix *p = malloc(sizeof(postfix));
    111 	if (p->op = isop(*in)) {
    112 		in++;
    113 		if (p->expr = parseExpr()) 
    114 			return p;		
    115 	}
    116 	return NULL;
    117 }
    118 
    119 value *parseValue() {
    120 	consumeleading(' ');
    121 	value *v = malloc(sizeof(value));
    122 	if (v->loc = parseLoc()) {
    123 		v->t = LOC;
    124 		return v;
    125 	}
    126 	else if (isdigit(*in)) {
    127 		int i;
    128 		sscanf(in, "%d%n", &v->num, &i);
    129 		if (i != 0) {
    130 			in += i;
    131 			v->t = NUM;
    132 			return v;
    133 		}
    134 		TODO("ERROR");
    135 	} 
    136 	return NULL;
    137 }
    138 
    139 expr *parseExpr() {
    140 	consumeleading(' ');
    141 	expr *e = malloc(sizeof(expr));
    142 	if (e->value = parseValue()) {
    143 		e->t = VALUE;
    144 		if (e->postfix = parsePostfix())
    145 			e->t = POSTFIX;
    146 
    147 		return e;
    148 	}
    149 
    150 	else if (*in == '(') {
    151 		in++;
    152 		if (e->nested = parseExpr()) 
    153 			if (*in == ')')	{
    154 				e->t = NESTED;
    155 				return e;
    156 			}
    157 		TODO("ERROR");
    158 	}
    159 
    160 	return NULL;
    161 }
    162 
    163 double evalExpr(expr *e, sheet *s);
    164 
    165 double evalValue(value *v, sheet *s) {
    166 	if (v->t == NUM) return v->num;	
    167 	return evalExpr(s->cells[v->loc->y][v->loc->x], s);
    168 }
    169 
    170 double evalPostfix(value *v, postfix *p, sheet *s) {
    171 	switch (p->op) {
    172 		case '+': return evalValue(v, s) + evalExpr(p->expr, s);
    173 		case '-': return evalValue(v, s) - evalExpr(p->expr, s);
    174 		case '*': return evalValue(v, s) * evalExpr(p->expr, s);
    175 		case '/': return evalValue(v, s) / evalExpr(p->expr, s);
    176 		case '^': return pow(evalValue(v, s), evalExpr(p->expr, s));
    177 	}
    178 }
    179 
    180 double evalExpr(expr *e, sheet *s) {
    181 	switch (e->t) {  
    182 		case VALUE: return evalValue(e->value, s); break;
    183 		case POSTFIX: return evalPostfix(e->value, e->postfix, s); break;
    184 		case NESTED: return evalExpr(e->nested, s);
    185 	}
    186 }
    187 
    188 expr *makeNumber(int n) {
    189 	in = Pin;
    190 	memset(in, 0, 255);
    191 	snprintf(in, 16, "%d", n);
    192 	expr *e = parseExpr();
    193 	e->expr = strdup(Pin);
    194 	return e;
    195 }
    196 
    197 void freeValue(value *v) {
    198 	if (v->t == LOC) free(v->loc);
    199 	free(v);
    200 }
    201 
    202 void freePostfix(value *v, postfix *p) {
    203 	freeValue(v);
    204 	freeExpr(p->expr);
    205 	free(p);
    206 }
    207 
    208 void freeExpr(expr *e) {
    209 	switch (e->t) {  
    210 		case VALUE: freeValue(e->value); break;
    211 		case POSTFIX: freePostfix(e->value, e->postfix); break;
    212 		case NESTED: freeExpr(e->nested); break;
    213 	}
    214 	free(e);
    215 }