001: package org.acm.seguin.pmd.cpd.cppast;
002:
003: import java.util.Hashtable;
004:
005: /**
006: * Manages the symbol table and scopes within a given compilation unit.
007: */
008: public class SymtabManager {
009: /**
010: * Global symbol table indexed by the name of the scope (class/function).
011: */
012: static Hashtable scopeTable = new Hashtable();
013:
014: /**
015: * Stack of scopes. Currently max. nesting allowed is 100.
016: */
017: static Scope[] scopeStack = new Scope[100];
018:
019: /**
020: * Current depth of scope nesting.
021: */
022: static int depth = 0;
023:
024: /**
025: * Dummy at the bottom of the stack so that no need to check for null.
026: */
027: static {
028: scopeStack[depth] = new Scope(null);
029: }
030:
031: /**
032: * Opens a new scope (with optional name and type flag).
033: */
034: public static Scope OpenScope(String scopeName, boolean isType) {
035: Scope newScope;
036:
037: if (scopeName != null) {
038: if (isType) {
039: newScope = new ClassScope(scopeName, scopeStack[depth]);
040: scopeStack[depth].PutTypeName(scopeName, newScope);
041: } else {
042: newScope = new Scope(scopeName, isType,
043: scopeStack[depth]);
044: }
045:
046: scopeTable.put(scopeName, newScope);
047: } else
048: newScope = new Scope(scopeStack[depth]);
049:
050: scopeStack[++depth] = newScope;
051: return newScope;
052: }
053:
054: public static void OpenScope(Scope sc) {
055: scopeStack[++depth] = sc;
056: }
057:
058: public static void PutTypeName(String name) {
059: scopeStack[depth].PutTypeName(name);
060: }
061:
062: public static boolean IsFullyScopedTypeName(String name) {
063: if (name == null)
064: return false;
065:
066: if (name.indexOf("::") == -1)
067: return IsTypeName(name);
068:
069: Scope sc = GetScopeOfFullyScopedName(name);
070:
071: if (sc != null)
072: return sc.IsTypeName(name.substring(
073: name.lastIndexOf("::") + 2, name.length()));
074:
075: return false;
076: }
077:
078: public static boolean IsTypeName(String name) {
079: int i = depth;
080:
081: while (i >= 0) {
082: if (scopeStack[i--].IsTypeName(name))
083: return true;
084: }
085:
086: return false;
087: }
088:
089: public static void CloseScope() {
090: depth--;
091: }
092:
093: /**
094: * For now, we just say if it is a class name, it is OK to call it a
095: * constructor.
096: */
097: public static boolean IsCtor(String name) {
098: if (name == null)
099: return false;
100:
101: if (name.indexOf("::") == -1)
102: return GetScope(name) != null;
103:
104: Scope sc = GetScopeOfFullyScopedName(name);
105:
106: if (sc != null && sc.parent != null)
107: return sc.parent.GetScope(name.substring(name
108: .lastIndexOf("::") + 2, name.length())) == sc;
109:
110: return false;
111: }
112:
113: public static Scope GetCurScope() {
114: return scopeStack[depth];
115: }
116:
117: public static Scope GetScope(String name) {
118: int i = depth;
119: Scope sc = null;
120:
121: while (i >= 0)
122: if ((sc = scopeStack[i--].GetScope(name)) != null)
123: return sc;
124:
125: return null;
126: }
127:
128: /**
129: * Returns the Scope of B in A::B::C.
130: */
131: public static Scope GetScopeOfFullyScopedName(String name) {
132: Scope sc;
133: int i = 0, j = 0;
134:
135: if (name.indexOf("::") == -1)
136: return GetScope(name);
137:
138: if (name.indexOf("::") == 0) {
139: sc = scopeStack[1];
140: j = 2;
141: } else
142: sc = GetCurScope();
143:
144: String tmp = name.substring(j, name.lastIndexOf("::"));
145:
146: while ((j = tmp.indexOf("::", i)) != -1) {
147: sc = sc.GetScope(tmp.substring(i, j));
148: i = j + 2;
149:
150: if (sc == null)
151: return null;
152: }
153:
154: if (sc == GetCurScope())
155: return GetScope(tmp.substring(i, tmp.length()));
156:
157: return sc.GetScope(tmp.substring(i, tmp.length()));
158: }
159:
160: public static boolean IsGlobalScope() {
161: return depth == 1 || depth == 2;
162: }
163: }
|