示例#1
0
/* parse.c 612d */
static Exp parseexp(Par p) {
    switch (p->alt) {
    case ATOM:
        /* parseexp [[atom]] and return the result 612e */
        {
            const char *s = nametostr(p->u.atom);
            char *t;
            long l = strtol(s, &t, 10);
            if (*t == '\0') /* the number is the whole string */
                return mkLiteral(l);
            else
                return mkVar(p->u.atom);
        }
    case LIST:
        /* parseexp [[list]] and return the result 613a */
        {
            Parlist pl;
            Name first;
            Explist argl;

            pl = p->u.list;
            if (pl == NULL)
                error("%p: empty list in input", p);
            if (pl->hd->alt != ATOM)
                error("%p: first item of list not name", p);

            first = pl->hd->u.atom;
            argl  = parselist(pl->tl);
            if (first == strtoname("begin")) {
                /* parseexp [[begin]] and return the result 613b */
                return mkBegin(argl);
            } else if (first == strtoname("if")) {
                /* parseexp [[if]] and return the result 613c */
                if (lengthEL(argl) != 3)
                    error("%p: usage: (if cond true false)", p);
                return mkIfx(nthEL(argl, 0), nthEL(argl, 1), nthEL(argl, 2));
            } else if (first == strtoname("set")) {
                /* parseexp [[set]] and return the result 613e */
                if (lengthEL(argl) != 2)
                    error("%p: usage: (set var exp)", p);
                if (nthEL(argl, 0)->alt != VAR)
                    error("%p: set needs variable as first param", p);
                return mkSet(nthEL(argl, 0)->u.var, nthEL(argl, 1));
            } else if (first == strtoname("while")) {
                /* parseexp [[while]] and return the result 613d */
                if (lengthEL(argl) != 2)
                    error("%p: usage: (while cond body)", p);
                return mkWhilex(nthEL(argl, 0), nthEL(argl, 1));
            } else {
                /* parseexp function application and return the result 614a */
                return mkApply(first, argl);
            }
        }
    default:
        assert(0);
        return NULL;
    }
}
/* parse.c 720f */
Exp parseexp(Par p) {
    switch (p->alt) {
    case ATOM:
        /* parseexp [[ATOM]] and return 721 */
        {
            Name n = p->u.atom;
            const char *s; /* string form of n */
            char *t;       /* nondigits in s, if any */
            long l;        /* number represented by s, if any */

            if (n == strtoname("#t"))
                return mkLiteral(truev);
            else if (n == strtoname("#f"))
                return mkLiteral(falsev);

            s = nametostr(n);
            l = strtol(s, &t, 10);
            if (*t == '\0' && *s != '\0')
                                /* all the characters in s are digits base 10 */
                return mkLiteral(mkNum(l));
            else
                return mkVar(n);
        }
    case LIST:
        /* parseexp [[LIST]] and return 722a */
        {
            Parlist pl;                /* parenthesized list we are parsing */
            Name first;
                            /* first element, as a name (or NULL if not name) */
            Explist el;                /* remaining elements, as expressions */
            Exp rv;                    /* result of parsing */

            pl = p->u.list;
            if (pl == NULL)
                error("%p: empty list in input", p);

            first = pl->hd->alt == ATOM ? pl->hd->u.atom : NULL;
            if (first == strtoname("lambda")) {
                /* parseexp [[lambda]] and put the result in [[rv]] 722b */
                Par q;

                if (lengthPL(pl->tl) != 2)
                    error("%p: usage: (lambda (formals) exp)", p);
                q = nthPL(pl->tl, 0);
                if (q->alt != LIST)
                    error("%p: usage: (lambda (formals) exp)", p);
                rv = mkLambdax(mkLambda(getnamelist(p, q->u.list), parseexp(
                                                            nthPL(pl->tl, 1))));
            } else if (first == strtoname("let")
                   ||  first == strtoname("let*")
                   ||  first == strtoname("letrec")) {
                /* parseexp let and put the result in [[rv]] 723a */
                Letkeyword letword;
                Par letbindings;

                if (first == strtoname("let"))
                    letword = LET;
                else if (first == strtoname("let*"))
                    letword = LETSTAR;
                else if (first == strtoname("letrec"))
                    letword = LETREC;
                else
                    assert(0);

                if (lengthPL(pl->tl) != 2)
                    error("%p: usage: (%n (letlist) exp)", p, first);

                letbindings = nthPL(pl->tl, 0);
                if (letbindings->alt != LIST)
                    error("%p: usage: (%n (letlist) exp)", p, first);

                rv = mkLetx(letword, NULL, NULL, parseexp(nthPL(pl->tl, 1)));

                parseletbindings(p, letbindings->u.list, rv);
            } else if (first == strtoname("quote")) {
                /* parseexp [[quote]] and put the result in [[rv]] 723d */
                {
                    if (lengthPL(pl) != 2)
                        error("%p: quote needs exactly one argument", p);
                    rv = mkLiteral(parsesx(nthPL(pl, 1)));
                }
            } else {
                el = parselist(pl->tl);
                if (first == strtoname("begin")) {
                    /* parseexp [[begin]] and put the result in [[rv]] 724e */
                    rv = mkBegin(el);
                } else if (first == strtoname("if")) {
                    /* parseexp [[if]] and put the result in [[rv]] 724f */
                    if (lengthEL(el) != 3)
                        error("%p: usage: (if cond true false)", p);
                    rv = mkIfx(nthEL(el, 0), nthEL(el, 1), nthEL(el, 2));
                } else if (first == strtoname("set")) {
                    /* parseexp [[set]] and put the result in [[rv]] 725b */
                    if (lengthEL(el) != 2)
                        error("%p: usage: (set var exp)", p);
                    if (nthEL(el, 0)->alt != VAR)
                        error("%p: set needs variable as first param", p);
                    rv = mkSet(nthEL(el, 0)->u.var, nthEL(el, 1));
                } else if (first == strtoname("while")) {
                    /* parseexp [[while]] and put the result in [[rv]] 725a */
                    if (lengthEL(el) != 2)
                        error("%p: usage: (while cond body)", p);
                    rv = mkWhilex(nthEL(el, 0), nthEL(el, 1));

 /* [[RBR else LBR]] possibly parse expressions that are in \uschemeplus 723e */
                  /* nothing happens */
                } else {
                   /* parseexp application and put the result in [[rv]] 724d */
                   rv = mkApply(parseexp(pl->hd), el);
                }
            }
            return rv;
        }
    default:
        assert(0);
        return NULL;
    }
}
示例#3
0
/*
 * <parse.c>=
 */
static Exp parseexp(Par p) {
    switch (p->alt) {
    case ATOM:
        /*
         * If we have a name, it must be either a literal value
         * or a variable.
         * <parseexp [[atom]] and return the result>=
         */
        {
            const char *s = nametostr(p->u.atom);
            char *t;
            long l = strtol(s, &t, 10);
            if (*t == '\0') /* the number is the whole string */
                return mkLiteral(l);
            else
                return mkVar(p->u.atom);
        }
    case LIST:
        /*
         * If we have a list, we need to look at the first
         * element, which must be a name.
         * <parseexp [[list]] and return the result>=
         */
        {
            Parlist pl;
            Name first;
            Explist argl;

            pl = p->u.list;
            if (pl == NULL)
                error("%p: empty list in input", p);
            if (pl->hd->alt != ATOM)
                error("%p: first item of list not name", p);

            first = pl->hd->u.atom;
            argl  = parselist(pl->tl);
            if (first == strtoname("begin")) {
                /*
                 * A [[begin]] expression can have any number of
                 * parameters.
                 * <parseexp [[begin]] and return the result>=
                 */
                return mkBegin(argl);
            } else if (first == strtoname("if")) {
                /*
                 * An [[if]] expression needs three parameters.
                 * <parseexp [[if]] and return the result>=
                 */
                if (lengthEL(argl) != 3)
                    error("%p: usage: (if cond true false)", p);
                return mkIfx(nthEL(argl, 0), nthEL(argl, 1), nthEL(argl, 2));
            } else if (first == strtoname("set")) {
                /*
                 * A [[set]] expression requires a variable and a value.
                 * <parseexp [[set]] and return the result>=
                 */
                if (lengthEL(argl) != 2)
                    error("%p: usage: (set var exp)", p);
                if (nthEL(argl, 0)->alt != VAR)
                    error("%p: set needs variable as first param", p);
                return mkSet(nthEL(argl, 0)->u.var, nthEL(argl, 1));
            } else if (first == strtoname("while")) {
                /*
                 * A [[while]] loop needs two.
                 * <parseexp [[while]] and return the result>=
                 */
                if (lengthEL(argl) != 2)
                    error("%p: usage: (while cond body)", p);
                return mkWhilex(nthEL(argl, 0), nthEL(argl, 1));
            } else {
                /*
                 * Anything else must be a function application. We
                 * can't check the number of parameters here, because
                 * the function definition might change before
                 * evaluation, or might not be present yet (as occurs,
                 * for example, when defining recursive functions).
                 * <parseexp function application and return the result>=
                 */
                return mkApply(first, argl);
            }
        }
    default:
        assert(0);
        return NULL;
    }
}