From e00e1c428305248b75bc5eace78b1efdb7d19f62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <peckato1@fit.cvut.cz>
Date: Fri, 7 Mar 2014 20:10:42 +0100
Subject: [PATCH] RegExp::isEmpty is now correct if called on unoptimized
 regexp. closes  #15

---
 alib/src/regexp/Alternation.cpp   |  8 ++++++++
 alib/src/regexp/Alternation.h     |  5 +++++
 alib/src/regexp/Concatenation.cpp | 10 +++++++++-
 alib/src/regexp/Concatenation.h   |  5 +++++
 alib/src/regexp/Iteration.cpp     |  4 ++++
 alib/src/regexp/Iteration.h       |  5 +++++
 alib/src/regexp/RegExp.cpp        |  2 +-
 alib/src/regexp/RegExpElement.h   |  5 +++++
 alib/src/regexp/RegExpEmpty.cpp   |  4 ++++
 alib/src/regexp/RegExpEmpty.h     |  5 +++++
 alib/src/regexp/RegExpEpsilon.cpp |  4 ++++
 alib/src/regexp/RegExpEpsilon.h   |  5 +++++
 alib/src/regexp/RegExpSymbol.cpp  |  4 ++++
 alib/src/regexp/RegExpSymbol.h    |  7 ++++++-
 14 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/alib/src/regexp/Alternation.cpp b/alib/src/regexp/Alternation.cpp
index 1c557224ef..81ff4f56fa 100644
--- a/alib/src/regexp/Alternation.cpp
+++ b/alib/src/regexp/Alternation.cpp
@@ -106,5 +106,13 @@ bool Alternation::containsEmptyString() const {
 	return false;
 }
 
+bool Alternation::isEmpty() const {
+	for(const auto& e : getElements())
+		if(!e->isEmpty())
+			return true;
+
+	return false;
+}
+
 } /* namespace regexp */
 
diff --git a/alib/src/regexp/Alternation.h b/alib/src/regexp/Alternation.h
index 52b8f8c184..e01aac375c 100644
--- a/alib/src/regexp/Alternation.h
+++ b/alib/src/regexp/Alternation.h
@@ -55,6 +55,11 @@ public:
 	 * @copydoc RegExpElement::containsEmptyString() const
 	 */
 	bool containsEmptyString() const;
+
+	/**
+	 * @copydoc RegExpElement::isEmpty() const
+	 */
+	bool isEmpty() const;
 };
 
 } /* namespace regexp */
diff --git a/alib/src/regexp/Concatenation.cpp b/alib/src/regexp/Concatenation.cpp
index c43e767dfd..602ebde3c8 100644
--- a/alib/src/regexp/Concatenation.cpp
+++ b/alib/src/regexp/Concatenation.cpp
@@ -95,11 +95,19 @@ bool Concatenation::operator==(const Concatenation& other) const {
 }
 
 bool Concatenation::containsEmptyString() const {
-	for( const auto& e : getElements())
+	for(const auto& e : getElements())
 		if( ! e->containsEmptyString())
 			return false;
 
 	return true;
 }
 
+bool Concatenation::isEmpty() const {
+	for(const auto& e : getElements())
+		if(!e->isEmpty())
+			return false;
+
+	return true;
+}
+
 } /* namespace regexp */
diff --git a/alib/src/regexp/Concatenation.h b/alib/src/regexp/Concatenation.h
index 9fead277d3..55b465ed9a 100644
--- a/alib/src/regexp/Concatenation.h
+++ b/alib/src/regexp/Concatenation.h
@@ -54,6 +54,11 @@ public:
 	 * @copydoc RegExpElement::containsEmptyString() const
 	 */
 	bool containsEmptyString() const;
+
+	/**
+	 * @copydoc RegExpElement::isEmpty() const
+	 */
+	bool isEmpty() const;
 };
 
 } /* namespace regexp */
diff --git a/alib/src/regexp/Iteration.cpp b/alib/src/regexp/Iteration.cpp
index 85e68a1025..3495f4a6bc 100644
--- a/alib/src/regexp/Iteration.cpp
+++ b/alib/src/regexp/Iteration.cpp
@@ -97,5 +97,9 @@ bool Iteration::containsEmptyString() const {
 	return true;
 }
 
+bool Iteration::isEmpty() const {
+	return false;
+}
+
 } /* namespace regexp */
 
diff --git a/alib/src/regexp/Iteration.h b/alib/src/regexp/Iteration.h
index 7466b2aedc..f7b755113c 100644
--- a/alib/src/regexp/Iteration.h
+++ b/alib/src/regexp/Iteration.h
@@ -62,6 +62,11 @@ public:
 	 * @copydoc RegExpElement::containsEmptyString() const
 	 */
 	bool containsEmptyString() const;
+
+	/**
+	 * @copydoc RegExpElement::isEmpty() const
+	 */
+	bool isEmpty() const;
 };
 
 } /* namespace regexp */
diff --git a/alib/src/regexp/RegExp.cpp b/alib/src/regexp/RegExp.cpp
index 2200f3999f..246a5ee7eb 100644
--- a/alib/src/regexp/RegExp.cpp
+++ b/alib/src/regexp/RegExp.cpp
@@ -71,7 +71,7 @@ void RegExp::setRegExp(RegExpElement* regExp) {
 }
 
 bool RegExp::isEmpty() const {
-	return regExp == NULL || dynamic_cast<const RegExpEmpty*>(regExp);
+	return regExp == NULL || regExp->isEmpty();
 }
 
 bool RegExp::containsEmptyString() const {
diff --git a/alib/src/regexp/RegExpElement.h b/alib/src/regexp/RegExpElement.h
index 69421fde01..58fe62bab1 100644
--- a/alib/src/regexp/RegExpElement.h
+++ b/alib/src/regexp/RegExpElement.h
@@ -59,6 +59,11 @@ public:
 	 * @return true if this subtree of regexp matches empty string (epsilon)
 	 */
 	virtual bool containsEmptyString() const = 0;
+
+	/**
+	 * @return true if this subtree describes empty language
+	 */
+	virtual bool isEmpty() const = 0;
 };
 
 } /* namespace regexp */
diff --git a/alib/src/regexp/RegExpEmpty.cpp b/alib/src/regexp/RegExpEmpty.cpp
index f7b5ad4f95..553cfd650f 100644
--- a/alib/src/regexp/RegExpEmpty.cpp
+++ b/alib/src/regexp/RegExpEmpty.cpp
@@ -57,5 +57,9 @@ bool RegExpEmpty::containsEmptyString() const {
 	return false;
 }
 
+bool RegExpEmpty::isEmpty() const {
+	return true;
+}
+
 } /* namespace regexp */
 
diff --git a/alib/src/regexp/RegExpEmpty.h b/alib/src/regexp/RegExpEmpty.h
index 7fb80a8935..3578afa59f 100644
--- a/alib/src/regexp/RegExpEmpty.h
+++ b/alib/src/regexp/RegExpEmpty.h
@@ -41,6 +41,11 @@ public:
 	 * @copydoc RegExpElement::containsEmptyString() const
 	 */
 	bool containsEmptyString() const;
+
+	/**
+	 * @copydoc RegExpElement::isEmpty() const
+	 */
+	bool isEmpty() const;
 };
 
 } /* namespace regexp */
diff --git a/alib/src/regexp/RegExpEpsilon.cpp b/alib/src/regexp/RegExpEpsilon.cpp
index ff8fbb4b12..e102539f5f 100644
--- a/alib/src/regexp/RegExpEpsilon.cpp
+++ b/alib/src/regexp/RegExpEpsilon.cpp
@@ -53,5 +53,9 @@ bool RegExpEpsilon::containsEmptyString() const {
 	return true;
 }
 
+bool RegExpEpsilon::isEmpty() const {
+	return false;
+}
+
 } /* namespace regexp */
 
diff --git a/alib/src/regexp/RegExpEpsilon.h b/alib/src/regexp/RegExpEpsilon.h
index a7dced2eaf..28b8a6c0a4 100644
--- a/alib/src/regexp/RegExpEpsilon.h
+++ b/alib/src/regexp/RegExpEpsilon.h
@@ -42,6 +42,11 @@ public:
 	 * @copydoc RegExpElement::containsEmptyString() const
 	 */
 	bool containsEmptyString() const;
+
+	/**
+	 * @copydoc RegExpElement::isEmpty() const
+	 */
+	bool isEmpty() const;
 };
 
 } /* namespace regexp */
diff --git a/alib/src/regexp/RegExpSymbol.cpp b/alib/src/regexp/RegExpSymbol.cpp
index 66b85aed26..f71609fc71 100644
--- a/alib/src/regexp/RegExpSymbol.cpp
+++ b/alib/src/regexp/RegExpSymbol.cpp
@@ -58,6 +58,10 @@ bool RegExpSymbol::containsEmptyString() const {
 	return false;
 }
 
+bool RegExpSymbol::isEmpty() const {
+	return false;
+}
+
 const string& RegExpSymbol::getSymbol() const {
 	return this->symbol;
 }
diff --git a/alib/src/regexp/RegExpSymbol.h b/alib/src/regexp/RegExpSymbol.h
index 77d24348e9..54e1b618aa 100644
--- a/alib/src/regexp/RegExpSymbol.h
+++ b/alib/src/regexp/RegExpSymbol.h
@@ -46,8 +46,13 @@ public:
 	 * @copydoc RegExpElement::containsEmptyString() const
 	 */
 	bool containsEmptyString() const;
-	
+
 	const string& getSymbol() const;
+
+	/**
+	 * @copydoc RegExpElement::isEmpty() const
+	 */
+	bool isEmpty() const;
 };
 
 } /* namespace regexp */
-- 
GitLab