symbol_tree.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "symbol_tree.h"
00016
00017 #include <basis/functions.h>
00018 #include <structures/symbol_table.h>
00019 #include <textual/parser_bits.h>
00020 #include <textual/string_manipulation.h>
00021
00022
00023
00024
00025 #undef LOG
00026 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
00027
00028 using namespace basis;
00029 using namespace structures;
00030 using namespace textual;
00031
00032 namespace nodes {
00033
00034 class symbol_tree_associations : public symbol_table<symbol_tree *>
00035 {
00036 public:
00037 symbol_tree_associations(int estimated_elements)
00038 : symbol_table<symbol_tree *>(estimated_elements) {}
00039 };
00040
00042
00043 symbol_tree::symbol_tree(const astring &node_name, int estimated_elements)
00044 : tree(),
00045 _associations(new symbol_tree_associations(estimated_elements)),
00046 _name(new astring(node_name))
00047 {
00048 }
00049
00050 symbol_tree::~symbol_tree()
00051 {
00052 WHACK(_name);
00053 WHACK(_associations);
00054 }
00055
00056 int symbol_tree::children() const { return _associations->symbols(); }
00057
00058 const astring &symbol_tree::name() const { return *_name; }
00059
00060 int symbol_tree::estimated_elements() const { return _associations->estimated_elements(); }
00061
00062 void symbol_tree::rehash(int estimated_elements) { _associations->rehash(estimated_elements); }
00063
00064 void symbol_tree::hash_appropriately(int estimated_elements)
00065 { _associations->hash_appropriately(estimated_elements); }
00066
00067 bool symbol_tree::add(symbol_tree *to_add)
00068 {
00069 #ifdef DEBUG_SYMBOL_TREE
00070 FUNCDEF("add");
00071 LOG(astring("adding node for ") + to_add->name());
00072 #endif
00073 attach(to_add);
00074 _associations->add(to_add->name(), to_add);
00075 return true;
00076 }
00077
00078 outcome symbol_tree::prune(tree *to_zap_in)
00079 {
00080 #ifdef DEBUG_SYMBOL_TREE
00081 FUNCDEF("prune");
00082 #endif
00083 symbol_tree *to_zap = dynamic_cast<symbol_tree *>(to_zap_in);
00084 if (!to_zap)
00085 throw("error: symbol_tree::prune: wrong type of node in prune");
00086 #ifdef DEBUG_SYMBOL_TREE
00087 LOG(astring("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 throw("error: symbol_tree::prune: 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 astring &to_find, find_methods how,
00129 string_comparator_function *comp)
00130 {
00131 #ifdef DEBUG_SYMBOL_TREE
00132 FUNCDEF("find");
00133 #endif
00134 if (comp == NIL) comp = astring_comparator;
00135 #ifdef DEBUG_SYMBOL_TREE
00136 LOG(astring("finding node called ") + to_find);
00137 #endif
00138
00139 if (comp(name(), to_find)) return this;
00140
00141
00142 if (how == recurse_upward) {
00143 symbol_tree *our_parent = dynamic_cast<symbol_tree *>(parent());
00144 if (!our_parent) return NIL;
00145 return our_parent->find(to_find, how, comp);
00146 }
00147
00148
00149 symbol_tree **found = _associations->find(to_find, comp);
00150 #ifdef DEBUG_SYMBOL_TREE
00151 if (!found) LOG(to_find + " was not found.")
00152 else LOG(to_find + " was found successfully.");
00153 #endif
00154 if (!found) {
00155 if (how == recurse_downward) {
00156
00157 symbol_tree *answer = NIL;
00158 for (int i = 0; i < branches(); i++) {
00159
00160
00161 symbol_tree *curr = dynamic_cast<symbol_tree *>(branch(i));
00162 #ifdef DEBUG_SYMBOL_TREE
00163 LOG(astring("recursing to ") + curr->name());
00164 #endif
00165 if (curr)
00166 answer = curr->find(to_find, how, comp);
00167 if (answer)
00168 return answer;
00169 }
00170 }
00171 return NIL;
00172 }
00173 return *found;
00174 }
00175
00176
00177 astring hier_prefix(int depth, int kids)
00178 {
00179 astring indent = string_manipulation::indentation( (depth - 1) * 2);
00180 if (!depth) return "";
00181 else if (!kids) return indent + "|--";
00182 else return indent + "+--";
00183 }
00184
00185 astring symbol_tree::text_form() const
00186 {
00187 #ifdef DEBUG_SYMBOL_TREE
00188 FUNCDEF("text_form");
00189 #endif
00190 astring to_return;
00191
00192 tree::iterator ted = start(prefix);
00193
00194
00195 tree *curr = (tree *)ted.next();
00196
00197
00198
00199 while (curr) {
00200
00201 symbol_tree *curr_cast = dynamic_cast<symbol_tree *>(curr);
00202 if (!curr_cast) {
00203
00204 #ifdef DEBUG_SYMBOL_TREE
00205 LOG("logic error: unknown type in symbol tree.");
00206 #endif
00207 ted.next();
00208 continue;
00209 }
00210 astring name_to_log = curr_cast->name();
00211 if (!ted.size()) name_to_log = "";
00212 #ifdef DEBUG_SYMBOL_TREE
00213 LOG(a_sprintf("depth %d kids %d name %s", ted.size(), curr_cast->branches(),
00214 name_to_log.s()));
00215 #endif
00216 to_return += hier_prefix(curr->depth(), curr_cast->branches());
00217 to_return += name_to_log;
00218 to_return += parser_bits::platform_eol_to_chars();
00219
00220 curr = (tree *)ted.next();
00221 }
00222
00223 return to_return;
00224 }
00225
00226 }
00227