meta_parse: my first metaprogram

E

Edgardo Hames

------=_Part_1458_27171303.1140371632402
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi guys,

After messing up with racc for a couple of hours I realized that most of th=
e
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 =3D <<ENDSTRING
def parse(str)
@q =3D []
scanner =3D StringScanner.new str
until scanner.empty?
case
ENDSTRING

ary.each do |type, exp, meth|
if meth
case_str << " when m =3D scanner.scan(#{exp}) ; @q << [:#{typ=
e},
m.#{meth}]\n"
else
case_str << " when m =3D scanner.scan(#{exp}) ; @q << [:#{typ=
e},
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=E1 a "Tu psic=F3pata favorito" http://tuxmaniac.blogspot.com

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

------=_Part_1458_27171303.1140371632402--
 
E

Erik Veenstra

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.erikveen.dds.nl/

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

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}'"}

----------------------------------------------------------------
 
D

David Vallner

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,129
Latest member
FastBurnketo
Top