#ifndef SEMI_H #define SEMI_H /////////////////////////////////////////////////////////////// // semi.h - build semiexpression, e.g., list of tokens // // ver 2.4 terminated by special characters // // // // Language: Visual C++, ver 6.0 // // Platform: Micron Dual Pentium Pro 200, Win NT 4.0 // // Application: CSE784 Example // // Author: Jim Fawcett, CST 2-187, Syracuse Univ. // // (315) 443-3948, fawcett@ecs.syr.edu // /////////////////////////////////////////////////////////////// /* Module Operations ================= The semiExp class provides public functions which build lists of tokens, called semiexpressions, from a file stream, which this module expects to be attached to a C or C++ source file. Semiexpressions are lists of tokens that terminate on the special tokens: '{', '}', ';', or '\n' when line starts with '#' Typical usage: while(se.get()) { // do analysis on collected semiExps } The public interface of the semiExp class is: semiExp se(input); // construct semiExp object attached stream se.get(); // collects a semiExp from input se.append(tok); // append string tok to end of se se += tok; // equivalent to se.append(tok); int nl = se.lines(); // number of lines so far int sl = se.scopeLevel(); // net number of braces, '{' and '}' string s = se[2] = tok; // read or write a semiExp element. int L = se.length(); // return number of tokens in semiExp se.flush(); // empty semiExpression array se.display(); // send semiExp to stdout se.remove(3); // remove fourth element of se int pos = se.find(tok); // return position of tok in se if there // else return se.size(); int pos = se.textFind("::"); // return position of "::" in se if there // else return se.size(); int pos = se.next(tok); // resume search where we left off with // last find or next se.resetNext(); // resets search to beginning of se. int pos = se.findClosure(); // If preceded by successful find("[") or // find("(") returns position of matching // ")" or "]" if successful, else se.size() int pos = se.findExClosure(); // If preceded by successful find("["), // find("("), or find("{"), returns posi- // tion of matching ")" "]", or "}" if // successful, else returns -1. Will // collect new semiExps until closure is // found or reach end of file. Returns // position of match or -1 if end of file packedTokens pt; // declare a packedTokens object string fmt = pt.format(se); // use packedToken object to format se se.collectSingleQuoteAsToken(false); // collect pieces instead Note that you have to check for a final semiExp the first time semiExp::get() returns false. See test stub for an example. */ // /////////////////////////////////////////////////////////////// // build process // /////////////////////////////////////////////////////////////// // Required Files: // // semi.h, semi.cpp, tok.h, tok.cpp // // Compile Command: // // cl -GX -DTEST_SEMI semi.cpp tok.cpp // /////////////////////////////////////////////////////////////// /* Maintenance History =================== ver 2.4 : 18 Apr 2003 - fixed an error in remove function. The ver 2.3 fix was motivated by a student's bug report that I could not reproduce. Thanks to Murat Gungor, the error has now been identified and fixed. ver 2.3 : 15 Mar 2003 - removed an unnecessary search in remove function ver 2.2 : 08 Feb 2003 - fixed potential index out of range in function get. - changed int to size_t in many places to avoid new warning ver 2.1 : 10 Mar 2002 - added semiExp::collectSingleQuotesAsToken(bool pred) to avoid problem of possessive form using single quote in text body of an XML element. If you have this problem, call function with false. ver 2.0 : 10 Mar 2002 - added a final tok push_back at the end of semiExp::get to avoid losing a tok at end of file. See note at the end of the manual page, above - allow newlines at the beginning of preproc statement by checking for leading newlines in semiExp::isTerminator for case '\n' - fixed problem with comment handling, e.g., made change in tok::eatComment() to return newline at the end of a C++ comment. Before this change a preproc with a comment at the end was collected as part of the next semiExp. - made cosmetic change to display function to eliminate a spurious space in displayed output ver 1.9 : 27 Nov 2001 - Modified the remove member to eliminate a possibly unnecessary erase operation and added fairly detailed testing of the remove function. This change was suggested by Pratyush Rai. ver 1.8 : 30 Sep 2001 - cosmetic changes to this header and implementation file ver 1.7, 26 Sep 2001 - cosmetic changes to test stub ver 1.6, 21 Apr 2000 - added member function void nestedComments(bool pred) to pass to token a nested comments option ver 1.5, 15 Dec 1999 - modified get() to take bool includeNewline as optional argument with default value of false - added function linesAtFirstToken() - added function textFind(...) ver 1.4, 04 Dec 1999 - added remove function - added packedToken class to format semi-expressions appropriate for displaying source code ver 1.3, 11 Sep 1999 - added counts of lines and net braces ver 1.2, 26 Apr 1999 - fixed bug in test stub, e.g., added in.close() and in.clear() at end of file loop ver 1.1, 07 Feb 1999 - improved abstraction of find by setting _next for next search - added capability to collect more semiExps in findClosure ver 1.0, 21 Sep 1998 - first release */ // /////////////////////////////////////////////////////////////// // declaration of semiExp class // /////////////////////////////////////////////////////////////// #pragma warning(disable : 4786) // stop compiler from waring about // STL code #include #include #include #include "tok.h" class semiExp { public: semiExp(std::istream &input); size_t append(const std::string &token); size_t length() const; void flush(); bool get(bool includeNewline=false); unsigned int lines(); unsigned int linesAtFirstToken(); unsigned int scopeLevel(); size_t find(const std::string &tok,size_t i=0); size_t textFind(const std::string &s, int i=0); size_t next(const std::string &tok); void resetNext(); size_t findClosure(); size_t findExClosure(); std::string& operator[](size_t n); semiExp& operator+=(const std::string &tok); void remove(size_t i); void display(size_t i=0, size_t j=1000); void collectSingleQuotesAsToken(bool pred=true); void nestedComments(bool pred=true); private: vector se; size_t _next; unsigned int linesAtFirstTok; toker Toker; bool isTerminator(const std::string &token); static void check(bool condition, const char *msg); std::string closes(const std::string &tok); }; inline unsigned int semiExp::lines() { return Toker.lines(); } inline unsigned int semiExp::scopeLevel() { return Toker.scopeLevel(); } inline void semiExp::collectSingleQuotesAsToken(bool pred) { Toker.collectSingleQuotes(pred); } inline void semiExp::nestedComments(bool pred) { Toker.nestedComments(pred); } // /////////////////////////////////////////////////////////////// // declaration of packedTokens class // /////////////////////////////////////////////////////////////// class packedTokens { public: enum packType { left, right, both, not }; packedTokens(); bool in(const string &s, packType pt) const; std::string format(semiExp &se); private: map toks; }; #endif