-
Jan Trávníček authoredJan Trávníček authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ToGrammarLeftRG.h 3.03 KiB
/*
* ToGrammarLeftRG.h
*
* Created on: 8. 3. 2014
* Author: Tomas Pecka
*/
#ifndef TO_GRAMMAR_LEFT_RG_H_
#define TO_GRAMMAR_LEFT_RG_H_
#include <grammar/Regular/LeftRG.h>
#include <grammar/Regular/RightRG.h>
#include <common/createUnique.hpp>
namespace grammar {
namespace convert {
/**
* Converts right regular grammar to left regular grammar.
*/
class ToGrammarLeftRG {
public:
/**
* Performs conversion.
*
* \tparam TerminalSymbolType used for the terminal alphabet of the grammar.
* \tparam NonterminalSymbolType used for the nonterminal alphabet, and the initial symbol of the grammar.
*
* \param grammar Right regular grammar to convert
*
* \return left regular grammar which is equivalent to source right regular grammar.
*/
template < class TerminalSymbolType, class NonterminalSymbolType >
static grammar::LeftRG < TerminalSymbolType, NonterminalSymbolType > convert(const grammar::RightRG < TerminalSymbolType, NonterminalSymbolType > & grammar);
};
template < class TerminalSymbolType, class NonterminalSymbolType >
grammar::LeftRG < TerminalSymbolType, NonterminalSymbolType > ToGrammarLeftRG::convert(const grammar::RightRG < TerminalSymbolType, NonterminalSymbolType > & grammar) {
// 1.
NonterminalSymbolType s = common::createUnique( grammar.getInitialSymbol( ), grammar.getNonterminalAlphabet(), grammar.getTerminalAlphabet() );
grammar::LeftRG < TerminalSymbolType, NonterminalSymbolType > lrg(s);
for(const auto & nonterminalSymbol : grammar.getNonterminalAlphabet()) {
lrg.addNonterminalSymbol( nonterminalSymbol );
}
lrg.setTerminalAlphabet( grammar.getTerminalAlphabet( ) );
lrg.setGeneratesEpsilon( grammar.getGeneratesEpsilon( ) );
// 2.
for( const auto & rule : grammar.getRules( ) ) {
const NonterminalSymbolType& lhs = rule.first;
for(const auto & ruleRHS : rule.second ) {
if( ruleRHS.template is<ext::pair<TerminalSymbolType, NonterminalSymbolType>>( ) ) {
const ext::pair<TerminalSymbolType, NonterminalSymbolType>& rhs = ruleRHS.template get<ext::pair<TerminalSymbolType, NonterminalSymbolType>>();
NonterminalSymbolType leftSide = rhs.second;
ext::pair<NonterminalSymbolType, TerminalSymbolType> rightSide = ext::make_pair( lhs, rhs.first );
lrg.addRule( leftSide, std::move ( rightSide ) );
if( lhs == grammar.getInitialSymbol( ) ) {
leftSide = rhs.second;
TerminalSymbolType rightSide2 = rhs.first;
lrg.addRule( leftSide, std::move ( rightSide2 ) );
}
} else {
const TerminalSymbolType& rhs = ruleRHS.template get<TerminalSymbolType>();
NonterminalSymbolType leftSide = lrg.getInitialSymbol( );
ext::pair<NonterminalSymbolType, TerminalSymbolType> rightSide = ext::make_pair ( lhs, rhs );
lrg.addRule( leftSide, std::move ( rightSide ) );
if( lhs == grammar.getInitialSymbol( ) ) {
leftSide = lrg.getInitialSymbol( );
TerminalSymbolType rightSide2 = rhs;
lrg.addRule( leftSide, std::move ( rightSide2 ) );
}
}
}
}
return lrg;
}
} /* namespace convert */
} /* namespace grammar */
#endif /* TO_GRAMMAR_LEFT_RG_H_ */