📄 inpptree.c
字号:
stack[0].token = TOK_END; next = PTlexer(line); while ((sp > 1) || (next->token != TOK_END)) { /* Find the top-most terminal. */ i = sp; do { top = &stack[i--]; } while (top->token == TOK_VALUE); switch (prectable[top->token][next->token]) { case L: case E: /* Push the token read. */ if (sp == (PT_STACKSIZE - 1)) { fprintf(stderr, "Error: stack overflow\n"); return (NULL); } bcopy((char *) next, (char *) &stack[++sp], sizeof (PTelement)); next = PTlexer(line); continue; case R: fprintf(stderr, "Syntax error.\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].token == TOK_VALUE) sp--; while (sp > 0) { if (stack[sp - 1].token == TOK_VALUE) i = 2; /* No 2 pnodes together... */ else i = 1; if (prectable[stack[sp - i].token] [stack[sp].token] == L) break; else sp = sp - i; } if (stack[sp - 1].token == TOK_VALUE) sp--; /* Now try and see what we can make of this. * The possibilities are: - node * node op node * ( node ) * func ( node ) * func ( node, node, node, ... ) <- new * node */ if (st == sp) { pn = makepnode(&stack[st]); if (pn == NULL) goto err; } else if ((stack[sp].token == TOK_UMINUS) && (st == sp + 1)) { lpn = makepnode(&stack[st]); if (lpn == NULL) goto err; pn = mkfnode("-", lpn); } else if ((stack[sp].token == TOK_LPAREN) && (stack[st].token == TOK_RPAREN)) { pn = makepnode(&stack[sp + 1]); if (pn == NULL) goto err; } else if ((stack[sp + 1].token == TOK_LPAREN) && (stack[st].token == TOK_RPAREN)) { lpn = makepnode(&stack[sp + 2]); if ((lpn == NULL) || (stack[sp].type != TYP_STRING)) goto err; if (!(pn = mkfnode(stack[sp].value.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].token, lpn, rpn); } stack[sp].token = TOK_VALUE; stack[sp].type = TYP_PNODE; stack[sp].value.pnode = pn; continue; } } pn = makepnode(&stack[1]); if (pn) return (pn);err: fprintf(stderr, "Syntax error.\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 INPparseNode *makepnode(elem) PTelement *elem;{ if (elem->token != TOK_VALUE) return (NULL); switch (elem->type) { case TYP_STRING: return (mksnode(elem->value.string)); case TYP_NUM: return (mknnode(elem->value.real)); case TYP_PNODE: return (elem->value.pnode); default: fprintf(stderr, "Internal Error: bad token type\n"); return (NULL); } }/* Binop node. */static INPparseNode *mkbnode(opnum, arg1, arg2) int opnum; INPparseNode *arg1, *arg2;{ INPparseNode *p; int i; for (i = 0; i < NUM_OPS; i++) if (ops[i].number == opnum) break; if (i == NUM_OPS) { fprintf(stderr, "Internal Error: no such op num %d\n", opnum); return (NULL); } p = (INPparseNode *) MALLOC(sizeof (INPparseNode)); p->type = opnum; p->funcname = ops[i].name; p->function = ops[i].funcptr; p->left = arg1; p->right = arg2; return (p);}static INPparseNode *mkfnode(fname, arg) char *fname; INPparseNode *arg;{ int i; INPparseNode *p; char buf[128], *name, *s; IFvalue temp; /* Make sure the case is ok. */ (void) strcpy(buf, fname); for (s = buf; *s; s++) if (isupper(*s)) *s = tolower(*s); p = (INPparseNode *) MALLOC(sizeof (INPparseNode)); if (!strcmp(buf, "v")) { name = MALLOC(128); if (arg->type == PT_PLACEHOLDER) { strcpy(name, arg->funcname); } else if (arg->type == PT_CONSTANT) { (void) sprintf(name, "%d", (int) arg->constant); } else if (arg->type != PT_COMMA) { fprintf(stderr, "Error: badly formed node voltage\n"); return (NULL); } if (arg->type == PT_COMMA) { /* Change v(a,b) into v(a) - v(b) */ p = mkb(PT_MINUS, mkfnode(fname, arg->left), mkfnode(fname, arg->right)); } else { /* printf("getting a node called '%s'\n", name); */ INPtermInsert(circuit, &name, tables, &(temp.nValue)); for (i = 0; i < numvalues; i++) if ((types[i] == IF_NODE) && (values[i].nValue == temp.nValue)) break; if (i == numvalues) { if (numvalues) { values = (IFvalue *) REALLOC((char *) values, (numvalues + 1) * sizeof (IFvalue)); types = (int *) REALLOC((char *) types, (numvalues + 1) * sizeof (int)); } else { values = (IFvalue *) MALLOC(sizeof (IFvalue)); types = (int *) MALLOC(sizeof (int)); } values[i] = temp; types[i] = IF_NODE; numvalues++; } p->valueIndex = i; p->type = PT_VAR; } } else if (!strcmp(buf, "i")) { name = MALLOC(128); if (arg->type == PT_PLACEHOLDER) strcpy(name, arg->funcname); else if (arg->type == PT_CONSTANT) (void) sprintf(name, "%d", (int) arg->constant); else { fprintf(stderr, "Error: badly formed branch current\n"); return (NULL); }/* printf("getting a device called '%s'\n", name); */ INPinsert(&name, tables); for (i = 0; i < numvalues; i++) if ((types[i] == IF_INSTANCE) && (values[i].uValue == temp.uValue)) break; if (i == numvalues) { if (numvalues) { values = (IFvalue *) REALLOC((char *) values, (numvalues + 1) * sizeof (IFvalue)); types = (int *) REALLOC((char *) types, (numvalues + 1) * sizeof (int)); } else { values = (IFvalue *) MALLOC(sizeof (IFvalue)); types = (int *) MALLOC(sizeof (int)); } values[i].uValue = (IFuid) name; types[i] = IF_INSTANCE; numvalues++; } p->valueIndex = i; p->type = PT_VAR; } else { for (i = 0; i < NUM_FUNCS; i++) if (!strcmp(funcs[i].name, buf)) break; if (i == NUM_FUNCS) { fprintf(stderr, "Error: no such function '%s'\n", buf); return (NULL); } p->type = PT_FUNCTION; p->left = arg; p->funcname = funcs[i].name; p->funcnum = funcs[i].number; p->function = funcs[i].funcptr; } return (p);}/* Number node. */static INPparseNode *mknnode(number) double number;{ struct INPparseNode *p; p = (INPparseNode *) MALLOC(sizeof (INPparseNode)); p->type = PT_CONSTANT; p->constant = number; return (p);}/* String node. */static INPparseNode *mksnode(string) char *string;{ int i, j; char buf[128], *s; INPparseNode *p; /* Make sure the case is ok. */ (void) strcpy(buf, string); for (s = buf; *s; s++) if (isupper(*s)) *s = tolower(*s); p = (INPparseNode *) MALLOC(sizeof (INPparseNode)); /* First see if it's something special. */ for (i = 0; i < ft_sim->numSpecSigs; i++) if (!strcmp(ft_sim->specSigs[i], buf)) break; if (i < ft_sim->numSpecSigs) { for (j = 0; j < numvalues; j++) if ((types[j] == IF_STRING) && !strcmp(buf, values[i].sValue)) break; if (j == numvalues) { if (numvalues) { values = (IFvalue *) REALLOC((char *) values, (numvalues + 1) * sizeof (IFvalue)); types = (int *) REALLOC((char *) types, (numvalues + 1) * sizeof (int)); } else { values = (IFvalue *) MALLOC(sizeof (IFvalue)); types = (int *) MALLOC(sizeof (int)); } values[i].sValue = MALLOC(strlen(buf) + 1); strcpy(values[i].sValue, buf); types[i] = IF_STRING; numvalues++; } p->valueIndex = i; p->type = PT_VAR; return (p); } for (i = 0; i < NUM_CONSTANTS; i++) if (!strcmp(constants[i].name, buf)) break; if (i == NUM_CONSTANTS) { /* We'd better save this in case it's part of i(something). */ p->type = PT_PLACEHOLDER; p->funcname = string; } else { p->type = PT_CONSTANT; p->constant = constants[i].value; } return (p);}/* The lexical analysis routine. */static PTelement *PTlexer(line) char **line;{ double td; int err; static PTelement el; static char *specials = " \t()^+-*/,"; static int lasttoken = TOK_END, lasttype; char *sbuf, *s; sbuf = *line;#ifdef notdef printf("entering lexer, sbuf = '%s', lastoken = %d, lasttype = %d\n", sbuf, lasttoken, lasttype);#endif while ((*sbuf == ' ') || (*sbuf == '\t') || (*sbuf == '=')) sbuf++; switch (*sbuf) { case '\0': el.token = TOK_END; break; case ',': el.token = TOK_COMMA; sbuf++; break; case '-': if ((lasttoken == TOK_VALUE) || (lasttoken == TOK_RPAREN)) el.token = TOK_MINUS; else el.token = TOK_UMINUS; sbuf++; break; case '+': el.token = TOK_PLUS; sbuf++; break; case '*': el.token = TOK_TIMES; sbuf++; break; case '/': el.token = TOK_DIVIDE; sbuf++; break; case '^': el.token = TOK_POWER; sbuf++; break; case '(': if (((lasttoken == TOK_VALUE) && ((lasttype == TYP_NUM))) || (lasttoken == TOK_RPAREN)) { el.token = TOK_END; } else { el.token = TOK_LPAREN; sbuf++; } break; case ')': el.token = TOK_RPAREN; sbuf++; break; default: if ((lasttoken == TOK_VALUE) || (lasttoken == TOK_RPAREN)) { el.token = TOK_END; break; } td = INPevaluate(&sbuf, &err, 0); if (err == OK) { el.token = TOK_VALUE; el.type = TYP_NUM; el.value.real = td; } else { el.token = TOK_VALUE; el.type = TYP_STRING; for (s = sbuf; *s; s++) if (index(specials, *s)) break; el.value.string = MALLOC(s - sbuf + 1); strncpy(el.value.string, sbuf, s - sbuf); el.value.string[s - sbuf] = '\0'; sbuf = s; } } lasttoken = el.token; lasttype = el.type; *line = sbuf;/* printf("PTlexer: token = %d, type = %d, left = '%s'\n", el.token, el.type, sbuf); */ return (&el);}#ifdef notdef/* Debugging stuff. */#ifdef __STDC__void printTree(INPparseNode*);#else /* stdc */void printTree();#endif /* stdc */voidINPptPrint(str, ptree) char *str; IFparseTree *ptree;{ int i; printf("%s\n\t", str); printTree(((INPparseTree *) ptree)->tree); printf("\n"); for (i = 0; i < ptree->numVars; i++) { printf("d / d v%d : ", i); printTree(((INPparseTree *) ptree)->derivs[i]); printf("\n"); } return;}voidprintTree(pt) INPparseNode *pt;{ switch (pt->type) { case PT_CONSTANT: printf("%g", pt->constant); break; case PT_VAR: printf("v%d", pt->valueIndex); break; case PT_PLUS: printf("("); printTree(pt->left); printf(") + ("); printTree(pt->right); printf(")"); break; case PT_MINUS: printf("("); printTree(pt->left); printf(") - ("); printTree(pt->right); printf(")"); break; case PT_TIMES: printf("("); printTree(pt->left); printf(") * ("); printTree(pt->right); printf(")"); break; case PT_DIVIDE: printf("("); printTree(pt->left); printf(") / ("); printTree(pt->right); printf(")"); break; case PT_POWER: printf("("); printTree(pt->left); printf(") ^ ("); printTree(pt->right); printf(")"); break; case PT_FUNCTION: printf("%s (", pt->funcname); printTree(pt->left); printf(")"); break; default: printf("oops"); break; } return;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -