// Initialize the prefixes map.
prefixesMap = new ArrayList[edgesMap.size()];
if(prefixesMapToAdd == null){ // The predecessor was the first node in the alternative, so the prefix of this node is just the predecessor's result.
int index = edgesMap.findKey(predecessor.getStartLocation());
addPrefix(new Link(null, predecessorResult), index);
}else{ // The predecessor has prefixes.
int nrOfPrefixes = edgesMapToAdd.size();
for(int i = nrOfPrefixes - 1; i >= 0; --i){
ArrayList<Link> prefixes = prefixesMap[i];
if(prefixes == null){
prefixes = new ArrayList<Link>(1);
prefixesMap[i] = prefixes;
}
prefixes.add(new Link(prefixesMapToAdd[i], predecessorResult));
}
}
}else if(edgesMap != edgesMapToAdd){ // A stack merge occurred (and the production is non-cyclic (expandable nodes, such as lists, can have cyclic child alternatives)).
// Initialize the prefixes map (if necessary).
int edgesMapSize = edgesMap.size();
int possibleMaxSize = edgesMapSize + edgesMapToAdd.size();
if(prefixesMap == null){
prefixesMap = new ArrayList[possibleMaxSize];
}else{
if(prefixesMap.length < possibleMaxSize){
ArrayList<Link>[] oldPrefixesMap = prefixesMap;
prefixesMap = new ArrayList[possibleMaxSize];
System.arraycopy(oldPrefixesMap, 0, prefixesMap, 0, edgesMapSize);
}
}
if(prefixesMapToAdd == null){ // The predecessor was the first node in the alternative, so the prefix of this node is just the predecessor's result.
addPrefix(new Link(null, predecessorResult), edgesMapSize);
edgesMap.add(edgesMapToAdd.getKey(0), edgesMapToAdd.getValue(0));
}else{ // The predecessor has prefixes.
for(int i = edgesMapToAdd.size() - 1; i >= 0; --i){
int startLocation = edgesMapToAdd.getKey(i);
int index = edgesMap.findKeyBefore(startLocation, edgesMapSize); // Only look where needed.
ArrayList<Link> prefixes;
if(index == -1){ // No prefix set for the given start location is present yet.
index = edgesMap.size();
edgesMap.add(startLocation, edgesMapToAdd.getValue(i));
prefixes = new ArrayList<Link>(1);
prefixesMap[index] = prefixes;
}else{ // A prefix set for the given start location is present.
prefixes = prefixesMap[index];
}
// Add the prefix to the appropriate prefix set.
prefixes.add(new Link(prefixesMapToAdd[i], predecessorResult));
}
}
}else{ // A stack merge occurred and the production is self cyclic (expandable nodes, such as lists, can have cyclic child alternatives).
if(prefixesMapToAdd == null){
int index = edgesMap.findKey(predecessor.getStartLocation());
addPrefix(new Link(null, predecessorResult), index);
}else{
int nrOfPrefixes = edgesMapToAdd.size();
for(int i = nrOfPrefixes - 1; i >= 0; --i){
// Add the prefix to the appropriate prefixes set.
prefixesMap[i].add(new Link(prefixesMapToAdd[i], predecessorResult));
}
}
}
}