DescendentType.java
package edu.udel.cis.vsl.tass.ast.parser;
/**
* Used exclusively by NodeTypeIF implementations to represent
* descendents
*
* @author Alex Stachnik (stachnik)
*/
class DescendentType {
/**
* True iff this descendent can appear an unbounded number of
* times in which case is appears after all bounded elements in a
* group with the other unbounded elements
*/
private final boolean isUnbounded;
/**
* If isUnbounded then this holds the interval between
* descendents of this type
*/
private final int stepVal;
/** The first position that this descendent can occur at */
private final int startPosition;
/** True if the descendent is an attribute, false if it's a child */
private final boolean isAttr;
/** True iff the descendent is a reference to another node */
private final boolean isReference;
public DescendentType(boolean isUnbounded,
int stepVal,
int startPosition,
boolean isAttr,
boolean isReference) {
this.isUnbounded = isUnbounded;
this.stepVal = stepVal;
this.startPosition = startPosition;
this.isAttr = isAttr;
this.isReference = isReference;
}
public boolean isReference() {
return isReference;
}
public boolean isAttr() {
return isAttr;
}
/**
* Given that this descendent has been encountered and the
* position of the last child (if this descendent is a child) or
* attribute (if this descendent is an attribute) return the attr
* or child position of this descendent
*/
public int getPosition(int lastPosition) {
if (lastPosition < startPosition) {
return startPosition;
}
if (isUnbounded) {
// lastPosition = startPosition + stepVal*N + oldOffset
int oldOffset = (lastPosition - startPosition) % stepVal;
// newOffset is congruent (-oldOffset) mod stepVal so
// either the last node encountered was of this type in
// which case: (newPosition = stepVal + lastPosition) or
// we can round up to the next slot for a descendent of
// this type and (newPosition = newOffset + lastPosition)
int newOffset = (stepVal - oldOffset) % stepVal;
if (newOffset == 0) {
return lastPosition + stepVal;
} else {
return lastPosition + newOffset;
}
} else {
return lastPosition + 1;
}
}
}