/* #includes */ /*{{{C}}}*//*{{{*/ #ifndef NO_POSIX_SOURCE #undef _POSIX_SOURCE #define _POSIX_SOURCE 1 #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 2 #endif #ifdef DMALLOC #include "dmalloc.h" #endif #include #include #include #include #include #include "eval.h" #include "main.h" #include "misc.h" #include "parser.h" #include "scanner.h" #include "sheet.h" /*}}}*/ /* #defines */ /*{{{*/ #define MAXARGC 16 /*}}}*/ /* prototypes */ /*{{{*/ static Token term(Token *n[], int *i); /*}}}*/ /* primary -- parse and evaluate a primary term */ /*{{{*/ static Token primary(Token *n[], int *i) { /* variables */ /*{{{*/ int argc,j; Token *ident,argv[MAXARGC],result; /*}}}*/ if (n[*i]==(Token*)0) /* error */ /*{{{*/ { result.type=EEK; result.u.err=strcpy(malloc(strlen(_("missing operator"))+1),_("missing operator")); return result; } /*}}}*/ else switch (n[*i]->type) { /* STRING, FLOAT, INT */ /*{{{*/ case STRING: case FLOAT: case INT: { return tcopy(*n[(*i)++]); } /*}}}*/ /* OPERATOR */ /*{{{*/ case OPERATOR: { if (n[*i]->u.op==OP) /* return paren term */ /*{{{*/ { ++(*i); result=term(n,i); if (result.type==EEK) return result; if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP) { ++(*i); return result; } tfree(&result); result.type=EEK; result.u.err=strcpy(malloc(strlen(_(") expected"))+1),_(") expected")); return result; } /*}}}*/ else if (n[*i]->u.op==MINUS) /* return negated term */ /*{{{*/ { ++(*i); return(tneg(primary(n,i))); } /*}}}*/ else /* return error, value expected */ /*{{{*/ { result.type=EEK; result.u.err=mystrmalloc(_("value expected")); return result; } /*}}}*/ } /*}}}*/ /* LIDENT */ /*{{{*/ case LIDENT: { ident=n[*i]; ++(*i); return findlabel(upd_sheet,ident->u.lident); } /*}}}*/ /* FIDENT */ /*{{{*/ case FIDENT: { ident=n[*i]; ++(*i); if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==OP) /* parse arguments and closing paren of function call, return its value */ /*{{{*/ { ++(*i); argc=0; if (!(n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP)) /* parse at least one argument */ /*{{{*/ { if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==COMMA) /* empty argument */ /*{{{*/ { argv[argc].type=EMPTY; } /*}}}*/ else argv[argc]=term(n,i); if (argv[argc].type==EEK) return argv[argc]; ++argc; while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==COMMA) /* parse the following argument */ /*{{{*/ { ++(*i); if (argc<=MAXARGC) { if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==COMMA || n[*i]->u.op==CP)) { argv[argc].type=EMPTY; } else argv[argc]=term(n,i); } else { result.type=EEK; result.u.err=strcpy(malloc(strlen(_("too many arguments"))+1),_("too many arguments")); for (j=0; j<=argc; ++j) tfree(&argv[j]); return result; } ++argc; } /*}}}*/ } /*}}}*/ if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP) /* eval function */ /*{{{*/ { ++(*i); result=tfuncall(ident,argc,argv); for (j=0; jtype==OPERATOR && n[*i]->u.op==POW) { Token result,r; ++(*i); r=primary(n,i); result=tpow(l,r); tfree(&l); tfree(&r); if (result.type==EEK) return result; l=result; } return l; } /*}}}*/ /* piterm -- parse and evaluate a product/division/modulo term */ /*{{{*/ static Token piterm(Token *n[], int *i) { Token l; l=powterm(n,i); if (l.type==EEK) return l; while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==DIV || n[*i]->u.op==MUL || n[*i]->u.op==MOD)) { Operator op; Token result,r; op=n[*i]->u.op; ++(*i); r=powterm(n,i); switch (op) { case MUL: result=tmul(l,r); break; case DIV: result=tdiv(l,r); break; case MOD: result=tmod(l,r); break; default: assert(0); } tfree(&l); tfree(&r); if (result.type==EEK) return result; l=result; } return l; } /*}}}*/ /* factor -- parse and evaluate a factor of sums/differences */ /*{{{*/ static Token factor(Token *n[], int *i) { Token l; l=piterm(n,i); if (l.type==EEK) return l; while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==PLUS || n[*i]->u.op==MINUS)) { Operator op; Token result,r; op=n[*i]->u.op; ++(*i); r=piterm(n,i); result=(op==PLUS ? tadd(l,r) : tsub(l,r)); tfree(&l); tfree(&r); if (result.type==EEK) return result; l=result; } return l; } /*}}}*/ /* term -- parse and evaluate a relational term */ /*{{{*/ static Token term(Token *n[], int *i) { Token l; l=factor(n,i); if (l.type==EEK) return l; while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op>=LT && n[*i]->u.op<=NE) { Operator op; Token result,r; op=n[*i]->u.op; ++(*i); r=factor(n,i); switch (op) { case LT: result=tlt(l,r); break; case LE: result=tle(l,r); break; case GE: result=tge(l,r); break; case GT: result=tgt(l,r); break; case ISEQUAL: result=teq(l,r); break; case ABOUTEQ: result=tabouteq(l,r); break; case NE: result=tne(l,r); break; default: assert(0); } tfree(&l); tfree(&r); if (result.type==EEK) return result; l=result; } return l; } /*}}}*/ /* eval -- parse and evaluate token sequence */ /*{{{*/ Token eval(Token **n) { Token result; int i; assert(upd_sheet!=(Sheet*)0); i=0; result=term(n,&i); if (result.type==EEK) return result; if (n[i]!=(Token*)0) { tfree(&result); result.type=EEK; result.u.err=strcpy(malloc(strlen(_("parse error after term"))+1),_("parse error after term")); return result; } return result; } /*}}}*/ /* eval_safe -- like eval, but handles null pointer to token sequence */ /*{{{*/ Token eval_safe(Token **n) { Token result; if (n == EMPTY_TVEC) { result.type = EMPTY; return result; } return eval(n); }