Справочное руководство по C++ — страница 37 из 41


name* look(char* p, int ins = 0)

{

 int ii= 0;

 char *pp = p;

 while (*pp) ii = ii‹‹1 ^ *pp++;

 if (ii ‹ 0) ii = -ii;

 ii %= TBLSZ;


 for (name* n=table [ii]; n; n=n-›next)

  if (strcmp(p,n-›string) == 0) return n;


 if (ins == 0) error("name not found");


 name* nn = new name;

 nn-›string = new char[strlen(p) + 1];

 strcpy(nn-›string,p);

 nn-›value = 1;

 nn-›next = table[ii];

 table[ii] = nn;

 return nn;

}


inline name* insert(char* s) { return look (s,1); }


token_value get_token();

double term();


double expr()

{

 double left = term();


 for (;;)

  switch (curr_tok) {

  case PLUS:

   get_token();

   left += term();

   break;

  case MINUS:

   get_token();

   left -= term();

   break;

  default:

   return left;

  }

}


double prim();


double term()

{

 double left = prim();


 for (;;)

  switch (curr_tok) {

  case MUL:

   get_token();

   left *= prim();

   break;

  case DIV:

   get_token();

   double d = prim();

   if (d == 0) return error("divide by 0");

   left /= d;

   break;

  default:

   return left;

  }

}

int number_value;

char name_string[80];


double prim()

{

 switch (curr_tok) {

 case NUMBER:

  get_token();

  return number_value;

 case NAME:

  if (get_token() == ASSIGN) {

   name* n = insert(name_string);

   get_token();

   n-›value = expr();

   return n-›value;

  }

  return look(name_string)-›value;

 case MINUS:

  get_token();

  return -prim();

 case LP:

  get_token();

  double e = expr();

  if (curr_tok != RP) return error(") expected");

  get_token();

  return e;

 case END:

  return 1;

 default:

  return error ("primary expected");

 }

}


token_value get_token()

{

 char ch = 0;


 do {

  if (!cin.get(ch)) return curr_tok = END;

 } while (ch !='\n' && isspace(ch));


 switch (ch) {

 case ';':

 case '\n':

  cin ›› WS;

  return curr_tok=PRINT;

 case '*':

 case '/':

 case '+':

 case '-':

 case '(':

 case ')':

 case '=':

  return curr_tok=ch;

 case '0': case '1': case '2': case '3': case '4':

 case '5': case '6': case '7': case '8': case '9':

 case '.':

  cin.putback(ch);

  cin ›› number_value;

  return curr_tok=NUMBER;

 default:

  if (isalpha(ch)) {

   char* p = name_string;

   *p++ = ch;

   while (cin.get(ch) && isalnum(ch)) *p++ = ch;

   cin.putback(ch);

   *p = 0;

   return curr_tok=NAME;

  }

  error ("bad token");

  return curr_tok=PRINT;

 }

}


int main(int argc, char* argv[])

{

 switch (argc) {

 case 1:

  break;

 case 2:

  cin = *new istream(strlen(argv[1]),argv[1]);

  break;

 default:

  error("too many arguments");

  return 1;

 }


 // insert predefined names:

 insert("pi")-›value = 3.1415926535897932385;

 insert("e")-›value = 2.7182818284590452354;


 while (1) {

  get_token();

  if (curr_tok == END) break;

  if (curr_tok == PRINT) continue;

  cout ‹‹ expr() ‹‹ "\n";

 }


 return no_of_errors;

}

b3_2_6a.cxx

extern void strcpy(char *,char *);

extern void exit(int);

extern int strlen(char *);


char *save_string(char* p)

{

 char* s = new char[strlen(p)+1];

 strcpy(s,p);

 return s;

}


int main (int argc, char* argv[])

{

 if (argc ‹ 2) exit(1);

 int size = strlen(argv[1])+1;

 char* p = save_string (argv[1]);

 delete[size] p;

}

b3_2_6b.cxx

#include ‹stream.hxx›


extern void exit(int);