[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

meta_parse: my first metaprogram

Edgardo Hames

2/19/2006 5:54:00 PM

Hi guys,

After messing up with racc for a couple of hours I realized that most of the
parse functions look pretty much the same, so I thought of stretching my
metaprogramming muscles and I wrote my first meta_parse function.

require 'strscan'

def meta_parse(*ary)
case_str = <<ENDSTRING
def parse(str)
@q = []
scanner = StringScanner.new str
until scanner.empty?
case
ENDSTRING

ary.each do |type, exp, meth|
if meth
case_str << " when m = scanner.scan(#{exp}) ; @q << [:#{type},
m.#{meth}]\n"
else
case_str << " when m = scanner.scan(#{exp}) ; @q << [:#{type},
m]\n"
end
end

case_str <<<<END_STRING
end
end
@q << [false,false]
do_parse
end
END_STRING
eval case_str
end

Here is a usage example:

meta_parse [:A, '/a/'], [:NUMBER, '/\d+/', :to_i], [:WS, '/(\s|\t)+/']
parse("a aaa 12132 ").each{|type,val| puts "#{type}: '#{val}'"}

I would like to hear your comments on it, but please be gentle ;-)

Cheers,
Ed
--
Encontrá a "Tu psicópata favorito" http://tuxmaniac.bl...

Thou shalt study thy libraries and strive not to reinvent them without
cause,
that thy code may be short and readable and thy days pleasant and
productive.
-- Seventh commandment for C programmers
3 Answers

Erik Veenstra

2/19/2006 6:36:00 PM

0

> After messing up with racc for a couple of hours I realized
> that most of the parse functions look pretty much the same,
> so I thought of stretching my metaprogramming muscles and I
> wrote my first meta_parse function.
>
> I would like to hear your comments on it, but please be
> gentle ;-)

I usually try to avoid those inline strings. I don't like them.
As long as you don't pass a block in the call to the
dynamically defined method, you can use "define_method"
instead. I moved a bit of code and came up with the code below.

(Next time, please provide runnable code... )

gegroet,
Erik V. - http://www.erikve...

----------------------------------------------------------------

require 'strscan'

def meta_parse(*ary)
self.class.module_eval do
define_method :parse do |str|
@q = []
scanner = StringScanner.new(str)
until scanner.empty?
ary.each do |type, exp, meth|
if m = scanner.scan(exp)
@q << [type, (meth ? m.send(meth) : m)]
end
end
end
@q << [false,false]
do_parse
end
end
end

def do_parse
p $q
@q
end

meta_parse [:A, /a/], [:NUMBER, /\d+/, :to_i], [:WS, /(\s|\t)+/]
parse("a aaa 12132 ").each{|type,val| puts "#{type}: '#{val}'"}

----------------------------------------------------------------

David Vallner

2/19/2006 6:52:00 PM

0

> I usually try to avoid those inline strings. I don't like them.
> As long as you don't pass a block in the call to the
> dynamically defined method, you can use "define_method"
> instead.
>

Seconded, metaprogramming code like that will get a major performance hit if
you whack YARV at it. Unless there's a shaman embedding voodoo chants into
YARV code for optimization of variable evals.

(Sidenote: it seems #eval is slightly faster than #define_method in trivial
benchmarks.)

David Vallner


Christian Neukirchen

2/19/2006 7:55:00 PM

0

"Erik Veenstra" <google@erikveen.dds.nl> writes:

>> After messing up with racc for a couple of hours I realized
>> that most of the parse functions look pretty much the same,
>> so I thought of stretching my metaprogramming muscles and I
>> wrote my first meta_parse function.
>>
>> I would like to hear your comments on it, but please be
>> gentle ;-)
>
> I usually try to avoid those inline strings. I don't like them.
> As long as you don't pass a block in the call to the
> dynamically defined method, you can use "define_method"
> instead. I moved a bit of code and came up with the code below.

I'd just return a block for this case, though.

> def meta_parse(*ary)
> self.class.module_eval do
> define_method :parse do |str|
...
> end
> end
> end
--
Christian Neukirchen <chneukirchen@gmail.com> http://chneuk...