Class: Moxml::XPath::Ruby::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/moxml/xpath/ruby/generator.rb

Overview

Class for converting a Ruby AST to a String.

This class takes a Node instance and converts it (and its child nodes) to a String that can be passed to ‘eval`.

Instance Method Summary collapse

Instance Method Details

#on_and(ast) ⇒ String

Processes a boolean “and” node.

Parameters:

Returns:

  • (String)


88
89
90
91
92
93
94
95
# File 'lib/moxml/xpath/ruby/generator.rb', line 88

def on_and(ast)
  left, right = *ast

  left_str = process(left)
  right_str = process(right)

  "#{left_str} && #{right_str}"
end

#on_array(ast) ⇒ String

Processes an array literal node.

Parameters:

Returns:

  • (String)


262
263
264
265
# File 'lib/moxml/xpath/ruby/generator.rb', line 262

def on_array(ast)
  elements = ast.to_a.map { |elem| process(elem) }
  "[#{elements.join(', ')}]"
end

#on_assign(ast) ⇒ String

Processes an assignment node.

Parameters:

Returns:

  • (String)


35
36
37
38
39
40
41
42
# File 'lib/moxml/xpath/ruby/generator.rb', line 35

def on_assign(ast)
  var, val = *ast

  var_str = process(var)
  val_str = process(val)

  "#{var_str} = #{val_str}"
end

#on_begin(ast) ⇒ String

Processes a ‘begin` node.

Parameters:

Returns:

  • (String)


61
62
63
64
65
66
67
68
69
# File 'lib/moxml/xpath/ruby/generator.rb', line 61

def on_begin(ast)
  body = process(ast.to_a[0])

  "    begin\n      \#{body}\n    end\n  RUBY\nend\n"

#on_block(ast) ⇒ String

Processes a block node.

Parameters:

Returns:

  • (String)


199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/moxml/xpath/ruby/generator.rb', line 199

def on_block(ast)
  receiver, args, body = *ast

  receiver_str = process(receiver)
  body_str = body ? process(body) : nil
  arg_strs = args.map { |arg| process(arg) }

  "    \#{receiver_str} do |\#{arg_strs.join(', ')}|\n      \#{body_str}\n    end\n  RUBY\nend\n"

#on_const(ast) ⇒ String

Processes a constant reference node (e.g., Moxml::Document).

Parameters:

Returns:

  • (String)


254
255
256
# File 'lib/moxml/xpath/ruby/generator.rb', line 254

def on_const(ast)
  ast.to_a.join("::")
end

#on_eq(ast) ⇒ String

Processes an equality node.

Parameters:

Returns:

  • (String)


75
76
77
78
79
80
81
82
# File 'lib/moxml/xpath/ruby/generator.rb', line 75

def on_eq(ast)
  left, right = *ast

  left_str = process(left)
  right_str = process(right)

  "#{left_str} == #{right_str}"
end

#on_followed_by(ast) ⇒ String

Parameters:

Returns:

  • (String)


27
28
29
# File 'lib/moxml/xpath/ruby/generator.rb', line 27

def on_followed_by(ast)
  ast.to_a.map { |child| process(child) }.join("\n\n")
end

#on_if(ast) ⇒ String

Processes an if statement node.

Parameters:

Returns:

  • (String)


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/moxml/xpath/ruby/generator.rb', line 114

def on_if(ast)
  cond, body, else_body = *ast

  cond_str = process(cond)
  body_str = process(body)

  if else_body
    else_str = process(else_body)

    "      if \#{cond_str}\n        \#{body_str}\n      else\n        \#{else_str}\n      end\n    RUBY\n  else\n    <<~RUBY\n      if \#{cond_str}\n        \#{body_str}\n      end\n    RUBY\n  end\nend\n"

#on_lit(ast) ⇒ String

Processes a literal node.

Parameters:

Returns:

  • (String)


246
247
248
# File 'lib/moxml/xpath/ruby/generator.rb', line 246

def on_lit(ast)
  ast.to_a[0]
end

#on_massign(ast) ⇒ String

Processes a mass assignment node.

Parameters:

Returns:

  • (String)


48
49
50
51
52
53
54
55
# File 'lib/moxml/xpath/ruby/generator.rb', line 48

def on_massign(ast)
  vars, val = *ast

  var_names = vars.map { |var| process(var) }
  val_str = process(val)

  "#{var_names.join(', ')} = #{val_str}"
end

#on_or(ast) ⇒ String

Processes a boolean “or” node.

Parameters:

Returns:

  • (String)


101
102
103
104
105
106
107
108
# File 'lib/moxml/xpath/ruby/generator.rb', line 101

def on_or(ast)
  left, right = *ast

  left_str = process(left)
  right_str = process(right)

  "(#{left_str} || #{right_str})"
end

#on_range(ast) ⇒ String

Processes a Range node.

Parameters:

Returns:

  • (String)


217
218
219
220
221
222
223
224
# File 'lib/moxml/xpath/ruby/generator.rb', line 217

def on_range(ast)
  start, stop = *ast

  start_str = process(start)
  stop_str = process(stop)

  "(#{start_str}..#{stop_str})"
end

#on_send(ast) ⇒ String

Processes a method call node.

Parameters:

Returns:

  • (String)


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/moxml/xpath/ruby/generator.rb', line 160

def on_send(ast)
  children = ast.to_a
  receiver = children[0]
  name = children[1]
  args = children[2..] || []

  call = name
  brackets = name == "[]"

  unless args.empty?
    arg_strs = []
    args.each do |arg|
      result = process(arg)
      # Keep processing if we got a Node back (happens with nested send nodes)
      while result.respond_to?(:type)
        result = process(result)
      end
      arg_strs << result
    end
    arg_str = arg_strs.join(", ")
    call = brackets ? "[#{arg_str}]" : "#{call}(#{arg_str})"
  end

  if receiver
    rec_str = process(receiver)
    # Keep processing if we got a Node back
    while rec_str.respond_to?(:type)
      rec_str = process(rec_str)
    end
    call = brackets ? "#{rec_str}#{call}" : "#{rec_str}.#{call}"
  end

  call
end

#on_string(ast) ⇒ String

Processes a string node.

Parameters:

Returns:

  • (String)


230
231
232
# File 'lib/moxml/xpath/ruby/generator.rb', line 230

def on_string(ast)
  ast.to_a[0].inspect
end

#on_symbol(ast) ⇒ String

Processes a Symbol node.

Parameters:

Returns:

  • (String)


238
239
240
# File 'lib/moxml/xpath/ruby/generator.rb', line 238

def on_symbol(ast)
  ast.to_a[0].to_sym.inspect
end

#on_while(ast) ⇒ String

Processes a while statement node.

Parameters:

Returns:

  • (String)


143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/moxml/xpath/ruby/generator.rb', line 143

def on_while(ast)
  cond, body = *ast

  cond_str = process(cond)
  body_str = process(body)

  "    while \#{cond_str}\n      \#{body_str}\n    end\n  RUBY\nend\n"

#process(ast) ⇒ String

Parameters:

Returns:

  • (String)


15
16
17
18
19
20
21
22
23
# File 'lib/moxml/xpath/ruby/generator.rb', line 15

def process(ast)
  handler = :"on_#{ast.type}"
  unless respond_to?(handler, true)
    raise NotImplementedError,
          "Generator missing handler for node type :#{ast.type}. Node: #{ast.inspect}"
  end

  send(handler, ast)
end