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