def to_sexp(node)
return nil if node.nil?
c_type = nd_type(node)
type = NODE_SYMBOLS[c_type]
if type == :newline
if @newlines
newline_sexp = []
newline_sexp << :newline
newline_sexp << nd_line(node)
newline_sexp << node.nd_file
@current_sexp << newline_sexp
end
return to_sexp(node.nd_next)
end
sexp = []
sexp.extend Sexp
last_current_sexp = @current_sexp
@current_sexp = sexp
sexp << type
case type
when :block, :array
begin
sexp << to_sexp(node.nd_head)
end while node = node.nd_next
when :method
when :fbody
when :cfunc
when :scope
locals_before = @locals
@locals = node.nd_tbl
nd_next = node.nd_next
sexp << to_sexp(nd_next) unless nd_next.nil?
@locals = locals_before
when :if
sexp << to_sexp(node.nd_cond)
sexp << to_sexp(node.nd_body)
sexp << to_sexp(node.nd_else)
when :case
sexp << to_sexp(node.nd_head)
child = node.nd_body
loop do
child_sexp = to_sexp(child)
sexp << child_sexp
if child_sexp[0] == :when
child = child.nd_next
if child.nil?
sexp << nil
break
end
else
break
end
end
when :when
sexp << to_sexp(node.nd_head)
sexp << to_sexp(node.nd_body)
when :while, :until
sexp << to_sexp(node.nd_cond)
sexp << to_sexp(node.nd_body)
sexp << !node.nd_3rd.nil?
when :iter, :for
sexp << to_sexp(node.nd_iter)
if node.nd_var
sexp << to_sexp(node.nd_var)
else
sexp << nil
end
sexp << to_sexp(node.nd_body)
when :break, :next, :return, :yield
stts = node.nd_stts
sexp << to_sexp(stts) unless stts.nil?
when :begin, :opt_n, :not
sexp << to_sexp(node.nd_body)
when :rescue
sexp << to_sexp(node.nd_1st)
sexp << to_sexp(node.nd_2nd)
nd_3rd = node.nd_3rd
sexp << to_sexp(nd_3rd) unless nd_3rd.nil?
when :resbody
sexp << to_sexp(node.nd_3rd)
nd_2nd = node.nd_2nd
sexp << to_sexp(nd_2nd) unless nd_2nd.nil?
nd_1st = node.nd_1st
sexp << to_sexp(nd_1st) unless nd_1st.nil?
when :ensure
sexp << to_sexp(node.nd_head)
ensr = node.nd_ensr
sexp << zo_sexp(ensr) unless ensr.nil?
when :and, :or
sexp << to_sexp(node.nd_1st)
sexp << to_sexp(node.nd_2nd)
when :masgn
sexp << to_sexp(node.nd_head)
args = node.nd_args
sexp << to_sexp(args) unless args.nil?
value = node.nd_value
sexp << to_sexp(node.nd_value) unless value.nil?
when :lasgn, :dasgn, :dasgn_curr, :gasgn, :iasgn, :cdecl, :cvasgn, :cvdecl
sexp << ID2SYM(node.nd_vid)
value = node.nd_value
sexp << to_sexp(value) unless value.nil?
when :op_asgn1
when :op_asgn2
when :op_asgn_and, :op_asgn_or
sexp << to_sexp(node.nd_head)
sexp << to_sexp(node.nd_value)
when :call, :fcall, :vcall
sexp << to_sexp(node.nd_recv) if type == :call
sexp << ID2SYM(node.nd_mid)
if type == :call || type == :fcall
args = node.nd_args
sexp << to_sexp(args) if args
end
when :super
when :hash
list = node.nd_head
while list
sexp << to_sexp(list.nd_head)
list = list.nd_next
raise "ParseTree error: Odd number list for Hash" if list.nil?
sexp << to_sexp(list.nd_head)
list = list.nd_next
end
when :lvar, :dvar, :gvar, :ivar, :const, :cvar, :attrset
sexp << ID2SYM(node.nd_vid)
when :nth_ref
sexp << node.nd_nth
when :back_ref
when :match
when :match2, :match3
sexp << to_sexp(node.nd_recv)
sexp << to_sexp(node.nd_value)
when :lit, :str, :xstr
sexp << node.nd_lit
when :dstr, :dxstr, :dregx, :dregx_once, :dsym
sexp << node.nd_lit
list = node.nd_next
while list
head = list.nd_head
if head
child_sexp = to_sexp(head)
child_sexp = child_sexp[1] if child_sexp[0] == :evstr
sexp << child_sexp
end
list = list.nd_next
end
when :evstr
sexp << to_sexp(node.nd_body)
when :args
arg_flag = node.nd_rest
if @locals
i = 0
while i < node.nd_cnt do
sexp << ID2SYM(@locals[i + 3])
i += 1
end
optnode = node.nd_opt
while optnode do
sexp << ID2SYM(@locals[i + 3])
i += 1
optnode = optnode.nd_next
end
case
when arg_flag > 0: sexp << "*#{locals[i + 3].to_s}".to_sym
when arg_flag == 0:
when arg_flag == -1:
when arg_flag == -2:
else raise "ParseTree error: Unknown arg flag #{arg_flag}"
end
opt = node.nd_opt;
if opt
sexp << to_sexp(opt)
end
end
when :argscat, :argspush
sexp << to_sexp(node.nd_head)
sexp << to_sexp(node.nd_body)
when :splat, :to_ary, :svalue
sexp << to_sexp(node.nd_head)
when :block_arg
sexp << ID2SYM(node.nd_u1id)
when :block_pass
sexp << to_sexp(node.nd_body)
sexp << to_sexp(node.nd_iter)
when :defn, :defs
defn = node.nd_defn
if defn
sexp << to_sexp(node.nd_recv) if type == :defs
sexp << ID2SYM(node.nd_mid)
sexp << to_sexp(defn)
end
when :alias
when :valias
when :undef
when :class, :module
sexp << ID2SYM(node.nd_cpath.nd_mid)
sexp << to_sexp(node.nd_super) if type == :class
sexp << to_sexp(node.nd_body)
when :sclass
when :colon2
when :colon3
when :cref
when :dot2
when :dot3
when :flip2
when :flip3
when :defined
when :postexe
when :alloca
when :dmethod
when :bmethod
block = DATA_PTR(node.nd_cval).to_struct_BLOCK
var = block.var
sexp << to_sexp(var) unless var.nil?
sexp << to_sexp(block.body)
when :memo
when :ifunc
when :attrasgn
nd_1st = node.nd_1st
if nd_1st == RNODE(1)
sexp << to_sexp(NEW_SELF())
else
sexp << to_sexp(nd_1st)
end
sexp << ID2SYM(node.nd_u2id)
sexp << to_sexp(node.nd_3rd)
when :last
when :retry, :redo, :self, :nil, :true, :false, :zsuper, :zarray
when :last
raise "ParseTree error: Unsupported node type '#{type}'"
else
raise "ParseTree error: Unknown node type '#{c_type}'"
end
@current_sexp = last_current_sexp
sexp
end