From f9de4179eecb09e20a936ad8ffb1321bc71ae15a Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Mon, 21 Aug 2017 22:30:46 +0200
Subject: [PATCH] proper string in cli lexer and parser

---
 alib2cli/src/lexer/Lexer.cpp   | 46 ++++++++++++++++++++++++++++------
 alib2cli/src/lexer/Lexer.h     |  3 +++
 alib2cli/src/parser/Parser.cpp |  8 ++++--
 alib2cli/src/parser/Parser.h   |  8 ++++++
 4 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/alib2cli/src/lexer/Lexer.cpp b/alib2cli/src/lexer/Lexer.cpp
index 294f51e4db..2041b330c2 100644
--- a/alib2cli/src/lexer/Lexer.cpp
+++ b/alib2cli/src/lexer/Lexer.cpp
@@ -7,7 +7,7 @@ namespace cli {
 Lexer::Token Lexer::nextToken () {
 	Token res { "", TokenType::ERROR };
 
-q0:		if ( m_index >= m_line.size ( ) ) {
+q0:	if ( m_index >= m_line.size ( ) ) {
 		res.m_type = TokenType::END;
 		return res;
 	}
@@ -76,6 +76,11 @@ q0:		if ( m_index >= m_line.size ( ) ) {
 		goto q2;
 	}
 
+	if ( m_line [ m_index ] == '"' ) {
+		m_index ++;
+		goto q4;
+	}
+
 	if ( ( m_line [ m_index ] >= '0' && m_line [ m_index ] <= '9' ) ) {
 		res.m_value += m_line [ m_index ];
 		m_index++;
@@ -84,8 +89,8 @@ q0:		if ( m_index >= m_line.size ( ) ) {
 
 	if ( ( m_line [ m_index ] >= 'a' && m_line [ m_index ] <= 'z' )
 	  || ( m_line [ m_index ] >= 'A' && m_line [ m_index ] <= 'Z' )
-	  || m_line [ m_index ] == '/' || m_line [ m_index ] == '.'
-	  || m_line [ m_index ] == '~' || m_line [ m_index ] == '_' ) {
+	  ||   m_line [ m_index ] == '/' || m_line [ m_index ] == '.'
+	  ||   m_line [ m_index ] == '~' || m_line [ m_index ] == '_' ) {
 		res.m_value += m_line [ m_index ];
 		m_index++;
 		goto q3;
@@ -120,8 +125,8 @@ q2:	if ( m_index >= m_line.size ( ) ) {
 
 	if ( ( m_line [ m_index ] >= 'a' && m_line [ m_index ] <= 'z' )
 	  || ( m_line [ m_index ] >= 'A' && m_line [ m_index ] <= 'Z' )
-	  || m_line [ m_index ] == '/' || m_line [ m_index ] == '.' || m_line [ m_index ] == '-'
-	  || m_line [ m_index ] == '~' || m_line [ m_index ] == '_' || m_line [ m_index ] == ':' ) {
+	  ||   m_line [ m_index ] == '/' || m_line [ m_index ] == '.' || m_line [ m_index ] == '-'
+	  ||   m_line [ m_index ] == '~' || m_line [ m_index ] == '_' || m_line [ m_index ] == ':' ) {
 		res.m_value += m_line [ m_index ];
 		m_index++;
 		goto q3;
@@ -138,8 +143,8 @@ q3:	if ( m_index >= m_line.size ( ) ) {
 	if ( ( m_line [ m_index ] >= '0' && m_line [ m_index ] <= '9' )
 	  || ( m_line [ m_index ] >= 'a' && m_line [ m_index ] <= 'z' )
 	  || ( m_line [ m_index ] >= 'A' && m_line [ m_index ] <= 'Z' )
-	  || m_line [ m_index ] == '/' || m_line [ m_index ] == '.' || m_line [ m_index ] == '-'
-	  || m_line [ m_index ] == '~' || m_line [ m_index ] == '_' || m_line [ m_index ] == ':' ) {
+	  ||   m_line [ m_index ] == '/' || m_line [ m_index ] == '.' || m_line [ m_index ] == '-'
+	  ||   m_line [ m_index ] == '~' || m_line [ m_index ] == '_' || m_line [ m_index ] == ':' ) {
 		res.m_value += m_line [ m_index ];
 		m_index++;
 		goto q3;
@@ -147,6 +152,33 @@ q3:	if ( m_index >= m_line.size ( ) ) {
 		res.m_type = is_kw ( res.m_value );
 		return res;
 	}
+
+q4:	if ( m_index >= m_line.size ( ) ) {
+		res.m_type = TokenType::ERROR;
+		return res;
+	}
+	if ( m_line [ m_index ] == '"' ) {
+		res.m_type = TokenType::STRING;
+		m_index++;
+		return res;
+	}
+	if ( m_line [ m_index ] == '\\' ) {
+		m_index++;
+		goto q5;
+	} else {
+		res.m_value += m_line [ m_index ];
+		m_index ++;
+		goto q4;
+	}
+
+q5:	if ( m_index >= m_line.size ( ) ) {
+		res.m_type = TokenType::ERROR;
+		return res;
+	}
+
+	res.m_value += m_line [ m_index ];
+	m_index++;
+	goto q4;
 }
 
 } /* namespace cli */
diff --git a/alib2cli/src/lexer/Lexer.h b/alib2cli/src/lexer/Lexer.h
index c946a5f716..7ed1d1676f 100644
--- a/alib2cli/src/lexer/Lexer.h
+++ b/alib2cli/src/lexer/Lexer.h
@@ -14,6 +14,7 @@ public:
 	enum class TokenType {
 		IDENTIFIER,
 		INTEGER,
+		STRING,
 		IN_REDIRECT,
 		OUT_REDIRECT,
 		LEFT_PAREN,
@@ -44,6 +45,8 @@ public:
 				return out << "identifier: " << token.m_value;
 			case TokenType::INTEGER :
 				return out << "number: " << token.m_value;
+			case TokenType::STRING :
+				return out << "string: \"" << token.m_value << "\"";
 			case TokenType::IN_REDIRECT :
 				return out << "in_redirect";
 			case TokenType::OUT_REDIRECT :
diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp
index 3001d2a506..e8da17a9d9 100644
--- a/alib2cli/src/parser/Parser.cpp
+++ b/alib2cli/src/parser/Parser.cpp
@@ -131,6 +131,9 @@ std::unique_ptr < Param > Parser::value_param ( ) {
 	} else if ( check ( cli::Lexer::TokenType::IDENTIFIER ) ) {
 		std::string value = matchIdentifier ( );
 		return std::make_unique < ImmediateParam < std::string > > ( value );
+	} else if ( check ( cli::Lexer::TokenType::STRING ) ) {
+		std::string value = matchString ( );
+		return std::make_unique < ImmediateParam < std::string > > ( value );
 	} else if ( check ( cli::Lexer::TokenType::INTEGER ) ) {
 		int value = matchInteger ( );
 		return std::make_unique < ImmediateParam < int > > ( value );
@@ -297,9 +300,10 @@ std::unique_ptr < Command > Parser::parse ( ) {
 		return introspect_command ( );
 	} else if ( check_nonreserved_kw ( "set" ) ) {
 		match_nonreserved_kw ( "set" );
-		std::string param = matchIdentifier ( );
-		std::string value = getTokenValue ( );
+		std::string param = getTokenValue ( );
 		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER );
+		std::string value = getTokenValue ( );
+		match ( cli::Lexer::TokenType::INTEGER, cli::Lexer::TokenType::IDENTIFIER, cli::Lexer::TokenType::STRING );
 		match ( cli::Lexer::TokenType::END );
 		return std::make_unique < SetCommand > ( std::move ( param ), std::move ( value ) );
 	} else {
diff --git a/alib2cli/src/parser/Parser.h b/alib2cli/src/parser/Parser.h
index 245b152086..79d88125e6 100644
--- a/alib2cli/src/parser/Parser.h
+++ b/alib2cli/src/parser/Parser.h
@@ -59,6 +59,14 @@ public:
 		return res;
 	}
 
+	std::string matchString ( ) {
+		if ( ! check ( Lexer::TokenType::STRING ) )
+			throw exception::CommonException ( "Mismatched token while matching a token." );
+		std::string res = m_current.m_value;
+		m_current = m_lexer.nextToken ( );
+		return res;
+	}
+
 	int matchInteger ( ) {
 		if ( ! check ( Lexer::TokenType::INTEGER ) )
 			throw exception::CommonException ( "Mismatched token while matching a token."  );
-- 
GitLab