*
* The modification drastically reduces computation time of
* "(a, (b, a+, (c, (b, a+)+, a+, (d, (c, (b, a+)+, a+)+, (b, a+)+, a+)+)+)+)+"
*/
fElementDecl = new XSElementDecl();
((XSElementDecl)fElementDecl).fName = fEOCString;
XSCMLeaf nodeEOC = new XSCMLeaf((XSElementDecl)fElementDecl);
fHeadNode = new XSCMBinOp(
XSParticleDecl.PARTICLE_SEQUENCE
, syntaxTree
, nodeEOC
);
//
// And handle specially the EOC node, which also must be numbered
// and counted as a non-epsilon leaf node. It could not be handled
// in the above tree build because it was created before all that
// started. We save the EOC position since its used during the DFA
// building loop.
//
fEOCPos = fLeafCount;
nodeEOC.setPosition(fLeafCount++);
//
// Ok, so now we have to iterate the new tree and do a little more
// work now that we know the leaf count. One thing we need to do is
// to calculate the first and last position sets of each node. This
// is cached away in each of the nodes.
//
// Along the way we also set the leaf count in each node as the
// maximum state count. They must know this in order to create their
// first/last pos sets.
//
// We also need to build an array of references to the non-epsilon
// leaf nodes. Since we iterate it in the same way as before, this
// will put them in the array according to their position values.
//
fLeafList = new XSCMLeaf[fLeafCount];
fLeafListType = new int[fLeafCount];
postTreeBuildInit(fHeadNode, 0);
//
// And, moving onward... We now need to build the follow position
// sets for all the nodes. So we allocate an array of state sets,
// one for each leaf node (i.e. each DFA position.)
//
fFollowList = new CMStateSet[fLeafCount];
for (int index = 0; index < fLeafCount; index++)
fFollowList[index] = new CMStateSet(fLeafCount);
calcFollowList(fHeadNode);
//
// And finally the big push... Now we build the DFA using all the
// states and the tree we've built up. First we set up the various
// data structures we are going to use while we do this.
//
// First of all we need an array of unique element names in our
// content model. For each transition table entry, we need a set of
// contiguous indices to represent the transitions for a particular
// input element. So we need to a zero based range of indexes that
// map to element types. This element map provides that mapping.
//
fElemMap = new Object [fLeafCount];
fElemMapType = new int[fLeafCount];
fElemMapSize = 0;
for (int outIndex = 0; outIndex < fLeafCount; outIndex++) {
// optimization from Henry Zongaro:
//fElemMap[outIndex] = new Object ();
fElemMap[outIndex] = null;
int inIndex = 0;
final Object decl = fLeafList[outIndex].getDecl();
// REVISIT: shouldn't we always compare the decls by reference?
// if we ever combine two different element decls with
// the same name and namespace, then this content model
// violates UPA.
// Comparing by name/namespace was inherited from Xerces1,
// where we only store name and uri, and couldn't compare
// whether two decls are the same.
// After we support UPA, change the following big "if"
// to the following 4 lines.
//for (; inIndex < fElemMapSize; inIndex++) {
// if (decl == fElemMap[inIndex])
// break;
//}
if (fLeafListType[outIndex] == XSParticleDecl.PARTICLE_WILDCARD) {
for (; inIndex < fElemMapSize; inIndex++) {
if (decl == fElemMap[inIndex])
break;
}
} else {
// Get the current leaf's element
final XSElementDecl element = (XSElementDecl)decl;
// See if the current leaf node's element index is in the list
for (; inIndex < fElemMapSize; inIndex++) {
if (fElemMapType[inIndex] == fLeafListType[outIndex] &&
((XSElementDecl)fElemMap[inIndex]).fTargetNamespace == element.fTargetNamespace &&
((XSElementDecl)fElemMap[inIndex]).fName == element.fName)
break;
}
}
// If it was not in the list, then add it, if not the EOC node
if (inIndex == fElemMapSize) {
fElemMap[fElemMapSize] = decl;
fElemMapType[fElemMapSize] = fLeafListType[outIndex];
fElemMapSize++;
}
}
// the last entry in the element map must be the EOC element.
// remove it from the map.
if (DEBUG) {
if (((XSElementDecl)fElemMap[fElemMapSize-1]).fName != fEOCString)
System.err.println("interal error in DFA: last element is not EOC.");
}
fElemMapSize--;
// set up the fLeafNameTypeVector object if there is one.
/**** but apparently there never will be since this was commented out for some reason...
if (fLeafNameTypeVector != null) {
fLeafNameTypeVector.setValues(fElemMap, fElemMapType, fElemMapSize);
}
******/
/***
* Optimization(Jan, 2001); We sort fLeafList according to
* elemIndex which is *uniquely* associated to each leaf.
* We are *assuming* that each element appears in at least one leaf.
**/
int[] fLeafSorter = new int[fLeafCount + fElemMapSize];
int fSortCount = 0;
for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {
final Object decl = fElemMap[elemIndex];
for (int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) {
// REVISIT: shouldn't we always compare the decls by reference?
// if we ever combine two different element decls with
// the same name and namespace, then this content model
// violates UPA.
// Comparing by name/namespace was inherited from Xerces1,
// where we only store name and uri, and couldn't compare
// whether two decls are the same.
// After we support UPA, change the following 2 "if"s
// to the following 2 lines.
//if (decl == fLeafList[leafIndex].getDecl())
// fLeafSorter[fSortCount++] = leafIndex;
if (fElemMapType[elemIndex] != fLeafListType[leafIndex])
continue;
if (fLeafListType[leafIndex] == XSParticleDecl.PARTICLE_WILDCARD) {
if (decl == fLeafList[leafIndex].getDecl())
fLeafSorter[fSortCount++] = leafIndex;
} else {
final XSElementDecl leaf = (XSElementDecl)fLeafList[leafIndex].getDecl();
final XSElementDecl element = (XSElementDecl)decl;
if (leaf.fTargetNamespace == element.fTargetNamespace &&
leaf.fName == element.fName ) {
fLeafSorter[fSortCount++] = leafIndex;
}
}