///////////////////////////////////////////////////////////////////////// // CppSemiExp.cpp - implements 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 // ///////////////////////////////////////////////////////////////////////// #include "CppSemiExp.h" #include "CppToker.h" #include #include #include #include #include using namespace Scanner; //----< is this a for loop? >-------------------------------------------- bool CForFilter::present(const CSemiExp& se) { size_t pos = se.find("for"); if(pos < se.length()-1 && se[pos+1]=="(") return true; return false; } //----< merge with remaining semi-expressions >-------------------------- void CForFilter::filter(CSemiExp& se) { do { se.append(); } while(se.find(")") == se.length()); } //----< return a pointer to clone >-------------------------------------- ISemiFilter* CForFilter::clone() const { return new CForFilter(); } // //----< is this an operator? >------------------------------------------- bool COperatorFilter::present(const CSemiExp& se) { size_t pos = se.find("operator"); if(pos < se.length()-1) return true; return false; } //----< bind operator type to operator token >--------------------------- void COperatorFilter::filter(CSemiExp& se) { size_t pos = se.find("operator"); size_t start = pos; while(se.length()>0 && pos < se.length()-1) { if(!ispunct(se[pos+1][0]) || se[pos+1][0] == '\"') break; se[pos] += se[pos+1]; se.erase((unsigned int)pos+1); if(se.length()>pos+1 && se[pos+1] == "(") break; } } //----< return a pointer to clone >-------------------------------------- ISemiFilter* COperatorFilter::clone() const { return new COperatorFilter(); } // //----< CSemiExp constructor >------------------------------------------- CSemiExp::CSemiExp(CToker *pToker) : _pToker(pToker) { } //----< CSemiExp Copy Constructor >-------------------------------------- CSemiExp::CSemiExp(const CSemiExp& se) { _pToker = se._pToker; // dump current tokens and push_back se's tokens _tok.clear(); std::vector::const_iterator cviter; for(cviter=se._tok.begin(); cviter!=se._tok.end(); cviter++) _tok.push_back(*cviter); // construct clones of all of se's filters // so *this and se each hold their own filter instances std::list::const_iterator cliter; for(cliter=se._filters.begin(); cliter != se._filters.end(); cliter++) _filters.push_back((*cliter)->clone()); } //----< CSemiExp destructor >-------------------------------------------- CSemiExp::~CSemiExp(void) { // - user created CToker so don't destroy // remove filters held by this instance std::list::iterator iter; for(iter=_filters.begin(); iter != _filters.end(); iter++) delete *iter; _filters.clear(); } // //----< assignment operator >-------------------------------------------- CSemiExp& CSemiExp::operator=(const CSemiExp& se) { if(this==&se) return *this; _pToker = se._pToker; // dump current tokens and push_back se's tokens _tok.clear(); std::vector::const_iterator cviter; for(cviter=se._tok.begin(); cviter!=se._tok.end(); cviter++) _tok.push_back(*cviter); // remove filters held by this instance std::list::iterator iter; for(iter=_filters.begin(); iter != _filters.end(); iter++) delete *iter; _filters.clear(); // assign clones of the filters held by se // so *this and se each hold their own instances of the filters std::list::const_iterator cliter; for(cliter=se._filters.begin(); cliter != se._filters.end(); cliter++) _filters.push_back((*cliter)->clone()); return *this; } //----< set new toker, return pointer to old toker >--------------------- CToker* CSemiExp::setToker(CToker* pToker) { CToker* temp = _pToker; _pToker = pToker; return temp; } // //----< return number of tokens in semi-expression >--------------------- size_t CSemiExp::length() const { return _tok.size(); } //----< does this token terminate a semi-expression? >------------------- bool CSemiExp::isTerminator(const std::string &token) const { if(length() == 0) return false; if(token=="{" || token=="}" || token==";") return true; if(token=="\n") { for(unsigned int i=0; i<_tok.size(); ++i) if(_tok[i] == "#") return true; } return false; } //----< remove all tokens >---------------------------------------------- void CSemiExp::clear() { _tok.clear(); } //----< register type derived from ITokenFilter >------------------------ // // register creates filter clone so does not take ownership // of user's filter // void CSemiExp::registerFilter(ISemiFilter *pISemiFilter) { _filters.push_back(pISemiFilter->clone()); } //----< register for and operator filters >------------------------------ void CSemiExp::registerDefaultFilters() { registerFilter(&forFilter); registerFilter(&operFilter); } // //----< remove or transform groups of tokens >--------------------------- void CSemiExp::filter() { std::string dummy; std::list::iterator iter; for(iter=_filters.begin(); iter!=_filters.end(); iter++) { if((*iter)->present(*this)) (*iter)->filter(*this); } return; } //----< extract semi-expressions from filtered stream >------------------ // // returns silently if no toker provided, e.g., created with default ctor // bool CSemiExp::get() { if(!_pToker) return false; clear(); std::string token; do { token = _pToker->getTok(); if(token == "") return (length() > 0); _tok.push_back(token); } while(!isTerminator(token)); filter(); return true; } //----< append next semi-expression >------------------------------------ bool CSemiExp::append() { if(!_pToker) return false; std::string token; do { token = _pToker->getTok(); if(token == "") return (length() > 0); _tok.push_back(token); } while(!isTerminator(token)); return true; } // //----< check for valid index >------------------------------------------ void CSemiExp::checkIndex(unsigned int i) { if(i<0 || _tok.size() <= i) throw std::exception("index out of domain in CSemiExp::insert"); } //----< insert token preceding element i >------------------------------- void CSemiExp::insert(unsigned int i, const std::string &token) { checkIndex(i); std::vector::iterator iter = _tok.begin(); _tok.insert(iter+i,token); } //----< append token at end of semi-expression >------------------------- void CSemiExp::push_back(const std::string &token) { std::vector::iterator iter = _tok.begin(); _tok.push_back(token); } //----< remove token from semi-expression >------------------------------ void CSemiExp::erase(unsigned int i) { checkIndex(i); std::vector::iterator iter = _tok.begin(); _tok.erase(iter+i); } //----< find token in semi-expression >---------------------------------- // // returns length() if not found // size_t CSemiExp::find(const std::string& token, size_t start) const { size_t len = length(); for(size_t i=start; i---------------- size_t CSemiExp::findStringInTokens(const std::string& str) const { for(unsigned int i=0; i------------------------- std::string& CSemiExp::operator [](unsigned int n) { if(n<0 || length()<= n) { std::string msg = "index out of domain in CSemiExp::operator[](int)"; throw std::exception(msg.c_str()); } return _tok[n]; } //----< return readonly reference to nth token >------------------------- std::string CSemiExp::operator [](unsigned int n) const { if(n<0 || length()<= n) { std::string msg = "index out of domain in CSemiExp::operator[](int)"; throw std::exception(msg.c_str()); } return _tok[n]; } //----< logical comparison operator >------------------------------------ bool CSemiExp::operator==(const CSemiExp& se) const { if(this->length() != se.length()) return false; for(unsigned int i=0; i------------------------------------ bool CSemiExp::operator!=(const CSemiExp& se) const { return !operator==(se); } //----< strip leading newlines >----------------------------------------- void CSemiExp::stripLeadingNewLines() { while(_tok.size()>0 && _tok[0] == "\n") _tok.erase(_tok.begin()); } // //----< display semi-expression to string with little formatting >------- std::string CSemiExp::showToString(const std::string& msg, bool showReturn) { std::ostringstream out; stripLeadingNewLines(); if(_tok.size() > 0) { if(msg.size() > 0) out << msg << ": "; for(unsigned int i=0; i------ void CSemiExp::show(const std::string& msg, bool keepReturn) { std::cout << showToString(msg, keepReturn); } // /////////////////////////////////////////////////////////////////////// // Test Stub #ifdef TEST_CPPSEMIEXP #include #include using namespace Scanner; int main(int argc, char* argv[]) { std::ifstream in; if(argc < 2) { std::string file = "..\\CppToker.cpp"; in.open(file.c_str()); if(!in.good()) { std::cout << "\n\n can't open file " << file << "\n\n"; return 1; } } else { for(int i=1; i