%begin

!
! Precedence of operators
!
! Highest: 1. \ (complement, unary not)
!          2. \, \\, <<, >>
!          3. *, /, //, &
! Lowest:  4. +, - (unary and binary), !, !!
!
! In general, sub-expressions with operators of equal precedence are evaluated from left to right.
!
! The one exception to the left-hand precedence rule is that consecutive
! exponentiations are evaluated from right to left; thus A**B**C is
! evaluated as A**(B**C), not as (A**B)**C.  (Imp80 documentation)

! Arithmetic operators:

! |...| modulus              also: !...!  (deprecated some time ago)

! !  inclusive or
! !! exclusive or
! &  and

! \  real exponentiation     also:  ^  (Imp77)  or  **    (ERCC compilers)
! \\ integer exponentiation  also:  ^^ (Imp77)  or  ****

! *  multiply
! /  real division
! // integer division

! << left shift
! >> right shift

! +  plus
! -  minus

! +  unary +                 
! -  unary -
! \  unary not               also ~ (can be *displayed* as: ¬ (&not;))

! .  string concatenation

! Comparison operators:
! =  eq
! #  not equals              also \= and <> (Imp80 documentation)
! == address equals
! ## address not equals      also \==
! -> string resolution       (a difficult to classify hybrid of a comparison and an assignment operator)
! <= less than or equals
! <  less than
! >= greater than or equals
! >

! Assignment operators:
! =  assignment
! == pointer assignment
! <- jam transfer
! -> string resolution

! Data structure operators:
! _  record field
! () array indexing
! [] pointer increment       (a Hamish extension in 68000 Imp only)

! Other:
! @  may be considered an operator in %real literals, usually handled by a BIP.


  %const %integer a = 19, b = 17, c = 5, d = 3
  %integer x = a * b // c * d
  print string("Imp77 precedence and associativity test."); newlines(2)
  %if x = 21 %start
    print string("In a * b // c * d, '*' has higher priority than '/'."); newline
    print string("A second test with '/' will be needed to determine associativity:"); newline
    x = a // c // d
    %if x = 1 %start
      print string("a // c // d is right associative, i.e. a // (b // c)"); newline
    %else %if x = 19
      print string("a // c // d is left associative, i.e. (a // b) // c"); newline
    %else
      print string("a // c // d is something weird!  I give up."); newline
    %finish
  %else %if x = 19
    print string("a * b // c * d is right associative and with equal precedence, i.e. a * (b // (c * d))"); newline
    newline
    print string("This grammar would support the above:"); newline
    newline
    print string("P<expr> = <term> <op-term-list> ;"); newline
    print string("P<op-term-list> = <op-term> <op-term-list> | ;"); newline
    print string("P<op-term> = <op> <term> ;"); newline
  %else %if x = 192
    print string("a * b // c * d is left associative and with equal precedence, i.e. ((a * b) // c) * d"); newline
    newline
    print string("This grammar would support the above:"); newline
    newline
    print string("P<expr> = <term-op-list> <term> ;"); newline
    print string("P<term-op-list> = <term-op> <term-op-list> | ;"); newline
    print string("P<term-op> = <term> <op> ;"); newline
  %else
    print string("a * b // c * d uses some weird non-standard combination of precedence and associativity!"); newline
  %finish
  newline


  %const %integer p = 4, q = 3, r = 2
  %integer y

  y = p ^^ q ^^ r

  %if y = 262144 %start
    print string("p ^^ q ^^ r is right associative, i.e. p ^^ (q ^^ r)"); newline
    newline
    print string("This grammar would support the above:"); newline
    newline
    print string("P<expr> = <term> <exp-term-list> ;"); newline
    print string("P<exp-term-list> = <exp-term> <exp-term-list> | ;"); newline
    print string("P<exp-term> = ""^^"" <term> ;"); newline
  %else %if y = 4096
    print string("p ^^ q ^^ r is left associative, i.e. (p ^^ q) ^^ r"); newline
    newline
    print string("This grammar would support the above:"); newline
    newline
    print string("P<expr> = <term-exp-list> <term> ;"); newline
    print string("P<term-exp-list> = <term-exp> <term-exp-list> | ;"); newline
    print string("P<term-exp> = <term> ""^^"" ;"); newline
  %else
    print string("p ^^ q ^^ r is something weird! ("); write(y, 0); print string(") - I give up."); newline
  %finish
  newline

! The remaining issue to be checked is how left/right associativity interact when the precedence is the same,
! which is only the case for exponentiation and shifts together, eg
!
! a << b << c ^^ d ^^ e   or   a ^^ b ^^ c >> d >> e
!

%endofprogram
