exprpars.c
来自「数学表达式计算和解析 用c语言编写的,内含有例.速度较快」· C语言 代码 · 共 999 行 · 第 1/2 页
C
999 行
/* Zero out the subnodes */
memset(tmp, 0, sizeof(exprNode) * 2);
/* Set the data */
n->type = EXPR_NODETYPE_FUNCTION;
n->data.function.fptr = __exprSubFunc;
n->data.function.nodecount = 2;
n->data.function.nodes = tmp;
/* parse the left side */
err = exprInternalParse(o, &(tmp[0]), expr, start, index - 1);
if(err != EXPR_ERROR_NOERROR)
return err;
/* parse the right side */
return exprInternalParse(o, &(tmp[1]), expr, index + 1, end);
}
/* Function to parse a multiplication function */
int exprInternalParseMul(exprObj *o, exprNode *n, char *expr, int start, int end, int index)
{
exprNode *tmp;
int err;
/* Make sure times sign is at a good place */
if(index <= start || index >= end)
return EXPR_ERROR_SYNTAX;
/* Allocate space for 2 subnodes */
tmp = exprAllocMem(sizeof(exprNode) * 2);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
/* Zero out the subnodes */
memset(tmp, 0, sizeof(exprNode) * 2);
/* Set the data */
n->type = EXPR_NODETYPE_FUNCTION;
n->data.function.fptr = __exprMulFunc;
n->data.function.nodecount = 2;
n->data.function.nodes = tmp;
/* parse the left side */
err = exprInternalParse(o, &(tmp[0]), expr, start, index - 1);
if(err != EXPR_ERROR_NOERROR)
return err;
/* parse the right side */
return exprInternalParse(o, &(tmp[1]), expr, index + 1, end);
}
/* Function to parse a division function */
int exprInternalParseDiv(exprObj *o, exprNode *n, char *expr, int start, int end, int index)
{
exprNode *tmp;
int err;
/* Make sure slash sign is at a good place */
if(index <= start || index >= end)
return EXPR_ERROR_SYNTAX;
/* Allocate space for 2 subnodes */
tmp = exprAllocMem(sizeof(exprNode) * 2);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
/* Zero out the subnodes */
memset(tmp, 0, sizeof(exprNode) * 2);
/* Set the data */
n->type = EXPR_NODETYPE_FUNCTION;
n->data.function.fptr = __exprDivFunc;
n->data.function.nodecount = 2;
n->data.function.nodes = tmp;
/* parse the left side */
err = exprInternalParse(o, &(tmp[0]), expr, start, index - 1);
if(err != EXPR_ERROR_NOERROR)
return err;
/* parse the right side */
return exprInternalParse(o, &(tmp[1]), expr, index + 1, end);
}
/* Function to parse for positive and negative */
int exprInternalParsePosNeg(exprObj *o, exprNode *n, char *expr, int start, int end, int index)
{
exprNode *tmp;
/* Position should be the same as start */
if(index != start)
return EXPR_ERROR_UNKNOWN;
/* If it is a positive, just parse the internal of it */
if(expr[index] == '+')
return exprInternalParse(o, n, expr, index + 1, end);
else
{
/* allocation subnode */
tmp = exprAllocMem(sizeof(exprNode));
if(tmp == NULL)
return EXPR_ERROR_NOERROR;
/* zero memory */
memset(tmp, 0, sizeof(exprNode));
/* Set data */
n->type = EXPR_NODETYPE_FUNCTION;
n->data.function.fptr = __exprNegFunc;
n->data.function.nodecount = 1;
n->data.function.nodes = tmp;
/* Parse the subnode */
return exprInternalParse(o, tmp, expr, index + 1, end);
}
}
/* Function will parse a call to a function */
int exprInternalParseFunction(exprObj *o, exprNode *n, char *expr, int start, int end, int p1, int p2)
{
int pos;
int num, cur;
int refnum, refcur;
int plevel = 0;
int lv, err;
exprNode *tmp;
char buf[EXPR_MAXIDENTSIZE + 1];
exprFuncType fptr;
int argmin, argmax;
int refargmin, refargmax;
int len;
exprFuncList *l;
exprValList *vars;
EXPRTYPE *addr;
EXPRTYPE **reftmp;
/* We should have a function list */
l = exprGetFuncList(o);
if(l == NULL)
return EXPR_ERROR_NOSUCHFUNCTION;
/* check paren. location */
if(p2 <= p1)
return EXPR_ERROR_SYNTAX;
/* second paren. should not be after the end */
if(p2 > end)
return EXPR_ERROR_SYNTAX;
/* Length of function name */
len = p1 - start;
if(len > EXPR_MAXIDENTSIZE)
return EXPR_ERROR_BADIDENTIFIER;
/* Copy function name */
strncpy(buf, expr + start, len);
buf[len] = '\0';
/* Valid identifier? */
if(exprValidIdent(buf) == 0)
return EXPR_ERROR_BADIDENTIFIER;
/* Look up the function */
err = exprFuncListGet(l, &fptr, buf, &argmin, &argmax, &refargmin, &refargmax);
if(err != EXPR_ERROR_NOERROR)
{
if(err == EXPR_ERROR_NOTFOUND)
return EXPR_ERROR_NOSUCHFUNCTION;
else
return err;
}
/* Make sure the function exists */
if(fptr == NULL)
return EXPR_ERROR_NOSUCHFUNCTION;
/* Count arguments */
if(p2 == p1 + 1)
{
num = 0;
refnum = 0;
}
else
{
num = 1;
refnum = 0;
/* count commas */
for(pos = p1 + 1; pos < p2; pos++)
{
switch(expr[pos])
{
case '(':
plevel++;
break;
case ')':
plevel--;
if(plevel < 0)
return EXPR_ERROR_UNMATCHEDPAREN;
break;
case ',':
/* Found comma */
if(plevel == 0)
num++;
break;
case '&':
/* Found reference mark */
if(plevel == 0)
{
/* This may only occur after the open parenthesis or comma */
if(expr[pos - 1] == '(' || expr[pos - 1] == ',')
refnum++;
else
return EXPR_ERROR_SYNTAX;
}
break;
}
}
/* plevel should be zero */
if(plevel != 0)
return EXPR_ERROR_UNMATCHEDPAREN;
}
/* We now have the number of total arguments and
number of ref arguments. Get number of normal
arguments */
num = num - refnum;
/* Make sure number of arguments is correct */
/* Here we make sure the limits are greater
or equal to zero because any negative number
could be used to specify no limit */
if(argmin >= 0 && num < argmin)
return EXPR_ERROR_BADNUMBERARGUMENTS;
if(argmax >= 0 && num > argmax)
return EXPR_ERROR_BADNUMBERARGUMENTS;
if(refargmin >= 0 && refnum < refargmin)
return EXPR_ERROR_BADNUMBERARGUMENTS;
if(refargmax >= 0 && refnum > refargmax)
return EXPR_ERROR_BADNUMBERARGUMENTS;
/* Set tmp to null in case of no arguments */
tmp = NULL;
reftmp = NULL;
if(num > 0)
{
/* Allocate subnodes */
tmp = exprAllocMem(sizeof(exprNode) * num);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
/* clear memory */
memset(tmp, 0, sizeof(exprNode) * num);
}
if(refnum > 0)
{
/* Allocate ref pointers */
reftmp = exprAllocMem(sizeof(EXPRTYPE*) * refnum);
if(reftmp == NULL)
{
exprFreeMem(tmp);
return EXPR_ERROR_MEMORY;
}
/* Clear memory */
memset(reftmp, 0, sizeof(EXPRTYPE*) * refnum);
}
/* Set this node's data */
n->type = EXPR_NODETYPE_FUNCTION;
n->data.function.fptr = fptr;
n->data.function.nodecount = num;
n->data.function.nodes = tmp;
n->data.function.refcount = refnum;
n->data.function.refitems = reftmp;
/* parse each subnode */
if(num + refnum > 0)
{
plevel = 0;
cur = 0;
refcur = 0;
lv = p1 + 1;
/* look for commas if more than 1 arg */
if(num + refnum > 1)
{
for(pos = p1 + 1; pos < p2; pos++)
{
switch(expr[pos])
{
case '(':
plevel++;
break;
case ')':
plevel--;
break; /* Already checked paren nesting above */
case ',':
/* Found comma */
if(plevel == 0)
{
/* parse inside */
if(expr[lv] == '&')
{
/* It is a reference */
len = pos - lv - 1;
if(len > EXPR_MAXIDENTSIZE)
return EXPR_ERROR_BADIDENTIFIER;
/* Copy name into buffer */
strncpy(buf, expr + lv + 1, len);
buf[len] = '\0';
/* Get variable list */
vars = exprGetVarList(o);
if(vars == NULL)
return EXPR_ERROR_NOVARLIST;
/* Get variable address */
exprValListGetAddress(vars, buf, &addr);
if(addr == NULL)
{
/* Add variable to list */
exprValListAdd(vars, buf, 0.0);
/* Try to get address again */
exprValListGetAddress(vars, buf, &addr);
if(addr == NULL)
return EXPR_ERROR_MEMORY; /* Could not add variable */
}
/* Set reference item */
reftmp[refcur] = addr;
/* increase ref arg number and lv position*/
refcur++;
lv = pos + 1;
}
else
{
err = exprInternalParse(o, &(tmp[cur]), expr, lv, pos - 1);
if(err != EXPR_ERROR_NOERROR)
return err;
/* increase arg number and lv position*/
lv = pos + 1;
cur++;
}
}
break;
}
}
}
/* lv should point after the last comma, or open paren. if only 1 arg */
if(expr[lv] == '&')
{
/* It is a reference */
len = p2 - lv - 1;
if(len > EXPR_MAXIDENTSIZE)
return EXPR_ERROR_BADIDENTIFIER;
/* Copy name into buffer */
strncpy(buf, expr + lv + 1, len);
buf[len] = '\0';
/* Get variable list */
vars = exprGetVarList(o);
if(vars == NULL)
return EXPR_ERROR_NOVARLIST;
/* Get variable address */
exprValListGetAddress(vars, buf, &addr);
if(addr == NULL)
{
/* Add variable to list */
exprValListAdd(vars, buf, 0.0);
/* Try to get address again */
exprValListGetAddress(vars, buf, &addr);
if(addr == NULL)
return EXPR_ERROR_MEMORY; /* Could not add variable */
}
/* Set reference item */
reftmp[refcur] = addr;
}
else
{
err = exprInternalParse(o, &(tmp[cur]), expr, lv, p2 - 1);
if(err != EXPR_ERROR_NOERROR)
return err;
}
}
return EXPR_ERROR_NOERROR;
}
/* Parse a variable or value */
int exprInternalParseVarVal(exprObj *o, exprNode *n, char *expr, int start, int end)
{
int len;
char buf[EXPR_MAXIDENTSIZE + 1];
exprValList *l;
EXPRTYPE val;
EXPRTYPE *addr;
/* Make sure positions are correct */
if(end < start)
return EXPR_ERROR_UNKNOWN;
/* Get length of the variable, value, or constant */
len = end - start + 1;
/* even values should not be this big */
if(len > EXPR_MAXIDENTSIZE)
return EXPR_ERROR_BADIDENTIFIER;
/* Copy it into the buffer */
strncpy(buf, expr + start, len);
buf[len] = '\0';
/* are we an identifier */
if(exprValidIdent(buf) != 0)
{
/* we are an identifier */
/* check to see if it is a constant */
l = exprGetConstList(o);
if(l != NULL)
{
if(exprValListGet(l, buf, &val) == EXPR_ERROR_NOERROR)
{
/* We found it in the constant list */
n->type = EXPR_NODETYPE_VALUE;
n->data.value.value = val;
return EXPR_ERROR_NOERROR;
}
}
/* Not found in the constant list, so it must be a variable */
/* Set node type */
n->type = EXPR_NODETYPE_VARIABLE;
/*
The fast access method directly accesses the memory address
of the variable's value at evaluation time. Because of this,
we must make sure the variable does exists in the variable list.
*/
/* Get the variable list */
l = exprGetVarList(o);
if(l == NULL)
return EXPR_ERROR_NOVARLIST;
/* Get variable address if already in the list */
exprValListGetAddress(l, buf, &addr);
if(addr == NULL) /* Variable not in the list, add it */
{
exprValListAdd(l, buf, 0.0);
/* Try to get address again */
exprValListGetAddress(l, buf, &addr);
if(addr == NULL) /* Could not add variable */
return EXPR_ERROR_MEMORY; /* Could not add variable to list */
}
n->data.variable.var_addr = addr;
return EXPR_ERROR_NOERROR;
}
else
{
/* we are a value */
if(exprValidNumber(buf) == 0)
return EXPR_ERROR_BADIDENTIFIER;
val = atof(buf);
n->type = EXPR_NODETYPE_VALUE;
n->data.value.value = val;
return EXPR_ERROR_NOERROR;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?