#ifndef SEMI_H #define SEMI_H /////////////////////////////////////////////////////////////// // semi.h - build semiexpression, e.g., list of tokens // // ver 2.1 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 // to istream input. 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 returns se.size() int pos = se.findExClosure(); // If preceded by successful find("["), // find("("), or find("{"), returns // position 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 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 =================== Thanks to Mahesh Narayan, Chong Mei, Matt Miling, and Ozer Ozkaraoglu for bug reports 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 the function with false argument. 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 - I have 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. Thanks Pratyush. 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 - cosmetic modifications to these pages - 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); int append(const std::string &token); int length() const; void flush(); bool get(bool includeNewline=false); unsigned int lines(); unsigned int linesAtFirstToken(); unsigned int scopeLevel(); int find(const std::string &tok,int i=0); int textFind(const std::string &s, int i=0); int next(const std::string &tok); void resetNext(); int findClosure(); int findExClosure(); std::string& operator[](int n); semiExp& operator+=(const std::string &tok); void remove(int i); void display(int i=0, int j=1000); void collectSingleQuotesAsToken(bool pred=true); void nestedComments(bool pred=true); private: vector se; int _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