I have a mathematical expression such as cos(pi*cos(pi * sin(pi*y)))
and I want to solve it.
No, you want to evaluate it. Solving tells you the conditions under which something is true. Evaluating it just gives you a resulting value.
I think the best way to parse it is starting by the end of the string.
The traditional way of parsing expressions like this is using recursive descent. It's more general and much easier to implement. The control flow looks something like this:
This is exactly the way the C expression cos(M_PI * cos(M_PI * sin(M_PI * y)))
works (assuming the common but non-standard constant for π).
It is evaluated roughly right-to-left (actually inner-to-outer), but still read left-to-right. We've just labelled the temporary values for clarity.
This control flow is often simply turned into a tree like
[cos of _]
|
[pi * _]
|
[cos of _]
|
[pi * _]
|
[sin of _]
|
[pi * y]
But obviously you can just evaluate the result once unless you need to save the tree for later. (Note this lopsided tree is still a tree, it's just degenerate because of the way your expression is nested).
...What do you think about it?
The problem with your solution is that it breaks for different nesting structures, eg.
cos( sin((pi * x) + y) + sin(y + (pi * x)) )
can't simply be evaluated right-to-left.
Could you help me to implement the code?
Separate the string processing (tokenization) from the parsing and evaluation. It's much easier to reason independently about your string processing and your maths.