Precedence Chart

The precedence of operators in expressions is as follows:
        highest precedence:     parenthesis/function/type calls/ternary operator

                                subscripts/slices

                                unary-  unary+  not

                                *  /

                                +  -

                                &

                                <  >  <=  >=  =  !=

                                and  or  xor

        lowest precedence:      { , , , }
 
Thus 2+6*3 means 2+(6*3) rather than (2+6)*3. Operators on the same line have equal precedence and are evaluated left to right.

The equals symbol ('=') used in an assignment statement is not an operator, but just part of the syntax of the language.

Parenthesis is required to mix and, or, and xor in an expression. If, for example, the compiler finds a or b and c it will not assume "(a or b) and c" over "a or (b and c)" (or vice versa) but demands you state exactly which you mean. Most programmers have at one point or another coded something apparently "obvious" such as
    if a and b
    or c and d then
or
    if a or b 
    and c or d then
and then been surprised when (some other) compiler gets it completely wrong, unless they actually meant "(((a and b) or c) and d)", or "(((a or b) and c) or d)", which is what most other compilers will assume. [Python manages quite well on the first, and is probably correct in assuming "(a and b) or (c and d)", but (afaik) it will assume "a or (b and c) or d" for the second case, irrespective of any indentation.]

To avoid this issue, phix simply forces the programmer to supply enough additional explicit parenthesis until everything is completely unambiguous, eg/ie
    if (a and b)
    or (c and d) then
or
    if (a or b)
    and (c or d) then
The higher precedence of not usually means that not a or not b and (not a) or (not b) are equivalent, making the extra parenthesis strictly unnecessary, however I consider it good practice, since it avoids any "oh wait.. is that not (a or not b) or (not a) or (not b)?" moments.

On a related note, "a*(b/c)" and "(a*b)/c" are mathematically equivalent, however precision limits of the physical hardware may mean they give very different results, especially for partial results that approach or exceed the floating point hardware limits. In practice the compiler treats "a*b/c" as "(a*b)/c", however in general that is an implementation detail that should not be overly relied on - if one day some bright spark invented a safe and simple method to automatically minimise precision loss in the un-parenthesised case, I would take it.

Other programming languages may have subtle differences in precedence. For instance, in Python 'or' has a lower precedence than 'and', so take that into account when translating some Python code and Phix starts demanding extra parenthesis. In Python the 'not' operator has a lower precedence than '+', so idx + not flag + offset is treated as idx + not (flag + offset), quite unlike the Phix interpretation which is idx + (not flag) + offset. My recommendation is to use as much parenthesis as you can bear, and when it gets too much that is as good an excuse as any to break the expression down into more manageable pieces. Besides, storing partial results in appropriately named variables can not only make the intent much clearer but also make debugging significantly easier and faster, and does not normally incur any additional penalty whatsoever over the hidden unnamed temporary variable that the compiler would otherwise use anyway.