00001 #ifndef SYMBOL_TREE_IMPLEMENTATION_FILE
00002 #define SYMBOL_TREE_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "symbol_tree.h"
00023
00024 #include <basis/function.h>
00025 #include <data_struct/symbol_table.cpp>
00026 #include <textual/string_manipulation.h>
00027
00028
00029
00030
00031 #undef LOG
00032 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00033
00034 namespace nodes {
00035
00036 class symbol_tree_associations : public symbol_table<symbol_tree *>
00037 {
00038 public:
00039 symbol_tree_associations(int max_bits)
00040 : symbol_table<symbol_tree *>(max_bits) {}
00041 };
00042
00044
00045 symbol_tree::symbol_tree(const istring &node_name, int max_bits)
00046 : tree(),
00047 _associations(new symbol_tree_associations(max_bits)),
00048 _name(new istring(node_name))
00049 {
00050 }
00051
00052 symbol_tree::~symbol_tree()
00053 {
00054 WHACK(_name);
00055 WHACK(_associations);
00056 }
00057
00058 int symbol_tree::children() const { return _associations->symbols(); }
00059
00060 const istring &symbol_tree::name() const { return *_name; }
00061
00062 int symbol_tree::max_bits() const { return _associations->max_bits(); }
00063
00064 void symbol_tree::rehash(int max_bits) { _associations->rehash(max_bits); }
00065
00066 void symbol_tree::hash_appropriately(int max_per_bucket)
00067 { _associations->hash_appropriately(max_per_bucket); }
00068
00069 bool symbol_tree::add(symbol_tree *to_add)
00070 {
00071 FUNCDEF("add");
00072 #ifdef DEBUG_SYMBOL_TREE
00073 LOG(istring("adding node for ") + to_add->name());
00074 #endif
00075 attach(to_add);
00076 _associations->add(to_add->name(), to_add);
00077 return true;
00078 }
00079
00080 outcome symbol_tree::prune(tree *to_zap_in)
00081 {
00082 FUNCDEF("prune");
00083 symbol_tree *to_zap = dynamic_cast<symbol_tree *>(to_zap_in);
00084 if (!to_zap)
00085 non_continuable_error(static_class_name(), func, "wrong type of node in prune");
00086 #ifdef DEBUG_SYMBOL_TREE
00087 LOG(istring("zapping node for ") + to_zap->name());
00088 #endif
00089 int found = which(to_zap);
00090 if (negative(found)) return common::NOT_FOUND;
00091 #ifdef DEBUG_SYMBOL_TREE
00092 int kids = _associations->symbols();
00093 #endif
00094 _associations->whack(to_zap->name());
00095 #ifdef DEBUG_SYMBOL_TREE
00096 if (kids - 1 != _associations->symbols())
00097 deadly_error(static_class_name(), func, "failed to crop kid in symtab");
00098 #endif
00099 tree::prune(to_zap);
00100 return common::OKAY;
00101 }
00102
00103 symbol_tree *symbol_tree::branch(int index) const
00104 { return dynamic_cast<symbol_tree *>(tree::branch(index)); }
00105
00106
00107 void symbol_tree::sort()
00108 {
00109 int n = branches();
00110 symbol_tree *temp;
00111 int gap, i, j;
00112 for (gap = n / 2; gap > 0; gap /= 2) {
00113 for (i = gap; i < n; i++) {
00114 for (j = i - gap; j >= 0 && branch(j)->name() > branch(j + gap)->name();
00115 j = j - gap) {
00116
00117 temp = branch(j + gap);
00118 prune_index(j + gap);
00119 insert(j, temp);
00120 temp = branch(j + 1);
00121 prune_index(j + 1);
00122 insert(j + gap, temp);
00123 }
00124 }
00125 }
00126 }
00127
00128 symbol_tree *symbol_tree::find(const istring &to_find, find_methods how,
00129 string_comparator_function *comp)
00130 {
00131 FUNCDEF("find");
00132 if (comp == NIL) comp = istring_comparator;
00133 #ifdef DEBUG_SYMBOL_TREE
00134 LOG(istring("finding node called ") + to_find);
00135 #endif
00136
00137 if (comp(name(), to_find)) return this;
00138
00139
00140 if (how == recurse_upward) {
00141 symbol_tree *our_parent = dynamic_cast<symbol_tree *>(parent());
00142 if (!our_parent) return NIL;
00143 return our_parent->find(to_find, how, comp);
00144 }
00145
00146
00147 symbol_tree **found = _associations->find(to_find, comp);
00148 #ifdef DEBUG_SYMBOL_TREE
00149 if (!found) LOG(to_find + " was not found.")
00150 else LOG(to_find + " was found successfully.");
00151 #endif
00152 if (!found) {
00153 if (how == recurse_downward) {
00154
00155 symbol_tree *answer = NIL;
00156 for (int i = 0; i < branches(); i++) {
00157
00158
00159 symbol_tree *curr = dynamic_cast<symbol_tree *>(branch(i));
00160 #ifdef DEBUG_SYMBOL_TREE
00161 LOG(istring("recursing to ") + curr->name());
00162 #endif
00163 if (curr)
00164 answer = curr->find(to_find, how, comp);
00165 if (answer)
00166 return answer;
00167 }
00168 }
00169 return NIL;
00170 }
00171 return *found;
00172 }
00173
00174
00175 istring hier_prefix(int depth, int kids)
00176 {
00177 istring indent = string_manipulation::indentation( (depth - 1) * 2);
00178 if (!depth) return "";
00179 else if (!kids) return indent + "|--";
00180 else return indent + "+--";
00181 }
00182
00183 istring symbol_tree::text_form() const
00184 {
00185 FUNCDEF("text_form");
00186 istring to_return;
00187
00188 tree::iterator ted = start(prefix);
00189
00190
00191 tree *curr = (tree *)ted.next();
00192
00193
00194
00195 while (curr) {
00196
00197 symbol_tree *curr_cast = dynamic_cast<symbol_tree *>(curr);
00198 if (!curr_cast) {
00199
00200 #ifdef DEBUG_SYMBOL_TREE
00201 LOG("logic error: unknown type in symbol tree.");
00202 #endif
00203 ted.next();
00204 continue;
00205 }
00206 istring name_to_log = curr_cast->name();
00207 if (!ted.size()) name_to_log = "";
00208 #ifdef DEBUG_SYMBOL_TREE
00209 LOG(isprintf("depth %d kids %d name %s", ted.size(), curr_cast->branches(),
00210 name_to_log.s()));
00211 #endif
00212 to_return += hier_prefix(curr->depth(), curr_cast->branches());
00213 to_return += name_to_log;
00214 to_return += log_base::platform_ending();
00215
00216 curr = (tree *)ted.next();
00217 }
00218
00219 return to_return;
00220 }
00221
00222 }
00223
00224
00225 #endif //SYMBOL_TREE_IMPLEMENTATION_FILE
00226