Mercurial > hg > dmlib
changeset 764:181d659bba39
More work.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 09 May 2013 08:28:39 +0300 |
parents | ad512e54c689 |
children | c68258fd81a1 |
files | dmeval.c dmeval.h |
diffstat | 2 files changed, 221 insertions(+), 260 deletions(-) [+] |
line wrap: on
line diff
--- a/dmeval.c Thu May 09 06:36:54 2013 +0300 +++ b/dmeval.c Thu May 09 08:28:39 2013 +0300 @@ -4,6 +4,8 @@ #define DM_MAX_BUF 512 +/* Operators + */ const DMEvalOper dmEvalOpers[OP_NOPERS] = { { "-" , OT_UNARY }, @@ -66,12 +68,12 @@ */ static const DMEvalSymbol dmEvalBasicFuncs[] = { - { "sin", ID_FUNC, 1, func_sin, NULL, 0 }, - { "cos", ID_FUNC, 1, func_cos, NULL, 0 }, - { "clip", ID_FUNC, 1, func_int_clip, NULL, 0 }, - { "pow", ID_FUNC, 2, func_pow, NULL, 0 }, + { "sin", SYM_FUNC, 1, func_sin, NULL, 0 }, + { "cos", SYM_FUNC, 1, func_cos, NULL, 0 }, + { "clip", SYM_FUNC, 1, func_int_clip, NULL, 0 }, + { "pow", SYM_FUNC, 2, func_pow, NULL, 0 }, - { "pi", ID_CVAR, 0, NULL, NULL, DM_PI }, + { "pi", SYM_CVAR, 0, NULL, NULL, DM_PI }, }; static const int ndmEvalBasicFuncs = sizeof(dmEvalBasicFuncs) / sizeof(dmEvalBasicFuncs[0]); @@ -122,62 +124,68 @@ } -static DMEvalSymbol *dmEvalContextAddSymbol(DMEvalContext *ev, const char *name, const int type) +// Add a new symbol to the evaluation context. +// Return pointer to newly allocated symbol struct if successful. +// If the symbol already exists or there was a memory allocation +// error, NULL is returned. +static DMEvalSymbol * dmEvalContextAddSymbol(DMEvalContext *ev, const char *name, const int type) { - DMEvalSymbol *id = dmEvalContextFindSymbol(ev, name); - if (id != NULL) + DMEvalSymbol *symbol = dmEvalContextFindSymbol(ev, name); + if (symbol != NULL) return NULL; ev->symbols = dmRealloc(ev->symbols, sizeof(DMEvalSymbol) * (ev->nsymbols + 1)); if (ev->symbols == NULL) { - dmEvalError(ev, "Could not reallocate eval symbols array (#%d). Fatal error.\n", ev->nsymbols + 1); + dmEvalError(ev, + "Could not reallocate eval symbols array (#%d). Fatal error.\n", + ev->nsymbols + 1); return NULL; } - id = &(ev->symbols[ev->nsymbols]); + symbol = &(ev->symbols[ev->nsymbols]); ev->nsymbols++; - id->name = dm_strdup(name); - id->type = type; - id->func = NULL; - id->var = NULL; + memset(symbol, 0, sizeof(DMEvalSymbol)); + symbol->name = dm_strdup(name); + symbol->type = type; - return id; + return symbol; } DMEvalSymbol *dmEvalContextAddVar(DMEvalContext *ev, const char *name, DMValue *var) { - DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_VAR); - if (id == NULL) + DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_VAR); + if (symbol == NULL) return NULL; - id->var = var; - return id; + symbol->var = var; + return symbol; } DMEvalSymbol *dmEvalContextAddConst(DMEvalContext *ev, const char *name, DMValue value) { - DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_CVAR); - if (id == NULL) + DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_CVAR); + if (symbol == NULL) return NULL; - id->cvalue = value; - return id; + symbol->cvalue = value; + return symbol; } DMEvalSymbol *dmEvalContextAddFunc(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs) { - DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_VAR); - if (id == NULL) + DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_VAR); + if (symbol == NULL) return NULL; - id->func = func; - id->nargs = nargs; - return id; + symbol->func = func; + symbol->nargs = nargs; + + return DMERR_OK; } @@ -191,12 +199,15 @@ for (i = 0; i < ndmEvalBasicFuncs; i++) { - const DMEvalSymbol *id = &dmEvalBasicFuncs[i]; - DMEvalSymbol *nid = dmEvalContextAddSymbol(ev, id->name, id->type); - nid->nargs = id->nargs; - nid->func = id->func; - nid->var = id->var; - nid->cvalue = id->cvalue; + const DMEvalSymbol *symbol= &dmEvalBasicFuncs[i]; + DMEvalSymbol *nsymbol = dmEvalContextAddSymbol(ev, symbol->name, symbol->type); + if (nsymbol != NULL) + { + nsymbol->nargs = symbol->nargs; + nsymbol->func = symbol->func; + nsymbol->var = symbol->var; + nsymbol->cvalue = symbol->cvalue; + } } return ev; @@ -343,8 +354,8 @@ static int dmEvalTokenizeExpr(DMEvalContext *ev, DMEvalNode **list, char **str, int depth) { char *c = *str; - char tmpStr[DM_MAX_BUF + 2]; - int tmpStrLen = 0, argIndex; + char tmpStr[DM_MAX_BUF + 2], *tmp; + int tmpStrLen = 0, argIndex, op; DMEvalNode *node = NULL, *func = NULL; BOOL first = FALSE, decimal = FALSE; @@ -355,49 +366,46 @@ switch (ev->mode) { case PARSE_SUBEXPR_START: - { - char *tmp = c + 1; + tmp = c + 1; - ev->expect = PARSE_NORMAL; + ev->expect = PARSE_NORMAL; - if ((node = dmEvalAddNode(list, OP_SUBEXPR)) == NULL) - dmEvalSetMode(ev, PARSE_ERROR); - else - if (dmEvalTokenizeExpr(ev, &(node->subexpr), &tmp, depth + 1) != 0) - { - dmEvalError(ev, "Subexpression starting at '%s' contained errors.\n", c); - dmEvalSetMode(ev, PARSE_ERROR); - } + if ((node = dmEvalAddNode(list, OP_SUBEXPR)) == NULL) + dmEvalSetMode(ev, PARSE_ERROR); + else + if (dmEvalTokenizeExpr(ev, &(node->subexpr), &tmp, depth + 1) != 0) + { + dmEvalError(ev, "Subexpression starting at '%s' contained errors.\n", c); + dmEvalSetMode(ev, PARSE_ERROR); + } - if (ev->mode != PARSE_ERROR) - { - dmEvalSetMode(ev, PARSE_START); - ev->expect = PARSE_OPER | PARSE_SUBEXPR_END; - c = tmp; - } + if (ev->mode != PARSE_ERROR) + { + dmEvalSetMode(ev, PARSE_START); + ev->expect = PARSE_OPER | PARSE_SUBEXPR_END; + c = tmp; } break; case PARSE_ARGS: + tmp = c + 1; + + for (argIndex = 0; argIndex < func->symbol->nargs; argIndex++) { - char *tmp = c + 1; - for (argIndex = 0; argIndex < func->id->nargs; argIndex++) + if (dmEvalTokenizeExpr(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0) { - if (dmEvalTokenizeExpr(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0) - { - dmEvalError(ev, "Function argument subexpression starting at '%s' contained errors.\n", c); - dmEvalSetMode(ev, PARSE_ERROR); - } + dmEvalError(ev, "Function argument subexpression starting at '%s' contained errors.\n", c); + dmEvalSetMode(ev, PARSE_ERROR); } + } - func = NULL; + func = NULL; - if (ev->mode != PARSE_ERROR) - { - dmEvalSetMode(ev, PARSE_START); - ev->expect = PARSE_OPER | PARSE_END; - c = tmp; - } + if (ev->mode != PARSE_ERROR) + { + dmEvalSetMode(ev, PARSE_START); + ev->expect = PARSE_OPER | PARSE_END; + c = tmp; } break; @@ -492,7 +500,7 @@ { tmpStr[tmpStrLen] = 0; - if ((node = dmEvalAddNode(list, OP_CONST)) == NULL) + if ((node = dmEvalAddNode(list, OP_VALUE)) == NULL) { dmEvalSetMode(ev, PARSE_ERROR); } @@ -530,61 +538,59 @@ break; case PARSE_OPER: - { - int op = OP_INVALID; - - switch (*c) - { - case '+': op = OP_ADD; c++; break; - case '-': op = OP_SUB; c++; break; - case '*': op = OP_MUL; c++; break; - case '/': op = OP_DIV; c++; break; - case '%': op = OP_MOD; c++; break; - case '&': op = OP_BIT_AND; c++; break; - case '^': op = OP_BIT_XOR; c++; break; - case '|': op = OP_BIT_OR; c++; break; + op = OP_INVALID; - case '>': - if (c[1] == '>') - { - c += 2; - op = OP_BIT_RSHIFT; - } - else - { - op = (c[1] == '=') ? OP_GT_EQ : OP_GT; - c++; - } - break; - - case '<': - if (c[1] == '<') - { - c += 2; - op = OP_BIT_LSHIFT; - } - else - { - op = (c[1] == '=') ? OP_LT_EQ : OP_LT; - c++; - } - break; + switch (*c) + { + case '+': op = OP_ADD; c++; break; + case '-': op = OP_SUB; c++; break; + case '*': op = OP_MUL; c++; break; + case '/': op = OP_DIV; c++; break; + case '%': op = OP_MOD; c++; break; + case '&': op = OP_BIT_AND; c++; break; + case '^': op = OP_BIT_XOR; c++; break; + case '|': op = OP_BIT_OR; c++; break; - default: - dmEvalError(ev, "Unknown operator '%c' at %s\n", *c, c); - dmEvalSetMode(ev, PARSE_ERROR); - } - - if (op != OP_INVALID) - { - if ((node = dmEvalAddNode(list, op)) != NULL) + case '>': + if (c[1] == '>') { - ev->expect = PARSE_NORMAL | PARSE_OPER_UNARY; - dmEvalSetMode(ev, PARSE_START); + c += 2; + op = OP_BIT_RSHIFT; } else - dmEvalSetMode(ev, PARSE_ERROR); + { + op = (c[1] == '=') ? OP_GT_EQ : OP_GT; + c++; + } + break; + + case '<': + if (c[1] == '<') + { + c += 2; + op = OP_BIT_LSHIFT; + } + else + { + op = (c[1] == '=') ? OP_LT_EQ : OP_LT; + c++; + } + break; + + default: + dmEvalError(ev, "Unknown operator '%c' at %s\n", *c, c); + dmEvalSetMode(ev, PARSE_ERROR); + } + + if (op != OP_INVALID) + { + if ((node = dmEvalAddNode(list, op)) != NULL) + { + ev->expect = PARSE_NORMAL | PARSE_OPER_UNARY; + dmEvalSetMode(ev, PARSE_START); } + else + dmEvalSetMode(ev, PARSE_ERROR); } break; @@ -608,13 +614,13 @@ else { tmpStr[tmpStrLen] = 0; - DMEvalSymbol *id = dmEvalContextFindSymbol(ev, tmpStr); - if (id != NULL) + DMEvalSymbol *symbol = dmEvalContextFindSymbol(ev, tmpStr); + if (symbol != NULL) { - if ((node = dmEvalAddNode(list, id->type == ID_FUNC ? OP_FUNC : OP_VAR)) != NULL) + if ((node = dmEvalAddNode(list, symbol->type == SYM_FUNC ? OP_FUNC : OP_VAR)) != NULL) { - node->id = id; - if (id->type == ID_FUNC) + node->symbol = symbol; + if (symbol->type == SYM_FUNC) { func = node; ev->expect = PARSE_ARGS; @@ -658,143 +664,96 @@ - - -static int dmEvalGet(DMEvalContext *ev, const DMEvalNode *node, DMValue *result) +BOOL dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *node, DMValue *presult) { + DMValue val1, val2; + if (node == NULL) - return -32; - + return FALSE; + switch (node->op) { - case OP_VAR: - if (node->id->type == ID_VAR) - *result = *(node->id->var); - else - *result = node->id->cvalue; - break; - - case OP_CONST: - *result = node->val; - break; - - case OP_SUBEXPR: - return dmEvalTreeExecute(ev, node->subexpr, result); + case OP_VALUE: + *presult = node->val; + return TRUE; case OP_FUNC: + return TRUE; + + case OP_SUBEXPR: + return dmEvalTreeExecute(ev, node->subexpr, presult); + + // Binary operators + case OP_BIT_LSHIFT: + case OP_BIT_RSHIFT: + + case OP_BIT_AND: + case OP_BIT_XOR: + case OP_BIT_OR: + + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_MOD: + if (!dmEvalTreeExecute(ev, node->left, &val1) || + !dmEvalTreeExecute(ev, node->right, &val2)) + return FALSE; + + switch (node->op) { - DMValue tmp[DM_MAX_ARGS]; - int i; - for (i = 0; i < node->id->nargs; i++) - { - if (dmEvalTreeExecute(ev, node->args[i], &tmp[i]) != 0) - return -1; - } - - *result = node->id->func(tmp); - } - break; - - default: - return -16; - } - - return 0; -} + case OP_DIV: + if (val2 == 0) + { + dmEvalError(ev, "Division by zero.\n"); + return FALSE; + } + *presult = val1 / val2; + break; -int dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult) -{ - DMValue result = 0; - DMEvalNode *node = tree; - - while (node != NULL) - { - DMValue tmp = 0; - - switch (node->op) - { - case OP_BIT_LSHIFT: - case OP_BIT_RSHIFT: - - case OP_BIT_AND: - case OP_BIT_XOR: - case OP_BIT_OR: + case OP_MOD: + if (val2 == 0) + { + dmEvalError(ev, "Division by zero.\n"); + return FALSE; + } + *presult = DMCONVTYPE val1 % DMCONVTYPE val2; + break; - case OP_MUL: - case OP_DIV: - case OP_MOD: - if (dmEvalGet(ev, node->next, &tmp) != 0) - return -6; - - switch (node->op) - { - case OP_DIV: - if (tmp == 0) - { - dmEvalError(ev, "Division by zero.\n"); - return -1; - } - result /= tmp; - break; + case OP_BIT_LSHIFT: + if (val2 > 31) + dmEvalError(ev, "Left shift count >= width of type (%d << %d)\n", val1, val2); + *presult = DMCONVTYPE val1 << DMCONVTYPE val2; break; - case OP_MUL: result *= tmp; break; - - case OP_MOD: - if (tmp == 0) - { - dmEvalError(ev, "Division by zero.\n"); - return -1; - } - result = DMCONVTYPE result % DMCONVTYPE tmp; - break; + case OP_BIT_RSHIFT: + if (val2 > 31) + dmEvalError(ev, "Right shift count >= width of type (%d >> %d)\n", val1, val2); + *presult = DMCONVTYPE val1 >> DMCONVTYPE val2; break; - case OP_BIT_LSHIFT: - if (tmp > 31) - dmEvalError(ev, "Left shift count >= width of type"); - result = DMCONVTYPE result << DMCONVTYPE tmp; break; - - case OP_BIT_RSHIFT: - if (tmp > 31) - dmEvalError(ev, "Right shift count >= width of type"); - result = DMCONVTYPE result >> DMCONVTYPE tmp; break; + case OP_MUL : *presult = val1 * val2; break; + case OP_ADD : *presult = val1 + val2; break; + case OP_SUB : *presult = val1 - val2; break; + case OP_BIT_AND : *presult = DMCONVTYPE val1 & DMCONVTYPE val2; break; + case OP_BIT_OR : *presult = DMCONVTYPE val1 | DMCONVTYPE val2; break; + case OP_BIT_XOR : *presult = DMCONVTYPE val1 ^ DMCONVTYPE val2; break; + } + return TRUE; - case OP_BIT_AND: result = DMCONVTYPE result & DMCONVTYPE tmp; break; - case OP_BIT_OR: result = DMCONVTYPE result | DMCONVTYPE tmp; break; - case OP_BIT_XOR: result = DMCONVTYPE result ^ DMCONVTYPE tmp; break; - } - - node = node->next; - break; - - case OP_ADD: - case OP_SUB: - case OP_SUB_UNARY: - case OP_BIT_COMPLEMENT: - if (dmEvalGet(ev, node->next, &tmp) != 0) - return -6; - - switch (node->op) - { - case OP_ADD: result += tmp; break; - case OP_SUB: result -= tmp; break; - case OP_SUB_UNARY: result -= tmp; break; - case OP_BIT_COMPLEMENT: result = DMCONVTYPE ~(DMCONVTYPE tmp); break; - } + // Unary operators + case OP_SUB_UNARY: + case OP_BIT_COMPLEMENT: +/* + switch (node->op) + { + case OP_SUB_UNARY: *presult -= tmp; break; + case OP_BIT_COMPLEMENT: *presult = DMCONVTYPE ~(DMCONVTYPE tmp); break; + } +*/ + return TRUE; - node = node->next; - break; - - default: - if (dmEvalGet(ev, node, &result) != 0) - { - dmEvalError(ev, "Invalid opcode %d in node %p.\n", node->op, node); - return -4; - } - } - node = node->next; + default: + dmEvalError(ev, "Invalid opcode %d in node %p.\n", node->op, node); + return FALSE; } - - *presult = result; - return 0; }
--- a/dmeval.h Thu May 09 06:36:54 2013 +0300 +++ b/dmeval.h Thu May 09 08:28:39 2013 +0300 @@ -36,7 +36,7 @@ // Special ops OP_FUNC, OP_VAR, - OP_CONST, + OP_VALUE, OP_SUBEXPR, // Total number of operators @@ -65,32 +65,34 @@ enum { - ID_FUNC, - ID_VAR, - ID_CVAR, + SYM_FUNC, + SYM_VAR, + SYM_CVAR, } DMEvalSymbolType; typedef struct { - char *name; - int type; - int nargs; + char *name; // Name of the symbol + int type; // Type (SYM_*) + int nargs; // Number of arguments, if SYM_FUNC + DMValue (*func)(DMValue arg[DM_MAX_ARGS]); - DMValue *var, cvalue; + + DMValue *var; // Pointer to variable value if SYM_VAR + DMValue cvalue; // Const value, if SYM_CVAR } DMEvalSymbol; typedef struct DMEvalNode { - BOOL ok; - int op; - DMValue val; - DMEvalSymbol *id; + int op; // Operator/token type + DMValue val; // Value, if immediate constant + DMEvalSymbol *symbol; // Symbol pointer, if function/variable/constvar - struct DMEvalNode *args[DM_MAX_ARGS]; + struct DMEvalNode *args[DM_MAX_ARGS]; // Arguments, if function - struct DMEvalNode *subexpr, *next, *prev; + struct DMEvalNode *subexpr, *left, *right, *next, *prev; } DMEvalNode;