Module: Trepan::CmdParser

Defined in:
app/cmd_parse.rb

Class Method Summary collapse

Class Method Details

.meth_for_parse_struct(parse_struct, start_binding) ⇒ Object

Return the method by evaluating parse_struct. nil is returned if we can’t parse str



90
91
92
# File 'app/cmd_parse.rb', line 90

def meth_for_parse_struct(parse_struct, start_binding)
  resolve_method(parse_struct, start_binding)
end

.meth_for_string(str, start_binding) ⇒ Object

Parse str and return the method associated with that. nil is returned if we can’t parse str



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'app/cmd_parse.rb', line 96

def meth_for_string(str, start_binding)
  @cp ? @cp.setup_parser(str) : @cp = CmdParse.new(str)
  begin 
    if @cp._class_module_chain
      # Did we match all of it?
      if @cp.result.name == str.strip
        meth_for_parse_struct(@cp.result, start_binding)
      else
        nil
      end
    else
      # FIXME: change to raise ParseError? 
      nil
    end
  rescue NameError
    return nil
  end
end

.parse_breakpoint(str, opts = {}) ⇒ Object



125
126
127
128
# File 'app/cmd_parse.rb', line 125

def parse_breakpoint(str, opts={})
  parse = parse_terminal(:_breakpoint_stmt, str, opts)
  parse ? parse.result : nil
end

.parse_breakpoint_no_condition(str, opts = {}) ⇒ Object



130
131
132
133
# File 'app/cmd_parse.rb', line 130

def parse_breakpoint_no_condition(str, opts={})
  parse = parse_terminal(:_breakpoint_stmt_no_condition, str, opts)
  parse ? parse.result : nil
end

.parse_list(str, opts = {}) ⇒ Object



135
136
137
138
# File 'app/cmd_parse.rb', line 135

def parse_list(str, opts={})
  parse = parse_terminal(:_list_stmt, str, opts)
  parse ? parse.result : nil
end

.parse_location(loc_str, opts = {}) ⇒ Object



120
121
122
123
# File 'app/cmd_parse.rb', line 120

def parse_location(loc_str, opts={})
  parse = parse_terminal(:_location, loc_str, opts)
  parse ? parse.result : nil
end

.parse_terminal(terminal_name, loc_str, opts = {}) ⇒ Object



115
116
117
118
# File 'app/cmd_parse.rb', line 115

def parse_terminal(terminal_name, loc_str, opts={})
  @cp ? @cp.setup_parser(loc_str) : @cp = CmdParse.new(loc_str, opts)
  @cp.send(terminal_name) ? @cp : nil
end

.resolve_method(m, bind, parent_class = nil) ⇒ Object

Given a KPeg parse object, return the method of that parse or raise a Name error if we can’t find a method. parent_class is the parent class of the object we’ve found so far and “binding” is used if we need to use eval to find the method.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'app/cmd_parse.rb', line 13

def resolve_method(m, bind, parent_class = nil)
  name = m.name
  # DEBUG p  name
  errmsg = nil
  if m.type == :constant
    begin
      if parent_class
        klass = parent_class.const_get(m.chain[0].name)
      else
        errmsg = "Constant #{m} is not a class or module"
        raise NameError, errmsg unless m.chain[0]
        klass = eval(m.chain[0].name, bind)
      end
      errmsg = "Constant #{klass} is not a class or module" unless
      raise NameError, errmsg unless
        klass.kind_of?(Class) or klass.kind_of?(Module)
      m = m.chain[1]
      if klass.instance_methods.member?(:binding)
        bind = klass.bind
      elsif klass.private_instance_methods.member?(:binding)
        bind = klass.send(:binding)
      else
        bind = nil
      end
      resolve_method(m, bind, klass)
    rescue NameError 
      errmsg ||= "Can't resolve constant #{name}"
      raise NameError, errmsg
    end
  else
    is_class = 
      begin
        m.chain && m.chain[0] && 
          Class == eval("#{m.chain[0].name}.class", bind) 
      rescue 
        false
      end
    if is_class
      # Handles stuff like:
      #    x = File
      #    x.basename
      # Above, we tested we get a class back when we evalate m.chain[0]
      # below. So it is safe to run the eval.
      klass = eval("#{m.chain[0].name}", bind)
      resolve_method(m.chain[1], klass.send(:binding), klass)
    else
      begin
        errmsg = "Can't get method for #{name.inspect}"
        if m.chain && m.chain[0]
          parent_obj = eval("#{m.chain[0].name}", bind) if !parent_class && bind
        end
        parent = parent_class || parent_obj
        meth = 
          if parent
            errmsg << "in #{parent}"
            lookup_name = m.chain && m.chain[1] ? m.chain[1].name : name
            if parent.respond_to?('instance_methods') && 
                parent.instance_methods.member?(lookup_name.to_sym)
              parent.instance_method(lookup_name.to_sym)
            elsif parent.respond_to?('methods')
              parent.method(lookup_name.to_sym)
            end
          elsif m.chain && m.chain[1]
            eval("#{m.chain[0].name}.method(#{lookup_name.name.inspect})", bind)
          else
            eval("self.method(#{name.inspect})", bind)
          end
        return meth
      rescue
        raise NameError, errmsg
      end
    end
  end
end