Start with a simple grammar:
expr: n-expr {o-expr} | p-expr {o-expr} n-expr: [0-9]n-expr p-expr: ( expr ) o-expr: op expr op: + | - | * | /
This is probably the biggest hurdle to the question. You want to write a simple reverse down parser, so your grammar needs to be written for this to happen.
Then the implementation from there is quite simple:
bool expr (const char *&s, int &result, int eos = 0) { while (isspace(*s)) ++s; if (*s == eos) return false; if (isdigit(*s)) { if (!n_expr(s, result)) return false; } else if (*s == '(') { if (!p_expr(s, result)) return false; } else return false; while (isspace(*s)) ++s; if (*s == eos) return true; return o_expr(s, result, eos); } bool n_expr (const char *&s, int &result) { int n = 0; while (isdigit(*s)) n = 10 * n + (*s++ - '0'); result = n; return true; } bool p_expr (const char *&s, int &result) { if (expr(++s, result, ')')) { ++s; return true; } return false; } bool o_expr (const char *&s, int &result, int eos) { int oresult = 0; const char *op = strchr("+-*/", *s); if (op == 0) return false; if (!expr(++s, oresult, eos)) return false; switch (*op) { case '+': result += oresult; break; case '-': result -= oresult; break; case '*': result *= oresult; break; case '/': result /= oresult; break; default: return false; } return true; }
source share