blob: b786c6d949ceb0f7e8c551053933ffd7035a237c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 University of Illinois at Urbana-Champaign and others.
* 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:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.photran.internal.core.parser;
import org.eclipse.photran.internal.core.lexer.*; import org.eclipse.photran.internal.core.analysis.binding.ScopingNode; import org.eclipse.photran.internal.core.SyntaxException; import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.AbstractList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.photran.internal.core.parser.ASTNodeUtil.NonNullIterator;
@SuppressWarnings("all")
public class ASTSeparatedListNode<T extends IASTNode> extends AbstractList<T> implements IASTListNode<T>
{
private IASTNode parent = null;
private ArrayList<Token> separators = new ArrayList<Token>();
private ArrayList<T> entries = new ArrayList<T>();
public ASTSeparatedListNode() {}
public ASTSeparatedListNode(Token separator, List<T> entries)
{
this(separator, entries, false);
}
@SuppressWarnings("unchecked")
public ASTSeparatedListNode(Token separator, List<T> entries, boolean trimWhiteText)
{
boolean first = true;
Iterator<T> it = entries.iterator();
while (it.hasNext())
{
T entry = it.next();
if (trimWhiteText && entry != null && entry instanceof Token)
{
Token tok = (Token)((Token)entry).clone();
tok.setWhiteBefore("");
tok.setWhiteAfter("");
entry = (T)tok;
}
if (first)
{
add(null, entry);
first = false;
}
else
{
add(separator, entry);
}
}
}
public void add(Token separator, T entry)
{
this.separators.add(separator);
this.entries.add(entry);
if (separator != null) separator.setParent(this);
if (entry != null) entry.setParent(this);
}
@Override public T remove(int index)
{
Token separator = this.separators.remove(index);
T result = this.entries.remove(index);
if (index == 0 && separator == null && !this.separators.isEmpty())
this.separators.set(0, null);
// if (separator != null) separator.setParent(null);
// if (result != null) result.setParent(null);
return result;
}
public ASTNodePair<Token, T> getPair(int index)
{
return new ASTNodePair<Token, T>(this.separators.get(index), this.entries.get(index));
}
///////////////////////////////////////////////////////////////////////////
// IASTListNode Insertion Methods
///////////////////////////////////////////////////////////////////////////
public void insertBefore(T insertBefore, T newElement)
{
throw new UnsupportedOperationException();
}
public void insertAfter(T insertAfter, T newElement)
{
throw new UnsupportedOperationException();
}
///////////////////////////////////////////////////////////////////////////
// AbstractList Implementation
///////////////////////////////////////////////////////////////////////////
@Override
public T get(int index)
{
return entries.get(index);
}
@Override
public int size()
{
return entries.size();
}
///////////////////////////////////////////////////////////////////////////
// Traversal and Visitor Support
///////////////////////////////////////////////////////////////////////////
public IASTNode getParent()
{
return this.parent;
}
public void setParent(IASTNode parent)
{
this.parent = parent;
}
public Iterable<? extends IASTNode> getChildren()
{
return new Iterable<IASTNode>()
{
public Iterator<IASTNode> iterator()
{
return new NonNullIterator(new Iterator<IASTNode>()
{
private int index = !separators.isEmpty() && separators.get(0) == null ? 1 : 0;
private int count = entries.size() * 2;
public boolean hasNext()
{
return index < count;
}
public IASTNode next()
{
if (index % 2 == 0)
return separators.get(index++ / 2);
else
return entries.get(index++ / 2);
}
public void remove()
{
throw new UnsupportedOperationException();
}
});
}
};
}
public void accept(IASTVisitor visitor)
{
visitor.visitASTNode(this);
visitor.visitASTListNode(this);
}
///////////////////////////////////////////////////////////////////////////
// Searching
///////////////////////////////////////////////////////////////////////////
public <T extends IASTNode> Set<T> findAll(Class<T> targetClass)
{
return ASTNodeUtil.findAll(this, targetClass);
}
@SuppressWarnings("hiding")
public <T extends IASTNode> T findNearestAncestor(Class<T> targetClass)
{
return ASTNodeUtil.findNearestAncestor(this, targetClass);
}
public <T extends IASTNode> T findFirst(Class<T> targetClass)
{
return ASTNodeUtil.findFirst(this, targetClass);
}
public <T extends IASTNode> T findLast(Class<T> targetClass)
{
return ASTNodeUtil.findLast(this, targetClass);
}
public Token findFirstToken()
{
return ASTNodeUtil.findFirstToken(this);
}
public Token findLastToken()
{
return ASTNodeUtil.findLastToken(this);
}
public boolean isFirstChildInList()
{
return ASTNodeUtil.isFirstChildInList(this);
}
///////////////////////////////////////////////////////////////////////////
// Source Reproduction
///////////////////////////////////////////////////////////////////////////
public IPreprocessorReplacement printOn(PrintStream out, IPreprocessorReplacement currentPreprocessorDirective)
{
return ASTNodeUtil.print(this, currentPreprocessorDirective, out);
}
@Override public String toString()
{
return ASTNodeUtil.toString(this);
}
///////////////////////////////////////////////////////////////////////////
// Source Manipulation
///////////////////////////////////////////////////////////////////////////
public void replaceChild(IASTNode node, IASTNode withNode)
{
int i = entries.indexOf(node);
if (i >= 0)
{
entries.set(i, (T)withNode);
if (withNode != null) withNode.setParent(this);
return;
}
i = separators.indexOf(node);
if (i >= 0)
{
separators.set(i, (Token)withNode);
if (withNode != null) withNode.setParent(this);
return;
}
throw new IllegalStateException("Child node not found");
}
public void removeFromTree()
{
throw new UnsupportedOperationException();
}
public void replaceWith(IASTNode newNode)
{
throw new UnsupportedOperationException();
}
public void replaceWith(String literalString)
{
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
@Override public Object clone()
{
ASTSeparatedListNode<T> copy = new ASTSeparatedListNode<T>();
for (Token t : this.separators)
{
if (t == null)
copy.separators.add(null);
else
{
Token newChild = (Token)t.clone();
newChild.setParent(copy);
copy.separators.add(newChild);
}
}
for (T t : this.entries)
{
if (t == null)
copy.entries.add(null);
else
{
T newChild = (T)t.clone();
newChild.setParent(copy);
copy.entries.add(newChild);
}
}
return copy;
}
}