diff --git a/alib2algo/src/grammar/parsing/AbsorbTerminalSymbol.cpp b/alib2algo/src/grammar/parsing/AbsorbTerminalSymbol.cpp index 5521fbc6208b8628ff45b1c8cfe1981f96ee216d..596daa5172e99acf3d237b9a1a0c9f28e12773f6 100644 --- a/alib2algo/src/grammar/parsing/AbsorbTerminalSymbol.cpp +++ b/alib2algo/src/grammar/parsing/AbsorbTerminalSymbol.cpp @@ -14,18 +14,30 @@ namespace grammar { namespace parsing { -alphabet::Symbol AbsorbTerminalSymbol::handleAbsobtion ( const grammar::CFG & orig, grammar::CFG & res, const alphabet::Symbol & nonterminal, const alphabet::Symbol & terminal ) { - alphabet::Symbol newSymbol = alphabet::createUniqueSymbol ( alphabet::Symbol ( alphabet::SymbolPairSymbol ( std::make_pair ( nonterminal, terminal ) ) ), res.getTerminalAlphabet ( ), res.getNonterminalAlphabet ( ) ); +void AbsorbTerminalSymbol::handleAbsobtion ( const grammar::CFG & orig, grammar::CFG & res, const alphabet::Symbol & terminal, const std::set < alphabet::Symbol > & nonterminals, const std::map < alphabet::Symbol, alphabet::Symbol > & nonterminalsPrimed ) { + for ( const alphabet::Symbol & nonterminal : nonterminals ) + for ( const std::vector < alphabet::Symbol > & rhs : orig.getRules ( ).find ( nonterminal )->second ) { + std::vector < alphabet::Symbol > newRHS; - res.addNonterminalSymbol ( newSymbol ); + for ( std::vector < alphabet::Symbol >::const_iterator iter = rhs.begin ( ); iter != rhs.end ( ); ++iter ) { + if ( nonterminals.count ( * iter ) && ( ( iter + 1 == rhs.end ( ) ) || ( terminal == * ( iter + 1 ) ) ) ) { + newRHS.push_back ( nonterminalsPrimed.find ( * iter )->second ); - for ( const std::vector < alphabet::Symbol > & rhs : orig.getRules ( ).find ( nonterminal )->second ) { - std::vector < alphabet::Symbol > newRHS ( rhs.begin ( ), rhs.end ( ) ); - newRHS.push_back ( terminal ); - res.addRule ( newSymbol, newRHS ); - } + if ( iter + 1 != rhs.end ( ) ) ++iter; + } else if ( iter + 1 == rhs.end ( ) ) { + newRHS.push_back ( * iter ); + newRHS.push_back ( terminal ); + } else { + newRHS.push_back ( * iter ); + } + } + + if ( rhs.size ( ) == 0 ) + newRHS.push_back ( terminal ); + + res.addRule ( nonterminalsPrimed.find ( nonterminal )->second, newRHS ); + } - return newSymbol; } void AbsorbTerminalSymbol::absorbTerminalSymbol ( grammar::CFG & grammar, const alphabet::Symbol & terminal, const std::set < alphabet::Symbol > & nonterminals ) { @@ -37,10 +49,13 @@ void AbsorbTerminalSymbol::absorbTerminalSymbol ( grammar::CFG & grammar, const std::map < alphabet::Symbol, alphabet::Symbol > nonterminalsPrimed; // terminal is fixed in particular calls for ( const alphabet::Symbol & nonterminal : nonterminals ) { - alphabet::Symbol newSymbol = handleAbsobtion ( grammar, res, nonterminal, terminal ); + alphabet::Symbol newSymbol = alphabet::createUniqueSymbol ( alphabet::Symbol ( alphabet::SymbolPairSymbol ( std::make_pair ( nonterminal, terminal ) ) ), res.getTerminalAlphabet ( ), res.getNonterminalAlphabet ( ) ); + res.addNonterminalSymbol ( newSymbol ); nonterminalsPrimed.insert ( std::make_pair ( nonterminal, newSymbol ) ); } + handleAbsobtion ( grammar, res, terminal, nonterminals, nonterminalsPrimed ); + for ( const std::pair < alphabet::Symbol, std::set < std::vector < alphabet::Symbol > > > & rule : grammar.getRules ( ) ) { const alphabet::Symbol & lhs = rule.first; diff --git a/alib2algo/src/grammar/parsing/AbsorbTerminalSymbol.h b/alib2algo/src/grammar/parsing/AbsorbTerminalSymbol.h index a04ea6acb2ef138335086036b8354735937f033c..d1cd7028f817355615cfeb2a2ed7373c064f9181 100644 --- a/alib2algo/src/grammar/parsing/AbsorbTerminalSymbol.h +++ b/alib2algo/src/grammar/parsing/AbsorbTerminalSymbol.h @@ -11,6 +11,7 @@ #include <grammar/GrammarFeatures.h> #include <alphabet/Symbol.h> #include <set> +#include <map> namespace grammar { @@ -18,10 +19,9 @@ namespace parsing { class AbsorbTerminalSymbol { public: - static alphabet::Symbol handleAbsobtion ( const grammar::CFG & orig, grammar::CFG & res, const alphabet::Symbol & nonterminal, const alphabet::Symbol & terminal ); + static void handleAbsobtion ( const grammar::CFG & orig, grammar::CFG & res, const alphabet::Symbol & terminal, const std::set < alphabet::Symbol > & nonterminals, const std::map < alphabet::Symbol, alphabet::Symbol > & nonterminalPrimed ); static void absorbTerminalSymbol ( grammar::CFG & grammar, const alphabet::Symbol & terminal, const std::set < alphabet::Symbol > & nonterminals ); - }; } /* namespace parsing */ diff --git a/alib2algo/test-src/grammar/parsing/AbsorbTerminalSymbol.cpp b/alib2algo/test-src/grammar/parsing/AbsorbTerminalSymbol.cpp index 838e46e16b6e40cde8268b8d6f8e79e42fe47279..a7a5ff83ab318ee7ee308dbe242c62e76d382b9a 100644 --- a/alib2algo/test-src/grammar/parsing/AbsorbTerminalSymbol.cpp +++ b/alib2algo/test-src/grammar/parsing/AbsorbTerminalSymbol.cpp @@ -60,4 +60,96 @@ void AbsorbTerminalSymbol::testAbsorbTerminalSymbol ( ) { } void AbsorbTerminalSymbol::testAbsorbTerminalSymbol2 ( ) { + alphabet::Symbol A = alphabet::symbolFrom ( "A" ); + alphabet::Symbol B = alphabet::symbolFrom ( "B" ); + alphabet::Symbol C = alphabet::symbolFrom ( "C" ); + alphabet::Symbol X = alphabet::symbolFrom ( "X" ); + + alphabet::Symbol a = alphabet::symbolFrom ( 'a' ); + alphabet::Symbol b = alphabet::symbolFrom ( 'b' ); + alphabet::Symbol c = alphabet::symbolFrom ( 'c' ); + + alphabet::Symbol Ba = alphabet::createUniqueSymbol ( alphabet::Symbol ( alphabet::SymbolPairSymbol ( std::make_pair ( B, a ) ) ), { }, { } ); + alphabet::Symbol Xa = alphabet::createUniqueSymbol ( alphabet::Symbol ( alphabet::SymbolPairSymbol ( std::make_pair ( X, a ) ) ), { }, { } ); + + grammar::CFG grammar ( A ); + + grammar.setTerminalAlphabet ( { a, b, c } ); + grammar.setNonterminalAlphabet ( { A, B, C, X } ); + grammar.setInitialSymbol ( A ); + + grammar.addRule ( A, { X, a, C } ); + grammar.addRule ( X, { c, B } ); + grammar.addRule ( B, { } ); + grammar.addRule ( B, { a, a, C } ); + grammar.addRule ( C, { c } ); + grammar.addRule ( C, { b, C } ); + + grammar::CFG res = grammar; + grammar::parsing::AbsorbTerminalSymbol::absorbTerminalSymbol ( res, a, { B, X } ); + + grammar::CFG comp ( A ); + + comp.setTerminalAlphabet ( { a, b, c } ); + comp.setNonterminalAlphabet ( { A, B, Ba, C, X, Xa } ); + comp.setInitialSymbol ( A ); + + comp.addRule ( A, { Xa, C } ); + comp.addRule ( X, { c, B } ); + comp.addRule ( Xa, { c, Ba } ); + comp.addRule ( B, { } ); + comp.addRule ( B, { a, a, C } ); + comp.addRule ( Ba, { a } ); + comp.addRule ( Ba, { a, a, C, a } ); + comp.addRule ( C, { c } ); + comp.addRule ( C, { b, C } ); + + std::cout << "res " << alib::StringDataFactory::toString ( grammar::Grammar ( res ) ) << std::endl << "comp " << alib::StringDataFactory::toString ( grammar::Grammar ( comp ) ) << std::endl; + + CPPUNIT_ASSERT ( res == comp ); +} + +void AbsorbTerminalSymbol::testAbsorbTerminalSymbol3 ( ) { + alphabet::Symbol A = alphabet::symbolFrom ( "A" ); + alphabet::Symbol B = alphabet::symbolFrom ( "B" ); + alphabet::Symbol C = alphabet::symbolFrom ( "C" ); + + alphabet::Symbol a = alphabet::symbolFrom ( 'a' ); + alphabet::Symbol b = alphabet::symbolFrom ( 'b' ); + alphabet::Symbol c = alphabet::symbolFrom ( 'c' ); + + alphabet::Symbol Ba = alphabet::createUniqueSymbol ( alphabet::Symbol ( alphabet::SymbolPairSymbol ( std::make_pair ( B, a ) ) ), { }, { } ); + + grammar::CFG grammar ( A ); + + grammar.setTerminalAlphabet ( { a, b, c } ); + grammar.setNonterminalAlphabet ( { A, B, C } ); + grammar.setInitialSymbol ( A ); + + grammar.addRule ( A, { B, a, C } ); + grammar.addRule ( B, { } ); + grammar.addRule ( B, { a, a, B } ); + grammar.addRule ( C, { c } ); + grammar.addRule ( C, { b, C } ); + + grammar::CFG res = grammar; + grammar::parsing::AbsorbTerminalSymbol::absorbTerminalSymbol ( res, a, { B } ); + + grammar::CFG comp ( A ); + + comp.setTerminalAlphabet ( { a, b, c } ); + comp.setNonterminalAlphabet ( { A, B, Ba, C } ); + comp.setInitialSymbol ( A ); + + comp.addRule ( A, { Ba, C } ); + comp.addRule ( B, { } ); + comp.addRule ( B, { a, a, B } ); + comp.addRule ( Ba, { a } ); + comp.addRule ( Ba, { a, a, Ba } ); + comp.addRule ( C, { c } ); + comp.addRule ( C, { b, C } ); + + std::cout << alib::StringDataFactory::toString ( grammar::Grammar ( res ) ) << std::endl << alib::StringDataFactory::toString ( grammar::Grammar ( comp ) ) << std::endl; + + CPPUNIT_ASSERT ( res == comp ); } diff --git a/alib2algo/test-src/grammar/parsing/AbsorbTerminalSymbol.h b/alib2algo/test-src/grammar/parsing/AbsorbTerminalSymbol.h index ee81e520121535944a4e6ad4ff6dd0ed2bcc49cd..5067d8cf4d59818ed7a1a3a690a8f1460370bb1a 100644 --- a/alib2algo/test-src/grammar/parsing/AbsorbTerminalSymbol.h +++ b/alib2algo/test-src/grammar/parsing/AbsorbTerminalSymbol.h @@ -7,6 +7,7 @@ class AbsorbTerminalSymbol : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE ( AbsorbTerminalSymbol ); CPPUNIT_TEST ( testAbsorbTerminalSymbol ); CPPUNIT_TEST ( testAbsorbTerminalSymbol2 ); + CPPUNIT_TEST ( testAbsorbTerminalSymbol3 ); CPPUNIT_TEST_SUITE_END ( ); public: @@ -15,6 +16,7 @@ public: void testAbsorbTerminalSymbol ( ); void testAbsorbTerminalSymbol2 ( ); + void testAbsorbTerminalSymbol3 ( ); }; #endif /* ABSORB_TERMINAL_SYMBOL_TEST_H_ */