src/main/java/com/basistech/tclre/Nfa.java
boolean pull(Arc con) throws RegexException {
        State from = con.from;
        State to = con.to;
        Arc a;
        Arc nexta;
        State s;

        if (from == to) {   /* circular constraint is pointless */
            freearc(con);
            return true;
        }
        if (0 != from.flag) {   /* can't pull back beyond start */
            return false;
        }
        if (from.nins == 0) {   /* unreachable */
            freearc(con);
            return true;
        }

    /* first, clone from state if necessary to avoid other outarcs */
        if (from.nouts > 1) {
            s = newstate();

            assert to != from;        /* con is not an inarc */
            copyins(from, s);       /* duplicate inarcs */
            cparc(con, s, to);      /* move constraint arc */
            freearc(con);
            from = s;
            con = from.outs;
        }
        assert from.nouts == 1;

    /* propagate the constraint into the from state's inarcs */
        for (a = from.ins; a != null; a = nexta) {
            nexta = a.inchain;
            switch (combine(con, a)) {
            case INCOMPATIBLE:  /* destroy the arc */
                freearc(a);
                break;
            case SATISFIED:     /* no action needed */
                break;
            case COMPATIBLE:    /* swap the two arcs, more or less */
                s = newstate();
                cparc(a, s, to);        /* anticipate move */
                cparc(con, a.from, s);
                freearc(a);
                break;
            default:
                throw new RegexException("REG_ASSERT");
            }
        }

    /* remaining inarcs, if any, incorporate the constraint */
        moveins(from, to);
        dropstate(from);        /* will free the constraint */
        return true;
    }
boolean pull(Arc con) throws RegexException {
        State from = con.from;
        State to = con.to;
        Arc a;
        Arc nexta;
        State s;

        if (from == to) {   /* circular constraint is pointless */
            freearc(con);
            return true;
        }
        if (0 != from.flag) {   /* can't pull back beyond start */
            return false;
        }
        if (from.nins == 0) {   /* unreachable */
            freearc(con);
            return true;
        }

    /* first, clone from state if necessary to avoid other outarcs */
        if (from.nouts > 1) {
            s = newstate();

            assert to != from;        /* con is not an inarc */
            copyins(from, s);       /* duplicate inarcs */
            cparc(con, s, to);      /* move constraint arc */
            freearc(con);
            from = s;
            con = from.outs;
        }
        assert from.nouts == 1;

    /* propagate the constraint into the from state's inarcs */
        for (a = from.ins; a != null; a = nexta) {
            nexta = a.inchain;
            switch (combine(con, a)) {
            case INCOMPATIBLE:  /* destroy the arc */
                freearc(a);
                break;
            case SATISFIED:     /* no action needed */
                break;
            case COMPATIBLE:    /* swap the two arcs, more or less */
                s = newstate();
                cparc(a, s, to);        /* anticipate move */
                cparc(con, a.from, s);
                freearc(a);
                break;
            default:
                throw new RegexException("REG_ASSERT");
            }
        }

    /* remaining inarcs, if any, incorporate the constraint */
        moveins(from, to);
        dropstate(from);        /* will free the constraint */
        return true;
    }
- pull - pull a back constraint backward past its source state
A significant property of this function is that it deletes at most
one state -- the constraint's from state -- and only if the constraint
was that state's last outarc.

@return success