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

#include "LeftFactorize.h"

#include <grammar/ContextFree/CFG.h>
#include <common/createUnique.hpp>

namespace grammar {

namespace parsing {

void LeftFactorize::leftFactorize ( grammar::CFG < > & grammar, const DefaultSymbolType & terminal, const DefaultSymbolType & nonterminal ) {
	grammar::CFG < > res ( grammar.getInitialSymbol ( ) );

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

	DefaultSymbolType primed = common::createUnique ( nonterminal, grammar.getTerminalAlphabet ( ), grammar.getNonterminalAlphabet ( ) );
	res.addNonterminalSymbol ( primed );

	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 ) {
			if ( ( lhs == nonterminal ) && ( !rhs.empty ( ) ) && ( rhs[0] == terminal ) ) {
				res.addRule ( lhs, ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > > { terminal, primed } );
				res.addRule ( primed, ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > > ( rhs.begin ( ) + 1, rhs.end ( ) ) );
			} else {
				res.addRule ( lhs, rhs );
			}
		}
	}

	grammar = res;
}

} /* namespace parsing */

} /* namespace grammar */
