From eb58879c09de9d6565c4e330a3b8e1721aac6773 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Wed, 11 Nov 2015 13:36:32 +0100 Subject: [PATCH] test corner substitution --- .../grammar/parsing/CornerSubstitution.cpp | 2 +- .../grammar/parsing/ExtractRightContext.cpp | 12 +- .../parsing/HandleFirstFollowConflict.cpp | 2 +- .../src/grammar/parsing/common/Substitute.cpp | 7 +- .../grammar/parsing/CornerSubstitution.cpp | 109 ++++++++++++++++++ .../grammar/parsing/CornerSubstitution.h | 20 ++++ 6 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 alib2algo/test-src/grammar/parsing/CornerSubstitution.cpp create mode 100644 alib2algo/test-src/grammar/parsing/CornerSubstitution.h diff --git a/alib2algo/src/grammar/parsing/CornerSubstitution.cpp b/alib2algo/src/grammar/parsing/CornerSubstitution.cpp index ee0f90e2cc..eb113f2ec9 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 5a18645b25..6d1ad8f9a3 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 0365db173d..88a152ac6e 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 16e6b0fa02..07a91eb650 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 0000000000..8b383cf843 --- /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 0000000000..f24232b6a5 --- /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_ */ -- GitLab