Dominik Bathon
8/20/2006 8:08:00 PM
On Sun, 20 Aug 2006 20:37:58 +0200, Jonathan Maasland <nochoice@xs4all.n=
l> =
wrote:
> Dominik Bathon wrote:
>
>>
>> I don't know how to get Ripper working, but depending on what you wan=
t =
>> to do, there might be better solutions like RubyNode or ParseTree.
>>
>> --snip--
>
> It's what we currently use in FreeRIDE and I kinda like the way Ripper=
=
> is used. Currently we only use it to aquire all methods/modules/classe=
s. =
> I guess I could look into working with a different parser but I'd pref=
er =
> Ripper.
Ah okay, I thought you were trying to get Ripper running for the first =
time, for a new project. If you already have code then it might be easie=
r =
to get Ripper working.
Anyway, here is some basic code to get methods and classes with RubyNode=
=
(it's really basic and doesn't work with nested classes, just to get you=
=
started):
Lets say we have this file:
$ cat test.rb
class A
def a
1
end
def b
2
end
end
class B
def c
3
end
end
Then this code:
require "rubynode"
require "pp"
tree =3D IO.read("test.rb").parse_to_nodes.transform
def statements(block_or_single_node)
if block_or_single_node.first =3D=3D :block
block_or_single_node.last
else
[block_or_single_node] # only one statement
end
end
statements(tree).each { |s|
if s.first =3D=3D :class
p s.last[:cpath]
statements(s.last[:body].last[:next]).each { |d|
if d.first =3D=3D :defn
p d.last[:mid]
pp d.last[:defn]
end
}
end
}
outputs:
[:colon2, {:mid=3D>:A, :head=3D>false}]
:a
[:scope,
{:rval=3D>false,
:tbl=3D>nil,
:next=3D>
[:block, [[:args, {:cnt=3D>0, :opt=3D>false, :rest=3D>-1}], [:lit, =
{:lit=3D>1}]]]}]
:b
[:scope,
{:rval=3D>false,
:tbl=3D>nil,
:next=3D>
[:block, [[:args, {:cnt=3D>0, :opt=3D>false, :rest=3D>-1}], [:lit, =
{:lit=3D>2}]]]}]
[:colon2, {:mid=3D>:B, :head=3D>false}]
:c
[:scope,
{:rval=3D>false,
:tbl=3D>nil,
:next=3D>
[:block, [[:args, {:cnt=3D>0, :opt=3D>false, :rest=3D>-1}], [:lit, =
{:lit=3D>3}]]]}]
>> The only thing that RubyNode or ParseTree won't give you are the =
>> comments and whitespace in the code.
>
> That's a bit of a letdown, nothing too serious. Probably easy to work =
=
> around by wrapping the IO-source.
> Do you have any idea as to how memory-intensive either are?
They both wrap Ruby's internal NODEs. ParseTree converts them into =
s-expressions (nested arrays), RubyNode's transform converts them to =
something similar (see above, a mix of arrays and hashes). So they use a=
s =
much memory as their output needs.
If you really want to avoid the transformation to s-expressions then you=
=
can use RubyNodes directly without calling transform (see documentation)=
, =
but that usually shouldn't be necessary.
And btw. if you want to get the nodes without evaling the code then you =
=
currently have to use RubyNode, ParseTree doesn't support that (yet).
Dominik