/* parse.c 610a */
static XDef parse(Par p) {
    switch (p->alt) {
    case ATOM:
        /* parse [[atom]] and return the result 610b */
        return mkDef(mkExp(parseexp(p)));
    case LIST:
        /* parse [[list]] and return the result 610c */
        {
            Name first;
            Parlist pl = p->u.list;
            if (pl == NULL)
                error("%p: empty list", p);
            if (nthPL(pl, 0)->alt != ATOM)
                error("%p: first item of list not name", p);

            first = nthPL(pl, 0)->u.atom;
            if (first == strtoname("define")) {
                /* parse [[define]] and return the result 611b */
                if (lengthPL(pl) != 4 || nthPL(pl, 1)->alt != ATOM || nthPL(pl,
                                                                2)->alt != LIST)
                    error("%p: usage: (define fun (formals) body)", p);

                {
                  Name     name    = nthPL(pl, 1)->u.atom;
                  Namelist formals = getnamelist(name, p, nthPL(pl, 2)->u.list);
                  Exp      body    = parseexp(nthPL(pl, 3));
                  return mkDef(mkDefine(name, mkUserfun(formals, body)));
                }
            }
            if (first == strtoname("val")) {
                /* parse [[val]] and return the result 611c */
                Exp var, exp;

                if (lengthPL(pl) != 3)
                    error("%p: usage: (val var exp)", p);

                var = parseexp(nthPL(pl, 1));
                if (var->alt != VAR)
                    error("%p: usage: (val var exp) (bad variable)", p);

                exp = parseexp(nthPL(pl, 2));
                return mkDef(mkVal(var->u.var, exp));
            }
            if (first == strtoname("use")) {
                /* parse [[use]] and return the result 611d */
                if (lengthPL(pl) != 2 || nthPL(pl, 1)->alt != ATOM)
                    error("%p: usage: (use filename)", p);

                return mkUse(nthPL(pl, 1)->u.atom);
            }
            if (first == strtoname("check-expect")) {
                /* parse [[check-expect]] and return the result 611e */
                Exp check, expect;

                if (lengthPL(pl) != 3)
                    error("%p: usage: (check-expect exp exp)", p);

                check  = parseexp(nthPL(pl, 1));
                expect = parseexp(nthPL(pl, 2));
                return mkTest(mkCheckExpect(check, expect));
            }
            if (first == strtoname("check-error")) {
                /* parse [[check-error]] and return the result 612a */
                Exp check;

                if (lengthPL(pl) != 2)
                    error("%p: usage: (check-error exp)", p);

                check  = parseexp(nthPL(pl, 1));
                return mkTest(mkCheckError(check));
            }
            return mkDef(mkExp(parseexp(p)));
        }
    }
    assert(0);
    return NULL;
}
/* parse.c 718b */
XDef parse(Par p) {
    switch (p->alt) {
    case ATOM:
        /* parse ATOM and return 718c */
        return mkDef(mkExp(parseexp(p)));
    case LIST:
        /* parse LIST and return 718d */
        {
            Parlist pl = p->u.list;

            if (pl == NULL)
                error("%p: empty list", p);
            if (nthPL(pl, 0)->alt == ATOM) {
                Name first = nthPL(pl, 0)->u.atom;
                if (first == strtoname("define")) {
                    /* parse define and return 719a */
                    Name name;
                    Lambda l;

                    if (lengthPL(pl) != 4 || nthPL(pl, 1)->alt != ATOM || nthPL(
                                                            pl, 2)->alt != LIST)
                        error("%p: usage: (define fun (args) body)", p);

                    name      = nthPL(pl, 1)->u.atom;
                    l.formals = getnamelist(p, nthPL(pl, 2)->u.list);
                    l.body    = parseexp(nthPL(pl, 3));
                    return      mkDef(mkDefine(name, l));
                }
                if (first == strtoname("val")) {
                    /* parse val and return 719b */
                    Exp var, exp;

                    if (lengthPL(pl) != 3)
                        error("%p: usage: (val var exp)", p);

                    var = parseexp(nthPL(pl, 1));
                    if (var->alt != VAR)
                        error("%p: usage: (val var exp) (bad variable)", p);

                    exp = parseexp(nthPL(pl, 2));
                    return mkDef(mkVal(var->u.var, exp));
                }
                if (first == strtoname("use")) {
                    /* parse use and return 719c */
                    if (lengthPL(pl) != 2 || nthPL(pl, 1)->alt != ATOM)
                        error("%p: usage: (use filename)", p);

                    return mkUse(nthPL(pl, 1)->u.atom);
                }
                if (first == strtoname("check-expect")) {
                    /* parse check-expect and return 719d */
                    {
                    Exp check, expect;

                    if (lengthPL(pl) != 3)
                        error("%p: usage: (check-expect exp exp)", p);

                    check  = parseexp(nthPL(pl, 1));
                    expect = parseexp(nthPL(pl, 2));
                    return mkTest(mkCheckExpect(check, expect));
                    }
                }
                if (first == strtoname("check-error")) {
                    /* parse check-error and return 719e */
                    {
                    Exp check;

                    if (lengthPL(pl) != 2)
                        error("%p: usage: (check-error exp)", p);

                    check  = parseexp(nthPL(pl, 1));
                    return mkTest(mkCheckError(check));
                    }
                }
            }

            return mkDef(mkExp(parseexp(p)));
        }
    }
    assert(0);
    return NULL;
}