Here's an example expression parser I posted here a while back. It doesn't include support for variables or functions, but they could be added fairly easily.
Code:
#include <locale>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
enum TokenType { T_ADD, T_SUBTRACT, T_DIVIDE, T_MULTIPLY, T_NUMBER, T_EOS };
struct token
{
TokenType type;
double value;
};
class Scanner
{
public:
void init(istream* is_)
{
is = is_;
next();
}
token scan()
{
token t;
switch(current)
{
case T_EOS:
case ';':
t.type = T_EOS;
return t;
case '+':
t.type = T_ADD;
next();
return t;
case '-':
t.type = T_SUBTRACT;
next();
return t;
case '*':
t.type = T_MULTIPLY;
next();
return t;
case '/':
t.type = T_DIVIDE;
next();
return t;
default:
if(isdigit(current))
{
t.type = T_NUMBER;
t.value = getNumber();
return t;
}
throw string("invalid token");
}
}
private:
istream *is;
char current;
ostringstream buffer;
void next()
{
if(is->good())
(*is) >> current;
else
current = T_EOS;
}
double getNumber()
{
bool foundDecimal = false;
buffer.str(string());
while((isdigit(current) || current == '.'))
{
if(current == '.')
{
if(foundDecimal)
throw string("malformed number");
foundDecimal = true;
}
buffer << current;
next();
}
return atof(buffer.str().c_str());
}
};
class Parser
{
public:
vector<token> parse(istream* is)
{
scanner.init(is);
tokenSetup = false;
tokens.clear();
next();
expression();
return tokens;
}
private:
Scanner scanner;
vector<token> tokens;
token current, lookAhead;
bool tokenSetup;
void
next()
{
current = lookAhead;
lookAhead = scanner.scan();
if(!tokenSetup)
{
tokenSetup = true;
next();
}
}
void
expression() { additive_expression(); }
void
additive_expression()
{
multiplicative_expression();
while(lookAhead.type == T_ADD || lookAhead.type == T_SUBTRACT)
{
token op = lookAhead;
next(); next();
multiplicative_expression();
tokens.push_back(op);
}
}
void multiplicative_expression()
{
primary_expression();
while(lookAhead.type == T_MULTIPLY || lookAhead.type == T_DIVIDE)
{
token op = lookAhead;
next(); next();
primary_expression();
tokens.push_back(op);
}
}
void primary_expression()
{
if(current.type != T_NUMBER)
throw string("expected number");
tokens.push_back(current);
}
};
double Calculate(string expression)
{
vector<token> tokens;
vector<double> valueStack;
Parser parser;
expression += ";";
istringstream iss(expression);
try
{
tokens = parser.parse(&iss);
}
catch(string err)
{
cerr << "Error: " << err << endl;
return 0;
}
vector<token>::iterator itr = tokens.begin();
for( ; itr != tokens.end(); itr++)
{
token t = *itr;
if(t.type == T_NUMBER)
valueStack.push_back(t.value);
else
{
double lhs, rhs, result;
rhs = valueStack.back();
valueStack.pop_back();
lhs = valueStack.back();
valueStack.pop_back();
switch(t.type)
{
case T_ADD: result = lhs + rhs; break;
case T_SUBTRACT: result = lhs - rhs; break;
case T_MULTIPLY: result = lhs * rhs; break;
case T_DIVIDE: result = lhs / rhs; break;
default: break;
}
valueStack.push_back(result);
}
}
return valueStack.back();
}
int main()
{
string expression, answer;
do
{
cout << "Enter an expression: " << flush;
getline(cin, expression, '\n');
cout << "Value is: " << Calculate(expression) << endl;
cout << "Enter another? (yes/no) " << flush;
getline(cin, answer, '\n');
} while(answer[0] == 'y');
return 0;
}