⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 2 页
字号:
             *            node op node             *            ( node )             *            func ( node )             *            node             *  node [ node ] is considered node op node.             */            if (st == sp) {                pn = makepnode(&stack[st]);                if (pn == NULL)                    goto err;            } else if (((stack[sp].e_token == UMINUS) ||                    (stack[sp].e_token == NOT)) &&                     (st == sp + 1)) {                lpn = makepnode(&stack[st]);                if (lpn == NULL)                        goto err;                pn = mkunode(stack[sp].e_token, lpn);            } else if ((stack[sp].e_token == LPAREN) &&                       (stack[st].e_token == RPAREN)) {                pn = makepnode(&stack[sp + 1]);                if (pn == NULL)                    goto err;            } else if ((stack[sp + 1].e_token == LPAREN) &&                       (stack[st].e_token == RPAREN)) {                lpn = makepnode(&stack[sp + 2]);                if ((lpn == NULL) || (stack[sp].e_type !=                        STRING))                    goto err;                if (!(pn = mkfnode(stack[sp].e_string, lpn)))                    return (NULL);                /* va: avoid memory leakage:                    in case of variablenames (i.e. i(vd)) mkfnode makes in                    reality a snode, the old lpn (and its plotless vector) is                    then a memory leak */                if (pn->pn_func==NULL && pn->pn_value!=NULL) /* a snode */                {                   if (lpn->pn_value && lpn->pn_value->v_plot==NULL)                   {                       tfree(lpn->pn_value->v_name);                       tfree(lpn->pn_value);                   }                   free_pnode(lpn);                }            } else { /* node op node */                lpn = makepnode(&stack[sp]);                rpn = makepnode(&stack[st]);                if ((lpn == NULL) || (rpn == NULL))                    goto err;                pn = mkbnode(stack[sp + 1].e_token,                     lpn, rpn);            }            /* va: avoid memory leakage: tfree all old strings on stack,                   copied up to now within lexer */            for (i=sp; i<=spmax; i++) {                if (stack[i].e_token==VALUE && stack[i].e_type==STRING) {                    tfree(stack[i].e_string);                }            }            spmax=sp; /* up to there stack is now clean */            stack[sp].e_token = VALUE;            stack[sp].e_type = PNODE;            stack[sp].e_pnode = pn;            continue;        }    }    pn = makepnode(&stack[1]);    /* va: avoid memory leakage: tfree all remaining strings,       copied within lexer */    for (i=0; i<=spmax; i++) {        if (stack[i].e_token == VALUE && stack[i].e_type == STRING) {            tfree(stack[i].e_string);        }    }    if (next->e_token == VALUE && next->e_type == STRING) {        tfree(next->e_string);    }    if (pn)        return (pn);err:    fprintf(cp_err, "Syntax error: expression not understood '%s'.\n", parse_string);    return (NULL);}/* Given a pointer to an element, make a pnode out of it (if it already * is one, return a pointer to it). If it isn't of type VALUE, then return * NULL. */static struct pnode *makepnode(struct element *elem){    if (elem->e_token != VALUE)        return (NULL);    switch (elem->e_type) {        case STRING:            return (mksnode(elem->e_string));        case NUM:            return (mknnode(elem->e_double));        case PNODE:            return (elem->e_pnode);        default:            return (NULL);    }   }/*static char * get_token_name(int e_token){  / see include/fteparse.h /    switch (e_token) {    case   0: return "END   ";    case   1: return "PLUS  ";    case   2: return "MINUS ";    case   3: return "TIMES ";    case   4: return "MOD   ";    case   5: return "DIVIDE";    case   6: return "POWER ";    case   7: return "UMINUS";    case   8: return "LPAREN";    case   9: return "RPAREN";    case  10: return "COMMA ";    case  11: return "VALUE ";    case  12: return "EQ    ";    case  13: return "GT    ";    case  14: return "LT    ";    case  15: return "GE    ";    case  16: return "LE    ";    case  17: return "NE    ";    case  18: return "AND   ";    case  19: return "OR    ";    case  20: return "NOT   ";    case  21: return "INDX  ";    case  22: return "RANGE ";    default : return "UNKNOWN";    }}static void print_elem(struct element *elem){    printf("e_token = %d(%s)", elem->e_token, get_token_name(elem->e_token));     if (elem->e_token == VALUE) {        printf(", e_type  = %d", elem->e_type);         switch (elem->e_type) {            case STRING:                printf(", e_string = %s(%p)", elem->e_string,elem->e_string);                 break;             case NUM:                printf(", e_double = %g", elem->e_double); break;             case PNODE:                printf(", e_pnode  = %p", elem->e_pnode);  break;             default:                break;        }    }       printf("\n");}*//* Some auxiliary functions for building the parse tree. */staticstruct op ops[] = {         { PLUS, "+", 2, op_plus } ,        { MINUS, "-", 2, op_minus } ,        { TIMES, "*", 2, op_times } ,        { MOD, "%", 2, op_mod } ,        { DIVIDE, "/", 2, op_divide } ,        { COMMA, ",", 2, op_comma } ,        { POWER, "^", 2, op_power } ,        { EQ, "=", 2, op_eq } ,        { GT, ">", 2, op_gt } ,        { LT, "<", 2, op_lt } ,        { GE, ">=", 2, op_ge } ,        { LE, "<=", 2, op_le } ,        { NE, "<>", 2, op_ne } ,        { AND, "&", 2, op_and } ,        { OR, "|", 2, op_or } ,        { INDX, "[", 2, op_ind } ,        { RANGE, "[[", 2, op_range } ,        { 0, NULL, 0, NULL }} ;staticstruct op uops[] = {    { UMINUS, "-", 1, op_uminus } ,    { NOT, "~", 1, op_not } ,    { 0, NULL, 0, NULL }} ;/* We have 'v' declared as a function, because if we don't then the defines * we do for vm(), etc won't work. This is caught in evaluate(). Bad kludge. */struct func ft_funcs[] = {        { "mag",    cx_mag } ,        { "magnitude",  cx_mag } ,        { "ph",     cx_ph } ,        { "phase",  cx_ph } ,        { "j",      cx_j } ,        { "real",   cx_real } ,        { "re",     cx_real } ,        { "imag",   cx_imag } ,        { "im",     cx_imag } ,        { "db",     cx_db } ,        { "log",    cx_log } ,        { "log10",  cx_log } ,        { "ln",     cx_ln } ,        { "exp",    cx_exp } ,        { "abs",    cx_mag } ,        { "sqrt",   cx_sqrt } ,        { "sin",    cx_sin } ,        { "cos",    cx_cos } ,        { "tan",    cx_tan } ,        { "atan",   cx_atan } ,        { "norm",   cx_norm } ,        { "rnd",    cx_rnd } ,        { "pos",    cx_pos } ,        { "mean",   cx_mean } ,        { "vector", cx_vector } ,        { "unitvec",    cx_unitvec } ,        { "length", cx_length } ,        { "vecmin", cx_min } ,        { "vecmax", cx_max } ,        { "vecd", cx_d } ,        { "interpolate", cx_interpolate } ,        { "deriv",       cx_deriv } ,        { "v",      NULL } ,        { NULL,     NULL }} ;struct func func_uminus = { "minus", cx_uminus };struct func func_not = { "not", cx_not };/* Binary operator node. */static struct pnode *mkbnode(int opnum, struct pnode *arg1, struct pnode *arg2){    struct op *o;    struct pnode *p;    for (o = &ops[0]; o->op_name; o++)        if (o->op_num == opnum)            break;    if (!o->op_name)        fprintf(cp_err, "mkbnode: Internal Error: no such op num %d\n",                    opnum);    p = alloc(struct pnode);    p->pn_use = 0;    p->pn_value = NULL;    p->pn_name = NULL;	/* sjb */    p->pn_func = NULL;    p->pn_op = o;    p->pn_left = arg1;    if(p->pn_left) p->pn_left->pn_use++;    p->pn_right = arg2;    if(p->pn_right) p->pn_right->pn_use++;    p->pn_next = NULL;    return (p);}/* Unary operator node. */static struct pnode *mkunode(int op, struct pnode *arg){    struct pnode *p;    struct op *o;    p = alloc(struct pnode);    for (o = uops; o->op_name; o++)        if (o->op_num == op)            break;    if (!o->op_name)        fprintf(cp_err, "mkunode: Internal Error: no such op num %d\n",                op);    p->pn_op = o;    p->pn_use = 0;    p->pn_value = NULL;    p->pn_name = NULL;	/* sjb */    p->pn_func = NULL;    p->pn_left = arg;    if(p->pn_left) p->pn_left->pn_use++;    p->pn_right = NULL;    p->pn_next = NULL;    return (p);}/* Function node. We have to worry about a lot of things here. Something * like f(a) could be three things -- a call to a standard function, which * is easiest to deal with, a variable name, in which case we do the * kludge with 0-length lists, or it could be a user-defined function, * in which case we have to figure out which one it is, substitute for * the arguments, and then return a copy of the expression that it was * defined to be. */static struct pnode *mkfnode(char *func, struct pnode *arg){    struct func *f;    struct pnode *p, *q;    struct dvec *d;    char buf[BSIZE_SP], *s;    (void) strcpy(buf, func);    for (s = buf; *s; s++)      /* Make sure the case is ok. */        if (isupper(*s))            *s = tolower(*s);    for (f = &ft_funcs[0]; f->fu_name; f++)        if (eq(f->fu_name, buf))            break;    if (f->fu_name == NULL) {        /* Give the user-defined functions a try. */        q = ft_substdef(func, arg);        if (q)            return (q);    }    if ((f->fu_name == NULL) && arg->pn_value) {        /* Kludge -- maybe it is really a variable name. */        (void) sprintf(buf, "%s(%s)", func, arg->pn_value->v_name);        d = vec_get(buf);        if (d == NULL) {            /* Well, too bad. */            fprintf(cp_err, "Error: no such function as %s.\n",                     func);            return (NULL);        }        /* (void) strcpy(buf, d->v_name); XXX */        return (mksnode(buf));    } else if (f->fu_name == NULL) {        fprintf(cp_err, "Error: no function as %s with that arity.\n",                func);            return (NULL);    }    if (!f->fu_func && arg->pn_op && arg->pn_op->op_num == COMMA) {	p = mkbnode(MINUS, mkfnode(func, arg->pn_left),		mkfnode(func, arg->pn_right));	tfree(arg);	return p;    }    p = alloc(struct pnode);    p->pn_use = 0;    p->pn_name = NULL;    p->pn_value = NULL;    p->pn_func = f;    p->pn_op = NULL;    p->pn_left = arg;    if(p->pn_left) p->pn_left->pn_use++;    p->pn_right = NULL;    p->pn_next = NULL;    return (p);}/* Number node. */static struct pnode *mknnode(double number){    struct pnode *p;    struct dvec *v;    char buf[BSIZE_SP];    p = alloc(struct pnode);    v = alloc(struct dvec);    ZERO(v, struct dvec);    p->pn_use = 0;    p->pn_name = NULL;    p->pn_value = v;    p->pn_func = NULL;    p->pn_op = NULL;    p->pn_left = p->pn_right = NULL;    p->pn_next = NULL;    /* We don't use printnum because it screws up mkfnode above. We have     * to be careful to deal properly with node numbers that are quite     * large...     */    if (number < MAXPOSINT)        (void) sprintf(buf, "%d", (int) number);    else        (void) sprintf(buf, "%G", number);    v->v_name = copy(buf);    v->v_type = SV_NOTYPE;    v->v_flags = VF_REAL;    v->v_realdata = (double *) tmalloc(sizeof (double));    *v->v_realdata = number;    v->v_length = 1;    v->v_plot = NULL;    vec_new(v);    return (p);}/* String node. */static struct pnode *mksnode(char *string){    struct dvec *v, *nv, *vs, *newv = NULL, *end = NULL;    struct pnode *p;    p = alloc(struct pnode);    p->pn_use = 0;    p->pn_name = NULL;    p->pn_func = NULL;    p->pn_op = NULL;    p->pn_left = p->pn_right = NULL;    p->pn_next = NULL;    v = vec_get(string);    if (v == NULL) {        nv = alloc(struct dvec);	ZERO(nv, struct dvec);        p->pn_value = nv;        nv->v_name = copy(string);        return (p);    }    p->pn_value = NULL;    /* It's not obvious that we should be doing this, but... */    for (vs = v; vs; vs = vs->v_link2) {        nv = vec_copy(vs);        vec_new(nv);        if (end)            end->v_link2 = nv;        else            newv = end = nv;        end = nv;    }    p->pn_value = newv;        /* va: tfree v in case of @xxx[par], because vec_get created a new vec and       nobody will free it elsewhere */    if (v && v->v_name && *v->v_name=='@' && isreal(v) && v->v_realdata) {    	vec_free(v);    }    return (p);}/* Don't call this directly, always use the free_pnode() macro.    The linked pnodes do not necessarily form a perfect tree as some nodes get   reused.  Hence, in this recursive walk trough the 'tree' we only free node   that have their pn_use value at zero. Nodes that have pn_use values above   zero have the link severed and their pn_use value decremented.   In addition, we don't walk past nodes with pn_use values avoid zero, just   in case we have a circular reference (this probable does not happen in  practice, but it does no harm playing safe) */voidfree_pnode_x(struct pnode *t){    if (!t)	return;        /* don't walk past nodes used elsewhere. We decrement the pn_use value here,       but the link gets severed by the action of the free_pnode() macro */    if(t->pn_use>1)	t->pn_use--;    else {	/* pn_use is now 1, so its safe to free the pnode */	free_pnode(t->pn_left);	free_pnode(t->pn_right);	free_pnode(t->pn_next);	tfree(t->pn_name); /* va: it is a copy() of original string, can be free'd */	if (t->pn_value)	    vec_free(t->pn_value); /* patch by Stefan Jones */	tfree(t);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -