1#
2# dummyparser.rb
3#
4
5require 'ripper'
6
7class Node
8  def initialize(name, *nodes)
9    @name = name
10    @children = nodes
11  end
12
13  attr_reader :name, :children
14
15  def to_s
16    "#{@name}(#{Node.trim_nil(@children).map {|n| n.to_s }.join(',')})"
17  end
18
19  def self.trim_nil(list)
20    if !list.empty? and list.last.nil?
21      list = list[0...-1]
22      list.pop while !list.empty? and list.last.nil?
23    end
24    list
25  end
26end
27
28class NodeList
29  def initialize
30    @list = []
31  end
32
33  attr_reader :list
34
35  def push(item)
36    @list.push item
37    self
38  end
39
40  def prepend(items)
41    @list.unshift items
42  end
43
44  def to_s
45    "[#{@list.join(',')}]"
46  end
47end
48
49class DummyParser < Ripper
50  def hook(*names)
51    class << self; self; end.class_eval do
52      names.each do |name|
53        define_method(name) do |*a, &b|
54          result = super(*a, &b)
55          yield(name, *a)
56          result
57        end
58      end
59    end
60    self
61  end
62
63  def on_program(stmts)
64    stmts
65  end
66
67  def on_stmts_new
68    NodeList.new
69  end
70
71  def on_stmts_add(stmts, st)
72    stmts.push st
73    stmts
74  end
75
76  def on_void_stmt
77    Node.new('void')
78  end
79
80  def on_var_ref(name)
81    Node.new('ref', name)
82  end
83
84  def on_var_alias(a, b)
85    Node.new('valias', a, b)
86  end
87
88  def on_alias_error(a)
89    Node.new('aliaserr', a)
90  end
91
92  def on_arg_paren(args)
93    args
94  end
95
96  def on_args_new
97    NodeList.new
98  end
99
100  def on_args_add(list, arg)
101    list.push(arg)
102  end
103
104  def on_args_add_block(list, blk)
105    if blk
106      list.push('&' + blk.to_s)
107    else
108      list
109    end
110  end
111
112  def on_args_add_star(list, arg)
113    list.push('*' + arg.to_s)
114  end
115
116  def on_args_prepend(list, args)
117    list.prepend args
118    list
119  end
120
121  def on_method_add_arg(m, arg)
122    if arg == nil
123      arg = on_args_new
124    end
125    m.children.push arg
126    m
127  end
128
129  def on_method_add_block(m, b)
130    on_args_add_block(m.children, b)
131    m
132  end
133
134  def on_paren(params)
135    params
136  end
137
138  def on_brace_block(params, code)
139    Node.new('block', params, code)
140  end
141
142  def on_block_var(params, shadow)
143    params
144  end
145
146  def on_rest_param(var)
147    "*#{var}"
148  end
149
150  def on_blockarg(var)
151    "&#{var}"
152  end
153
154  def on_params(required, optional, rest, more, keyword, keyword_rest, block)
155    args = NodeList.new
156
157    required.each do |req|
158      args.push(req)
159    end if required
160
161    optional.each do |var, val|
162      args.push("#{var}=#{val}")
163    end if optional
164
165    args.push(rest) if rest
166
167    more.each do |m|
168      args.push(m)
169    end if more
170
171    args.push(block) if block
172    args
173  end
174
175  def on_assoc_new(a, b)
176    Node.new('assoc', a, b)
177  end
178
179  def on_bare_assoc_hash(assoc_list)
180    Node.new('assocs', *assoc_list)
181  end
182
183  def on_assoclist_from_args(a)
184    Node.new('assocs', *a)
185  end
186
187  def on_word_new
188    ""
189  end
190
191  def on_word_add(word, w)
192    word << w
193  end
194
195  def on_words_new
196    NodeList.new
197  end
198
199  def on_words_add(words, word)
200    words.push word
201  end
202
203  def on_qwords_new
204    NodeList.new
205  end
206
207  def on_qwords_add(words, word)
208    words.push word
209  end
210
211  (Ripper::PARSER_EVENTS.map(&:to_s) - instance_methods(false).map {|n|n.to_s.sub(/^on_/, '')}).each do |event|
212    define_method(:"on_#{event}") do |*args|
213      Node.new(event, *args)
214    end
215  end
216end
217