class ParseTree
Constants
- NODE_SYMBOLS
Public Class Methods
new(include_newlines = false)
click to toggle source
# File lib/parse_tree_reloaded.rb, line 81 def initialize(include_newlines = false) @include_newlines = include_newlines end
Public Instance Methods
parse_tree_for_method(klass, method, is_cls_method = false, newlines = @include_newlines)
click to toggle source
# File lib/parse_tree_reloaded.rb, line 85 def parse_tree_for_method(klass, method, is_cls_method = false, newlines = @include_newlines) @newlines = newlines @locals = [] @current_sexp = nil method = method.to_sym id = rb_to_id(method) table = RCLASS(klass).m_tbl if (r, n = st_lookup(table, id))[0] sexp = [:defn, method, to_sexp(n.dereference.to_NODE.nd_body)] sexp.extend Sexp sexp else [nil] end end
parse_tree_for_string(string, filename = nil, line = nil, newlines = @include_newlines)
click to toggle source
# File lib/parse_tree_reloaded.rb, line 101 def parse_tree_for_string(string, filename = nil, line = nil, newlines = @include_newlines) filename ||= '(string)' line ||= 1 @newlines = newlines @locals = [] @current_sexp = nil node = rb_compile_string(filename, string, line) [to_sexp(node)] end
to_sexp(node)
click to toggle source
# File lib/parse_tree_reloaded.rb, line 112 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