Sym.cpp

00001 /*          
00002  *             Copyright (C) 2005 Maarten Keijzer
00003  *
00004  *          This program is free software; you can redistribute it and/or modify
00005  *          it under the terms of version 2 of the GNU General Public License as 
00006  *          published by the Free Software Foundation. 
00007  *
00008  *          This program is distributed in the hope that it will be useful,
00009  *          but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *          GNU General Public License for more details.
00012  *
00013  *          You should have received a copy of the GNU General Public License
00014  *          along with this program; if not, write to the Free Software
00015  *          Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016  */
00017 
00018 #include <sstream>
00019 #include <vector>
00020 
00021 #include "Sym.h"
00022 
00023 using namespace std;
00024 
00025 typedef UniqueNodeStats* (*NodeStatFunc)(Sym&);
00026 
00027 UniqueNodeStats* (*Sym::factory)(const Sym&) = 0;
00028 
00029 SymMap Sym::dag(100000); // reserve space for so many nodes
00030 std::vector<unsigned> Sym::token_count;
00031         
00032 
00033 size_t get_size(const SymVec& vec) {
00034     size_t sz = 0;
00035     for (unsigned i = 0; i < vec.size(); ++i) {
00036         sz += vec[i].size();
00037     }
00038     return sz;
00039 }
00040 
00041 size_t get_depth(const SymVec& vec) {
00042     size_t dp = 1;
00043     for (unsigned i = 0; i < vec.size(); ++i) {
00044         dp = std::max(dp, vec[i].depth());
00045     }
00046     return dp;
00047 }
00048 
00049 Sym::Sym(token_t tok, const SymVec& args_) : node(dag.end())
00050 {
00051     detail::SymKey key(tok, detail::SymArgs(args_));
00052     detail::SymValue val;
00053 
00054     node = dag.insert(pair<const detail::SymKey, detail::SymValue>(key, val)).first; 
00055     
00056     if (__unchecked_refcount() == 0) { // new node, set some stats 
00057         node->second.size  = 1 + get_size(args_);
00058         node->second.depth = 1 + get_depth(args_);
00059         
00060         // token count
00061         if (tok >= token_count.size()) {
00062             token_count.resize(tok+1);
00063         }
00064         
00065         incref();
00066         node->first.fixate();   
00067         // call the factory function if available
00068         if (factory) node->second.uniqueNodeStats = factory(*this);
00069     
00070     }
00071     else incref();
00072 }
00073 
00074 Sym::Sym(token_t tok, const Sym& a) : node(dag.end()) { 
00075     SymVec args_; args_.push_back(a); 
00076     detail::SymKey key(tok, detail::SymArgs(args_));
00077     detail::SymValue val;
00078 
00079     node = dag.insert(pair<const detail::SymKey, detail::SymValue>(key, val)).first; 
00080     
00081     if (__unchecked_refcount() == 0) { // new node, set some stats 
00082         node->second.size = 1 + get_size(args_);
00083         node->second.depth = 1 + get_depth(args_);
00084         
00085         // token count
00086         if (tok >= token_count.size()) {
00087             token_count.resize(tok+1);
00088         }
00089         
00090         incref();
00091         node->first.fixate();
00092         // call the factory function if available
00093         if (factory) node->second.uniqueNodeStats = factory(*this);
00094     }
00095     else incref();
00096 }
00097 
00098 Sym::Sym(token_t tok) : node(dag.end()) {
00099     detail::SymKey key(tok);
00100     detail::SymValue val;
00101     node = dag.insert(pair<const detail::SymKey, detail::SymValue>(key, val)).first; 
00102     
00103     if (__unchecked_refcount() == 0) { // new node, set some stats 
00104         node->second.size = 1;
00105         node->second.depth = 1;
00106         
00107         // token count
00108         if (tok >= token_count.size()) {
00109             token_count.resize(tok+1);
00110         }
00111         
00112         incref();
00113 
00114         // call the factory function if available
00115         if (factory) node->second.uniqueNodeStats = factory(*this);
00116         
00117     }
00118     else incref();
00119 }
00120 
00121 std::pair<Sym,bool> insert_subtree_impl(const Sym& cur, size_t w, const Sym& nw) {
00122     if (w-- == 0) return make_pair(nw, !(nw == cur));
00123     
00124     const SymVec& vec = cur.args();
00125     std::pair<Sym,bool> result;
00126     unsigned i; 
00127     
00128     for (i = 0; i < vec.size(); ++i) {
00129         if (w < vec[i].size()) {
00130             result = insert_subtree_impl(vec[i], w, nw);
00131             if (result.second == false) return std::make_pair(cur, false); // unchanged
00132             break;
00133         }
00134         w -= vec[i].size();
00135     }
00136     SymVec newvec = cur.args();
00137     newvec[i] = result.first;
00138     return make_pair(Sym(cur.token(), newvec), true);
00139 }
00140 
00141 Sym insert_subtree(const Sym& cur, size_t w, const Sym& nw) {
00142     return insert_subtree_impl(cur,w,nw).first;
00143 }
00144 Sym get_subtree(const Sym& cur, size_t w) {
00145     if (w-- == 0) return cur;
00146     
00147     const SymVec& vec = cur.args();
00148     for (unsigned i = 0; i < vec.size(); ++i) {
00149         if (w < vec[i].size()) return get_subtree(vec[i], w);
00150         w-=vec[i].size();
00151     }
00152     return cur;
00153 }
00154 
00155 

Generated on Thu Oct 19 05:06:42 2006 for EO by  doxygen 1.3.9.1