diff --git a/alib2algo/src/grammar/parsing/CornerSubstitution.cpp b/alib2algo/src/grammar/parsing/CornerSubstitution.cpp index ee0f90e2ccc61bfa419c482fbc86537226ecf8e8..eb113f2ec98e2d2cf700f129db36535b9030731c 100644 --- a/alib2algo/src/grammar/parsing/CornerSubstitution.cpp +++ b/alib2algo/src/grammar/parsing/CornerSubstitution.cpp @@ -25,7 +25,7 @@ void CornerSubstitution::cornerSubstitution ( grammar::CFG & grammar, const alph const alphabet::Symbol & lhs = rule.first; for ( const std::vector < alphabet::Symbol > & rhs : rule.second ) { - if ( ( lhs == nonterminal ) && ( rhs.size ( ) > 0 ) && ( rhs[0] == nonterminal ) && First::first ( grammar, rhs ).count ( terminal ) ) + if ( ( lhs == nonterminal ) && ( rhs.size ( ) > 0 ) && ( grammar.getNonterminalAlphabet ( ).count ( rhs[0] ) ) && First::first ( grammar, rhs ).count ( terminal ) ) Substitute::substitute ( grammar, res, lhs, rhs, rhs.begin ( ) ); else res.addRule ( lhs, rhs ); diff --git a/alib2algo/src/grammar/parsing/ExtractRightContext.cpp b/alib2algo/src/grammar/parsing/ExtractRightContext.cpp index 5a18645b2518b13c0ba4237993798688dcf88758..6d1ad8f9a37f149d582ee75f46260baed723829e 100644 --- a/alib2algo/src/grammar/parsing/ExtractRightContext.cpp +++ b/alib2algo/src/grammar/parsing/ExtractRightContext.cpp @@ -24,17 +24,11 @@ void ExtractRightContext::extractRightContext ( grammar::CFG & grammar, const al const alphabet::Symbol & lhs = rule.first; for ( const std::vector < alphabet::Symbol > & rhs : rule.second ) - for ( std::vector < alphabet::Symbol >::const_iterator iter = rhs.begin ( ); iter + 1 != rhs.end ( ); ++iter ) { - bool substitued = false; - - if ( nonterminals.count ( * iter ) && First::first ( grammar, std::vector < alphabet::Symbol > ( iter + 1, rhs.end ( ) ) ).count ( terminal ) && !grammar.getTerminalAlphabet ( ).count ( * iter ) ) { - substitued = true; + for ( std::vector < alphabet::Symbol >::const_iterator iter = rhs.begin ( ); iter + 1 != rhs.end ( ); ++iter ) + if ( nonterminals.count ( * iter ) && grammar.getNonterminalAlphabet ( ).count ( * ( iter + 1 ) ) && First::first ( grammar, std::vector < alphabet::Symbol > ( iter + 1, rhs.end ( ) ) ).count ( terminal ) ) Substitute::substitute ( grammar, res, lhs, rhs, iter ); - } - - if ( !substitued ) + else res.addRule ( lhs, rhs ); - } } diff --git a/alib2algo/src/grammar/parsing/HandleFirstFollowConflict.cpp b/alib2algo/src/grammar/parsing/HandleFirstFollowConflict.cpp index 0365db173d8f8c66cb2ed1baad011a26b4c53759..88a152ac6e8939d0f08c9334c15bde2d9b7181b7 100644 --- a/alib2algo/src/grammar/parsing/HandleFirstFollowConflict.cpp +++ b/alib2algo/src/grammar/parsing/HandleFirstFollowConflict.cpp @@ -48,7 +48,7 @@ bool HandleFirstFollowConflict::handleFirstFollowConflict ( grammar::CFG & gramm for ( const std::pair < alphabet::Symbol, std::set < std::vector < alphabet::Symbol > > > & rule : grammar.getRules ( ) ) for ( const std::vector < alphabet::Symbol > & rhs : rule.second ) { for ( std::vector < alphabet::Symbol >::const_iterator iter = rhs.begin ( ); iter + 1 != rhs.end ( ); ++iter ) - if ( symbolsEndingWithNonterminal.count ( * iter ) && First::first ( grammar, std::vector < alphabet::Symbol > ( iter + 1, rhs.end ( ) ) ).count ( terminal ) && !grammar.getTerminalAlphabet ( ).count ( * iter ) ) { + if ( symbolsEndingWithNonterminal.count ( * iter ) && grammar.getNonterminalAlphabet ( ).count ( * ( iter + 1 ) ) && First::first ( grammar, std::vector < alphabet::Symbol > ( iter + 1, rhs.end ( ) ) ).count ( terminal ) ) { ExtractRightContext::extractRightContext ( grammar, terminal, symbolsEndingWithNonterminal ); return true; } diff --git a/alib2algo/src/grammar/parsing/common/Substitute.cpp b/alib2algo/src/grammar/parsing/common/Substitute.cpp index 16e6b0fa0259dcac5773f2ed9a9c469faa3a5af6..07a91eb6505148b831294086776e83bfa47dedf0 100644 --- a/alib2algo/src/grammar/parsing/common/Substitute.cpp +++ b/alib2algo/src/grammar/parsing/common/Substitute.cpp @@ -13,7 +13,12 @@ namespace grammar { namespace parsing { void Substitute::substitute ( const grammar::CFG & orig, grammar::CFG & res, const alphabet::Symbol & origLHS, const std::vector < alphabet::Symbol > & origRHS, std::vector < alphabet::Symbol >::const_iterator nonterminal ) { - for ( const std::vector < alphabet::Symbol > & rhs : orig.getRules ( ).find ( * nonterminal )->second ) { + auto iter = orig.getRules ( ).find ( * nonterminal ); + std::cout << * nonterminal << std::endl; + + if ( iter == orig.getRules ( ).end ( ) ) return; + + for ( const std::vector < alphabet::Symbol > & rhs : iter->second ) { std::vector < alphabet::Symbol > newRHS ( origRHS.begin ( ), nonterminal ); newRHS.insert ( newRHS.end ( ), rhs.begin ( ), rhs.end ( ) ); newRHS.insert ( newRHS.end ( ), nonterminal + 1, origRHS.end ( ) ); diff --git a/alib2algo/test-src/grammar/parsing/CornerSubstitution.cpp b/alib2algo/test-src/grammar/parsing/CornerSubstitution.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b383cf843d984ae684cf35a568f519401c0e0e5 --- /dev/null +++ b/alib2algo/test-src/grammar/parsing/CornerSubstitution.cpp @@ -0,0 +1,109 @@ +#include "CornerSubstitution.h" + +#include "grammar/ContextFree/CFG.h" +#include "grammar/parsing/CornerSubstitution.h" + +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( CornerSubstitution, "grammar" ); +CPPUNIT_TEST_SUITE_REGISTRATION ( CornerSubstitution ); + +void CornerSubstitution::setUp ( ) { +} + +void CornerSubstitution::tearDown ( ) { +} + +void CornerSubstitution::testCornerSubstitution ( ) { + 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 d = alphabet::symbolFrom ( 'd' ); + + grammar::CFG grammar ( A ); + + grammar.setTerminalAlphabet ( { a, b, c, d } ); + grammar.setNonterminalAlphabet ( { { A, B, C } + } ); + grammar.setInitialSymbol ( A ); + + grammar.addRule ( A, std::vector < alphabet::Symbol > { a, B } ); + grammar.addRule ( A, std::vector < alphabet::Symbol > { C, B } ); + grammar.addRule ( B, std::vector < alphabet::Symbol > { c, B } ); + grammar.addRule ( B, std::vector < alphabet::Symbol > { d } ); + grammar.addRule ( C, std::vector < alphabet::Symbol > { a, C } ); + grammar.addRule ( C, std::vector < alphabet::Symbol > { b, B } ); + + grammar::CFG res = grammar; + grammar::parsing::CornerSubstitution::cornerSubstitution ( res, a, A ); + + grammar::CFG comp ( A ); + + comp.setTerminalAlphabet ( { a, b, c, d } ); + comp.setNonterminalAlphabet ( { { A, B, C } + } ); + comp.setInitialSymbol ( A ); + + comp.addRule ( A, std::vector < alphabet::Symbol > { a, B } ); + comp.addRule ( A, std::vector < alphabet::Symbol > { a, C, B } ); + comp.addRule ( A, std::vector < alphabet::Symbol > { b, B, B } ); + comp.addRule ( B, std::vector < alphabet::Symbol > { c, B } ); + comp.addRule ( B, std::vector < alphabet::Symbol > { d } ); + comp.addRule ( C, std::vector < alphabet::Symbol > { a, C } ); + comp.addRule ( C, std::vector < alphabet::Symbol > { b, B } ); + + std::cout << res << std::endl << comp << std::endl; + + CPPUNIT_ASSERT ( res == comp ); +} + +void CornerSubstitution::testCornerSubstitution2 ( ) { + 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 d = alphabet::symbolFrom ( 'd' ); + + grammar::CFG grammar ( A ); + + grammar.setTerminalAlphabet ( { a, b, c, d } ); + grammar.setNonterminalAlphabet ( { { A, B, C } + } ); + grammar.setInitialSymbol ( A ); + + grammar.addRule ( A, std::vector < alphabet::Symbol > { a, B } ); + grammar.addRule ( A, std::vector < alphabet::Symbol > { C, B } ); + grammar.addRule ( B, std::vector < alphabet::Symbol > { c, B } ); + grammar.addRule ( B, std::vector < alphabet::Symbol > { a } ); + grammar.addRule ( C, std::vector < alphabet::Symbol > { a, C } ); + grammar.addRule ( C, std::vector < alphabet::Symbol > { B, b } ); + + grammar::CFG res = grammar; + grammar::parsing::CornerSubstitution::cornerSubstitution ( res, a, A ); + grammar::parsing::CornerSubstitution::cornerSubstitution ( res, a, A ); + + grammar::CFG comp ( A ); + + comp.setTerminalAlphabet ( { a, b, c, d } ); + comp.setNonterminalAlphabet ( { { A, B, C } + } ); + comp.setInitialSymbol ( A ); + + comp.addRule ( A, std::vector < alphabet::Symbol > { a, B } ); + comp.addRule ( A, std::vector < alphabet::Symbol > { a, C, B } ); + comp.addRule ( A, std::vector < alphabet::Symbol > { a, b, B } ); + comp.addRule ( A, std::vector < alphabet::Symbol > { c, B, b, B } ); + comp.addRule ( B, std::vector < alphabet::Symbol > { c, B } ); + comp.addRule ( B, std::vector < alphabet::Symbol > { a } ); + comp.addRule ( C, std::vector < alphabet::Symbol > { a, C } ); + comp.addRule ( C, std::vector < alphabet::Symbol > { B, b } ); + + std::cout << res << std::endl << comp << std::endl; + + CPPUNIT_ASSERT ( res == comp ); +} diff --git a/alib2algo/test-src/grammar/parsing/CornerSubstitution.h b/alib2algo/test-src/grammar/parsing/CornerSubstitution.h new file mode 100644 index 0000000000000000000000000000000000000000..f24232b6a54e40b353bcacd1476f5f2d65d01faf --- /dev/null +++ b/alib2algo/test-src/grammar/parsing/CornerSubstitution.h @@ -0,0 +1,20 @@ +#ifndef CORNER_SUBSTITUTION_TEST_H_ +#define CORNER_SUBSTITUTION_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class CornerSubstitution : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE ( CornerSubstitution ); + CPPUNIT_TEST ( testCornerSubstitution ); + CPPUNIT_TEST ( testCornerSubstitution2 ); + CPPUNIT_TEST_SUITE_END ( ); + +public: + void setUp ( ); + void tearDown ( ); + + void testCornerSubstitution ( ); + void testCornerSubstitution2 ( ); +}; + +#endif /* CORNER_SUBSTITUTION_TEST_H_ */