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



93
94
95
# File 'app/cmd_parse.rb', line 93

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



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

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



128
129
130
131
# File 'app/cmd_parse.rb', line 128

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

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



133
134
135
136
# File 'app/cmd_parse.rb', line 133

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



138
139
140
141
# File 'app/cmd_parse.rb', line 138

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

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



123
124
125
126
# File 'app/cmd_parse.rb', line 123

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



118
119
120
121
# File 'app/cmd_parse.rb', line 118

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.



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
87
88
89
# File 'app/cmd_parse.rb', line 14

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) ||
                 parent.instance_methods.member?(lookup_name.to_sym))
              parent.instance_method(lookup_name) || 
                parent.instance_method(lookup_name.to_sym)
            elsif parent.respond_to?('methods')
              parent.method(lookup_name)
            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