istringstream syntax error question

D

Donald Canton

Hi,

I'm using Bjarne's book to learn C++ and am stuck on the Calc program
in Section 6. Everything works fine except when I try to use
istringstream to parse a token from the command line. I thought I
followed his instructions on page 118 correctly, but I can't get it to
compile without syntax errors in the get_token() function. The whole
program follows with the four syntax errors flagged with the text "//
SYNTAX ERROR". Thanks in advance.

#include <iostream> // I/O
#include <string> // strings
#include <map> // map
#include <cctype> // isalpha(), etc.
#include <sstream> // so that we can use "istringstream"
using namespace std;

istream* input; //pointer to input stream

enum Token_value {
NAME, NUMBER, END,
PLUS='+', MINUS='-', MUL='*', DIV='/',
PRINT=';', ASSIGN='=', LP='(', RP=')'
};

Token_value curr_tok = PRINT;

//function prototypes
map<string, double> table;
double expr(bool);
double term(bool);
double prim (bool);
Token_value get_token();
double error(const string&);

double expr(bool get) //add and subtract
{
double left = term(get);

for (;;) //"forever"
switch (curr_tok) {
case PLUS:
left += term(true);
break;
case MINUS:
left -= term(true);
break;
default:
return left;
}
}

double term(bool get) //multiply and divide
{
double left = prim(get);

for (;;)
switch (curr_tok) {
case MUL:
left *= prim(true);
break;
case DIV:
if (double d = prim(true)) {
left /= d;
break;
}
return error("divide by 0");
default:
return left;
}
}

double number_value;
string string_value;

double prim (bool get) //handle primaries
{
if (get) get_token();

switch (curr_tok) {
case NUMBER:
{ double v = number_value;
get_token();
return v;
}
case NAME:
{ double& v = table[string_value];
if (get_token() == ASSIGN) v = expr(true);
return v;
}
case MINUS: //unary minus
return -prim(true);
case LP:
{ double e = expr(true);
if (curr_tok != RP) return error("')' expected");
get_token(); //eat ')'
return e;
}
default:
return error("primary expected");
}
}

Token_value get_token()
{
char ch;
do { //skip whitespace except '\n'
if (!*input.get(ch)) return curr_tok=END; // SYNTAX ERROR
} while (ch != '\n' && isspace(ch));

switch (ch) {
case ';':
case '\n':
return curr_tok=PRINT;
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=':
return curr_tok=Token_value(ch);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
*input.putback(ch); // SYNTAX ERROR
*input >> number_value;
return curr_tok=NUMBER;
default: //NAME, NAME=, or error
if (isalpha(ch)) {
string_value = ch;
while (*input.get(ch) && isalnum(ch)) // SYNTAX ERROR
string_value.push_back(ch);
*input.putback(ch); // SYNTAX ERROR
return curr_tok=NAME;
}
error("bad token");
return curr_tok=PRINT;
}
}

int no_of_errors;

double error(const string& s)
{
no_of_errors++;
cerr << "error:" << s << '\n';
return 1;
}

int main(int argc, char* argv[])
{
switch (argc) {
case 1:
input = &cin;
break;
case 2:
input = new istringstream(argv[1]);
break;
default:
error("too many arguments");
return 1;
}

table["pi"] = 3.1415926535897932384626433832795; //insert
predefined names
table["e"] = 2.7182818284590452353602874713527;

while (*input) {
get_token();
if (curr_tok==END) break;
if (curr_tok==PRINT) continue;
cout << expr(false) << '\n';
}
if (input != &cin) delete input;
return no_of_errors;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top