Perhaps this will explain it better. Take a look at the following line:
Code:
result = a() * b() + c() * d();
Precedence rules tell us that the parse tree looks like this:
Code:
+
/ \
* *
/ \ / \
a() b() c() d()
instead of for example this:
Code:
*
/ \
a() +
/ \
b() *
/ \
c() d()
However you don't know what order a(), b(), c() and d() will be called. That's evaluation, not precedence.
It could call c() then d(), then do the second *, then call a, then b, then do the first *, then do the +. If the functions a, b, c, and d all make certain modifications to a global variable and then return the current value of that global variable for example, then different evaluation orders would produce different results.
However, no compiler would be allowed to generate the second parse tree I showed as it has incorrect precedence rules applied to it. Only using brackets could allow such a parse tree to result.