From c3d79e29e2ae6f929287536c232c5dbad1fdbd67 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sat, 28 Jan 2017 04:40:54 +0100 Subject: [PATCH] added quotation marks handling to the parser --- parser.cpp | 67 +++++++++++++++++++++++++++++++++++++----------------- parser.h | 62 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 94 insertions(+), 35 deletions(-) diff --git a/parser.cpp b/parser.cpp index 3eaa23a9..5cdc7ad7 100644 --- a/parser.cpp +++ b/parser.cpp @@ -21,7 +21,7 @@ http://mozilla.org/MPL/2.0/. // cParser -- generic class for parsing text data. // constructors -cParser::cParser(std::string Stream, buffertype Type, std::string Path, bool tr) +cParser::cParser(std::string const Stream, buffertype Type, std::string Path, bool tr) { LoadTraction = tr; // build comments map @@ -73,28 +73,33 @@ bool cParser::getTokens(int Count, bool ToLower, const char *Break) else trtest="x"; //nie wczytywać */ +/* int i; this->str(""); this->clear(); - for (i = 0; i < Count; ++i) +*/ + for (int i = 0; i < Count; ++i) { - std::string string = readToken(ToLower, Break); - if( true == string.empty() ) { + std::string token = readToken(ToLower, Break); + if( true == token.empty() ) { // no more tokens break; } // collect parameters + tokens.emplace_back( token ); +/* if (i == 0) - this->str(string); + this->str(token); else { std::string temp = this->str(); temp.append("\n"); - temp.append(string); + temp.append(token); this->str(temp); } +*/ } - if (i < Count) + if (tokens.size() < Count) return false; else return true; @@ -146,6 +151,8 @@ std::string cParser::readToken(bool ToLower, const char *Break) if (ToLower) c = tolower(c); token += c; + if (findQuotes(token)) // do glue together words enclosed in quotes + break; if (trimComments(token)) // don't glue together words separated with comment break; } @@ -181,32 +188,50 @@ std::string cParser::readToken(bool ToLower, const char *Break) return token; } +std::string cParser::readQuotes(char const Quote) { // read the stream until specified char or stream end + std::string token = ""; + char c; + while( mStream->peek() != EOF && Quote != (c = mStream->get()) ) { // get all chars until the quote mark + token += c; + } + return token; +} + +std::string cParser::readComment( std::string const &Break ) { // pobieranie znaków aż do znalezienia znacznika końca + std::string token = ""; + while( mStream->peek() != EOF ) { // o ile nie koniec pliku + token += mStream->get(); // pobranie znaku + if( token.rfind( Break ) != std::string::npos ) // szukanie znacznika końca + break; + } + return token; +} + +bool cParser::findQuotes( std::string &String ) { + + if( String.rfind( '\"' ) != std::string::npos ) { + + String.erase( String.rfind( '\"' ), 1 ); + String += readQuotes(); + return true; + } + return false; +} + bool cParser::trimComments(std::string &String) { for (commentmap::iterator cmIt = mComments.begin(); cmIt != mComments.end(); ++cmIt) { - if (String.find((*cmIt).first) != std::string::npos) + if (String.rfind((*cmIt).first) != std::string::npos) { readComment((*cmIt).second); - String.resize(String.find((*cmIt).first)); + String.resize(String.rfind((*cmIt).first)); return true; } } return false; } -std::string cParser::readComment(std::string const &Break) -{ // pobieranie znaków aż do znalezienia znacznika końca - std::string token = ""; - while (mStream->peek() != EOF) - { // o ile nie koniec pliku - token += mStream->get(); // pobranie znaku - if (token.find(Break) != std::string::npos) // szukanie znacznika końca - break; - } - return token; -} - int cParser::getProgress() const { return static_cast( mStream->rdbuf()->pubseekoff(0, std::ios_base::cur) * 100 / mSize ); diff --git a/parser.h b/parser.h index 8abe5da1..80d6536f 100644 --- a/parser.h +++ b/parser.h @@ -18,7 +18,7 @@ http://mozilla.org/MPL/2.0/. ///////////////////////////////////////////////////////////////////////////////////////////////////// // cParser -- generic class for parsing text data, either from file or provided string -class cParser : public std::stringstream +class cParser //: public std::stringstream { public: // parameters: @@ -33,6 +33,15 @@ class cParser : public std::stringstream // destructor: virtual ~cParser(); // methods: + template + cParser& + operator>>( _Type &Right ); + template <> + cParser& + operator>>( std::string &Right ); + template <> + cParser& + operator>>( bool &Right ); template _Output getToken( bool const ToLower = true ) @@ -74,12 +83,14 @@ class cParser : public std::stringstream // load traction? bool LoadTraction; - protected: + private: // methods: std::string readToken(bool ToLower = true, const char *Break = "\n\t ;"); - std::string readComment(std::string const &Break = "\n\t ;"); - std::string trtest; - bool trimComments(std::string &String); + std::string readQuotes( char const Quote = '\"' ); + std::string readComment( std::string const &Break = "\n\t ;" ); +// std::string trtest; + bool findQuotes( std::string &String ); + bool trimComments( std::string &String ); // members: std::istream *mStream; // relevant kind of buffer is attached on creation. std::string mPath; // path to open stream, for relative path lookups. @@ -88,19 +99,42 @@ class cParser : public std::stringstream commentmap mComments; cParser *mIncludeParser; // child class to handle include directives. std::vector parameters; // parameter list for included file. + std::deque tokens; }; -inline +template cParser& -operator>>( cParser &Parser, bool &Right ) { +cParser::operator>>( _Type &Right ) { - std::istream::sentry const streamokay( Parser ); - if( streamokay ) { + if( true == this->tokens.empty() ) { return *this; } - std::string value; - Parser >> value; - Right = ( value == "true" ); - } + std::stringstream converter( this->tokens.front() ); + converter >> Right; + this->tokens.pop_front(); - return Parser; + return *this; +} + +template<> +cParser& +cParser::operator>>( std::string &Right ) { + + if( true == this->tokens.empty() ) { return *this; } + + Right = this->tokens.front(); + this->tokens.pop_front(); + + return *this; +} + +template<> +cParser& +cParser::operator>>( bool &Right ) { + + if( true == this->tokens.empty() ) { return *this; } + + Right = ( this->tokens.front() == "true" ); + this->tokens.pop_front(); + + return *this; }