📄 parse.c
字号:
stack[0].e_token = END; next = lexer(); while ((sp > 1) || (next->e_token != END)) { /* Find the top-most terminal. */ i = sp; do { top = &stack[i--]; } while (top->e_token == VALUE); rel = prectable[top->e_token][next->e_token]; switch (rel) { case L: case E: /* Push the token read. */ if (sp == (STACKSIZE - 1)) { fprintf(cp_err, "Error: stack overflow\n"); return (NULL); } bcopy((char *) next, (char *) &stack[++sp], sizeof (struct element)); next = lexer(); continue; case R: fprintf(cp_err, "Syntax error: parsing expression.\n"); return (NULL); case G: /* Reduce. Make st and sp point to the elts on the * stack at the end and beginning of the junk to * reduce, then try and do some stuff. When scanning * back for a <, ignore VALUES. */ st = sp; if (stack[sp].e_token == VALUE) sp--; while (sp > 0) { if (stack[sp - 1].e_token == VALUE) i = 2; /* No 2 pnodes together... */ else i = 1; if (prectable[stack[sp - i].e_token] [stack[sp].e_token] == L) break; else sp = sp - i; } if (stack[sp - 1].e_token == VALUE) sp--; /* Now try and see what we can make of this. * The possibilities are: unop node * 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); } 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); } stack[sp].e_token = VALUE; stack[sp].e_type = PNODE; stack[sp].e_pnode = pn; continue; } } pn = makepnode(&stack[1]); if (pn) return (pn);err: fprintf(cp_err, "Syntax error: expression not understood.\n"); 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(elem) 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); } }/* 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 } , { "interpolate",cx_interpolate } , { "deriv", cx_deriv } , { "v", NULL } , { NULL, NULL }} ;struct func func_uminus = { "minus", cx_uminus };struct func func_not = { "not", cx_not };/* Binop node. */static struct pnode *mkbnode(opnum, arg1, arg2) struct pnode *arg1, *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_value = NULL; p->pn_func = NULL; p->pn_op = o; p->pn_left = arg1; p->pn_right = arg2; p->pn_next = NULL; return (p);}/* Unop node. */static struct pnode *mkunode(op, arg) 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_value = NULL; p->pn_func = NULL; p->pn_left = arg; 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(func, arg) 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_name = NULL; p->pn_value = NULL; p->pn_func = f; p->pn_op = NULL; p->pn_left = arg; p->pn_right = NULL; p->pn_next = NULL; return (p);}/* Number node. */static struct pnode *mknnode(number) 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_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(string) char *string;{ struct dvec *v, *nv, *vs, *newv = NULL, *end = NULL; struct pnode *p; p = alloc(struct pnode); 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; return (p);}voidfree_pnode(t) struct pnode *t;{ if (!t) return; free_pnode(t->pn_left); free_pnode(t->pn_right); free_pnode(t->pn_next); tfree(t);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -