Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<iostream>
- #include<stack>
- #include<string>
- #include<stdexcept>
- #include<cctype>
- #include<cmath>
- #include<vector>
- #include<utility>
- class functions
- {
- public:
- static const std::string unary_func[];
- static const std::string binary_func[];
- };
- const std::string functions::unary_func[] = {"sin", "cos", "tan", "log", "ln", "sqrt","exp"};
- const std::string functions::binary_func[]={"pow","abs"};
- int precedence(char op)
- {
- if (op=='(' || op == ')')
- return -2;
- else if (op == ',')
- return -1;
- else if (op=='+' || op=='-')
- return 1;
- else if (op=='*' || op=='/' || op == '%')
- return 2;
- return 0;
- }
- std::string modify_str(std::string s)
- {
- std::string s1;
- int len = s.length();
- for (int i = 0;i<len;++i)
- {
- if(s[i] == ' ')
- continue;
- while (!precedence(s[i]) && i<len)
- {
- s1.push_back(std::tolower(s[i++]));
- if (s[i] == ' ')
- break;
- }
- if (s[i] != ' ')
- {
- s1.push_back(' ');
- s1.push_back(s[i]);
- s1.push_back(' ');
- }
- }
- return s1;
- }
- bool check_braces_comma(std::string s)
- {
- int c1 = 0, c2 = 0,len = s.length(), p;
- if (s[len-1] == '(')
- return false;
- for (int i = 0;i<len;++i)
- {
- if (s[i] == '(')
- {
- c1++;
- p = i;
- }
- if (s[i] == ')')
- {
- if (!c1 || i == p+1)
- return false;
- c2++;
- }
- if (!c1 && s[i] == ',')
- return false;
- if (c1 && !p && s[i] == ',')
- return false;
- }
- if (c1 != c2)
- return false;
- return true;
- }
- bool check_operators(std::string s)
- {
- int len = s.length();
- if (s[len-1] != ')' && precedence(s[len-1]))
- return false;
- if (precedence(s[0]) && s[0]!='!' && s[0]!='-' && s[0]!='+' && s[0]!='(' && s[0]!= ')')
- return false;
- int p;
- for (int i = len-1;i >= 0;--i)
- {
- if (s[i] == ')')
- {
- p = i;
- break;
- }
- }
- for (int i = 0;i<len;++i)
- {
- if (s[i] == '(')
- {
- if (s[i+1] == ',')
- return false;
- while (++i != p)
- {
- if (s[i] != '(' && s[i] != ')')
- if (precedence(s[i]) && s[i+1] != '(' && precedence(s[i+1]))
- return false;
- }
- if (i != len-1 && s[i+1] == ',')
- return false;
- }
- if (s[i] != '(' && s[i] != ')' && s[i+1] != '(' && s[i+1] != ')'&& precedence(s[i]) && precedence(s[i+1]))
- return false;
- }
- return true;
- }
- std::string func_type(std::string s)
- {
- static int size=sizeof(functions::binary_func)/sizeof(functions::binary_func[0]);
- for(int i=0;i<size;++i)
- if(s==functions::binary_func[i])
- return "binary";
- return "unary";
- }
- bool is_func(std::string s)
- {
- static int size1=sizeof(functions::unary_func)/sizeof(functions::unary_func[0]);
- for (int i = 0;i<size1;++i)
- if (functions::unary_func[i] == s)
- return true;
- static int size2=sizeof(functions::binary_func)/sizeof(functions::binary_func[0]);
- for (int i = 0;i<size2;++i)
- if (functions::binary_func[i] == s)
- return true;
- return false;
- }
- bool is_dig(char op)
- {
- if(op>='0' && op<='9')
- return true;
- return false;
- }
- bool is_alpha(char op)
- {
- if(op>='a' && op<='z')
- return true;
- return false;
- }
- bool check_functions(std::string s, std::vector<std::pair<std::string, int> > &my_func)
- {
- int len = s.length();
- if (len == 1)
- {
- if (is_alpha(s[0]))
- return false;
- return true;
- }
- for (int i = 0;i<len;++i)
- {
- if (is_alpha(s[i]))
- {
- std::string s1;
- bool flag = false;
- s1.push_back(s[i]);
- while (++i<len)
- {
- if (s[i] == '(')
- {
- flag = true;
- break;
- }
- s1.push_back(s[i]);
- }
- if (!flag)
- return false;
- if (is_func(s1))
- my_func.push_back(std::make_pair(s1,i));
- else
- return false;
- int c = 0, k;
- std::string type=func_type(s1);
- for(k=i+1;k<len-1;++k)
- {
- if(type=="binary" && s[k]==')' && (k+1==len || precedence(s[k+1]>=1)))
- break;
- else if(type=="unary" && s[k]==')')
- break;
- }
- int pos=k;
- k=i;
- while (++k!= pos && k<len)
- {
- if (is_alpha(s[k]))
- while (s[++k] != ')' && k<len);
- if (type=="unary" && s[k] == ',')
- return false;
- else if(type=="binary" && s[k] == ',' && ++c>1)
- return false;
- }
- if (type=="binary" && !c)
- return false;
- }
- }
- return true;
- }
- bool check_syntax(std::string s, std::vector<std::pair<std::string, int> > &my_func)
- {
- return check_braces_comma(s) && check_operators(s) && check_functions(s,my_func);
- }
- void pop_operators(std::string &pf, std::stack<char> &stk)
- {
- while (!stk.empty())
- {
- char t = stk.top();
- if (t != '(')
- pf.push_back(stk.top());
- stk.pop();
- }
- }
- void modify_pf(std::string s,std::string &pf,std::stack<char> &stk, int &i)
- {
- if (s[i] == ')' || s[i]==',')
- {
- pop_operators(pf, stk);
- if(s[i]==',')
- pf.push_back(',');
- }
- else if (precedence(s[i]))
- {
- char op = s[i];
- if (stk.empty())
- stk.push(op);
- else
- {
- char t = stk.top();
- if (precedence(op) <= precedence(t))
- {
- if (t != '(')
- pf.push_back(stk.top());
- stk.pop();
- stk.push(op);
- }
- else
- stk.push(op);
- }
- }
- else
- pf.push_back(s[i]);
- }
- std::string add_spaces(std::string s)
- {
- std::string s1;
- int len=s.length();
- for(int i=0;i<len;++i)
- {
- if(s[i]==' ')
- continue;
- while(i<len && is_alpha(s[i]))
- {
- s1.push_back(s[i++]);
- if(s[i]==' ')
- s1.push_back(' ');
- }
- while(i<len && is_dig(s[i]))
- {
- s1.push_back(s[i++]);
- if(s[i]==' ')
- s1.push_back(' ');
- }
- if(s[i]!=' ' && precedence(s[i]))
- {
- s1.push_back(s[i]);
- s1.push_back(' ');
- }
- if(s[i]=='.')
- s1.push_back('.');
- }
- return s1;
- }
- std::string to_postfix(std::string s)
- {
- std::stack<char> stk;
- std::string pf;
- int len = s.length();
- for (int i = 0;i<len;++i)
- {
- if (s[i] == '(')
- {
- stk.push(s[i]);
- while (s[++i] != ')' && i<len)
- {
- if (s[i] == '(')
- stk.push(s[i]);
- modify_pf(s,pf,stk,i);
- }
- }
- modify_pf(s,pf,stk,i);
- }
- pop_operators(pf, stk);
- return add_spaces(pf);
- }
- std::string eval_func(std::string s,std::vector<std::pair<std::string, int> > &my_func) {}
- double operation(double a, double b, char op)
- {
- switch (op)
- {
- case '+': return a+b;
- case '-': return a-b;
- case '*': return a*b;
- case '/': return a/b;
- case '%': return std::fmod(a, b);
- }
- }
- int to_num(std::string s, int &i, double &n)
- {
- int c = 0;
- while (is_dig(s[i]) && i<s.length())
- {
- c++;
- n = n*10+(s[i++]-48);
- }
- return c;
- }
- double result(std::string s)
- {
- int len = s.length();
- std::stack<double> stk;
- for (int i = 0;i<len;++i)
- {
- if (s[i] == ' ')
- continue;
- double num = 0, k = 0;
- int c = to_num(s, i, num);
- if (s[i] == '.')
- c = -to_num(s, ++i, k);
- num += k*std::pow(10, c);
- if (c)
- stk.push(num);
- if (s[i] != ' ' && precedence(s[i]))
- {
- double a = stk.top();
- stk.pop();
- double b=0;
- if(stk.size()>=1)
- {
- b = stk.top();
- stk.pop();
- }
- stk.push(operation(b, a, s[i]));
- }
- }
- double r = stk.top();
- stk.pop();
- return r;
- }
- std::string remove_spaces(std::string s)
- {
- int len = s.length();
- std::string s1;
- for (int i = 0;i<len;++i)
- {
- if (s[i] == ' ')
- continue;
- s1.push_back(s[i]);
- }
- return s1;
- }
- int main()
- {
- std::string s;
- while (std::getline(std::cin, s))
- {
- try
- {
- if(!s.length())
- throw std::runtime_error("Invalid entry");
- s = remove_spaces(s);
- std::vector<std::pair<std::string, int> > my_func;
- if(!check_syntax(s,my_func))
- throw std::runtime_error("Syntax error");
- std::string infix= modify_str(s);
- std::cout <<"Infix: "<< infix << "\n";
- std::string pf(infix);
- /*if (!my_func.empty())
- pf= eval_func(infix, my_func);*/
- pf = to_postfix(pf);
- std::cout << "Postfix: "<<pf << "\n";
- if(my_func.empty())
- {
- double val = result(pf);
- std::cout << "Result= "<< val << "\n";
- }
- else
- {
- std::cout<<"Function evaluation to be implemented later :P\n";
- }
- }
- catch (const std::exception &e)
- {
- std::cerr<<e.what() << "\n";
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement