On this page
article
Parsing de Expressao
Sobre
Operacoes associativas a esquerda por default
Para mudar isso, colocar em r_assoc
Operacoes com maior prioridade sao feitas primeiro
Link original: parsing.cpp
Código
bool blank(char c) {
return c == ' ';
}
bool is_unary(char c) {
return c == '+' or c == '-';
}
bool is_op(char c) {
if (is_unary(c)) return true;
return c == '*' or c == '/' or c == '+' or c == '-';
}
bool r_assoc(char op) {
// operator unario - deve ser assoc. a direita
return op < 0;
}
int priority(char op) {
// operator unario - deve ter precedencia maior
if (op < 0) return INF;
if (op == '*' or op == '/') return 2;
if (op == '+' or op == '-') return 1;
return -1;
}
void process_op(stack<int>& st, stack<int>& op) {
char o = op.top(); op.pop();
if (o < 0) {
o *= -1;
int l = st.top(); st.pop();
if (o == '+') st.push(l);
if (o == '-') st.push(-l);
} else {
int r = st.top(); st.pop();
int l = st.top(); st.pop();
if (o == '*') st.push(l * r);
if (o == '/') st.push(l / r);
if (o == '+') st.push(l + r);
if (o == '-') st.push(l - r);
}
}
int eval(string& s) {
stack<int> st, op;
bool un = true;
for (int i = 0; i < s.size(); i++) {
if (blank(s[i])) continue;
if (s[i] == '(') {
op.push('(');
un = true;
} else if (s[i] == ')') {
while (op.top() != '(') process_op(st, op);
op.pop();
un = false;
} else if (is_op(s[i])) {
char o = s[i];
if (un and is_unary(o)) o *= -1;
while (op.size() and (
(!r_assoc(o) and priority(op.top()) >= priority(o)) or
(r_assoc(o) and priority(op.top()) > priority(o))))
process_op(st, op);
op.push(o);
un = true;
} else {
int val = 0;
while (i < s.size() and isalnum(s[i]))
val = val * 10 + s[i++] - '0';
i--;
st.push(val);
un = false;
}
}
while (op.size()) process_op(st, op);
return st.top();
}