Example #1
0
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();
}
Example #2
0
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);
}
Example #3
0
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() );
	}
}