1. 计算器所接受的语言的语法:
program:
END: //END表示输入结束
expr_list END
expr_list:
expression PRINT //PRINT是分号
expression PRINT expr_list
expression:
expression + term
expression - term
term:
term / primary
term * primary
primary
primary:
NUMBER
NAME
NAME = expression
-primary
(expression)
2. 实现代码:
#include<iostream>
#include<string>
#include<map>
#include<cctype>
using namespace std;
map<string,double>table;
enum Token_value{
NAME, NUMBER, END,
PLUS='+', MINUS='-', MUL='*', DIV='/',
PRINT=';', ASSIGN='=', LP='(', RP=')'
};
Token_value curr_tok = PRINT;
double number_value;
string string_value;
int no_of_errors;
double error(const string&);
Token_value get_token();
double prim(bool);
double term(bool);
double expr(bool);
double error(const string&s)
{
no_of_errors++;
cerr<<"error:"<<s<<'\n';
return 1;
}
Token_value get_token()
{
char ch = 0;
do{
if(!cin.get(ch))
return curr_tok = END;
}while(ch != '\n' && isspace(ch));
switch(ch){
case 0:
return curr_tok = END;
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'.':
cin.putback(ch);
cin>>number_value;
return curr_tok = NUMBER;
default:
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;
}
}
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() == ASSIGN)
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;
}
}
}
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;
}
3. 结果演示:
注:
1. 参考C++程序设计语言(c++之父的经典之作)
2. 退出程序:[enter] Ctrl+Z [enter]