/*
 * ExtractRightContext.cpp
 *
 *  Created on: 9. 6. 2015
 *	  Author: Jan Travnicek
 */

#include "ExtractRightContext.h"
#include "First.h"
#include "common/Substitute.h"
#include <grammar/ContextFree/CFG.h>

namespace grammar {

namespace parsing {

void ExtractRightContext::extractRightContext ( grammar::CFG < > & grammar, const DefaultSymbolType & terminal, const ext::set < DefaultSymbolType > & nonterminals ) {
	grammar::CFG < > res ( grammar.getInitialSymbol ( ) );

	res.setNonterminalAlphabet ( grammar.getNonterminalAlphabet ( ) );
	res.setTerminalAlphabet ( grammar.getTerminalAlphabet ( ) );

	for ( const std::pair < const DefaultSymbolType, ext::set < ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > > > > & rule : grammar.getRules ( ) ) {
		const DefaultSymbolType & lhs = rule.first;

		for ( const ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > > & rhs : rule.second ) {
			bool substitued = false;
			if(!rhs.empty ( ))
				for ( ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > >::const_iterator iter = rhs.begin ( ); iter + 1 != rhs.end ( ); ++iter )
					if ( nonterminals.contains ( * iter ) && grammar.getNonterminalAlphabet ( ).contains ( * ( iter + 1 ) ) && First::first ( grammar, ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > > ( iter + 1, rhs.end ( ) ) ).contains ( ext::vector < DefaultSymbolType > { terminal } ) ) {
						Substitute::substitute ( grammar, res, lhs, rhs, iter + 1 );
						substitued = true;
						break;
					}
			if( ! substitued )
				res.addRule ( lhs, rhs );
		}

	}

	grammar = res;
}

} /* namespace parsing */

} /* namespace grammar */
