[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Specifying Binary and Unary Operator Precedence



Patrick's suggestion should work. I have another suggestion too.

Patrick LAM wrote:
I get the shift-reduce with
(stack) r ! E
M -> r E s
E -> E (.) [ E ] |
      ! E (.)          // => followed by [

The problem is that you are mixing a left unary operator and a right unary operator at the same precedence level.

e.g.
  ++a  => ++ is a left unary operator (takes *one* argument)
  a++  => ++ is a right unary operator (takes *one* argument)

When you specify precedence [using one production (with alternatives) to
encode this precedence], you should follow rigorously the following
guidelines:

1- Unary operators and binary operators must not share the same precedence
   level.
2- Left and right unary operators must not share the same precedence level.
3- All unary operators must have a higher precedence than any binary
   operator.
4- Left-associative and right-associative binary operators must not share
   the same precedence level.

If you do not follow guidelines 1, 2, and 4, you will get conflicts (as the
grammar will be ambiguous).  If you do not follow guideline 3, you will
modify the *language* described by the grammar (in other words, seemingly
valid sentences will be rejected by the parser).


So, another solution to your problem is to give distinct precedence level to the left unary operator "!" and to the right unary operator "[...]".

E.g. if you want to give higher precedence to "!" over "[...]" you would
write:

E =
  E [ E ] |
  higher_E;

higher_E =
  ! higher_E |
  term;

term =
  anything_that_does_not_start_or_end_with_E |
  again |
  ...;


If you have binary operators, they MUST have a lower precedence. e.g.:


E =
  E    some_lassoc_binop higher_E |
  E another_lassoc_binop higher_E |
  higher_E;

higher_E =
  evenhigher_E    some_rassoc_binop higher_E |
  evenhigher_E another_rassoc_binop higher_E |
  evenhigher_E;

evenhigher_E =
  evenhigher_E yetanother_lassoc_binop lunary_E |
  lunary_E;

lunary_E =
  ! lunary_E |
  runary_E;

runary_E =
  runary_E [ E ] |
  term;


Have fun!


Etienne

--
Etienne M. Gagnon, Ph.D.             http://www.info.uqam.ca/~egagnon/
SableVM:                                       http://www.sablevm.org/
SableCC:                                       http://www.sablecc.org/