#ifndef CPPSEMIEXP_H // compile if CPPSEMIEXP_H is not in symbol table #define CPPSEMIEXP_H // put CPPSEMIEXP_H in symbol table ///////////////////////////////////////////////////////////////////////// // CppSemiExp.h - declares semi-expression which collects tokens // // ver 2.4 from input stream via a CToker instance // // // // Language: Visual C++, ver 7.0 // // Platform: Dell Dimension 8300, Windows XP Prof, SP 1 // // Application: CSE687 prototype for project #1, Spring 2004 // // Author: Jim Fawcett, CST 2-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////////// /* * Module Operations: * ================== * CppSemiExp.h Declares a class CSemiExp designed to collect tokens from * a std stream and assemble them into meaningful sequences. Semi-expressions. * end in single character tokens "{", "}", ";", or "\n" following a #. * * A semi-expression contains just the right amount of code for analysis * without requiring a lot of state management. * * CSemiExp accepts plug-in filters, using ISemiFilter interface. * Two useful sample filters are provided, e.g.: * CForFilter - collects up to terminator after for's closing parenthesis. * COperatorFilter - appends punctuators after "operator" to that token. * * Public Interface: * ================= * std::fstream in(someFile); * CToker toker(&in); * CSemiExp semi(&toker); // create CSemiExp instance * while(semi.get()) // extract next semi-expression * // do something with semi * semi.append(); // get another semi and append to current * int n = semi.length(); // get number of tokens * std::string tok = semi[2]; // read 3rd token's value * semi[1] = "test"; // change 2nd token's value * size_t loc = se.find("{"); // find occurance of "{" token * size_t loc = se.findStringInTokens("//"); * semi.show(); // display on cout * semi.clear(); // remove all tokens * semi.insert(2,"aToken"); // insert token into semi * semi.push_back("aToken"); // append a token * semi.erase(1); // remove 2nd token * CSemiExp semi1(&toker); * CSemiExp semi2 = semi1; // copy construction * semi2 = semi1; // assignment * if(semi1 == semi2) { ... } // equality test * if(semi1 != semi2) { ... } // inequality test * ITokenFilter *pFilter = CCCommentFilter(&toker); * // create a filter * semi.registerFilter(pFilter); // register filter - semi takes ownership * semi.registerDefaultFilters(); // filter comments and quotes * */ // /* * Maintenance History: * ==================== * ver 2.4 : 22 Jan 05 * - minor changes to test stub * ver 2.3 : 13 Mar 04 * - only cosmetic changes (pagination and manual page entries) * ver 2.2 : 10 Mar 04 * - modified isTerminator to return true on first newline after a "#" token * ver 2.1 : 09 Mar 04 * - made stripLeadingNewLines() public for grammar constructor to use. * ver 2.0 : 29 Feb 04 * - added semi-expression filters to collect complete for expression * and pull operator symbols into the operator keyword token * - filters have clone function so CSemiExp can clone filters in * registerFilter without taking ownership of user's filters * - this supports building registerDefaultFilter function without * statics and no memory leaks * (contrary to comment below, it did return) * - added append function to allow appending a CSemiExp instance with * another, used by CForFilter, but also useful for clients * - added operator== and operator!=, useful for testing * - added findStringInTokens, useful for testing and clients * - fixed annoying visual bug in show function. * ver 1.3 : 24 Feb 04 * - Fixed a bug reported by Carmen Vaca Ruiz and Ashish Poddar. * - Thanks Carmen and Ashish! * With version 1.2, if you set the working directory to, say, ".." in * scan project properties then the scanner crashes. The problem was * still due to registerDefaultFilters. Specifically due to the * static filters I put there holding a pointer to the wrong CToker * object when you come out of the scanner's recursion. I've fixed * this by wiping out the registerDefaultFilters() function, never to * return. * - Now you must register the filters individually in place * of the call to that function. Sigh. * ver 1.2 : 18 Feb 04 * - added a test harness to make detailed testing easier. * - fixed two bugs reported by Priyaa Nachimuthu - Thanks Priyaa! * - CppSemiExp crashes when copied or assigned to another instance * in a nested scope and use filtering after copy is destroyed. * Problem was due to deletions in the destructor for filters * created by another instance. Sigh. * Fixed by making default filters static and not deleting in * destructor. * - C++ comment filter hung if there was a comment at the end of * a file with no newline following. Fixed by checking for bad * stream state in all the filters. * ver 1.1 : 08 Feb 04 * - added Find function * - added bodies for CDoubleQuoteFilter and CSingleQuoteFilter * ver 1.0 : 12 Jan 04 * - first release * * Build Process: * ============== * Required Files: * CppSemiExp.h, CppSemiExp.cpp, CppToker.h, CppToker.cpp * * Compiler Command: * cl /DTest_CPPSEMIEXP /EHsc CppSemiExp.cpp CppToker.cpp; */ // #include "CppToker.h" #include #include namespace Scanner { /////////////////////////////////////////////////////////////////////// // family of token filters class CSemiExp; class ISemiFilter { public: virtual bool present(const CSemiExp& se)=0; virtual void filter(CSemiExp& se)=0; virtual ISemiFilter* clone() const=0; }; class CForFilter : public ISemiFilter { public: virtual bool present(const CSemiExp& se); virtual void filter(CSemiExp& se); virtual ISemiFilter* clone() const; }; class COperatorFilter : public ISemiFilter { public: virtual bool present(const CSemiExp& se); virtual void filter(CSemiExp& se); virtual ISemiFilter* clone() const; }; // /////////////////////////////////////////////////////////////////////// // class representing semi-expressions class CSemiExp { public: CSemiExp(CToker *pToker=0); // constructor with default argument CSemiExp(const CSemiExp& se); ~CSemiExp(); CToker* setToker(CToker* pToker); bool get(); bool append(); size_t length() const; CSemiExp& operator=(const CSemiExp& se); std::string& operator[](size_t n); std::string operator[](size_t n) const; bool operator==(const CSemiExp& se) const; bool operator!=(const CSemiExp& se) const; void insert(unsigned int i, const std::string &token); void push_back(const std::string &token); void erase(unsigned int i); size_t find(const std::string& token, size_t start=0) const; size_t findStringInTokens(const std::string& str) const; void clear(); void stripLeadingNewLines(); void show(const std::string& msg="", bool keepReturn=false); std::string showToString(const std::string& msg="", bool keepReturn=false); void registerFilter(ISemiFilter *pITokenFilter); void registerDefaultFilters(); private: bool isTerminator(const std::string &tok) const; void filter(); void checkIndex(unsigned int); CToker *_pToker; std::vector _tok; std::list _filters; CForFilter forFilter; COperatorFilter operFilter; }; } #endif