/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.parser.gtd.result;
import java.net.URI;
import org.rascalmpl.parser.gtd.result.struct.Link;
import org.rascalmpl.parser.gtd.util.ArrayList;
/**
* All nodes in the resulting tree that can contain other nodes are a subtype
* of this class.
*/
public abstract class AbstractContainerNode<P> extends AbstractNode{
// Location related.
protected final URI input;
protected final int offset;
protected final int endOffset;
// Flags.
protected final boolean isNullable;
protected final boolean isSeparator;
protected final boolean isLayout;
// Children.
protected Link firstAlternative;
protected P firstProduction;
protected ArrayList<Link> alternatives;
protected ArrayList<P> productions;
public AbstractContainerNode(URI input, int offset, int endOffset, boolean isNullable, boolean isSeparator, boolean isLayout){
super();
this.input = input;
this.offset = offset;
this.endOffset = endOffset;
this.isNullable = isNullable;
this.isSeparator = isSeparator;
this.isLayout = isLayout;
}
/**
* Adds a result to this container node.
* In case there is only one alternative (i.e. this node does not contain
* any ambiguities), only the 'first' fields will be set. In case
* additional alternatives are added later on, the lists will be
* initialized and used for storage.
*/
public void addAlternative(P production, Link children){
if(firstAlternative == null){
firstAlternative = children;
firstProduction = production;
}else{
if(alternatives == null){
alternatives = new ArrayList<Link>(1);
productions = new ArrayList<P>(1);
}
alternatives.add(children);
productions.add(production);
}
}
/**
* Returns the input location; may be null.
*/
public URI getInput(){
return input;
}
/**
* Returns the offset in the input string the results in this node start at.
*/
public int getOffset(){
return offset;
}
/**
* Returns the offset in the input string the results in this node end at.
*/
public int getEndOffset(){
return endOffset;
}
/**
* Checks if the results contained in this node are zero length or not.
*/
public boolean isEmpty(){
return isNullable;
}
/**
* Checks if the results contained in this node represent a separator.
*/
public boolean isNonterminalSeparator(){
return isSeparator;
}
/**
* Checks if the results contained in this node represent layout.
*/
public boolean isLayout(){
return isLayout;
}
/**
* Returns the production associated with the first result alternative in
* this container node.
*/
public P getFirstProduction(){
return firstProduction;
}
/**
* Returns the first result alternative in this container node.
*/
public Link getFirstAlternative(){
return firstAlternative;
}
/**
* Returns the set of all 'other' productions contained in this node. In
* case additional alternative results are present, the order in the
* returned list will match with the order of the alternative results in
* the accompanied alternatives list. In case this node does not contain
* ambiguous results, 'null' will be returned.
*/
public ArrayList<P> getAdditionalProductions(){
return productions;
}
/**
* Returns the set of all 'other' alternative results contained in this
* node. In case this node does not contain ambiguous results, 'null' will
* be returned. Note that the order in the list of alternative results
* matches the order in the associated list of productions.
*/
public ArrayList<Link> getAdditionalAlternatives(){
return alternatives;
}
}