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

#include "First.h"
#include "common/Substitute.h"
#include "CornerSubstitution.h"

#include <grammar/ContextFree/CFG.h>

namespace grammar::parsing {

void CornerSubstitution::cornerSubstitution ( grammar::CFG < > & grammar, const DefaultSymbolType & terminal, const DefaultSymbolType & nonterminal ) {
	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 ) {
			ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > > rawRhs ( rhs.begin ( ), rhs.end ( ) );
			if ( ( lhs == nonterminal ) && ( !rhs.empty ( ) ) && ( grammar.getNonterminalAlphabet ( ).contains ( rhs[0] ) ) && First::first ( grammar, rawRhs ).contains ( ext::vector < DefaultSymbolType > { terminal } ) )
				Substitute::substitute ( grammar, res, lhs, rhs, rhs.begin ( ) );
			else
				res.addRule ( lhs, rhs );
		}
	}

	grammar = res;
}

} /* namespace grammar::parsing */

