Issue #9251 has been updated by duerst (Martin Dürst).

File parse.y added
Status changed from Feedback to Third Party's Issue
Assignee set to pragdave (Dave Thomas)

rits (First Last) wrote:

> Note that I have not asserted that lfs is or should be an expression, so your focus on this is a straw man, the issue is whether it's necessary or desirable to have different precedence rules for the lfs of = than for rhs.

There are no different precedence rules.

> I submit it is neither necessary nor desirable.  a * -b = -c / d should mean (a * -b) = (-c / d) per the spec, and produce an error. That's the path of logic, clarity, simplicity and least surprise. For it to mean a * -(b = (-c / d)) is beyond useless, it's dangerous, will conceal bugs.

The spec isn't in the book. A draft of an "official" spec can be found at http://www.ipa.go.jp/files/000011432.pdf. Other spec-like grammars can be found e.g. at http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/yacc.html or http://www.cse.buffalo.edu/~regan/cse305/RubyBNF.pdf.

The actual spec is given by the implementation, in particular the file parse.y, and by yacc/bison (see e.g. http://www.gnu.org/software/bison/manual/bison.html), which is used to produce executable code from the grammar in parse.y, or in other words by the LALR parser generator algorithm.

Parsing isn't necessarily an easy subject, and the Ruby grammar isn't exactly the simplest of grammars. I have written a strongly simplified grammar, which is attached. This can be run on any system where bison is available; a simple one-liner is:
> bison -v parse.y && gcc parse.tab.c && ./a.out
(use ./a.exe on Cygwin or similar)
The simplified grammar doesn't allow any spaces, and will produce an error on the first newline. But expressions such as a*!b=!c/d; can easily be tried, and the workings of the parser followed ('!' is interpreted as unary minus). Also, a look at the file parse.output (produced by the -v option to bison) will show lots of details about the grammar.

Studying this simple grammar with some examples shows that LALR is capable of figuring out that the restriction on LHS is more 'important' than the priority of operations with higher priority than '='.

The Ruby grammar is in many ways more fluid than most other programming language grammars. The fact that semicolons and parentheses around argument lists are mostly optional is a good example. You seem to have found a corner of the Ruby grammar that can lead to confusion and isn't documented very well. For the moment, I have assigned this issue to Dave, the author of the book you cite, and marked it as "third party" (because the book isn't part of what's tracked here), but I guess there are also ways to improve the documentation inside the Ruby source code.
----------------------------------------
Bug #9251: ! operator has lower precedence than = in an assignment expression
https://bugs.ruby-lang.org/issues/9251#change-43721

Author: rits (First Last)
Status: Third Party's Issue
Priority: Low
Assignee: pragdave (Dave Thomas)
Category: doc
Target version: 
ruby -v: ruby 2.0.0p353 (2013-11-22 revision 43784) [i686-linux]
Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN


irb(main):001:0> !a = 1
(irb):1: warning: found = in conditional, should be ==
=> false
irb(main):002:0> a
=> 1

! is supposed to have higher precedence than =, so !a = 1 should be (!a) = 1, and thus an error, not !(a = 1) 



-- 
http://bugs.ruby-lang.org/