Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Obscure syntax error

Reply
Thread Tools

Obscure syntax error

 
 
Rolf Timmermans
Guest
Posts: n/a
 
      01-17-2011
Hi all,

Today I came across a very strange scenario that raises a syntax error =
in pretty much all Ruby implementations. I have absolutely no =
explanation for the following behaviour:

x :y
#=3D> bar.rb:1:in `<main>': undefined method `x' for main:Object =
(NoMethodError)

x =3D nil
x "y"
#=3D> bar.rb:2:in `<main>': undefined method `x' for main:Object =
(NoMethodError)

x =3D nil
x :y
#=3D> bar.rb:2: syntax error, unexpected ':', expecting $end

Why does that latter case raise a syntax error during parsing? Why would =
this be invalid Ruby? Why is it only invalid when supplying a symbol =
argument, and why only when the local variable with the same name is =
already defined? I would expect all three examples above to be run and =
abort with a NoMethodError.

The behaviour is consistent in Rubinius, JRuby, Ruby 1.9 and Ruby 1.8. =
What's going on, does anyone know?


Kind regareds,

Rolf Timmermans


 
Reply With Quote
 
 
 
 
Peter Hickman
Guest
Posts: n/a
 
      01-17-2011
The format

x ...followed by something else...

means that x is a method and anything that follows it is a parameter.
Since you don't have a method called x you get "undefined method `x'"
just like it says in the error message.

When x is a reference to a variable by itself it just returns its
value, but when you put a parameter after it it looks for a method
called x, because you are passing it a parameter "y" and the only
things you pass parameters to are methods so you get the "undefined
method `x'" message again.

In the final case again you have no method called x and therefore a
parameter, in this case the :y, is unexpected. In that you don't pass
parameters to a variable only to methods.

It's good that you checked it out in all the various implementations
of Ruby but the error message was quite clear, "undefined method `x'"
means that Ruby thinks x should be a method but you don't have a
method x defined.

 
Reply With Quote
 
 
 
 
Alex Gutteridge
Guest
Posts: n/a
 
      01-17-2011
On Mon, 17 Jan 2011 20:02:58 +0900, Peter Hickman wrote:
> The format
>
> x ...followed by something else...
>
> means that x is a method and anything that follows it is a parameter.
> Since you don't have a method called x you get "undefined method `x'"
> just like it says in the error message.
>
> When x is a reference to a variable by itself it just returns its
> value, but when you put a parameter after it it looks for a method
> called x, because you are passing it a parameter "y" and the only
> things you pass parameters to are methods so you get the "undefined
> method `x'" message again.
>
> In the final case again you have no method called x and therefore a
> parameter, in this case the :y, is unexpected. In that you don't pass
> parameters to a variable only to methods.


I think Rolf's point is that in *both* of those last two cases there is
no method called x - the only difference being that in the first case he
tries to pass a string to the non-existent method in the second a
symbol. So why is the first (correctly) throwing a NoMethodError and the
second gives a *syntax* error?

--
Alex Gutteridge

 
Reply With Quote
 
Jesús Gabriel y Galán
Guest
Posts: n/a
 
      01-17-2011
On Mon, Jan 17, 2011 at 12:02 PM, Peter Hickman
<(E-Mail Removed)> wrote:
> The format
>
> x ...followed by something else...
>
> means that x is a method and anything that follows it is a parameter.
> Since you don't have a method called x you get "undefined method `x'"
> just like it says in the error message.
>
> When x is a reference to a variable by itself it just returns its
> value, but when you put a parameter after it it looks for a method
> called x, because you are passing it a parameter "y" and the only
> things you pass parameters to are methods so you get the "undefined
> method `x'" message again.
>
> In the final case again you have no method called x and therefore a
> parameter, in this case the :y, is unexpected. In that you don't pass
> parameters to a variable only to methods.
>
> It's good that you checked it out in all the various implementations
> of Ruby but the error message was quite clear, "undefined method `x'"
> means that Ruby thinks x should be a method but you don't have a
> method x defined.


What I don't understand is the difference between x "y" and x :y

irb(main):001:0> x = nil
=> nil
irb(main):002:0> x "y"
NoMethodError: undefined method `x' for main:Object
from (irb):2
from :0
irb(main):003:0> x :y
SyntaxError: compile error
(irb):3: syntax error, unexpected ':', expecting $end
from (irb):3
from :0

Why the second case is not a NoMethodError too?

Jesus.

 
Reply With Quote
 
Peter Hickman
Guest
Posts: n/a
 
      01-17-2011
Well, and I have to admit I am guessing here, the source is parsed in
the context of the code that precedes it. So 'x :y' is parsed when
nothing (no method or variable) called x exists so the parser is
thinking that x should be a method, because it has not been told
otherwise and the :y makes sense as a parameter to a method.

In the case of 'x = nil; x :y' the 'x = nil' means that we now have
something defined for x (a variable) which the parser can then take
into account when it gets to 'x :y'. Whereas before with 'x :y' it
assumes that x is a method because x has not been defined. But with 'x
= nil; x :y' we know that x is a variable and the parser no longer
assumes that x is a method and tries to make sense of 'a variable'
followed by 'a symbol'. Which make no sense, thus the error.

I don't know if this is the case as I do not routinely browse the Ruby
parser code but from what I know this makes sense - even if I may not
have explained it clearly.

 
Reply With Quote
 
Rolf Timmermans
Guest
Posts: n/a
 
      01-17-2011
On Jan 17, 2011, at 12:19 , Alex Gutteridge wrote:

> I think Rolf's point is that in *both* of those last two cases there =

is no method called x - the only difference being that in the first case =
he tries to pass a string to the non-existent method in the second a =
symbol. So why is the first (correctly) throwing a NoMethodError and the =
second gives a *syntax* error?

Exactly. And to be entirely clear, the fact that the method does not =
exist doesn't even matter. If the method does exist, the same syntax =
error is raised if the first argument is a symbol. And when using =
parentheses, no syntax error occurs...

Compare:

def x(*args); end
x :y
# No error

def x(*args); end
x =3D nil
x "y"
# No error

def x(*args); end
x =3D nil
x :y
# foo.rb:3: syntax error, unexpected ':', expecting $end

def x(*args); end
x =3D nil
x(:y)
# No error

def x(*args); end
x =3D nil
x :y, "z"
# foo.rb:3: syntax error, unexpected ':', expecting $end

def x(*args); end
x =3D nil
x "y", :z
# No error


Kind regards,

Rolf Timmermans


 
Reply With Quote
 
Colin Bartlett
Guest
Posts: n/a
 
      01-17-2011
On Mon, Jan 17, 2011 at 12:39 PM, Rolf Timmermans <(E-Mail Removed)> wrote:
> ...
> Exactly. And to be entirely clear, the fact that the method does not exist doesn't even matter.
> If the method does exist, the same syntax error is raised if the first argument is a symbol.
> And when using parentheses, no syntax error occurs
> ...
> def x(*args); end
> x :y
> # No error
>
> def x(*args); end
> x = nil
> x :y
> # foo.rb:3: syntax error, unexpected ':', expecting $end
>
> def x(*args); end
> x = nil
> x(:y)
> # No error


I don't have an explanation for why using the symbol gives a
SyntaxError rather than a NoMethodError, but the above three of your
new examples seem to me to be the key examples, together with maybe
the following on Ruby1.9.1. Note that using "eval" with x not being
defined as a variable also raises a SyntaxError.

## two types of error message:
## NoMethodErr === #<NoMethodError: undefined method `x' for main:Object>
## SyntaxErr === #<SyntaxError: syntax error, unexpected ':', expecting ')'
y = nil
puts "** not eval; defined?( x ) #=> #{defined?( x ).inspect}"
(x :y) rescue (p $!) # NoMethodErr
(x 'y') rescue (p $!) # NoMethodErr
(x y) rescue (p $!) # NoMethodErr

puts "** eval; defined?( x ) #=> #{defined?( x ).inspect}"
begin; eval "(x :y)"; rescue SyntaxError; p $!; end # SyntaxErr
eval "(x 'y')" rescue (p $!) # NoMethodErr
eval "(x y)" rescue (p $!) # NoMethodErr

 
Reply With Quote
 
Ryan Davis
Guest
Posts: n/a
 
      01-17-2011

On Jan 17, 2011, at 02:25 , Rolf Timmermans wrote:

> x =3D nil
> x "y"
> #=3D> bar.rb:2:in `<main>': undefined method `x' for main:Object =

(NoMethodError)
>=20
> x =3D nil
> x :y
> #=3D> bar.rb:2: syntax error, unexpected ':', expecting $end


I think the explanation is simple: you (most likely) found a bug in the =
parser.

You should report this to ruby-core@


 
Reply With Quote
 
Abinoam Jr.
Guest
Posts: n/a
 
      01-17-2011
> I think the explanation is simple: you (most likely) found a bug in the parser.
>
> You should report this to ruby-core@


In my humble opinion I think it's even simpler than that.
Sorry if I'm wrong, but...

If you have an object (expression returning an object reference) what
are the syntactic constructs allowed after that?

When the variable is not defined the parser can think that it is a
method name (an undefined method error) and the "Symbol" is an
argument. But, when it is defined, it returns an object, and the colon
is not allowed syntactically in this context.
I just couldn't figure out why using constants renders different behavior.

Look

nil is an object.

Try this:

nil:y
nil :y
nil: y
nil : y
nil : y

class A; end
a = A.new

a:y
a :y
a: y
a : y

A:y (No Method)
A :y (No Method)
A: y
A : y

Only "A:y" and "A :y" raises a Method error. The others, all of them
raises Syntax error.
(tested against ruby 1.9).

Abinoam Jr.

 
Reply With Quote
 
Ryan Davis
Guest
Posts: n/a
 
      01-18-2011

On Jan 17, 2011, at 14:56 , Abinoam Jr. wrote:

>> I think the explanation is simple: you (most likely) found a bug in =

the parser.
>>=20
>> You should report this to ruby-core@

>=20
> In my humble opinion I think it's even simpler than that.
> ...
> If you have an object (expression returning an object reference) what
> are the syntactic constructs allowed after that?


A symbol should be allowed anywhere any other literal is allowed.

> % echo 'x =3D nil; x "y"' | ruby -c
> Syntax OK
> % echo 'x =3D nil; x :y' | ruby -c
> -:1: syntax error, unexpected ':', expecting $end
> % echo 'x =3D nil; x :"y"' | ruby -c
> -:1: syntax error, unexpected ':', expecting $end




 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
obscure coding error thedarkman HTML 5 04-25-2012 01:10 PM
Obscure baffling "module not exported" error: can someone help mefind the cause? Henry Law Perl Misc 4 01-31-2008 11:39 PM
Syntax error? What syntax error? Assignment fo default values? Mark Richards Perl Misc 3 11-18-2007 05:01 PM
Drag select speed (most obscure bug ever?) zeeeej Firefox 1 04-24-2006 09:44 AM
Obscure Syntax tw2035@googlemail.com C++ 2 04-02-2006 01:01 PM



Advertisments