// **************************************************************************** // Method: Parser::Reduce // // Purpose: // Reduces what is on the stack using the given rule. // // Programmer: Jeremy Meredith // Creation: April 5, 2002 // // Modifications: // Jeremy Meredith, Wed Nov 24 09:02:32 PST 2004 // Added list of tokens. Also, significant refactoring. // // Hank Childs, Fri Jan 28 13:19:33 PST 2005 // Use exception macros. // // Jeremy Meredith, Mon Jun 13 15:53:51 PDT 2005 // I made other changes to enforce that no Token will be stored // inside a parse tree node, leaving us free to delete them after // applying the reduction. This fixes a number of memory leaks. // I also ensured that pos was well populated in all cases. // // Jeremy Meredith, Wed Jul 23 13:26:26 EDT 2008 // Add the rule index to the debug info. // // Kathleen Bonnell, Thu Nov 6 11:57:28 PST 2008 // To prevent a crash on windows for referencing (from GetParseTree) // elems[0] when elems is empty, don't pop elems if rule->index is 0. // // Jeremy Meredith, Mon Nov 17 17:07:04 EST 2008 // The windows bug (see previous comment) was truly a multi-platform // bug. Now we store the result parse tree directly instead of // trying to pretend it's still on the parse elem stack (which // wasn't even happening anyway; it only worked due to a lot of luck!)... // // **************************************************************************** void Parser::Reduce(int r) { #ifdef MOREDEBUG cerr << "Reducing using rule " << G->GetRule(r)->GetIndex() << ": " << *(G->GetRule(r)) << endl; #endif const Rule *rule = G->GetRule(r); const Symbol *lhs = rule->GetLHS(); const Symbol &sym = *lhs; int len = rule->GetRHS().Length(); vector<ParseTreeNode*> E; vector<Token*> T; Pos p; int i; for (i=0; i<len; i++) { int index = (int)elems.size() - len + i; E.push_back(elems[index].node); T.push_back(elems[index].token); p.Join(elems[index].pos); } ParseTreeNode *node = ApplyRule(sym, rule, E, T, p); // We're done with the tokens now that we've applied the rule for (i=0; i<len; i++) { delete T[i]; } if (!node) { EXCEPTION2(UnhandledReductionException, p, rule); } node->GetPos().Join(p); for (i=0; i<len; i++) { states.pop_back(); elems.pop_back(); } State &state = G->GetState(states.back()); if (G->GetStartSymbol() == lhs) { parseTree = node; PrintState(cerr); #ifdef MOREDEBUG cerr << "Accepting!\n\n"; #endif accept = true; return; } // now do the goto elems.push_back(ParseElem(lhs, node)); states.push_back(state.shift[lhs]); PrintState(cerr); }