// ptreenode.cc see license.txt for copyright and terms of use // code for ptreenode.h #include "ptreenode.h" // this module #include "typ.h" // STATICDEF #include "str.h" // string #include "trace.h" // tracingSys #include // strchr int PTreeNode::allocCount = 0; int PTreeNode::alternativeCount = 0; void PTreeNode::init() { merged = NULL; allocCount++; } TreeCount PTreeNode::countTrees() { // memoize to avoid exponential blowup if (count != 0) { return count; } else { // a single tree can have any possibility for each of // its children, so the result is their product count = 1; for (int i=0; icountTrees(); } // are there alternatives? if (merged) { // add them too (recurse down the list of alts) count += merged->countTrees(); } } return count; } void PTreeNode::printTree(ostream &out, PrintFlags pf) const { if (tracingSys("ptreeAddrs")) { pf = (PrintFlags)(pf | PF_ADDRS); } innerPrintTree(out, 0 /*indentation*/, pf); } // amount to indent per level enum { INDENT_INC = 2 }; void PTreeNode::innerPrintTree(ostream &out, int indentation, PrintFlags pf) const { int alts = 1; string LHS; if (merged) { // this is an ambiguity node alts = countMergedList(); // since all of the alternatives should rewrite the same LHS // nonterminal, extract it from the first one char const *firstSpace = strchr(type, ' '); if (!firstSpace) { LHS = type; // no space, use whole thing } else { LHS = substring(type, firstSpace-type); } indentation += INDENT_INC; } // iterate over interpretations int ct=1; for (PTreeNode const *n = this; n != NULL; n = n->merged) { if (alts > 1) { indent(out, indentation - INDENT_INC); out << "--------- ambiguous " << LHS << ": " << ct << " of " << alts << " ---------\n"; } indent(out, indentation); out << n->type; if (pf & PF_EXPAND) { // the type is just the LHS name; write out the RHS names // after an "->" if (n->numChildren) { out << " ->"; for (int c=0; c < n->numChildren; c++) { out << " " << n->children[c]->type; } } } if (pf & PF_ADDRS) { // print the parse tree node address, so I can verify proper sharing out << " (" << ((void*)n) << ")"; } out << "\n"; // iterate over children for (int c=0; c < n->numChildren; c++) { // recursively print children n->children[c]->innerPrintTree(out, indentation + INDENT_INC, pf); } ct++; } if (merged) { // close up ambiguity display indentation -= INDENT_INC; indent(out, indentation); out << "--------- end of ambiguous " << LHS << " ---------\n"; } } STATICDEF void PTreeNode::indent(ostream &out, int n) { for (int i=0; imerged) { ct++; } return ct; } void PTreeNode::addAlternative(PTreeNode *alt) { // insert as 2nd element alt->merged = this->merged; this->merged = alt; alternativeCount++; }