JCExpression term2Rest(JCExpression t, int minprec) {
        List<JCExpression[]> savedOd = odStackSupply.elems;
        JCExpression[] odStack = newOdStack();
        List<Token[]> savedOp = opStackSupply.elems;
        Token[] opStack = newOpStack();
        List<int[]> savedPos = posStackSupply.elems;
        int[] posStack = newPosStack();
        // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
        int top = 0;
        odStack[0] = t;
        int startPos = S.pos();
        Token topOp = ERROR;
        int topOpPos = Position.NOPOS;
        while (prec(S.token()) >= minprec) {
            posStack[top] = topOpPos;
            opStack[top] = topOp;
            top++;
            topOp = S.token();
            topOpPos = S.pos();
            S.nextToken();
            odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3();
            while (top > 0 && prec(topOp) >= prec(S.token())) {
                odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1],
                                        odStack[top]);
                top--;
                topOp = opStack[top];
                topOpPos = posStack[top];
            }
        }
        Assert.check(top == 0);
        t = odStack[0];

        if (t.getTag() == JCTree.PLUS) {
            StringBuffer buf = foldStrings(t);
            if (buf != null) {
                t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
            }
        }

        odStackSupply.elems = savedOd; // optimization
        opStackSupply.elems = savedOp; // optimization
        posStackSupply.elems = savedPos; // optimization
        return t;
    }