/*
 * GrammarTransformCommon.h
 *
 * This file is part of Algorithms library toolkit.
 * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)

 * Algorithms library toolkit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * Algorithms library toolkit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with Algorithms library toolkit.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  Created on: 05. 11. 2019
 *	  Author: Tomas Pecka
 */

#include <grammar/ContextFree/CFG.h>

#ifndef GRAMMAR_TRANSFORM_COMMON_H_
#define GRAMMAR_TRANSFORM_COMMON_H_

template < class TerminalSymbolType, class NonterminalSymbolType >
void copyNonterminalsRename ( grammar::CFG < TerminalSymbolType, ext::pair < NonterminalSymbolType, unsigned > > & dst, const grammar::CFG < TerminalSymbolType, NonterminalSymbolType > & src, const unsigned suffix ) {
	for ( const NonterminalSymbolType & symb : src.getNonterminalAlphabet ( ) )
		dst.addNonterminalSymbol ( ext::make_pair ( symb, suffix ) );
}

template < class TerminalSymbolType, class NonterminalSymbolType >
void copyRulesRenameNonterminals ( grammar::CFG < TerminalSymbolType, ext::pair < NonterminalSymbolType, unsigned > > & dst, const grammar::CFG < TerminalSymbolType, NonterminalSymbolType > & src, const unsigned suffix ) {
	for ( const std::pair < const NonterminalSymbolType, ext::set < ext::vector < ext::variant < TerminalSymbolType, NonterminalSymbolType > > > > & kv : src.getRules ( ) ) {
		const NonterminalSymbolType & lhs = kv.first;

		for ( const ext::vector < ext::variant < TerminalSymbolType, NonterminalSymbolType > > & rhs : kv.second ) {
			ext::vector < ext::variant < TerminalSymbolType, ext::pair < NonterminalSymbolType, unsigned > > > newRhs;

			for ( const ext::variant < TerminalSymbolType, NonterminalSymbolType > & symb : rhs ) {
				if ( symb.template is < TerminalSymbolType > ( ) && src.getTerminalAlphabet ( ).count ( symb.template get < TerminalSymbolType > ( ) ) )
					newRhs.push_back ( symb.template get < TerminalSymbolType > ( ) );
				else
					newRhs.push_back ( ext::make_pair ( symb.template get < NonterminalSymbolType > ( ), suffix ) );
			}

			dst.addRule ( ext::make_pair ( lhs, suffix ), newRhs );
		}
	}
}

#endif /* GRAMMAR_TRANSFORM_COMMON_H_ */
