mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 08:48:55 +00:00
[util.formallang] small improvements
This commit is contained in:
parent
99a1285cce
commit
d0f13a42ae
2 changed files with 94 additions and 30 deletions
|
@ -18,6 +18,7 @@ import java.util.Set;
|
|||
import java.util.Stack;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
@ -51,6 +52,26 @@ public class NfaUtil {
|
|||
this.result = result;
|
||||
this.followers = followers.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return result == null ? "null" : result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class GetToken<E, T> implements Function<E, T> {
|
||||
|
||||
protected Production<E, T> production;
|
||||
|
||||
public GetToken(Production<E, T> production) {
|
||||
super();
|
||||
this.production = production;
|
||||
}
|
||||
|
||||
public T apply(E from) {
|
||||
return production.getToken(from);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MappedComparator<S, COMPARABLE extends Comparable<COMPARABLE>> implements Comparator<S> {
|
||||
|
@ -71,6 +92,21 @@ public class NfaUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static class NFAFactory<S> implements NfaFactory<Nfa<S>, S, S> {
|
||||
|
||||
public Nfa<S> create(S start, S stop) {
|
||||
return new NFAImpl<S>(start, stop, Maps.<S, List<S>> newHashMap());
|
||||
}
|
||||
|
||||
public S createState(Nfa<S> nfa, S token) {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setFollowers(Nfa<S> nfa, S owner, Iterable<S> followers) {
|
||||
((NFAImpl<S>) nfa).followers.put(owner, Lists.newArrayList(followers));
|
||||
}
|
||||
}
|
||||
|
||||
public static class NFAImpl<S> implements Nfa<S> {
|
||||
|
||||
protected final Map<S, List<S>> followers;
|
||||
|
@ -209,25 +245,35 @@ public class NfaUtil {
|
|||
return result;
|
||||
}
|
||||
|
||||
public <E, T> Nfa<E> create(Production<E, T> production, FollowerFunction<E> ff, E start, E stop) {
|
||||
return create(production, ff, Functions.<E> identity(), new NFAFactory<E>(), start, stop);
|
||||
}
|
||||
|
||||
public <S, E, T, NFA extends Nfa<S>> NFA create(Production<E, T> production, FollowerFunction<E> ff,
|
||||
NfaFactory<NFA, S, ? super T> factory) {
|
||||
return create(production, ff, new GetToken<E, T>(production), factory, null, null);
|
||||
}
|
||||
|
||||
public <S, E, T1, T2, NFA extends Nfa<S>> NFA create(Production<E, T1> production, FollowerFunction<E> ff,
|
||||
Function<E, T2> tokenFunc, NfaFactory<NFA, S, ? super T2> factory, T2 start, T2 stop) {
|
||||
Map<E, S> states = Maps.newHashMap();
|
||||
NFA nfa = factory.create(null, null);
|
||||
NFA nfa = factory.create(start, stop);
|
||||
states.put(null, nfa.getStop());
|
||||
create(production, nfa, nfa.getStart(), ff.getStarts(production.getRoot()), ff, factory, states);
|
||||
create(production, nfa, nfa.getStart(), ff.getStarts(production.getRoot()), ff, tokenFunc, factory, states);
|
||||
return nfa;
|
||||
}
|
||||
|
||||
protected <S, E, T, NFA extends Nfa<S>> void create(Production<E, T> production, NFA nfa, S state,
|
||||
Iterable<E> followerElements, FollowerFunction<E> followerFunc, NfaFactory<NFA, S, ? super T> factory,
|
||||
Map<E, S> ele2state) {
|
||||
protected <S, E, T1, T2, NFA extends Nfa<S>> void create(Production<E, T1> production, NFA nfa, S state,
|
||||
Iterable<E> followerElements, FollowerFunction<E> followerFunc, Function<E, T2> tokenFunc,
|
||||
NfaFactory<NFA, S, ? super T2> factory, Map<E, S> ele2state) {
|
||||
List<S> sfollower = Lists.newArrayList();
|
||||
for (E follower : followerElements) {
|
||||
S fs = ele2state.get(follower);
|
||||
if (fs == null) {
|
||||
fs = factory.createState(nfa, production.getToken(follower));
|
||||
fs = factory.createState(nfa, tokenFunc.apply(follower));
|
||||
ele2state.put(follower, fs);
|
||||
create(production, nfa, fs, followerFunc.getFollowers(follower), followerFunc, factory, ele2state);
|
||||
create(production, nfa, fs, followerFunc.getFollowers(follower), followerFunc, tokenFunc, factory,
|
||||
ele2state);
|
||||
}
|
||||
sfollower.add(fs);
|
||||
}
|
||||
|
@ -249,16 +295,6 @@ public class NfaUtil {
|
|||
});
|
||||
}
|
||||
|
||||
public <S> void removeOrphans(Nfa<S> nfa) {
|
||||
Map<S, Integer> distances = distanceToFinalStateMap(nfa);
|
||||
for (S s : collect(nfa)) {
|
||||
Iterator<S> i = nfa.getFollowers(s).iterator();
|
||||
while (i.hasNext())
|
||||
if (!distances.containsKey(i.next()))
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public <S> Map<S, Integer> distanceToStateMap(Nfa<S> nfa, Predicate<S> matches) {
|
||||
return distanceFromStateMap(inverse(nfa), matches);
|
||||
}
|
||||
|
@ -323,6 +359,13 @@ public class NfaUtil {
|
|||
};
|
||||
}
|
||||
|
||||
public <S> Set<S> filterFollowers(Nfa<S> nfa, Iterable<S> followers, Predicate<S> filter) {
|
||||
Set<S> result = Sets.newHashSet();
|
||||
for (S follower : followers)
|
||||
collectFollowers(nfa, follower, result, Sets.<S> newHashSet(), filter);
|
||||
return result;
|
||||
}
|
||||
|
||||
// protected <S> void collectFinalStates(INfaAdapter<S> nfa, S owner, S last, Set<S> result,
|
||||
// Set<S> visited, Set<S> ends, Predicate<S> filter) {
|
||||
// if (!visited.add(owner))
|
||||
|
@ -335,13 +378,6 @@ public class NfaUtil {
|
|||
// collectFinalStates(nfa, follower, last, result, visited, ends, filter);
|
||||
// }
|
||||
|
||||
public <S> Set<S> filterFollowers(Nfa<S> nfa, Iterable<S> followers, Predicate<S> filter) {
|
||||
Set<S> result = Sets.newHashSet();
|
||||
for (S follower : followers)
|
||||
collectFollowers(nfa, follower, result, Sets.<S> newHashSet(), filter);
|
||||
return result;
|
||||
}
|
||||
|
||||
public <S, ITERABLE extends Iterable<? extends S>> S find(Nfa<S> nfa, Iterable<S> starts, Predicate<S> matcher) {
|
||||
Set<S> visited = Sets.newHashSet();
|
||||
for (S s : starts) {
|
||||
|
@ -352,6 +388,11 @@ public class NfaUtil {
|
|||
return null;
|
||||
}
|
||||
|
||||
public <S> S find(Nfa<S> nfa, Predicate<S> matcher) {
|
||||
Set<S> visited = Sets.newHashSet();
|
||||
return find(nfa, nfa.getStart(), matcher, visited);
|
||||
}
|
||||
|
||||
// public <S, TOKEN> ITokenNfaAdapter<S, TOKEN> filter(final ITokenNfaAdapter<S, TOKEN> nfa, final Predicate<S> filter) {
|
||||
// return new ITokenNfaAdapter<S, TOKEN>() {
|
||||
//
|
||||
|
@ -384,11 +425,6 @@ public class NfaUtil {
|
|||
// return result;
|
||||
// }
|
||||
|
||||
public <S> S find(Nfa<S> nfa, Predicate<S> matcher) {
|
||||
Set<S> visited = Sets.newHashSet();
|
||||
return find(nfa, nfa.getStart(), matcher, visited);
|
||||
}
|
||||
|
||||
protected <S, ITERABLE extends Iterable<? extends S>> S find(Nfa<S> nfa, S state, Predicate<S> matcher,
|
||||
Set<S> visited) {
|
||||
if (!visited.add(state))
|
||||
|
@ -430,6 +466,16 @@ public class NfaUtil {
|
|||
return new NFAImpl<S>(nfa.getStop(), nfa.getStart(), inverseMap);
|
||||
}
|
||||
|
||||
public <S> void removeOrphans(Nfa<S> nfa) {
|
||||
Map<S, Integer> distances = distanceToFinalStateMap(nfa);
|
||||
for (S s : collect(nfa)) {
|
||||
Iterator<S> i = nfa.getFollowers(s).iterator();
|
||||
while (i.hasNext())
|
||||
if (!distances.containsKey(i.next()))
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public <S extends Comparable<S>> Nfa<S> sort(Nfa<S> nfa) {
|
||||
Map<S, List<S>> followerMap = Maps.newHashMap();
|
||||
for (S state : new NfaUtil().collect(nfa)) {
|
||||
|
|
|
@ -40,13 +40,17 @@ public class StringProduction implements Production<ProdElement, String> {
|
|||
|
||||
protected String value;
|
||||
|
||||
protected ProdElement(ElementType type) {
|
||||
public ProdElement(ElementType type) {
|
||||
super();
|
||||
this.type = type;
|
||||
if (type != ElementType.TOKEN)
|
||||
this.children = Lists.newArrayList();
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
protected void addChild(ProdElement ele) {
|
||||
children.add(ele);
|
||||
ele.parent = this;
|
||||
|
@ -56,6 +60,18 @@ public class StringProduction implements Production<ProdElement, String> {
|
|||
return children;
|
||||
}
|
||||
|
||||
public void setMany(boolean many) {
|
||||
this.many = many;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setOptional(boolean optional) {
|
||||
this.optional = optional;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -67,6 +83,7 @@ public class StringProduction implements Production<ProdElement, String> {
|
|||
public ElementType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
@ -92,6 +109,7 @@ public class StringProduction implements Production<ProdElement, String> {
|
|||
protected enum Token {
|
||||
AND("&"), //
|
||||
COLON(":"), //
|
||||
EQ("="), //
|
||||
ID("[a-zA-Z][a-zA-Z0-9]*"), //
|
||||
PIPE("\\|"), //
|
||||
PL("\\("), //
|
||||
|
|
Loading…
Reference in a new issue