public <S, P, T, D extends Pda<S, P>> D expand( Pda<S, P> pda, Function<S, Pda<S, P>> expand, Function<S, T> tokens, PdaFactory<D, S, P, T> fact) { D result = fact.create(tokens.apply(pda.getStart()), tokens.apply(pda.getStop())); Identity<S> identity = new Identity<S>(); Map<S, S> idstates = Maps.newIdentityHashMap(); Multimap<S, S> followers = LinkedHashMultimap.create(); for (S s_old : nfaUtil.collect(pda)) { S s_new = idstates.get(s_old); if (s_new == null) { Pda<S, P> sub = expand.apply(s_old); if (sub != null) { S s_start = identity.get(fact.createPush(result, tokens.apply(s_old))); S s_stop = identity.get(fact.createPop(result, tokens.apply(s_old))); idstates.put(s_old, s_start); idstates.put(sub.getStart(), s_start); idstates.put(sub.getStop(), s_stop); followers.putAll(s_start, sub.getFollowers(sub.getStart())); followers.putAll(s_stop, pda.getFollowers(s_old)); for (S f_old : nfaUtil.collect(sub)) if (f_old != sub.getStart() && f_old != sub.getStop()) { S f_new = idstates.get(f_old); if (f_new == null) { idstates.put(f_old, f_new = clone(f_old, sub, result, tokens, fact, identity)); followers.putAll(f_new, pda.getFollowers(f_old)); } } } else { idstates.put(s_old, s_new = clone(s_old, pda, result, tokens, fact, identity)); followers.putAll(s_new, pda.getFollowers(s_old)); } } } for (Map.Entry<S, Collection<S>> entry : followers.asMap().entrySet()) { Set<S> f = Sets.newLinkedHashSet(); for (S s : entry.getValue()) f.add(idstates.get(s)); fact.setFollowers(result, entry.getKey(), f); } return result; }
public <S, P, D extends Pda<S, P>> Map<P, Pair<S, S>> collectPopsAndPushs(Pda<S, P> pda) { Map<P, Pair<S, S>> result = Maps.newLinkedHashMap(); for (S s : nfaUtil.collect(pda)) { P push = pda.getPush(s); if (push != null) { Pair<S, S> o = result.get(push); Pair<S, S> n = Tuples.create(s, o == null ? null : o.getSecond()); result.put(push, n); } P pop = pda.getPop(s); if (pop != null) { Pair<S, S> o = result.get(pop); Pair<S, S> n = Tuples.create(o == null ? null : o.getFirst(), s); result.put(pop, n); } } return result; }