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

📄 parse.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group**********//* * A simple operator-precedence parser for algebraic expressions. * This also handles relational and logical expressions. */#include "spice.h"#include "util.h"#include "cpdefs.h"#include "ftedefs.h"#include "fteparse.h"#include "ftedata.h"#include "ftecmath.h"#include "suffix.h"static bool checkvalid();static struct pnode *parse();static struct element *lexer();static struct pnode *mksnode();static struct pnode *mknnode();static struct pnode *mkfnode();static struct pnode *mkbnode();static struct pnode *mkunode();static struct pnode *makepnode();static int lasttoken = END, lasttype;static char *sbuf;struct pnode *ft_getpnames(wl, check)    wordlist *wl;    bool check;{    struct pnode *pn = NULL, *lpn = NULL, *p;    char *xsbuf;    char buf[BSIZE_SP], *thisone, *s;    if (!wl) {        fprintf(cp_err, "Warning: NULL arithmetic expression\n");        return (NULL);    }    lasttoken = END;    xsbuf = sbuf = wl_flatten(wl);    thisone = sbuf;    while (*sbuf != '\0') {        if (!(p = parse())) {	    tfree(xsbuf);            return (NULL);	}        /* Now snag the name... Much trouble... */        while (isspace(*thisone))            thisone++;        for (s = buf; thisone < sbuf; s++, thisone++)            *s = *thisone;        *s = '\0';        p->pn_name = copy(buf);        if (pn) {            lpn->pn_next = p;            lpn = p;        } else            pn = lpn = p;    }    tfree(xsbuf);    if (check)        if (!checkvalid(pn))            return (NULL);    return (pn);}/* See if there are any variables around which have length 0 and are * not named 'list'. There should really be another flag for this... */static boolcheckvalid(pn)    struct pnode *pn;{    while (pn) {        if (pn->pn_value) {            if ((pn->pn_value->v_length == 0) &&                 !eq(pn->pn_value->v_name, "list")) {                if (eq(pn->pn_value->v_name, "all"))                    fprintf(cp_err,                    "Error: %s: no matching vectors.\n",                        pn->pn_value->v_name);                else                    fprintf(cp_err,                        "Error: %s: no such vector.\n",                        pn->pn_value->v_name);                return (false);            }        } else if (pn->pn_func ||                 (pn->pn_op && (pn->pn_op->op_arity == 1))) {            if (!checkvalid(pn->pn_left))                return (false);        } else if (pn->pn_op && (pn->pn_op->op_arity == 2)) {            if (!checkvalid(pn->pn_left))                return (false);            if (!checkvalid(pn->pn_right))                return (false);        } else            fprintf(cp_err,                 "checkvalid: Internal Error: bad node\n");        pn = pn->pn_next;    }    return (true);}/* Everything else is a string or a number. Quoted strings are kept in  * the form "string", and the lexer strips off the quotes... */static struct element *lexer(){    double *td;    int j = 0;    static struct element el;    static struct element end = { END };    static char *specials = " \t%()-^+*,/|&<>~=";    static bool bracflag = false;    char *ss, *s;    int atsign;    if (bracflag) {        bracflag = false;        el.e_token = LPAREN;        goto done;    }    el.e_token = END;    while ((*sbuf == ' ') || (*sbuf == '\t'))        sbuf++;    if (*sbuf == '\0')        goto done;    switch (*sbuf) {        case '-':        if ((lasttoken == VALUE) || (lasttoken == RPAREN))            el.e_token = MINUS;        else            el.e_token = UMINUS;        sbuf++;        break;        case '+':        el.e_token = PLUS;         sbuf++;        break;        case ',':        el.e_token = COMMA;        sbuf++;        break;        case '*':        el.e_token = TIMES;         sbuf++;        break;        case '%':        el.e_token = MOD;         sbuf++;        break;        case '/':        el.e_token = DIVIDE;         sbuf++;        break;        case '^':        el.e_token = POWER;         sbuf++;        break;        case '[':        if (sbuf[1] == '[') {            el.e_token = RANGE;            sbuf += 2;        } else {            el.e_token = INDX;            sbuf++;        }        bracflag = true;        break;        case '(':        if (((lasttoken == VALUE) && ((lasttype == NUM))) || (lasttoken                == RPAREN)) {            el = end;            goto done;        } else {            el.e_token = LPAREN;             sbuf++;            break;        }        case ']':        el.e_token = RPAREN;         if (sbuf[1] == ']')            sbuf += 2;        else            sbuf++;        break;        case ')':        el.e_token = RPAREN;         sbuf++;        break;        case '=':        el.e_token = EQ;        sbuf++;        break;        case '>':        case '<':        for (j = 0; isspace(sbuf[j]); j++)            ; /* The lexer makes <> into < > */        if (((sbuf[j] == '<') || (sbuf[j] == '>')) &&                (sbuf[0] != sbuf[j])) {            /* Allow both <> and >< for NE. */            el.e_token = NE;            sbuf += 2 + j;        } else if (sbuf[1] == '=') {            if (sbuf[0] == '>')                el.e_token = GE;            else                el.e_token = LE;            sbuf += 2;        } else {            if (sbuf[0] == '>')                el.e_token = GT;            else                el.e_token = LT;            sbuf++;        }        break;        case '&':        el.e_token = AND;        sbuf++;        break;        case '|':        el.e_token = OR;        sbuf++;        break;        case '~':        el.e_token = NOT;        sbuf++;        break;        case '"':        if ((lasttoken == VALUE) || (lasttoken == RPAREN)) {            el = end;            goto done;        }        el.e_token = VALUE;        el.e_type = STRING;        el.e_string = copy(++sbuf);        for (s = el.e_string; *s && (*s != '"'); s++, sbuf++)            ;        *s = '\0';        sbuf++;        break;    }    if (el.e_token != END)        goto done;    ss = sbuf;    td = ft_numparse(&ss, false);    if ((!ss || *ss != ':') && td) {        if ((lasttoken == VALUE) || (lasttoken == RPAREN)) {            el = end;            goto done;        }        el.e_double = *td;        el.e_type = NUM;        el.e_token = VALUE;        sbuf = ss;        if (ft_parsedb)            fprintf(stderr, "lexer: double %G\n",                    el.e_double);    } else {        /* First, let's check for eq, ne, and so on. */        if ((sbuf[0] == 'g') && (sbuf[1] == 't') &&                 index(specials, sbuf[2])) {            el.e_token = GT;            sbuf += 2;        } else if ((sbuf[0] == 'l') && (sbuf[1] == 't') &&                 index(specials, sbuf[2])) {            el.e_token = LT;            sbuf += 2;        } else if ((sbuf[0] == 'g') && (sbuf[1] == 'e') &&                 index(specials, sbuf[2])) {            el.e_token = GE;            sbuf += 2;        } else if ((sbuf[0] == 'l') && (sbuf[1] == 'e') &&                 index(specials, sbuf[2])) {            el.e_token = LE;            sbuf += 2;        } else if ((sbuf[0] == 'n') && (sbuf[1] == 'e') &&                 index(specials, sbuf[2])) {            el.e_token = NE;            sbuf += 2;        } else if ((sbuf[0] == 'e') && (sbuf[1] == 'q') &&                 index(specials, sbuf[2])) {            el.e_token = EQ;            sbuf += 2;        } else if ((sbuf[0] == 'o') && (sbuf[1] == 'r') &&                 index(specials, sbuf[2])) {            el.e_token = OR;            sbuf += 2;        } else if ((sbuf[0] == 'a') && (sbuf[1] == 'n') &&                 (sbuf[2] == 'd') && index(specials, sbuf[3])) {            el.e_token = AND;            sbuf += 3;        } else if ((sbuf[0] == 'n') && (sbuf[1] == 'o') &&                 (sbuf[2] == 't') && index(specials, sbuf[3])) {            el.e_token = NOT;            sbuf += 3;        } else {            if ((lasttoken == VALUE) || (lasttoken == RPAREN)) {                el = end;                goto done;            }            el.e_string = copy(sbuf);	/* XXXX !!!! */            /* It is bad how we have to recognise '[' -- sometimes             * it is part of a word, when it defines a parameter             * name, and otherwise it isn't.             */	    atsign = 0;            for (s = el.e_string; *s && !index(specials, *s); s++, sbuf++) {                if (*s == '@')		    atsign = 1;                else if (*s == '[' && !atsign)                    break;	    }            if (*s)                *s = '\0';            el.e_type = STRING;            el.e_token = VALUE;            if (ft_parsedb)                fprintf(stderr, "lexer: string %s\n",                        el.e_string);        }    }done:    lasttoken = el.e_token;    lasttype = el.e_type;    if (ft_parsedb)        fprintf(stderr, "lexer: token %d\n", el.e_token);    return (&el);}/* The operator-precedence parser. */#define G 1 /* Greater than. */#define L 2 /* Less than. */#define E 3 /* Equal. */#define R 4 /* Error. */#define STACKSIZE 200static char prectable[23][23] = {       /* $  +  -  *  %  /  ^  u- (  )  ,  v  =  >  <  >= <= <> &  |  ~ IDX R *//* $ */ { R, L, L, L, L, L, L, L, L, R, L, L, L, L, L, L, L, L, L, L, L, L, L },/* + */ { G, G, G, L, L, L, L, L, L, G, G, L, G, G, G, G, G, G, G, G, G, L, L },/* - */ { G, G, G, L, L, L, L, L, L, G, G, L, G, G, G, G, G, G, G, G, G, L, L },/* * */ { G, G, G, G, G, G, L, L, L, G, G, L, G, G, G, G, G, G, G, G, G, L, L },/* % */ { G, G, G, G, G, G, L, L, L, G, G, L, G, G, G, G, G, G, G, G, G, L, L },/* / */ { G, G, G, G, G, G, L, L, L, G, G, L, G, G, G, G, G, G, G, G, G, L, L },/* ^ */ { G, G, G, G, G, G, L, L, L, G, G, L, G, G, G, G, G, G, G, G, G, L, L },/* u-*/ { G, G, G, G, G, G, G, G, L, G, G, L, G, G, G, G, G, G, G, G, G, L, L },/* ( */ { R, L, L, L, L, L, L, L, L, E, L, L, L, L, L, L, L, L, L, L, L, L, L },/* ) */ { G, G, G, G, G, G, G, G, R, G, G, R, G, G, G, G, G, G, G, G, G, G, G },/* , */ { G, L, L, L, L, L, L, L, L, G, L, L, G, G, G, G, G, G, G, G, G, L, L },/* v */ { G, G, G, G, G, G, G, G, G, G, G, R, G, G, G, G, G, G, G, G, G, G, G },/* = */ { G, L, L, L, L, L, L, L, L, G, L, L, G, G, G, G, G, G, G, G, L, L, L },/* > */ { G, L, L, L, L, L, L, L, L, G, L, L, G, G, G, G, G, G, G, G, L, L, L },/* < */ { G, L, L, L, L, L, L, L, L, G, L, L, G, G, G, G, G, G, G, G, L, L, L },/* >=*/ { G, L, L, L, L, L, L, L, L, G, L, L, G, G, G, G, G, G, G, G, L, L, L },/* <=*/ { G, L, L, L, L, L, L, L, L, G, L, L, G, G, G, G, G, G, G, G, L, L, L },/* <>*/ { G, L, L, L, L, L, L, L, L, G, L, L, G, G, G, G, G, G, G, G, L, L, L },/* & */ { G, L, L, L, L, L, L, L, L, G, L, L, L, L, L, L, L, L, G, G, L, L, L },/* | */ { G, L, L, L, L, L, L, L, L, G, L, L, L, L, L, L, L, L, L, G, L, L, L },/* ~ */ { G, L, L, L, L, L, L, L, L, G, L, L, G, G, G, G, G, G, G, G, G, L, L },/*INDX*/{ G, G, G, G, G, G, G, G, L, G, G, L, G, G, G, G, G, G, G, G, G, G, L },/*RAN*/ { G, G, G, G, G, G, G, G, L, G, G, L, G, G, G, G, G, G, G, G, G, G, G }} ;/* Return an expr. */static struct pnode *parse(){    struct element stack[STACKSIZE];    int sp = 0, st, i;    struct element *top, *next;    struct pnode *pn, *lpn, *rpn;    char rel;

⌨️ 快捷键说明

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