From 184d1e6e66002cdda52419d95f882ffaa9842364 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 3 Oct 2017 16:39:18 +0200
Subject: [PATCH] improve automata string parsers

---
 .../automaton/AutomatonFromStringLexer.cpp    | 41 ++++++++++++++++---
 .../src/automaton/AutomatonFromStringLexer.h  | 10 ++++-
 alib2str/src/automaton/string/FSM/DFA.h       |  5 +--
 .../src/automaton/string/FSM/EpsilonNFA.h     |  5 +--
 .../string/FSM/MultiInitialStateNFA.h         |  5 +--
 alib2str/src/automaton/string/FSM/NFA.h       |  5 +--
 6 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/alib2str/src/automaton/AutomatonFromStringLexer.cpp b/alib2str/src/automaton/AutomatonFromStringLexer.cpp
index 839fe6ec8f..8e1401147e 100644
--- a/alib2str/src/automaton/AutomatonFromStringLexer.cpp
+++ b/alib2str/src/automaton/AutomatonFromStringLexer.cpp
@@ -6,6 +6,8 @@
  */
 
 #include "AutomatonFromStringLexer.h"
+#include <exception/CommonException.h>
+#include <iterator>
 
 namespace automaton {
 
@@ -75,7 +77,7 @@ L0:
 		return token;
 	} else {
 		in.clear();
-		putback(in, std::move(token));
+		putback(in, token);
 		token.type = TokenType::ERROR;
 		return token;
 	}
@@ -92,19 +94,46 @@ L1:
 	} else {
 		in.clear ( );
 		in.unget ( );
-		putback(in, std::move(token));
+		putback(in, token);
 		token.type = TokenType::ERROR;
 		return token;
 	}
 }
 
-void AutomatonFromStringLexer::putback(std::istream& in, AutomatonFromStringLexer::Token token) {
+AutomatonFromStringLexer::Token AutomatonFromStringLexer::peek ( std::istream & in ) {
+	Token token = next ( in );
+	putback ( in, token );
+	return token;
+}
+
+void AutomatonFromStringLexer::putback ( std::istream& in, const std::string & data ) {
 	in.clear();
 
-	while(!token.raw.empty()) {
-		in.putback(token.raw.back());
-		token.raw.pop_back();
+	for ( char character : ext::make_reverse ( data ) )
+		in.putback ( character );
+}
+
+void AutomatonFromStringLexer::putback ( std::istream& in, const Token & token ) {
+	putback ( in, token.raw );
+}
+
+bool AutomatonFromStringLexer::test ( std::istream & in, const std::string & value ) {
+	if ( testAndConsume ( in, value ) ) {
+		in.clear ( );
+		putback ( in, value );
+		return true;
+	} else {
+		return false;
 	}
 }
 
+bool AutomatonFromStringLexer::testAndConsume ( std::istream & in, const std::string & value ) {
+	return ( bool ) ( in >> ext::string ( value ) );
+}
+
+void AutomatonFromStringLexer::consume ( std::istream & in, const std::string & value ) {
+	if ( ! testAndConsume ( in, value ) )
+		throw exception::CommonException ( "Can't consume " + value + " from input stream." );
+}
+
 } /* namespace automaton */
diff --git a/alib2str/src/automaton/AutomatonFromStringLexer.h b/alib2str/src/automaton/AutomatonFromStringLexer.h
index cca67001b4..077480a67a 100644
--- a/alib2str/src/automaton/AutomatonFromStringLexer.h
+++ b/alib2str/src/automaton/AutomatonFromStringLexer.h
@@ -36,8 +36,14 @@ public:
 		std::string raw;
 	};
 
-	static Token next(std::istream& input);
-	static void putback(std::istream&, Token token);
+	static Token next(std::istream & input);
+	static Token peek(std::istream & input);
+	static void putback ( std::istream&, const std::string & token);
+	static void putback ( std::istream&, const Token & token);
+
+	static bool test ( std::istream & input, const std::string & value );
+	static void consume ( std::istream & input, const std::string & value );
+	static bool testAndConsume ( std::istream & input, const std::string & value );
 };
 
 } /* namepsace automaton */
diff --git a/alib2str/src/automaton/string/FSM/DFA.h b/alib2str/src/automaton/string/FSM/DFA.h
index 145846aa13..3bfae51c1d 100644
--- a/alib2str/src/automaton/string/FSM/DFA.h
+++ b/alib2str/src/automaton/string/FSM/DFA.h
@@ -123,10 +123,7 @@ void stringApi < automaton::DFA < SymbolType, StateType > >::parseTransition(std
 
 template<class SymbolType, class StateType >
 bool stringApi < automaton::DFA < SymbolType, StateType > >::first ( std::istream & input ) {
-	automaton::AutomatonFromStringLexer::Token token = automaton::AutomatonFromStringLexer::next ( input );
-	bool res = token.type == automaton::AutomatonFromStringLexer::TokenType::DFA;
-	automaton::AutomatonFromStringLexer::putback ( input, token );
-	return res;
+	return automaton::AutomatonFromStringLexer::peek ( input ).type == automaton::AutomatonFromStringLexer::TokenType::DFA;
 }
 
 template<class SymbolType, class StateType >
diff --git a/alib2str/src/automaton/string/FSM/EpsilonNFA.h b/alib2str/src/automaton/string/FSM/EpsilonNFA.h
index 71e93d520a..ae651b0625 100644
--- a/alib2str/src/automaton/string/FSM/EpsilonNFA.h
+++ b/alib2str/src/automaton/string/FSM/EpsilonNFA.h
@@ -132,10 +132,7 @@ void stringApi < automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > >:
 
 template<class SymbolType, class EpsilonType, class StateType >
 bool stringApi < automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > >::first ( std::istream & input ) {
-	automaton::AutomatonFromStringLexer::Token token = automaton::AutomatonFromStringLexer::next ( input );
-	bool res = token.type == automaton::AutomatonFromStringLexer::TokenType::EPSILON_NFA;
-	automaton::AutomatonFromStringLexer::putback ( input, token );
-	return res;
+	return automaton::AutomatonFromStringLexer::peek ( input ).type == automaton::AutomatonFromStringLexer::TokenType::EPSILON_NFA;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
diff --git a/alib2str/src/automaton/string/FSM/MultiInitialStateNFA.h b/alib2str/src/automaton/string/FSM/MultiInitialStateNFA.h
index f1e6c1d895..d680cbf1f2 100644
--- a/alib2str/src/automaton/string/FSM/MultiInitialStateNFA.h
+++ b/alib2str/src/automaton/string/FSM/MultiInitialStateNFA.h
@@ -104,10 +104,7 @@ void stringApi < automaton::MultiInitialStateNFA < SymbolType, StateType > >::pa
 
 template<class SymbolType, class StateType >
 bool stringApi < automaton::MultiInitialStateNFA < SymbolType, StateType > >::first ( std::istream & input ) {
-	automaton::AutomatonFromStringLexer::Token token = automaton::AutomatonFromStringLexer::next ( input );
-	bool res = token.type == automaton::AutomatonFromStringLexer::TokenType::MULTI_INITIAL_STATE_NFA;
-	automaton::AutomatonFromStringLexer::putback ( input, token );
-	return res;
+	return automaton::AutomatonFromStringLexer::peek ( input ).type == automaton::AutomatonFromStringLexer::TokenType::MULTI_INITIAL_STATE_NFA;
 }
 
 template<class SymbolType, class StateType >
diff --git a/alib2str/src/automaton/string/FSM/NFA.h b/alib2str/src/automaton/string/FSM/NFA.h
index f490f74fb0..1934aae330 100644
--- a/alib2str/src/automaton/string/FSM/NFA.h
+++ b/alib2str/src/automaton/string/FSM/NFA.h
@@ -124,10 +124,7 @@ void stringApi < automaton::NFA < SymbolType, StateType > >::parseTransition(std
 
 template<class SymbolType, class StateType >
 bool stringApi < automaton::NFA < SymbolType, StateType > >::first ( std::istream & input ) {
-	automaton::AutomatonFromStringLexer::Token token = automaton::AutomatonFromStringLexer::next ( input );
-	bool res = token.type == automaton::AutomatonFromStringLexer::TokenType::NFA;
-	automaton::AutomatonFromStringLexer::putback ( input, token );
-	return res;
+	return automaton::AutomatonFromStringLexer::peek ( input ).type == automaton::AutomatonFromStringLexer::TokenType::NFA;
 }
 
 template<class SymbolType, class StateType >
-- 
GitLab