From 55a363432f8d2f53e58f854d72ff0b6fe6605563 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Fri, 9 May 2014 13:07:30 +0200
Subject: [PATCH] fix UnknownAutomaton and UnknownTransition

---
 alib2/src/automaton/UnknownAutomaton.cpp      |  1 +
 alib2/src/automaton/UnknownTransition.cpp     | 26 +++---
 alib2/src/sax/ComposerException.cpp           | 22 +++++
 alib2/src/sax/ComposerException.h             | 31 +++++++
 alib2/src/sax/ParserException.cpp             |  1 +
 alib2/src/sax/ParserException.h               |  1 +
 alib2/src/sax/SaxComposeInterface.cpp         | 81 +++++++++++++++++++
 ...PrintInterface.h => SaxComposeInterface.h} | 11 +--
 alib2/src/sax/SaxPrintInterface.cpp           | 62 --------------
 alib2/test-src/automaton/AutomatonTest.cpp    |  7 +-
 alib2/test-src/regexp/RegExpTest.cpp          |  4 +-
 11 files changed, 165 insertions(+), 82 deletions(-)
 create mode 100644 alib2/src/sax/ComposerException.cpp
 create mode 100644 alib2/src/sax/ComposerException.h
 create mode 100644 alib2/src/sax/SaxComposeInterface.cpp
 rename alib2/src/sax/{SaxPrintInterface.h => SaxComposeInterface.h} (89%)
 delete mode 100644 alib2/src/sax/SaxPrintInterface.cpp

diff --git a/alib2/src/automaton/UnknownAutomaton.cpp b/alib2/src/automaton/UnknownAutomaton.cpp
index 993fca8204..9a3d7787d5 100644
--- a/alib2/src/automaton/UnknownAutomaton.cpp
+++ b/alib2/src/automaton/UnknownAutomaton.cpp
@@ -159,6 +159,7 @@ bool UnknownAutomaton::operator==(const UnknownAutomaton& other) {
 std::ostream& operator<<(std::ostream& out, const UnknownAutomaton& automaton) {
 	out << "(UnknownAutomaton"
 		<< " states = " << automaton.states
+		<< " inputAlphabet = " << automaton.inputAlphabet
 		<< " initialStates = " << automaton.initialStates
 		<< " finalStates = " << automaton.finalStates
 		<< " stackAlphabet = " << automaton.stackAlphabet
diff --git a/alib2/src/automaton/UnknownTransition.cpp b/alib2/src/automaton/UnknownTransition.cpp
index 9a1addb622..9b3f63d2fb 100644
--- a/alib2/src/automaton/UnknownTransition.cpp
+++ b/alib2/src/automaton/UnknownTransition.cpp
@@ -128,18 +128,26 @@ void UnknownTransition::setShift(const Shift& shift) {
 }
 
 bool UnknownTransition::operator <(const UnknownTransition& other) const {
-	if (*from != *other.from) {
-		return *from < *other.from;
-	} else if (*input != *other.input) {
-		return *input < *other.input;
+	if (from != other.from && from != NULL && other.from != NULL && *from != *other.from) {
+		if(from == NULL) return -1;
+		else if(other.from == NULL) return 1;
+		else return *from < *other.from;
+	} else if (input != other.input && input != NULL && other.input != NULL && *input != *other.input) {
+		if(input == NULL) return -1;
+		else if(other.input == NULL) return 1;
+		else return *input < *other.input;
 	} else if (pop != other.pop) {
 		return pop < other.pop;
 	} else if (shift != other.shift) {
 		return shift < other.shift;
-	} else if (*to != *other.to) {
-		return *to < *other.to;
-	} else if (*output != *other.output) {
-		return *output < *other.output;
+	} else if (to != other.to && to != NULL && other.to != NULL && *to != *other.to) {
+		if(to == NULL) return 1;
+		else if(other.to == NULL) return -1;
+		else return *to < *other.to;
+	} else if (output != other.output && output != NULL && other.output != NULL && *output != *other.output) {
+		if(output == NULL) return 1;
+		else if(other.output == NULL) return -1;
+		else return *output < *other.output;
 	} else {
 		return push < other.push;
 	}
@@ -147,7 +155,7 @@ bool UnknownTransition::operator <(const UnknownTransition& other) const {
 
 bool UnknownTransition::operator ==(const UnknownTransition& other) const {
 	return (from == other.from || (from != NULL && other.from != NULL && *from == *other.from))
-		&& (input == other.input && (input != NULL && other.input != NULL && *input == *other.input))
+		&& (input == other.input || (input != NULL && other.input != NULL && *input == *other.input))
 		&& pop == other.pop
 		&& shift == other.shift
 		&& (to == other.to || (to != NULL && other.to != NULL && *to == *other.to))
diff --git a/alib2/src/sax/ComposerException.cpp b/alib2/src/sax/ComposerException.cpp
new file mode 100644
index 0000000000..261a57693c
--- /dev/null
+++ b/alib2/src/sax/ComposerException.cpp
@@ -0,0 +1,22 @@
+/*
+ * ComposerException.cpp
+ *
+ *  Created on: Apr 16, 2013
+ *      Author: Jan Travnicek
+ */
+
+#include "ComposerException.h"
+
+namespace sax {
+
+ComposerException::ComposerException(const Token& expected, const Token& read) :
+		expected(expected), read(read) {
+
+	cause = "Composer Exception: Expected: " + expected.getData() + " Read: " + read.getData();
+}
+
+ComposerException::~ComposerException() noexcept {
+
+}
+
+} /* namespace sax */
diff --git a/alib2/src/sax/ComposerException.h b/alib2/src/sax/ComposerException.h
new file mode 100644
index 0000000000..fe662196e2
--- /dev/null
+++ b/alib2/src/sax/ComposerException.h
@@ -0,0 +1,31 @@
+/*
+ * ComposerException.h
+ *
+ *  Created on: Apr 16, 2013
+ *      Author: Jan Travnicek
+ */
+
+#ifndef COMPOSER_EXCEPTION_H_
+#define COMPOSER_EXCEPTION_H_
+
+#include "../AlibException.h"
+#include "Token.h"
+
+namespace sax {
+
+/**
+ * Exception thrown by XML parser when is expected different tag than the one which is read.
+ */
+class ComposerException: public alib::AlibException {
+protected:
+	Token expected;
+	Token read;
+public:
+	ComposerException(const Token& expected, const Token& read);
+	~ComposerException() noexcept;
+};
+
+} /* namespace sax */
+
+#endif /* COMPOSER_EXCEPTION_H_ */
+
diff --git a/alib2/src/sax/ParserException.cpp b/alib2/src/sax/ParserException.cpp
index 55ff89d8c8..f767901976 100644
--- a/alib2/src/sax/ParserException.cpp
+++ b/alib2/src/sax/ParserException.cpp
@@ -20,3 +20,4 @@ ParserException::~ParserException() noexcept {
 }
 
 } /* namespace sax */
+
diff --git a/alib2/src/sax/ParserException.h b/alib2/src/sax/ParserException.h
index 23905d95d1..af17aa0d8f 100644
--- a/alib2/src/sax/ParserException.h
+++ b/alib2/src/sax/ParserException.h
@@ -28,3 +28,4 @@ public:
 } /* namespace sax */
 
 #endif /* PARSER_EXCEPTION_H_ */
+
diff --git a/alib2/src/sax/SaxComposeInterface.cpp b/alib2/src/sax/SaxComposeInterface.cpp
new file mode 100644
index 0000000000..b4b28594eb
--- /dev/null
+++ b/alib2/src/sax/SaxComposeInterface.cpp
@@ -0,0 +1,81 @@
+/*
+ * SaxComposeInterface.cpp
+ *
+ *  Created on: 8.8.2012
+ *      Author: Martin Zak
+ */
+
+#include "SaxComposeInterface.h"
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <deque>
+#include "ComposerException.h"
+
+namespace sax {
+
+void SaxComposeInterface::printMemory(std::string& xmlOut, const std::list<Token>& in) {
+	xmlBufferPtr buf = xmlBufferCreate();
+	xmlTextWriterPtr writer = xmlNewTextWriterMemory(buf, 0);
+	
+	SaxComposeInterface::xmlSAXUserPrint(writer, in);
+	
+	xmlFreeTextWriter(writer);
+	xmlOut = (const char*) buf->content;
+	xmlBufferFree(buf);
+}
+
+void SaxComposeInterface::printFile(const std::string& filename, const std::list<Token>& in) {
+	xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0);
+
+	SaxComposeInterface::xmlSAXUserPrint(writer, in);
+	
+	xmlFreeTextWriter(writer);
+}
+
+void SaxComposeInterface::printStdout(const std::list<Token>& in) {
+	SaxComposeInterface::printStream(std::cout, in);
+}
+
+void SaxComposeInterface::printStream(std::ostream& out, const std::list<Token>& in) {
+	xmlBufferPtr buf = xmlBufferCreate();
+	xmlTextWriterPtr writer = xmlNewTextWriterMemory(buf, 0);
+	
+	SaxComposeInterface::xmlSAXUserPrint(writer, in);
+	
+	xmlFreeTextWriter(writer);
+	out << (const char*) buf->content;
+	xmlBufferFree(buf);
+}
+
+void SaxComposeInterface::xmlSAXUserPrint(xmlTextWriterPtr writer, const std::list<Token>& in) {
+	xmlTextWriterStartDocument(writer, NULL, NULL, NULL);
+	std::deque<Token> stack;
+	for(const Token& token : in) {
+	  switch(token.getType()) {
+		case Token::START_ELEMENT:
+		  xmlTextWriterStartElement(writer, (const xmlChar*) token.getData().c_str());
+		  stack.push_back(token);
+		  break;
+		case Token::END_ELEMENT:
+		  if(stack.empty() || stack.back().getData() != token.getData()) {
+			throw ComposerException(Token(stack.back().getData(), Token::END_ELEMENT), token);
+		  }
+		  stack.pop_back();
+		  xmlTextWriterEndElement(writer);
+		  break;
+		case Token::CHARACTER:
+		  xmlTextWriterWriteString(writer, (const xmlChar*) token.getData().c_str());
+		  break;
+		case Token::ATTRIBUTE:
+		  //TODO
+		  break;
+	  }
+	}
+	xmlTextWriterEndDocument(writer);
+}
+
+} /* namespace sax */
+
diff --git a/alib2/src/sax/SaxPrintInterface.h b/alib2/src/sax/SaxComposeInterface.h
similarity index 89%
rename from alib2/src/sax/SaxPrintInterface.h
rename to alib2/src/sax/SaxComposeInterface.h
index 21bb98bb45..312eea82aa 100644
--- a/alib2/src/sax/SaxPrintInterface.h
+++ b/alib2/src/sax/SaxComposeInterface.h
@@ -1,12 +1,12 @@
 /*
- * SaxPrintInterface.h
+ * SaxComposeInterface.h
  *
  *  Created on: 8.8.2012
  *      Author: Martin Zak
  */
 
-#ifndef SAX_PRINT_INTERFACE_H_
-#define SAX_PRINT_INTERFACE_H_
+#ifndef SAX_COMPOSE_INTERFACE_H_
+#define SAX_COMPOSE_INTERFACE_H_
 
 #include <libxml/xmlwriter.h>
 #include <list>
@@ -18,7 +18,7 @@ namespace sax {
  * This class performs parsing of file or string containing XML. Contains callback
  * methods for libxml SAX parser.
  */
-class SaxPrintInterface {
+class SaxComposeInterface {
 	static void xmlSAXUserPrint(xmlTextWriterPtr writer, const std::list<Token>& in);
 public:
 	/**
@@ -53,4 +53,5 @@ public:
 
 } /* namespace sax */
 
-#endif /* SAX_PRINT_INTERFACE_H_ */
+#endif /* SAX_COMPOSE_INTERFACE_H_ */
+
diff --git a/alib2/src/sax/SaxPrintInterface.cpp b/alib2/src/sax/SaxPrintInterface.cpp
deleted file mode 100644
index 59c78dca7d..0000000000
--- a/alib2/src/sax/SaxPrintInterface.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SaxPrintInterface.cpp
- *
- *  Created on: 8.8.2012
- *      Author: Martin Zak
- */
-
-#include "SaxPrintInterface.h"
-
-#include <string>
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include "../AlibException.h"
-
-namespace sax {
-
-void SaxPrintInterface::printMemory(std::string& xmlOut, const std::list<Token>& in) {
-	xmlBufferPtr buf = xmlBufferCreate();
-	xmlTextWriterPtr writer = xmlNewTextWriterMemory(buf, 0);
-	
-	SaxPrintInterface::xmlSAXUserPrint(writer, in);
-	
-	xmlFreeTextWriter(writer);
-	xmlOut = (const char*) buf->content;
-	xmlBufferFree(buf);
-}
-
-void SaxPrintInterface::printFile(const std::string& filename, const std::list<Token>& in) {
-	xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0);
-
-	SaxPrintInterface::xmlSAXUserPrint(writer, in);
-	
-	xmlFreeTextWriter(writer);
-}
-
-void SaxPrintInterface::printStdout(const std::list<Token>& in) {
-	SaxPrintInterface::printStream(std::cout, in);
-}
-
-void SaxPrintInterface::printStream(std::ostream& out, const std::list<Token>& in) {
-	xmlBufferPtr buf = xmlBufferCreate();
-	xmlTextWriterPtr writer = xmlNewTextWriterMemory(buf, 0);
-	
-	SaxPrintInterface::xmlSAXUserPrint(writer, in);
-	
-	xmlFreeTextWriter(writer);
-	out << (const char*) buf->content;
-	xmlBufferFree(buf);
-}
-
-void SaxPrintInterface::xmlSAXUserPrint(xmlTextWriterPtr writer, const std::list<Token>& in) {
-	xmlTextWriterStartDocument(writer, NULL, NULL, NULL);
-	for(const Token& token : in) {
-	  if(token.getType() == Token::START_ELEMENT) xmlTextWriterStartElement(writer, (const xmlChar*) token.getData().c_str());
-	  if(token.getType() == Token::END_ELEMENT) xmlTextWriterEndElement(writer);
-	  if(token.getType() == Token::CHARACTER) xmlTextWriterWriteString(writer, (const xmlChar*) token.getData().c_str());
-	}
-	xmlTextWriterEndDocument(writer);
-}
-
-} /* namespace sax */
diff --git a/alib2/test-src/automaton/AutomatonTest.cpp b/alib2/test-src/automaton/AutomatonTest.cpp
index a0c8a23e15..5d5c658714 100644
--- a/alib2/test-src/automaton/AutomatonTest.cpp
+++ b/alib2/test-src/automaton/AutomatonTest.cpp
@@ -2,7 +2,7 @@
 #include "AutomatonTest.h"
 
 #include "sax/SaxParseInterface.h"
-#include "sax/SaxPrintInterface.h"
+#include "sax/SaxComposeInterface.h"
 
 #include "automaton/UnknownAutomaton.h"
 #include "automaton/AutomatonFromXMLParser.h"
@@ -27,15 +27,14 @@ void AutomatonTest::testXMLParser() {
   automaton::AutomatonToXMLComposer composer;
   std::list<sax::Token> tokens = composer.compose(automaton);
   std::string tmp;
-  sax::SaxPrintInterface::printMemory(tmp, tokens);
+  sax::SaxComposeInterface::printMemory(tmp, tokens);
   
   std::list<sax::Token> tokens2;
   sax::SaxParseInterface::parseMemory(tmp, tokens2);
   automaton::AutomatonFromXMLParser parser;
   automaton::UnknownAutomaton automaton2 = parser.parse(tokens2);
 
-  std::cout << std::endl << automaton << std::endl << automaton2 << std::endl;
-  
+  CPPUNIT_ASSERT( automaton == automaton );
   CPPUNIT_ASSERT( automaton == automaton2 );
 }
 
diff --git a/alib2/test-src/regexp/RegExpTest.cpp b/alib2/test-src/regexp/RegExpTest.cpp
index dbc69d0286..a4cdd33d21 100644
--- a/alib2/test-src/regexp/RegExpTest.cpp
+++ b/alib2/test-src/regexp/RegExpTest.cpp
@@ -2,7 +2,7 @@
 #include "RegExpTest.h"
 
 #include "sax/SaxParseInterface.h"
-#include "sax/SaxPrintInterface.h"
+#include "sax/SaxComposeInterface.h"
 
 #include "regexp/RegExp.h"
 #include "regexp/RegExpFromStringParser.h"
@@ -76,7 +76,7 @@ void RegExpTest::testXMLParser() {
   regexp::RegExpToXMLComposer composer;
   std::list<sax::Token> tokens = composer.compose(regexp);
   std::string tmp;
-  sax::SaxPrintInterface::printMemory(tmp, tokens);
+  sax::SaxComposeInterface::printMemory(tmp, tokens);
   
   std::list<sax::Token> tokens2;
   sax::SaxParseInterface::parseMemory(tmp, tokens2);
-- 
GitLab