Example #1
0
// ****************************************************************************
//  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);
}