⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap6.lst

📁 The Art of C++一书的配套源代码
💻 LST
字号:
listing 1
// A translator for experimental C++ extensions.  
#include <iostream>  
#include <fstream>  
#include <cctype>  
#include <cstring>  
#include <string>  
  
using namespace std;  
  
// Prototypes for the functions that handle  
// the extended keywords.  
void foreach();  
void cases();  
void repeat();  
void until();  
void typeof();  
  
// Prototypes for tokenizing the input file.  
bool gettoken(string &tok);  
void skipspaces();  
  
// Indentation padding string.  
string indent = "";  
  
// The input and output file streams.  
ifstream fin;  
ofstream fout;  
  
// Exception class for syntax errors.  
class SyntaxExc {  
  string what;  
public:  
  SyntaxExc(char *e) { what = string(e); }  
  string geterror() { return what; }  
};  
  
int main(int argc, char *argv[]) {  
  string token;  
  
  if(argc != 3) {  
    cout << "Usage: ep <input file> <output file>\n";  
    return 1;  
  }  
  
  fin.open(argv[1]);  
  
  if(!fin) {  
    cout << "Cannot open " << argv[1] << endl;  
    return 1;  
  }  
  
  fout.open(argv[2]);  
  
  if(!fout) {  
    cout << "Cannot open " << argv[2] << endl;  
    return 1;  
  }  
  
  // Write header.  
  fout << "// Translated from an .exp source file.\n";  
  
  try {  
    // Main translation loop.  
    while(gettoken(token)) {  
  
      // Skip over // comments.  
      if(token == "//") {  
        do {  
          fout << token;  
          gettoken(token);  
        } while(token.find('\n') == string::npos);  
        fout << token;  
      }  
  
      // Skip over /* comments.  
      else if(token == "/*") {  
        do {  
          fout << token;  
          gettoken(token);  
        } while(token != "*/");  
        fout << token;  
      }  
  
      // Skip over quoted string.  
      else if(token == "\"") {  
        do {  
          fout << token;  
          gettoken(token);  
        } while(token != "\"");  
        fout << token;  
      }  
  
      else if(token == "foreach") foreach();  
  
      else if(token == "cases") cases();  
  
      else if(token == "repeat") repeat();  
  
      else if(token == "until") until();  
  
      else if(token == "typeof") typeof();  
  
      else fout << token;  
    }  
  } catch(SyntaxExc exc) {  
    cout << exc.geterror() << endl;  
    return 1;  
  }  
  
  return 0;  
}  
  
// Get the next token from the input stream.  
bool gettoken(string &tok) {  
  char ch;  
  char ch2;  
  static bool trackIndent = true;  
  
  tok = "";  
  
  ch = fin.get();  
  
  // Check for EOF and return false if EOF  
  // is found.  
  if(!fin) return false;  
  
  // Read whitespace.  
  if(isspace(ch)) {    
    while(isspace(ch)) {  
      tok += ch;  
  
      // Reset indent counter with each new line.  
      if(ch == '\n') {  
        indent = "";  
        trackIndent = true;  
      }  
      else if(trackIndent) indent += ch;  
  
      ch = fin.get();  
    }  
    fin.putback(ch);  
    return true;  
  }  
  
  // Stop tracking indentation after encountering  
  // first non-whitespace character on a line.  
  trackIndent = false;  
  
  // Read an identifier or keyword.  
  if(isalpha(ch) || ch=='_') {  
    while(isalpha(ch) || isdigit(ch) || ch=='_') {  
      tok += ch;  
      ch = fin.get();  
    }  
    fin.putback(ch);  
    return true;  
  }  
  
  // Read a number.  
  if(isdigit(ch)) {  
    while(isdigit(ch) || ch=='.' ||  
          tolower(ch) == 'e' ||  
          ch == '-' || ch =='+') {  
      tok += ch;  
      ch = fin.get();  
    }  
    fin.putback(ch);  
    return true;  
  }  
  
  // Check for \"  
  if(ch == '\\') {  
    ch2 = fin.get();  
    if(ch2 == '"') {  
      tok += ch;  
      tok += ch2;  
      ch = fin.get();  
    } else   
      fin.putback(ch2);  
  }  
  
  // Check for '"'  
  if(ch == '\'') {  
    ch2 = fin.get();  
    if(ch2 == '"') {  
      tok += ch;  
      tok += ch2;  
      return true;  
    } else   
      fin.putback(ch2);  
  }  
  
  // Check for begin comment symbols.  
  if(ch == '/') {  
    tok += ch;  
    ch = fin.get();  
    if(ch == '/' || ch == '*') {  
      tok += ch;  
    }  
    else fin.putback(ch);  
    return true;  
  }  
  
  // Check for end comment symbols.  
  if(ch == '*') {  
    tok += ch;  
    ch = fin.get();  
    if(ch == '/') {  
      tok += ch;  
    }  
    else fin.putback(ch);  
    return true;  
  }  
  
  tok += ch;  
  
  return true;  
}   
  
// Translate a foreach loop.  
void foreach() {  
  string token;  
  string varname;  
  string arrayname;  
  
  char forvarname[5] = "_i";  
  static char counter[2] = "a";  
  
  // Create loop control variable for generated  
  // for loop.  
  strcat(forvarname, counter);  
  counter[0]++;  
  
  // Only 26 foreach loops in a file because  
  // generated loop control variables limited to  
  // _ia to _iz. This can be changed if desired.  
  if(counter[0] > 'z')   
    throw SyntaxExc("Too many foreach loops.");  
  
  fout << "int " << forvarname  
       << " = 0;\n";  
  
  // Write beginning of generated for loop.  
  fout << indent << "for(";  
  
  skipspaces();  
  
  // Read the (  
  gettoken(token);  
  if(token[0] != '(')   
    throw SyntaxExc("( expected in foreach.");  
  
  skipspaces();  
  
  // Get the type of the foreach variable.   
  gettoken(token);  
  fout << token << " ";  
  
  skipspaces();  
  
  // Read and save the foreach variable's name.  
  gettoken(token);  
  varname = token;  
  
  skipspaces();  
  
  // Read the "in"  
  gettoken(token);  
  if(token != "in")   
    throw SyntaxExc("in expected in foreach.");  
  
  skipspaces();  
  
  // Read the array name.  
  gettoken(token);  
  arrayname = token;  
  
  fout << varname << " = " << arrayname << "[0];\n";  
  
  // Construct target value.  
  fout << indent + "    " << forvarname << " < "  
       << "((sizeof " << token << ")/"   
       << "(sizeof " << token << "[0]));\n";  
  
  fout << indent + "    " << forvarname << "++, "  
       << varname << " = " << arrayname << "["  
       << forvarname << "])";  
  
  skipspaces();  
  
  // Read the )  
  gettoken(token);  
  if(token[0] != ')')  
    throw SyntaxExc(") expected in foreach.");  
}  
  
// Translate a cases statement.  
void cases() {  
  string token;  
  int start, end;  
  
  skipspaces();  
  
  // Get starting value.  
  gettoken(token);  
  
  if(isdigit(token[0])) {  
    // is an int constant  
    start = atoi(token.c_str());  
  }  
  else if(token[0] == '\'') {  
    // is char constant  
    gettoken(token);  
  
    start = (int) token[0];  
  
    // discard closing '  
    gettoken(token);  
    if(token[0] != '\'')  
      throw SyntaxExc("' expected in cases.");  
  }  
  else  
   throw SyntaxExc("Constant expected in cases.");  
  
  skipspaces();  
  
  // Read and discard the "to".  
  gettoken(token);  
  if(token != "to")  
    throw SyntaxExc("to expected in cases.");  
  
  skipspaces();  
  
  // Get ending value.  
  gettoken(token);  
  
  if(isdigit(token[0])) {  
    // is an int constant  
    end = atoi(token.c_str());  
  }  
  else if(token[0] == '\'') {  
    // is char constant  
    gettoken(token);  
  
    end = (int) token[0];  
  
    // discard closing '  
    gettoken(token);  
    if(token[0] != '\'')  
      throw SyntaxExc("' expected in cases.");  
  }  
  else  
   throw SyntaxExc("Constant expected in cases.");  
  
  skipspaces();  
  
  // Read and discard the :  
  gettoken(token);  
  
  if(token != ":")   
    throw SyntaxExc(": expected in cases.");  
  
  // Generate stacked case statments.  
  fout << "case " << start << ":\n";  
  for(int i = start+1 ; i <= end; i++) {  
    fout << indent << "case " << i << ":";  
    if(i != end) fout << endl;  
  }  
}  
  
// Translate a repeat loop.  
void repeat() {  
  fout << "do";  
}    
  
// Translate an until.  
void until() {  
  string token;  
  int parencount = 1;  
  
  fout << "while";  
  
  skipspaces();  
  
  // Read and store the (  
  gettoken(token);  
  if(token != "(")  
    throw SyntaxExc("( expected in typeof.");  
  fout << "(";  
  
  // Begin while by reversing and  
  // parenthesizing the condition.  
  fout << "!(";  
  
  // Now, read the expression.  
  do {  
    if(!gettoken(token))  
      throw SyntaxExc("Unexpected EOF encountered.");  
  
    if(token == "(") parencount++;  
    if(token == ")") parencount--;  
  
    fout << token;  
  } while(parencount > 0);  
  fout << ")";  
}  
  
// Translate a typeof expression.   
void typeof() {  
  string token;  
  string temp;  
  
  fout << "typeid(";  
  
  skipspaces();  
  
  gettoken(token);  
  
  do {  
    temp = token;  
  
    if(!gettoken(token))  
      throw SyntaxExc("Unexpected EOF encountered.");  
    
    if(token != "same") fout << temp;  
  } while(token != "same");  
  
  skipspaces();  
  
  gettoken(token);  
  
  if(token != "as") throw SyntaxExc("as expected.");  
  
  fout << ") == typeid(";  
  
  skipspaces();  
  
  do {  
    if(!gettoken(token))  
      throw SyntaxExc("Unexpected EOF encountered.");  
  
    fout << token;  
  } while(token != ")");  
  fout << ")";  
}  
  
void skipspaces() {  
  char ch;  
  
  do {  
    ch = fin.get();  
  } while(isspace(ch));  
  fin.putback(ch);  
}


listing 2
// Demonstrate the foreach loop. 
#include <iostream> 
using namespace std; 
 
int main() { 
  int nums[] = { 1, 6, 19, 4, -10, 88 }; 
  int min; 
 
  // Find the minimum value. 
  min = nums[0]; 
  foreach(int x in nums) 
    if(min > x) min = x; 
 
  cout << "Minimum is " << min << endl; 
 
  return 0; 
}

listing 3
// Demonstrate all of the experimental features 
// supported by the translator. 
#include <iostream> 
using namespace std; 
 
// Create a polymorphic base class. 
class A { 
public: 
  virtual void f() { }; 
}; 
 
// And a concrete subclass. 
class B: public A { 
public: 
  void f() {} 
}; 
 
int main() { 
  int n[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
  double dn[] = {1.1, 2.2, 3.3, 4.4 }; 
 
  cout << "Using a foreach loop.\n"; 
 
  /* Keywords, such as foreach or typeof 
     are ignored when inside comments 
     or quoted strings. */ 
 
  // A foreach loop. 
  foreach(int x in n ) 
    cout << x << ' '; 
 
  cout << "\n\n"; 
 
  cout << "Using nested foreach loops.\n"; 
 
  // A foreach loop with a block. 
  foreach(double f in dn) { 
    cout << f << ' '; 
    cout << f*f << ' '; 
 
    // A nested foreach loop. 
    foreach(double f in dn)  
      cout << f/3 << " "; 
 
    cout << endl; 
  } 
 
  cout << endl; 
 
  cout << "Demonstrate cases statement.\n"; 
 
  cout << "A cases statement that uses integer constants:\n"; 
 
  // Demonstrate cases statement that uses 
  // integer constants. 
  for(int i=0; i < 12; i++)  
    switch(i) { 
      case 0: 
        cout << "case 0\n"; 
        break; 
      cases 1 to 6: 
        cout << "cases 1 to 6\n"; 
        break; 
      case 7:  
        cout << "case 7\n"; 
        break; 
      cases 8 to 10: 
        cout << "cases 8 to 10\n"; 
        break; 
      default: 
        cout << "case 11\n"; 
    } 
   
  cout << "\n"; 
 
  cout << "A cases statement that uses character constants:\n"; 
 
  // Demonstrate a cases statement that uses 
  // character constants.  
  for(char ch='a'; ch <= 'e'; ch++)  
    switch(ch) { 
      case 'a': 
        cout << "case a\n"; 
        break; 
      cases 'b' to 'd': 
        cout << "cases b to d\n"; 
        break; 
      case 'e':  
        cout << "case e\n"; 
    } 
 
  cout << endl; 
 
  cout << "A repeat/until loop.\n"; 
 
  // Demonstrate a repeat/until loop. 
  int k = 0; 
  repeat { 
    k++; 
    cout << "k: " << k << " "; 
  } until(k==10); 
 
  cout << "\n\n"; 
 
  cout << "Use typeof.\n"; 
 
  // Demonstrate typeof. 
  A *aPtr; 
  B *bPtr, bObj; 
   
  // Assign a base pointer to derived object. 
  aPtr = &bObj; 
  bPtr = &bObj; 
 
  if(typeof *aPtr same as *bPtr) 
    cout << "aPtr points to same type of object as bPtr\n"; 
 
  if(typeof *aPtr same as B) 
   cout << "aPtr points to B object\n"; 
 
  return 0; 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -