#include "expression.h"
expression::expression(string _expression_)
{
expression_ = _expression_;
}
expression::~expression()
{
}
/*--------------------------------词法分析常量----------------------------*/
int expression::word_analysis()
{
for (int i = 0; i < expression_.length(); ++i)
{
// 如果是 + - * / ( )
if (expression_[i] == '(' || expression_[i] == ')' || expression_[i] == '+'
|| expression_[i] == '-' || expression_[i] == '*' || expression_[i] == '/')
{
string tmp;
tmp.push_back(expression_[i]);
switch (expression_[i])
{
case '+':
word.push_back(make_pair(tmp, 1));
break;
case '-':
word.push_back(make_pair(tmp, 2));
break;
case '*':
word.push_back(make_pair(tmp, 3));
break;
case '/':
word.push_back(make_pair(tmp, 4));
break;
case '(':
word.push_back(make_pair(tmp, 6));
break;
case ')':
word.push_back(make_pair(tmp, 7));
break;
}
}
// 如果是数字开头
else if (expression_[i] >= '0' && expression_[i] <= '9')
{
string tmp;
while (expression_[i] >= '0' && expression_[i] <= '9')
{
tmp.push_back(expression_[i]);
++i;
}
if (expression_[i] == '.')
{
++i;
if (expression_[i] >= '0' && expression_[i] <= '9')
{
tmp.push_back('.');
while (expression_[i] >= '0' && expression_[i] <= '9')
{
tmp.push_back(expression_[i]);
++i;
}
}
else
{
return -1; // .后面不是数字,词法错误
}
}
word.push_back(make_pair(tmp, 5));
--i;
}
// 如果以.开头
else
{
return -1; // 以.开头,词法错误
}
}
return 0;
}
/*--------------------------------词法分析变量----------------------------*/
int expression::word_analysis_var()
{
for (int i = 0; i < expression_.length(); ++i)
{
// 如果是 + - * / ( )
if (expression_[i] == '(' || expression_[i] == ')' || expression_[i] == '+'
|| expression_[i] == '-' || expression_[i] == '*' || expression_[i] == '/')
{
string tmp;
tmp.push_back(expression_[i]);
switch (expression_[i])
{
case '+':
word.push_back(make_pair(tmp, 1));
break;
case '-':
word.push_back(make_pair(tmp, 2));
break;
case '*':
word.push_back(make_pair(tmp, 3));
break;
case '/':
word.push_back(make_pair(tmp, 4));
break;
case '(':
word.push_back(make_pair(tmp, 6));
break;
case ')':
word.push_back(make_pair(tmp, 7));
break;
}
}
// 如果是字幕开头
else
{
string tmp;
while (expression_[i] == '0' || (expression_[i] >= 'a' && expression_[i] <= 'z'))
{
tmp.push_back(expression_[i]);
++i;
}
word.push_back(make_pair(tmp, 5));
--i;
}
}
return 0;
}
/*--------------------------------语法分析----------------------------*/
// 读下一单词的种别编码
void expression::Next()
{
if (idx < word.size())
sym = word[idx++].second;
else
sym = 0;
}
// E → T { +T | -T }
void expression::E()
{
T();
while (sym == 1 || sym == 2)
{
Next();
T();
}
}
// T → F { *F | /F }
void expression::T()
{
F();
while (sym == 3 || sym == 4)
{
Next();
F();
}
}
// F → (E) | d
void expression::F()
{
if (sym == 5)
{
Next();
}
else if (sym == 6)
{
Next();
E();
if (sym == 7)
{
Next();
}
else
{
err = -1;
}
}
else
{
err = -1;
}
}
// 获取运算符的优先级
int expression::prior(int sym)
{
switch (sym)
{
case 1:
case 2:
return 1;
case 3:
case 4:
return 2;
default:
return 0;
}
}
// 通过 种别编码 判定是否是运算符
bool expression::isOperator(int sym)
{
switch (sym)
{
case 1:
case 2:
case 3:
case 4:
return true;
default:
return false;
}
}
// 中缀转后缀
vector<pair<string, int>> expression::getPostfix(const vector<pair<string, int>>& expr)
{
vector<pair<string, int>> output; // 输出
stack<pair<string, int>> s; // 操作符栈
for (int i = 0; i<expr.size(); ++i)
{
pair<string, int> p = expr[i];
if (isOperator(p.second))
{
while (!s.empty() && isOperator(s.top().second) && prior(s.top().second) >= prior(p.second))
{
output.push_back(s.top());
s.pop();
}
s.push(p);
}
else if (p.second == 6)
{
s.push(p);
}
else if (p.second == 7)
{
while (s.top().second != 6)
{
output.push_back(s.top());
s.pop();
}
s.pop();
}
else
{
output.push_back(p);
}
}
while (!s.empty())
{
output.push_back(s.top());
s.pop();
}
return output;
}
// 从栈中连续弹出两个操作数
void expression::popTwoNumbers(stack<double>& s, double& first, double& second)
{
first = s.top();
s.pop();
second = s.top();
s.pop();
}
// 把string转换为double
double expression::stringToDouble(const string& str)
{
double d;
stringstream ss;
ss << str;
ss >> d;
return d;
}
// 计算后缀表达式的值
double expression::expCalculate(const vector<pair<string, int>>& postfix)
{
double first, second;
stack<double> s;
for (int i = 0; i<postfix.size(); ++i)
{
pair<string, int> p = postfix[i];
switch (p.second)
{
case 1:
popTwoNumbers(s, first, second);
s.push(second + first);
break;
case 2:
popTwoNumbers(s, first, second);
s.push(second - first);
break;
case 3:
popTwoNumbers(s, first, second);
s.push(second*first);
break;
case 4:
popTwoNumbers(s, first, second);
try
{
if (fabs(first - 0) < 0.000001)
throw - 1;
}
catch (int e) {
std::cerr << "attempt to divide integer by 0." << std::endl;
system("pause");
exit(1);
}
s.push(second / first);
break;
default:
s.push(stringToDouble(p.first));
break;
}
}
double result = s.top();
s.pop();
return result;
}