# File lib/parse_tree_reloaded.rb, line 113
  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
    
    #    puts(('  ' * @level) + type.to_s)
    #    @level += 1
    
    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 #when clause
          child = child.nd_next
          if child.nil? #no else clause used
            sexp << nil
            break
          end
        else #else clause
          break
        end
      end
    when :when
      #    if (!case_level) { /* when without case, ie, no expr in case */
      #      rb_ary_pop(ary); /* reset what current is pointing at */
      #      node = NEW_CASE(0, node);
      #      goto again;
      #    }
      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 != (NODE *)1
      #        && node->nd_var != (NODE *)2
      #        && node->nd_var != NULL) {
      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
        #regular args
        i = 0
        while i < node.nd_cnt do
          sexp << ID2SYM(@locals[i + 3])
          i += 1
        end
        #optional args
        optnode = node.nd_opt
        while optnode do
          sexp << ID2SYM(@locals[i + 3])
          i += 1
          optnode = optnode.nd_next
        end
        #special args
        case
        when arg_flag > 0: sexp << "*#{locals[i + 3].to_s}".to_sym #*arg
        when arg_flag == 0: #empty list
        when arg_flag == -1: #all handled above
        when arg_flag == -2: #no name
        else raise "ParseTree error: Unknown arg flag #{arg_flag}"
        end
        #assigns of optional args
        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
      # empty nodes
    when :last
      raise "ParseTree error: Unsupported node type '#{type}'"
    else
      raise "ParseTree error: Unknown node type '#{c_type}'"
    end
    
    #    @level -= 1
    #    puts(('  ' * @level) + type.to_s + ' end')
    
    @current_sexp = last_current_sexp
    sexp
  end