On Jan 3, 2008, at 15:50 , Giles Bowkett wrote: >>>>> Sort of. It is obviously full of nifty and then some, and I >>>>> think you > could use it to unit test metaprogramming, which is something the > metaprogramming-averse complain about the absence of. > > But say I do this: > >>> pt = ParseTree.new.parse_tree_for_string("1 + 2 ; 1 * 2") > (string):1: warning: useless use of + in void context > => [[:block, [:call, [:lit, 1], :, [:array, [:lit, 2]]], [:call, > [:lit, 1], :, [:array, [:lit, 2]]]]] >>> Ruby2Ruby.new.process(pt.first) > => "(1 + 2)\n(1 * 2)\n" > > What if I just want 1 * 2? It depends on what sort of '1 * 2' you want... Do you want the last expression in a block/defn/whatever? Like, are you trying to analyze what the return type is? Or do you want to be aware of that void context warning and discard the crap? Or do you simply want the second thingy? Or do you want something entirely different that I am not anticipating? There are a couple ways to go about it, depending on your answer above. The easiest is Sexp/Array manipulation. Let's say you were interested in the arg list of the last call in the block: > >> sexp = Sexp.from_array pt.first > => s(:block, s(:call, s(:lit, 1), :+, s(:array, s(:lit, 2))), > s(:call, s(:lit, 1), :*, s(:array, s(:lit, 2)))) > >> sexp.last > => s(:call, s(:lit, 1), :*, s(:array, s(:lit, 2))) > >> sexp.last.array > => s(:array, s(:lit, 2)) This is a bad example because it has two calls in the block. With unique sub-sexp types in a sexp, you can just pull them out by name: > >> sexp.call.array But it balks when it is ambiguous. But... if that isn't what you want, there are more powerful means of dealing with stuff: class CallArgAnalyzer < SexpProcessor def process_call sexp sexp.shift # :call recv = sexp.shift name = sexp.shift args = sexp.shift # do something with args return s(:nil) # or whatever... depends on context end end > >> CallArgAnalyzer.new.process(sexp.first) > => s(:nil) Granted, this doesn't actually DO anything, but the framework to do something is there and solid... Do note that SexpProcessor is meant for transformational processing so it generally expects a sexp back (you can set what the return type should be for all process_* methods). The real point is that it is very easy to get at what you want and mess with it.