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;
		}

    }
}