List<SearchKnot<Tuple<Token, Integer>>> discoveryBoundaryList = new ArrayList<SearchKnot<Tuple<Token, Integer>>>();
List<Token> discoveryExploredList = new ArrayList<Token>();
List<SearchKnot<Tuple<Token, Integer>>> discoveryFinalList = new ArrayList<SearchKnot<Tuple<Token, Integer>>>();
List<SearchKnot<Tuple<Token, Integer>>> newDiscoveryBoundaryList = new ArrayList<SearchKnot<Tuple<Token, Integer>>>();
for (int i = 0; i < symbolList.size(); i++) {
Symbol actualSymbol = symbolList.get(i);
if (actualSymbol.getType() == Type.PUSH || actualSymbol.getType() == Type.POP) {
SearchKnot<Tuple<Token, Integer>> root = new SearchKnot<Tuple<Token, Integer>>(new Tuple<Token, Integer>(tokens[i], i), null);
newDiscoveryBoundaryList.clear();
discoveryFinalList.clear();
discoveryBoundaryList.clear();
discoveryBoundaryList.add(root);
discoveryExploredList.clear();
while (discoveryBoundaryList.isEmpty() == false) {
while (discoveryBoundaryList.isEmpty() == false) {
SearchKnot<Tuple<Token, Integer>> actual = discoveryBoundaryList.remove(0);
discoveryExploredList.add(actual.getValue().getFirst());
for (int succ : connectionsMap.get(actual.getValue().getFirst())) {
Symbol succSymbol = symbolList.get(succ);
if (succSymbol == actualSymbol) {
discoveryFinalList.add(new SearchKnot<Tuple<Token, Integer>>(new Tuple<Token, Integer>(tokens[succ], succ), actual));
} else if (Symbol.isMetaSymbol(succSymbol.getType()) && succ < symbolList.size() - 1) {
if (discoveryExploredList.contains(tokens[succ]) == false) {
newDiscoveryBoundaryList.add(new SearchKnot<Tuple<Token, Integer>>(new Tuple<Token, Integer>(tokens[succ], succ), actual));
}
}
}
}
discoveryBoundaryList.clear();
discoveryBoundaryList.addAll(newDiscoveryBoundaryList);
newDiscoveryBoundaryList.clear();
}
if (discoveryFinalList.isEmpty() == false) {
List<String> selfIdList = new ArrayList<String>();
for (SearchKnot<Tuple<Token, Integer>> discoveryFinal : discoveryFinalList) {
while (discoveryFinal.getParent() != null) {
Symbol symbol = symbolList.get(discoveryFinal.getValue().getSecond());
if (symbol.getType() == Type.CLOSED_SELF_START || symbol.getType() == Type.CLOSED_SELF_END) {
selfIdList.add(closedSelfIdMap.get(discoveryFinal.getValue().getSecond()));
}
discoveryFinal = discoveryFinal.getParent();
}
}
StringBuilder sb = new StringBuilder();
sb.append("(" + selfIdList.get(0));
for (int j = 1; j < selfIdList.size(); j++) {
sb.append("|" + selfIdList.get(j));
}
sb.append(")*");
symbolList.set(i, new Symbol("", actualSymbol.getType() == Type.PUSH ? Type.INFINI_PUSH : Type.INFINI_POP));
String prefix = actualSymbol.getType() == Type.PUSH ? "" : "-";
infiniLateralStackMap.put(i, prefix + sb.toString());
} else {
infiniLateralStackMap.put(i, "");
}
}
}
for (int i = 0; i < symbolList.size(); i++) {
Symbol actualSymbol = symbolList.get(i);
if (i == 0 || (Symbol.isMetaSymbol(actualSymbol.getType()) == false)) {
boundary.clear();
boundary.add(new Step(tokens[i], new ArrayList<Event>()));
explored.clear();
successorList.clear();
while (boundary.isEmpty() == false) {
Step actual = boundary.remove(0);
explored.add(actual.getDestination());
for (int succ : connectionsMap.get(actual.getDestination())) {
Symbol succSymbol = symbolList.get(succ);
List<Event> eventList = new ArrayList<Event>(actual.getEventList());
if (succSymbol.getLikeness() != 0) {
eventList.add(new LikenessEvent(succSymbol.getLikeness()));
}
if (succSymbol.getMarkIndex() != 0) {
eventList.add(new MarkEvent(succSymbol.getMarkIndex() > 0, Math.abs(succSymbol.getMarkIndex()), succSymbol.getMarkName()));
}
if (succSymbol.getType() == Type.CHECK_IN || succSymbol.getType() == Type.CHECK_OUT) {
eventList.add(new CheckEvent(succSymbol.getType() == Type.CHECK_IN));
}
if (succSymbol.getType() == Type.CLOSED_SELF_START || succSymbol.getType() == Type.CLOSED_SELF_END) {
eventList.add(new LateralStepEvent(closedSelfIdMap.get(succ)));
}
if (Symbol.isStackRelated(succSymbol.getType())) {
String minDepth = "";
String maxDepth = "";
switch (succSymbol.getType()) {
case PUSH:
minDepth = "1";
maxDepth = "1";
break;
case POP:
minDepth = "-1";
maxDepth = "-1";
break;
case INFINI_PUSH:
minDepth = "1";
maxDepth = "+I";
eventList.add(new LateralStepEvent(infiniLateralStackMap.get(succ)));
break;
case INFINI_POP:
minDepth = "-I";
maxDepth = "-1";
eventList.add(new LateralStepEvent(infiniLateralStackMap.get(succ)));
break;
}
eventList.add(new ChangeDepthEvent(minDepth, maxDepth));
}
if ((Symbol.isMetaSymbol(succSymbol.getType()) == false) || succ == symbolList.size() - 1) {
successorList.add(new Step(tokens[succ], eventList));
} else {
Step newStep = new Step(tokens[succ], eventList);
if (explored.contains(tokens[succ]) == false) {
boundary.add(newStep);