blob: 9d601fe8abdff0ac96ebaab6fbb9f0e6e131b0b5 [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;
import java.util.Iterator;
import org.eclipse.core.resources.IFile;
import org.eclipse.photran.core.IFortranAST;
import org.eclipse.photran.internal.core.lexer.FileOrIFile;
import org.eclipse.photran.internal.core.lexer.Token;
import org.eclipse.photran.internal.core.lexer.TokenList;
import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode;
import org.eclipse.photran.internal.core.parser.IASTVisitor;
import org.eclipse.photran.internal.core.util.IterableWrapper;
/**
* A Fortran abstract syntax tree container class (canonical implementation of {@link IFortranAST}).
*
* @author Jeff Overbey
*/
public class FortranAST implements IFortranAST
{
private IFile file;
private ASTExecutableProgramNode root;
private TokenList tokenList;
public FortranAST(IFile file, ASTExecutableProgramNode root, TokenList tokenList)
{
this.file = file;
this.root = root;
this.tokenList = tokenList;
FileOrIFile f = new FileOrIFile(file);
for (Token token : new IterableWrapper<Token>(tokenList))
{
if (token.getPhysicalFile() == null)
token.setPhysicalFile(f);
token.setLogicalFile(file);
}
}
public void accept(IASTVisitor visitor)
{
root.accept(visitor);
}
public IFile getFile()
{
return file;
}
public ASTExecutableProgramNode getRoot()
{
return root;
}
public Iterator<Token> iterator()
{
return tokenList.iterator();
}
// public void rebuildTokenList()
// {
// this.tokenList = new TokenList(root);
// }
public Token findTokenByStreamOffsetLength(final int offset, final int length)
{
// Binary Search
return tokenList.findStreamOffsetLength(offset, length);
// or Linear Search...
// for (int i = 0; i < tokenList.size(); i++)
// {
// Token token = (Token)tokenList.get(i);
// if (token.getOffset() == offset && token.getLength() == length)
// return token;
// }
// return null;
// or Parse Tree Traversal...
// try
// {
// root.visitUsing(new GenericParseTreeVisitor()
// {
// public void visitToken(Token token)
// {
// if (token.getOffset() == offset && token.getLength() == length)
// throw new Notification(token);
// }
// });
// }
// catch (Notification n)
// {
// return (Token)n.getResult();
// }
// return null;
}
/** WARNING: Files are compared by identity, not equality */
public Token findTokenByFileOffsetLength(IFile file, int offset, int length)
{
for (int i = 0; i < tokenList.size(); i++)
{
Token token = (Token)tokenList.get(i);
FileOrIFile physicalFile = token.getPhysicalFile();
if (physicalFile != null
&& physicalFile.getIFile() != null
&& physicalFile.getIFile().hashCode() == file.hashCode() // OPTIMIZATION: Profile indicates lots
&& physicalFile.getIFile().equals(file) // << of time spent in String#equals here
&& token.getFileOffset() == offset
&& token.getLength() == length)
return token;
}
return null;
}
public Token findFirstTokenOnLine(int line)
{
// Binary Search
return tokenList.findFirstTokenOnLine(line);
}
public Token findFirstTokenOnOrAfterLine(int line)
{
// Binary Search
return tokenList.findFirstTokenOnOrAfterLine(line);
}
public Token findLastTokenOnLine(int line)
{
// Binary Search
return tokenList.findLastTokenOnLine(line);
}
public Token findLastTokenOnOrBeforeLine(int line)
{
// Binary Search
return tokenList.findLastTokenOnOrBeforeLine(line);
}
}