package net.sourceforge.pmd.cpd.cppast;
import java.util.Hashtable;
/**
* Manages the symbol table and scopes within a given compilation unit.
*/
public class SymtabManager
{
/**
* Global symbol table indexed by the name of the scope (class/function).
*/
static Hashtable scopeTable = new Hashtable();
/**
* Stack of scopes. Currently max. nesting allowed is 100.
*/
static Scope[] scopeStack = new Scope[100];
/**
* Current depth of scope nesting.
*/
static int depth = 0;
/**
* Dummy at the bottom of the stack so that no need to check for null.
*/
static
{
scopeStack[depth] = new Scope(null);
}
/**
* Opens a new scope (with optional name and type flag).
*/
public static Scope OpenScope(String scopeName, boolean isType)
{
Scope newScope;
if (scopeName != null)
{
if (isType)
{
newScope = new ClassScope(scopeName, scopeStack[depth]);
scopeStack[depth].PutTypeName(scopeName, newScope);
}
else
{
newScope = new Scope(scopeName, isType, scopeStack[depth]);
}
scopeTable.put(scopeName, newScope);
}
else
newScope = new Scope(scopeStack[depth]);
scopeStack[++depth] = newScope;
return newScope;
}
public static void OpenScope(Scope sc)
{
scopeStack[++depth] = sc;
}
public static void PutTypeName(String name)
{
scopeStack[depth].PutTypeName(name);
}
public static boolean IsFullyScopedTypeName(String name)
{
if (name == null)
return false;
if (name.indexOf("::") == -1)
return IsTypeName(name);
Scope sc = GetScopeOfFullyScopedName(name);
if (sc != null)
return sc.IsTypeName(name.substring(name.lastIndexOf("::") + 2,
name.length()));
return false;
}
public static boolean IsTypeName(String name)
{
int i = depth;
while (i >= 0)
{
if (scopeStack[i--].IsTypeName(name))
return true;
}
return false;
}
public static void CloseScope()
{
depth--;
}
/**
* For now, we just say if it is a class name, it is OK to call it a
* constructor.
*/
public static boolean IsCtor(String name)
{
if (name == null)
return false;
if (name.indexOf("::") == -1)
return GetScope(name) != null;
Scope sc = GetScopeOfFullyScopedName(name);
if (sc != null && sc.parent != null)
return sc.parent.GetScope(name.substring(name.lastIndexOf("::") + 2,
name.length())) == sc;
return false;
}
public static Scope GetCurScope()
{
return scopeStack[depth];
}
public static Scope GetScope(String name)
{
int i = depth;
Scope sc = null;
while (i >= 0)
if ((sc = scopeStack[i--].GetScope(name)) != null)
return sc;
return null;
}
/**
* Returns the Scope of B in A::B::C.
*/
public static Scope GetScopeOfFullyScopedName(String name)
{
Scope sc;
int i = 0, j = 0;
if (name.indexOf("::") == -1)
return GetScope(name);
if (name.indexOf("::") == 0)
{
sc = scopeStack[1];
j = 2;
}
else
sc = GetCurScope();
String tmp = name.substring(j, name.lastIndexOf("::"));
while ((j = tmp.indexOf("::", i)) != -1)
{
sc = sc.GetScope(tmp.substring(i, j));
i = j + 2;
if (sc == null)
return null;
}
if (sc == GetCurScope())
return GetScope(tmp.substring(i, tmp.length()));
return sc.GetScope(tmp.substring(i, tmp.length()));
}
public static boolean IsGlobalScope()
{
return depth == 1 || depth == 2;
}
}