numparm, cleanup rewrite formula()
This commit is contained in:
parent
e5e08b6f93
commit
2f508696a6
|
|
@ -765,19 +765,19 @@ parseunit(const char *s)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
fetchid(const char *s, SPICE_DSTRINGPTR t, int ls, int i)
|
||||
static const char *
|
||||
fetchid(SPICE_DSTRINGPTR t, const char *s_end, const char *iptr)
|
||||
/* copy next identifier from s into t, advance and return scan index i */
|
||||
{
|
||||
char c;
|
||||
bool ok;
|
||||
|
||||
c = s[i];
|
||||
i++;
|
||||
c = *iptr;
|
||||
iptr++;
|
||||
|
||||
while (!alfa(c) && (i < ls)) {
|
||||
i++;
|
||||
c = s[i - 1];
|
||||
while (!alfa(c) && (iptr < s_end)) {
|
||||
iptr++;
|
||||
c = iptr[-1];
|
||||
}
|
||||
|
||||
spice_dstring_reinit(t);
|
||||
|
|
@ -785,9 +785,9 @@ fetchid(const char *s, SPICE_DSTRINGPTR t, int ls, int i)
|
|||
|
||||
do
|
||||
{
|
||||
i++;
|
||||
if (i <= ls)
|
||||
c = s[i - 1];
|
||||
iptr++;
|
||||
if (iptr <= s_end)
|
||||
c = iptr[-1];
|
||||
else
|
||||
c = '\0';
|
||||
|
||||
|
|
@ -799,33 +799,31 @@ fetchid(const char *s, SPICE_DSTRINGPTR t, int ls, int i)
|
|||
|
||||
} while (ok);
|
||||
|
||||
return i; /* return updated i */
|
||||
return iptr; /* return updated iptr */
|
||||
}
|
||||
|
||||
|
||||
static double
|
||||
exists(tdico *d, const char *s, int *pi, bool *perror)
|
||||
exists(tdico *d, const char *s_end, const char **pi, bool *perror)
|
||||
/* check if s in simboltable 'defined': expect (ident) and return 0 or 1 */
|
||||
{
|
||||
bool error = *perror;
|
||||
int i = *pi;
|
||||
const char *iptr = *pi;
|
||||
double x;
|
||||
int ls;
|
||||
char c;
|
||||
bool ok;
|
||||
SPICE_DSTRING t;
|
||||
|
||||
ls = length(s);
|
||||
spice_dstring_init(&t);
|
||||
x = 0.0;
|
||||
|
||||
do
|
||||
{
|
||||
i++;
|
||||
if (i > ls)
|
||||
iptr++;
|
||||
if (iptr > s_end)
|
||||
c = '\0';
|
||||
else
|
||||
c = s[i - 1];
|
||||
c = iptr[-1];
|
||||
|
||||
ok = (c == '(');
|
||||
|
||||
|
|
@ -833,20 +831,20 @@ exists(tdico *d, const char *s, int *pi, bool *perror)
|
|||
|
||||
if (ok)
|
||||
{
|
||||
i--;
|
||||
i = fetchid(s, &t, ls, i);
|
||||
i--;
|
||||
iptr--;
|
||||
iptr = fetchid(&t, s_end, iptr);
|
||||
iptr--;
|
||||
if (entrynb(d, spice_dstring_value(&t)))
|
||||
x = 1.0;
|
||||
|
||||
do
|
||||
{
|
||||
i++;
|
||||
iptr++;
|
||||
|
||||
if (i > ls)
|
||||
if (iptr > s_end)
|
||||
c = '\0';
|
||||
else
|
||||
c = s[i - 1];
|
||||
c = iptr[-1];
|
||||
|
||||
ok = (c == ')');
|
||||
|
||||
|
|
@ -859,7 +857,7 @@ exists(tdico *d, const char *s, int *pi, bool *perror)
|
|||
/* keep pointer on last closing ")" */
|
||||
|
||||
*perror = error;
|
||||
*pi = i;
|
||||
*pi = iptr;
|
||||
spice_dstring_free(&t);
|
||||
|
||||
return x;
|
||||
|
|
@ -867,13 +865,13 @@ exists(tdico *d, const char *s, int *pi, bool *perror)
|
|||
|
||||
|
||||
static double
|
||||
fetchnumber(tdico *dico, const char *s, int *pi, bool *perror)
|
||||
fetchnumber(tdico *dico, const char **pi, bool *perror)
|
||||
/* parse a Spice number in string s */
|
||||
{
|
||||
double u;
|
||||
int n = 0;
|
||||
|
||||
s += *pi;
|
||||
const char *s = *pi;
|
||||
|
||||
if (1 != sscanf(s, "%lG%n", &u, &n)) {
|
||||
|
||||
|
|
@ -901,49 +899,49 @@ fetchnumber(tdico *dico, const char *s, int *pi, bool *perror)
|
|||
|
||||
static char
|
||||
fetchoperator(tdico *dico,
|
||||
const char *s, int ls,
|
||||
int *pi,
|
||||
const char *s_end,
|
||||
const char **pi,
|
||||
unsigned char *pstate, unsigned char *plevel,
|
||||
bool *perror)
|
||||
/* grab an operator from string s and advance scan index pi.
|
||||
each operator has: one-char alias, precedence level, new interpreter state.
|
||||
*/
|
||||
{
|
||||
int i = *pi;
|
||||
const char *iptr = *pi;
|
||||
unsigned char state = *pstate;
|
||||
unsigned char level = *plevel;
|
||||
bool error = *perror;
|
||||
char c, d;
|
||||
|
||||
c = s[i];
|
||||
i++;
|
||||
c = *iptr;
|
||||
iptr++;
|
||||
|
||||
if (i < ls)
|
||||
d = s[i];
|
||||
if (iptr < s_end)
|
||||
d = iptr[0];
|
||||
else
|
||||
d = '\0';
|
||||
|
||||
if ((c == '!') && (d == '=')) {
|
||||
c = '#';
|
||||
i++;
|
||||
iptr++;
|
||||
} else if ((c == '<') && (d == '>')) {
|
||||
c = '#';
|
||||
i++;
|
||||
iptr++;
|
||||
} else if ((c == '<') && (d == '=')) {
|
||||
c = 'L';
|
||||
i++;
|
||||
iptr++;
|
||||
} else if ((c == '>') && (d == '=')) {
|
||||
c = 'G';
|
||||
i++;
|
||||
iptr++;
|
||||
} else if ((c == '*') && (d == '*')) {
|
||||
c = '^';
|
||||
i++;
|
||||
iptr++;
|
||||
} else if ((c == '=') && (d == '=')) {
|
||||
i++;
|
||||
iptr++;
|
||||
} else if ((c == '&') && (d == '&')) {
|
||||
i++;
|
||||
iptr++;
|
||||
} else if ((c == '|') && (d == '|')) {
|
||||
i++;
|
||||
iptr++;
|
||||
} if ((c == '+') || (c == '-')) {
|
||||
state = S_binop; /* pending operator */
|
||||
level = 4;
|
||||
|
|
@ -970,7 +968,7 @@ fetchoperator(tdico *dico,
|
|||
error = message(dico, "Syntax error: letter [%c]", c);
|
||||
}
|
||||
|
||||
*pi = i;
|
||||
*pi = iptr;
|
||||
*pstate = state;
|
||||
*plevel = level;
|
||||
*perror = error;
|
||||
|
|
@ -1137,7 +1135,7 @@ operate(char op, double x, double y)
|
|||
|
||||
|
||||
static double
|
||||
formula(tdico *dico, const char *s, bool *perror)
|
||||
formula(tdico *dico, const char *s, const char *s_end, bool *perror)
|
||||
{
|
||||
/* Expression parser.
|
||||
s is a formula with parentheses and math ops +-* / ...
|
||||
|
|
@ -1156,10 +1154,14 @@ formula(tdico *dico, const char *s, bool *perror)
|
|||
double accu[nprece + 1];
|
||||
char oper[nprece + 1];
|
||||
char uop[nprece + 1];
|
||||
int i, k, ls, natom, arg2, arg3;
|
||||
int i, k, natom;
|
||||
char c, d;
|
||||
bool ok;
|
||||
SPICE_DSTRING tstr;
|
||||
const char *iptr;
|
||||
const char *kptr;
|
||||
const char *arg2;
|
||||
const char *arg3;
|
||||
|
||||
spice_dstring_init(&tstr);
|
||||
|
||||
|
|
@ -1168,11 +1170,11 @@ formula(tdico *dico, const char *s, bool *perror)
|
|||
oper[i] = ' ';
|
||||
}
|
||||
|
||||
i = 0;
|
||||
ls = length(s);
|
||||
iptr = s;
|
||||
|
||||
while ((ls > 0) && (s[ls - 1] <= ' '))
|
||||
ls--; /* clean s */
|
||||
/* trim trailing whitespace */
|
||||
while ((s_end > s) && (s_end[-1] <= ' '))
|
||||
s_end--;
|
||||
|
||||
state = S_init;
|
||||
natom = 0;
|
||||
|
|
@ -1183,25 +1185,25 @@ formula(tdico *dico, const char *s, bool *perror)
|
|||
error = 0;
|
||||
level = 0;
|
||||
|
||||
while ((i < ls) && !error) {
|
||||
i++;
|
||||
c = s[i - 1];
|
||||
while ((iptr < s_end) && !error) {
|
||||
iptr++;
|
||||
c = iptr[-1];
|
||||
if (c == '(') {
|
||||
/* sub-formula or math function */
|
||||
level = 1;
|
||||
/* new: must support multi-arg functions */
|
||||
k = i;
|
||||
arg2 = 0;
|
||||
kptr = iptr;
|
||||
arg2 = NULL;
|
||||
v = 1.0;
|
||||
arg3 = 0;
|
||||
arg3 = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
k++;
|
||||
if (k > ls)
|
||||
kptr++;
|
||||
if (kptr > s_end)
|
||||
d = '\0';
|
||||
else
|
||||
d = s[k - 1];
|
||||
d = kptr[-1];
|
||||
|
||||
if (d == '(')
|
||||
level++;
|
||||
|
|
@ -1209,30 +1211,27 @@ formula(tdico *dico, const char *s, bool *perror)
|
|||
level--;
|
||||
|
||||
if ((d == ',') && (level == 1)) {
|
||||
if (arg2 == 0)
|
||||
arg2 = k;
|
||||
if (arg2 == NULL)
|
||||
arg2 = kptr;
|
||||
else
|
||||
arg3 = k; /* kludge for more than 2 args (ternary expression) */
|
||||
arg3 = kptr; /* kludge for more than 2 args (ternary expression) */
|
||||
} /* comma list? */
|
||||
|
||||
} while ((k <= ls) && !((d == ')') && (level <= 0)));
|
||||
} while ((kptr <= s_end) && !((d == ')') && (level <= 0)));
|
||||
|
||||
if (k > ls) {
|
||||
if (kptr > s_end) {
|
||||
error = message(dico, "Closing \")\" not found.");
|
||||
natom++; /* shut up other error message */
|
||||
} else {
|
||||
if (arg2 > i) {
|
||||
pscopy(&tstr, s, i, arg2 - i - 1);
|
||||
v = formula(dico, spice_dstring_value(&tstr), &error);
|
||||
i = arg2;
|
||||
if (arg2 > iptr) {
|
||||
v = formula(dico, iptr, arg2 - 1, &error);
|
||||
iptr = arg2;
|
||||
}
|
||||
if (arg3 > i) {
|
||||
pscopy(&tstr, s, i, arg3 - i - 1);
|
||||
w = formula(dico, spice_dstring_value(&tstr), &error);
|
||||
i = arg3;
|
||||
if (arg3 > iptr) {
|
||||
w = formula(dico, iptr, arg3 - 1, &error);
|
||||
iptr = arg3;
|
||||
}
|
||||
pscopy(&tstr, s, i, k - i - 1);
|
||||
u = formula(dico, spice_dstring_value(&tstr), &error);
|
||||
u = formula(dico, iptr, kptr - 1, &error);
|
||||
state = S_atom;
|
||||
if (fu > 0) {
|
||||
if ((fu == 18))
|
||||
|
|
@ -1251,13 +1250,13 @@ formula(tdico *dico, const char *s, bool *perror)
|
|||
u = mathfunction(fu, v, u);
|
||||
}
|
||||
}
|
||||
i = k;
|
||||
iptr = kptr;
|
||||
fu = 0;
|
||||
} else if (alfa(c)) {
|
||||
i--;
|
||||
i = fetchid(s, &tstr, ls, i); /* user id, but sort out keywords */
|
||||
iptr--;
|
||||
iptr = fetchid(&tstr, s_end, iptr); /* user id, but sort out keywords */
|
||||
state = S_atom;
|
||||
i--;
|
||||
iptr--;
|
||||
kw = keyword(&keyS, &tstr); /* debug ws('[',kw,']'); */
|
||||
if (kw == 0) {
|
||||
fu = keyword(&fmathS, &tstr); /* numeric function? */
|
||||
|
|
@ -1269,19 +1268,20 @@ formula(tdico *dico, const char *s, bool *perror)
|
|||
c = opfunctkey(dico, kw, c, &state, &level, &error);
|
||||
}
|
||||
|
||||
if (kw == Defd)
|
||||
u = exists(dico, s, &i, &error);
|
||||
if (kw == Defd) {
|
||||
u = exists(dico, s_end, &iptr, &error);
|
||||
}
|
||||
} else if (((c == '.') || ((c >= '0') && (c <= '9')))) {
|
||||
i--;
|
||||
u = fetchnumber(dico, s, &i, &error);
|
||||
iptr--;
|
||||
u = fetchnumber(dico, &iptr, &error);
|
||||
if (negate) {
|
||||
u = -1 * u;
|
||||
negate = 0;
|
||||
}
|
||||
state = S_atom;
|
||||
} else {
|
||||
i--;
|
||||
c = fetchoperator(dico, s, ls, &i, &state, &level, &error);
|
||||
iptr--;
|
||||
c = fetchoperator(dico, s_end, &iptr, &state, &level, &error);
|
||||
}
|
||||
|
||||
/* may change c to some other operator char! */
|
||||
|
|
@ -1307,7 +1307,7 @@ formula(tdico *dico, const char *s, bool *perror)
|
|||
} else if (state == S_atom) {
|
||||
/* atom pending */
|
||||
natom++;
|
||||
if (i >= ls) {
|
||||
if (iptr >= s_end) {
|
||||
state = S_stop;
|
||||
level = topop;
|
||||
} /* close all ops below */
|
||||
|
|
@ -1416,7 +1416,7 @@ evaluate(tdico *dico, SPICE_DSTRINGPTR qstr_p, char *t, unsigned char mode)
|
|||
"\"%s\" not evaluated.%s", t,
|
||||
nolookup ? " Lookup failure." : "");
|
||||
} else {
|
||||
u = formula(dico, t, &err);
|
||||
u = formula(dico, t, t + strlen(t), &err);
|
||||
numeric = 1;
|
||||
}
|
||||
|
||||
|
|
@ -1956,7 +1956,8 @@ nupa_assignment(tdico *dico, char *s, char mode)
|
|||
dtype = getexpress(s, &ustr, &i);
|
||||
|
||||
if (dtype == 'R') {
|
||||
rval = formula(dico, spice_dstring_value(&ustr), &error);
|
||||
const char *tmp = spice_dstring_value(&ustr);
|
||||
rval = formula(dico, tmp, tmp + strlen(tmp), &error);
|
||||
if (error) {
|
||||
message(dico, " Formula() error.");
|
||||
fprintf(stderr, " %s\n", s);
|
||||
|
|
|
|||
Loading…
Reference in New Issue