///////////////////////////////////////////////////////////////////////// // CppSemiExp.cpp - declares semi-expression which collects tokens // // ver 1.0 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 using namespace Project1; //----< is this a C language comment? >---------------------------------- bool CCCommentFilter::present() { if(_pToker->curr() == "/*") return true; return false; } //----< discard C language comment >------------------------------------- bool CCCommentFilter::extract(std::string &token) { while(_pToker->getTok() != "*/") ; // discard token return false; // no token returned } //----< is this a C++ language comment? >-------------------------------- bool CCppCommentFilter::present() { std::string temp = _pToker->curr(); if(temp.length() >= 2 && temp[0] == '/' && temp[1] == '/') return true; return false; } //----< discard C++ language comment >----------------------------------- bool CCppCommentFilter::extract(std::string &token) { std::string debug; while((debug = _pToker->getTok()) != "\n") ; // discard token token = "\n"; return true; // token returned } // //----< is this a quoted string? >--------------------------------------- bool CDoubleQuoteFilter::present() { return false; } //----< collect quoted string as a token >------------------------------- bool CDoubleQuoteFilter::extract(std::string &token) { return false; } //----< is this a quoted character? >------------------------------------ bool CSingleQuoteFilter::present() { return false; } //----< collect quoted character as a token >---------------------------- bool CSingleQuoteFilter::extract(std::string &token) { return false; } // //----< CSemiExp constructor >------------------------------------------- CSemiExp::CSemiExp(CToker *pToker) : _pToker(pToker) { } //----< CSemiExp destructor >-------------------------------------------- CSemiExp::~CSemiExp(void) { // - user created CToker so don't destroy // - destroy filters std::list::iterator iter; for(iter=_filter.begin(); iter != _filter.end(); iter++) delete *iter; } //----< register type derived from ITokenFilter >------------------------ void CSemiExp::registerFilter(ITokenFilter *pITokenFilter) { _filter.push_back(pITokenFilter); } //----< register default filters >--------------------------------------- void CSemiExp::registerDefaultFilters() { ITokenFilter *pFilter = new CCppCommentFilter(_pToker); registerFilter(pFilter); pFilter = new CCCommentFilter(_pToker); registerFilter(pFilter); } //----< return number of tokens in semi-expression >--------------------- size_t CSemiExp::length() const { return _tok.size(); } //----< does this character terminat a semi-expression? >---------------- bool CSemiExp::isTerminator(const std::string &token) const { if(token=="{" || token=="}" || token==";") return true; if(length() == 0) return false; if(token=="\n" && _tok[0]=="#") return true; return false; } //----< remove all tokens >---------------------------------------------- void CSemiExp::clear() { _tok.clear(); } // //----< remove or transform groups of tokens >--------------------------- bool CSemiExp::filter(std::string &token) { std::string dummy; std::list::iterator iter; for(iter=_filter.begin(); iter!=_filter.end(); iter++) { if((*iter)->present()) { if((*iter)->extract(dummy=token)) { token = dummy; // return token via side effect return true; } else { return false; // don't return token } } } return true; } //----< 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 false; if(filter(token)) { if(token != "\n") _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); } // //----< return writable reference to nth token >------------------------- 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]; } //----< display semi-expression on cout with little formatting >--------- void CSemiExp::show() const { std::cout << " "; for(unsigned int i=0; i<_tok.size(); i++) if(_tok[i] != "\n") std::cout << _tok[i] << " "; std::cout << std::endl; } // ///////////////////////////////////////////////////////////////////////// // Test Stub #ifdef TEST_CPPSEMIEXP int main() { std::string file = "CppSemiExp.h"; std::ifstream in(file.c_str()); if(in.good()) { try { CToker toker(&in); CSemiExp semi(&toker); semi.registerDefaultFilters(); while(semi.get()) semi.show(); semi.show(); std::cout << "\n\n"; CSemiExp test1; // default construction test1.push_back("one"); test1.show(); test1.push_back("two"); test1.show(); test1.insert(1,"three"); test1.show(); test1.push_back(";"); test1.show(); test1.get(); // does nothing since it has no CToker instance CSemiExp test2 = test1; // compiler generated copy construction CSemiExp test3; test3 = test2; // compiler generated assignment test1.erase(0); test1.show(); test1.erase(1); test1.show(); test1.erase(0); test1.show(); test1.erase(0); test1.show(); test3.show(); // demonstrates that default assignment worked } catch(std::exception e) { std::cout << "\n\n " << e.what() << "\n\n"; } } else { std::cout << "\n\n Can't open file " << file << "\n\n"; } } #endif