#include <list>
#include "trimTest.h"

#include "automaton/simplify/Trim.h"
#include "grammar/simplify/Trim.h"

#include "automaton/FSM/DFA.h"
#include "grammar/Regular/RightRG.h"

#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))

CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( trimTest, "automaton" );
CPPUNIT_TEST_SUITE_REGISTRATION( trimTest );

void trimTest::setUp() {
}

void trimTest::tearDown() {
}

void trimTest::testTrimAutomaton() {
  automaton::DFA < > automaton(label::labelFrom(1));

  automaton.addState(label::labelFrom(1));
  automaton.addState(label::labelFrom(2));
  automaton.addState(label::labelFrom(3));
  automaton.addInputSymbol(alphabet::symbolFrom("a"));
  automaton.addInputSymbol(alphabet::symbolFrom("b"));
  
  automaton.addTransition(label::labelFrom(1), alphabet::symbolFrom("a"), label::labelFrom(2));
  automaton.addTransition(label::labelFrom(2), alphabet::symbolFrom("b"), label::labelFrom(1));
  automaton.addTransition(label::labelFrom(3), alphabet::symbolFrom("b"), label::labelFrom(1));

  automaton.addFinalState(label::labelFrom(1));
  
  automaton::DFA<> trimed = automaton::simplify::Trim::trim(automaton);

  CPPUNIT_ASSERT(trimed.getStates().size() == 2);
}

void trimTest::testTrimGrammar() {
  grammar::RightRG < > rrGrammar(alphabet::symbolFrom(1));

  rrGrammar.addNonterminalSymbol(alphabet::symbolFrom(1));
  rrGrammar.addNonterminalSymbol(alphabet::symbolFrom(2));
  rrGrammar.addNonterminalSymbol(alphabet::symbolFrom(3));
  rrGrammar.addNonterminalSymbol(alphabet::symbolFrom(4));
  rrGrammar.addNonterminalSymbol(alphabet::symbolFrom(5));
  rrGrammar.addNonterminalSymbol(alphabet::symbolFrom(6));
  rrGrammar.addTerminalSymbol(alphabet::symbolFrom("a"));
  rrGrammar.addTerminalSymbol(alphabet::symbolFrom("b"));
  
  rrGrammar.addRule(alphabet::symbolFrom(1), std::make_pair(alphabet::symbolFrom("a"), alphabet::symbolFrom(2)));
  rrGrammar.addRule(alphabet::symbolFrom(2), std::make_pair(alphabet::symbolFrom("b"), alphabet::symbolFrom(3)));
  rrGrammar.addRule(alphabet::symbolFrom(3), alphabet::symbolFrom("a"));

  rrGrammar.addRule(alphabet::symbolFrom(4), std::make_pair(alphabet::symbolFrom("b"), alphabet::symbolFrom(5)));
  rrGrammar.addRule(alphabet::symbolFrom(5), alphabet::symbolFrom("a"));
  rrGrammar.addRule(alphabet::symbolFrom(5), std::make_pair(alphabet::symbolFrom("b"), alphabet::symbolFrom(2)));
  rrGrammar.addRule(alphabet::symbolFrom(6), std::make_pair(alphabet::symbolFrom("b"), alphabet::symbolFrom(6)));

  grammar::RightRG < > trimed = grammar::simplify::Trim::trim(rrGrammar);

  CPPUNIT_ASSERT(trimed.getNonterminalAlphabet().size() == 3);
}