void Grammar::findStates( void ) { Symbol *startSym = getStartSymbol( true ); if ( ! startSym ) { Error::get()->add( "No rules to choose as start rule." ); return; } if ( RuleTable::get()->isOnRightSide( startSym->getName() ) ) { Error::get()->add( "The start symbol \"%s\" occurs on the " "right-hand side of a rule. This will result " "in a parser which does not work properly.", startSym->getName().c_str() ); } myCurConfigList.reset(); Rule *startRule = RuleTable::get()->findFirstRule( startSym->getName() ); while ( startRule ) { Config *tmpCfg = myCurConfigList.addWithBasis( startRule, 0 ); // All start rules have the start symbol as their left hand side // tmpCfg->addFollowSet( startSym->getName() ); tmpCfg->addFollowSet( SymbolTable::get()->getNthSymbol( 0 )->getName() ); startRule = RuleTable::get()->getNextRule( startRule ); } getNextState(); }
void Grammar::findReachable() { getSymbol(getStartSymbol()).m_reachable = true; const int n = getProductionCount(); bool stable; do { // gotoxy(0, 0); dump(); pause(); stable = true; for(int p = 0; p < n; p++) { const Production &prod = m_productions[p]; if(getSymbol(prod.m_leftSide).m_reachable) { const int length = prod.getLength(); for(int s = 0; s < length; s++) { GrammarSymbol &rightSymbol = getSymbol(prod.m_rightSide[s]); if(!rightSymbol.m_reachable) { // printf(_T(")%s is reachable\n", rightSymbol.m_name.cstr()); rightSymbol.m_reachable = true; stable = false; } } } } } while(!stable); }
void Grammar::findActions( void ) { size_t i, j, nState, nSym, nRule; State *stp; nState = StateTable::get()->getNumStates(); nSym = SymbolTable::get()->getNumSymbols(); // Find all reduce actions... for ( i = 0; i < nState; ++i ) { stp = StateTable::get()->getNthState( i ); for ( Config *cfp = stp->getConfig(); cfp; cfp = cfp->getNext() ) { // Check if dot at extreme right if ( size_t( cfp->getDot() ) == cfp->getRule()->getRHS().size() ) { for ( j = 0; j < nSym; ++j ) { Symbol *sp = SymbolTable::get()->getNthSymbol( j ); if ( ( Symbol::TERMINAL == sp->getType() || sp->getName() == "$" ) && cfp->getFollowSet().isSet( sp->getName() ) ) { stp->addAction( Action::REDUCE, sp->getName(), 0, cfp->getRule() ); } } } } } Symbol *startSym = getStartSymbol(); stp = StateTable::get()->getNthState( 0 ); // Add the accepting token to the first state which is always the // starting state of the finite state machine as an action to accept // if the lookahead is the start nonterminal. if ( startSym && stp ) stp->addAction( Action::ACCEPT, startSym->getName(), 0, 0 ); // Resolve conflicts for ( i = 0; i < nState; ++i ) { stp = StateTable::get()->getNthState( i ); // Check for SHIFT-SHIFT conflicts first (nothing we can do to resolve) for ( Config *cfp = stp->getConfig(); cfp; cfp = cfp->getNext() ) { if ( ! cfp->getForwardPropLinks().empty() ) continue; Rule *curRule = cfp->getRule(); if ( size_t( cfp->getDot() ) == curRule->getRHS().size() ) continue; for ( Config *next = stp->getConfig(); next; next = next->getNext() ) { if ( next == cfp ) continue; Rule *nextRule = next->getRule(); if ( size_t( next->getDot() ) == nextRule->getRHS().size() ) continue; if ( curRule->getRHS()[cfp->getDot()].first == nextRule->getRHS()[next->getDot()].first ) { std::cout << "Unresolved SHIFT-SHIFT conflict between:\n" << std::endl; curRule->print( std::cout ); std::cout << std::endl << "\nand\n" << std::endl; nextRule->print( std::cout ); std::cout << std::endl << std::endl; ++myNumConflicts; } } } stp->sortActions(); ActionList &ap = stp->getActions(); size_t nAct = ap.getNumActions(); if ( nAct > 0 ) { for ( j = 0; j < (nAct - 1); ++j ) { Action &act = ap.getNthAction( j ); for ( size_t k = j + 1; k < nAct; ++k ) { Action &nact = ap.getNthAction( k ); int numCs = resolveConflict( act, nact ); if ( 0 != numCs ) { std::cout << " Conflict in state " << i << std::endl; myNumConflicts += numCs; } } } } } // Report errors for each rule that can never be reduced. nRule = RuleTable::get()->getNumRules(); for ( i = 0; i < nRule; ++i ) RuleTable::get()->getNthRule( i )->setCanReduce( false ); for ( i = 0; i < nState; ++i ) { stp = StateTable::get()->getNthState( i ); ActionList &ap = stp->getActions(); size_t nAct = ap.getNumActions(); for ( j = 0; j < nAct; ++j ) { Action &act = ap.getNthAction( j ); if ( act.getType() == Action::REDUCE ) act.getRule()->setCanReduce( true ); } } for ( i = 0; i < nRule; ++i ) { Rule *rp = RuleTable::get()->getNthRule( i ); if ( rp->canReduce() ) continue; std::ostringstream tmpOut; rp->print( tmpOut ); Error::get()->add( rp->getRuleLine(), "Rule for '%s':\n %s\ncan not be reduced.\n", rp->getLHS().c_str(), tmpOut.str().c_str() ); } }