blob: 8ad426e9437f8b822e75a3457c47b992eb3bb6fc [file] [log] [blame]
package org.eclipse.cdt.internal.core.parser;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* @author aniefer
*
* To change this generated comment edit the template variable "typecomment":
* Window>Preferences>Java>Templates.
* To enable and disable the creation of type comments go to
* Window>Preferences>Java>Code Generation.
*/
public class Declaration {
/**
* Constructor for Declaration.
*/
public Declaration() {
super();
}
public Declaration( String name ){
_name = name;
}
public Declaration( String name, Object obj ){
_name = name;
_object = obj;
}
//Type information, only what we need for now...
public static final int typeMask = 0x0001f;
public static final int isStatic = 0x00020;
// Types
public static final int t_type = 0; // Type Specifier
public static final int t_class = 1;
public static final int t_struct = 2;
public static final int t_union = 3;
public static final int t_enum = 4;
public void setStatic( boolean b ) { setBit( b, isStatic ); }
public boolean isStatic() { return checkBit( isStatic ); }
public void setType(int t) throws ParserSymbolTableException {
if( t > typeMask )
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
_typeInfo = _typeInfo & ~typeMask | t;
}
public int getType(){
return _typeInfo & typeMask;
}
public boolean isType( int t ){
return ( t == -1 || getType() == t );
}
public Declaration getTypeDeclaration() { return _typeDeclaration; }
public void setTypeDeclaration( Declaration type ){
try { setType( t_type ); }
catch (ParserSymbolTableException e) { /*will never happen*/ }
_typeDeclaration = type;
}
public String getName() { return _name; }
public void setName(String name) { _name = name; }
public Object getObject() { return _object; }
public void setObject( Object obj ) { _object = obj; }
public Declaration getContainingScope() { return _containingScope; }
protected void setContainingScope( Declaration scope ) { _containingScope = scope; }
public void addParent( Declaration parent ){
addParent( parent, false );
}
public void addParent( Declaration parent, boolean virtual ){
_parentScopes.add( new ParentWrapper( parent, virtual ) );
}
protected void addDeclaration( Declaration obj ){
obj.setContainingScope( this );
_containedDeclarations.put( obj.getName(), obj );
}
public Map getContainedDeclarations(){
return _containedDeclarations;
}
/**
* Lookup the given name in this context.
* @param type: for elaborated lookups, only return declarations of this
* type
* @param name: Name of the object to lookup
* @return Declaration
* @throws ParserSymbolTableException
* @see ParserSymbolTable#Lookup
*/
protected Declaration Lookup( int type, String name ) throws ParserSymbolTableException{
if( type != -1 && type < t_class && type > t_union )
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
Declaration decl = null;
//if this name define in this scope?
decl = (Declaration) _containedDeclarations.get( name );
//if yes, it hides any others, we are done.
if( decl != null && decl.isType( type ) ){
return decl;
}
//if no, we next check any parents we have
decl = LookupInParents( type, name, new HashSet() );
//if still not found, check our containing scope.
if( decl == null && _containingScope != null )
decl = _containingScope.Lookup( type, name );
return decl;
}
private Declaration LookupInParents( int type, String name, Set virtualsVisited ) throws ParserSymbolTableException{
Declaration decl = null, temp = null;
Iterator iterator = _parentScopes.iterator();
ParentWrapper wrapper = null;
try{
wrapper = (ParentWrapper) iterator.next();
}
catch ( NoSuchElementException e ){
wrapper = null;
}
while( wrapper != null )
{
if( !wrapper.isVirtual || !virtualsVisited.contains( wrapper.parent ) ){
if( wrapper.isVirtual )
virtualsVisited.add( wrapper.parent );
//is this name define in this scope?
temp = (Declaration) wrapper.parent._containedDeclarations.get( name );
if( temp == null || !temp.isType( type ) )
temp = wrapper.parent.LookupInParents( type, name, virtualsVisited );
}
if( temp != null && temp.isType( type ) ){
if( decl == null )
decl = temp;
else if ( temp != null )
{
//it is not ambiguous if temp & decl are the same thing and it is static
//or an enum
if( decl == temp && ( temp.isStatic() || temp.getType() == t_enum) )
temp = null;
else
throw( new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ) );
}
}
else
temp = null;
try{
wrapper = (ParentWrapper) iterator.next();
}
catch (NoSuchElementException e){
wrapper = null;
}
}
return decl;
}
// Convenience methods
private void setBit(boolean b, int mask) {
if (b) _typeInfo = _typeInfo | mask;
else _typeInfo = _typeInfo & ~mask;
}
private boolean checkBit(int mask) {
return (_typeInfo & mask) != 0;
}
//Other scopes to check if the name is not in currRegion
//we might want another Vector to deal with namespaces & using...
private Declaration _containingScope = null;
private Declaration _type = null;
private Declaration _typeDeclaration = null;
private int _typeInfo = 0;
private Object _object = null;
private List _parentScopes = new LinkedList();
private Map _containedDeclarations = new HashMap();
private String _name;
private class ParentWrapper{
public ParentWrapper( Declaration p, boolean v ){
parent = p;
isVirtual = v;
}
public boolean isVirtual = false;
public Declaration parent = null;
}
}