//6.1
#include<iostream>//I/O
#include<string> //字符串
#include<map> //映射
#include<cctype>//isatpha()
using namespace std;
int no_of_errors;
double error(const string& s)
{
no_of_errors++;
cerr<<"error:";
cerr<<s;
cerr<<"/n";
return 1;
}
enum Token_value
{
NAME,NUMBER,END,PLUS='+',MINUS='-',MUL='*',
DIV='/',PRINT=';',ASSING='=',LP='(',RP=')'
};
Token_value curr_tok=PRINT;
double number_value;
string string_value;
Token_value get_token()
{
char ch;
do{//跳过空白,除了'\n'
if(!cin.get(ch))return curr_tok=END;
}while(ch!='\n'&&isspace(ch));
switch(ch){
case ';':
case '\n':
return curr_tok=PRINT;
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 '.':
cin.putback(ch);
cin>>number_value;
return curr_tok=NUMBER;
default: //NAME,NAME=,或者错误
if(isalpha(ch)){
string_value=ch;
while(cin.get(ch)&&isalnum(ch))
string_value.push_back(ch);
cin.putback(ch);
return curr_tok=NAME;
}
error("bad token");
return curr_tok=PRINT;
}
}
map<string,double> table;
double expr(bool);
double prim(bool get) //处理初等式
{
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()==ASSING)v=expr(true);
return v;
}
case MINUS: //一元
return -prim(true);
case LP:
{double e=expr(true);
if(curr_tok!=RP)return error(") expected");
get_token();
return e;
}
default:
return error("primary expected");
}
}
double term(bool get) //乘和除
{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 expr(bool get) //加和减
{
double left=term(get);
for(;;)
switch(curr_tok){
case PLUS:
left+=term(true);
break;
case MINUS:
left-=term(true);
break;
default:
return left;
}
}
int main()
{
table["pi"]=3.1415926535897932385;
table["e"]=2.7182818284590452354;
while(cin){
get_token();
if(curr_tok==END)break;
if(curr_tok==PRINT)continue;
cout<<expr(false)<<"\n";
}
return no_of_errors;
}