melbourne 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. data/HISTORY +3 -0
  2. data/LICENSE +27 -0
  3. data/README.rdoc +38 -0
  4. data/Rakefile +38 -0
  5. data/VERSION.yml +4 -0
  6. data/ext/melbourne/bstring-license.txt +29 -0
  7. data/ext/melbourne/bstrlib.c +2918 -0
  8. data/ext/melbourne/bstrlib.h +302 -0
  9. data/ext/melbourne/extconf.rb +76 -0
  10. data/ext/melbourne/grammar.cpp +11885 -0
  11. data/ext/melbourne/grammar.hpp +14 -0
  12. data/ext/melbourne/grammar.y +6013 -0
  13. data/ext/melbourne/internal.hpp +137 -0
  14. data/ext/melbourne/lex.c.tab +136 -0
  15. data/ext/melbourne/local_state.hpp +41 -0
  16. data/ext/melbourne/melbourne.cpp +37 -0
  17. data/ext/melbourne/node.hpp +262 -0
  18. data/ext/melbourne/node_types.cpp +245 -0
  19. data/ext/melbourne/node_types.hpp +135 -0
  20. data/ext/melbourne/node_types.rb +190 -0
  21. data/ext/melbourne/quark.cpp +52 -0
  22. data/ext/melbourne/quark.hpp +14 -0
  23. data/ext/melbourne/symbols.cpp +219 -0
  24. data/ext/melbourne/symbols.hpp +116 -0
  25. data/ext/melbourne/var_table.cpp +113 -0
  26. data/ext/melbourne/var_table.hpp +33 -0
  27. data/ext/melbourne/visitor.cpp +1052 -0
  28. data/ext/melbourne/visitor.hpp +20 -0
  29. data/lib/melbourne/ast/constants.rb +128 -0
  30. data/lib/melbourne/ast/control_flow.rb +382 -0
  31. data/lib/melbourne/ast/data.rb +19 -0
  32. data/lib/melbourne/ast/definitions.rb +561 -0
  33. data/lib/melbourne/ast/exceptions.rb +182 -0
  34. data/lib/melbourne/ast/file.rb +15 -0
  35. data/lib/melbourne/ast/grapher.rb +75 -0
  36. data/lib/melbourne/ast/literals.rb +268 -0
  37. data/lib/melbourne/ast/node.rb +21 -0
  38. data/lib/melbourne/ast/operators.rb +117 -0
  39. data/lib/melbourne/ast/self.rb +17 -0
  40. data/lib/melbourne/ast/sends.rb +451 -0
  41. data/lib/melbourne/ast/values.rb +74 -0
  42. data/lib/melbourne/ast/variables.rb +251 -0
  43. data/lib/melbourne/ast.rb +22 -0
  44. data/lib/melbourne/parser.rb +38 -0
  45. data/lib/melbourne/processor.rb +460 -0
  46. data/lib/melbourne.rb +46 -0
  47. data/spec/helpers/ast/node.rb +15 -0
  48. data/spec/helpers/ast/reduced_graph.rb +64 -0
  49. data/spec/lib/parser/alias_spec.rb +97 -0
  50. data/spec/lib/parser/and_spec.rb +63 -0
  51. data/spec/lib/parser/array_spec.rb +157 -0
  52. data/spec/lib/parser/attrasgn_spec.rb +401 -0
  53. data/spec/lib/parser/back_ref_spec.rb +20 -0
  54. data/spec/lib/parser/call_spec.rb +958 -0
  55. data/spec/lib/parser/case_spec.rb +577 -0
  56. data/spec/lib/parser/cdecl_spec.rb +108 -0
  57. data/spec/lib/parser/class_spec.rb +221 -0
  58. data/spec/lib/parser/colon2_spec.rb +13 -0
  59. data/spec/lib/parser/colon3_spec.rb +12 -0
  60. data/spec/lib/parser/const_spec.rb +12 -0
  61. data/spec/lib/parser/cvar_spec.rb +55 -0
  62. data/spec/lib/parser/cvasgn_spec.rb +71 -0
  63. data/spec/lib/parser/cvdecl_spec.rb +31 -0
  64. data/spec/lib/parser/defined_spec.rb +353 -0
  65. data/spec/lib/parser/defn_spec.rb +1409 -0
  66. data/spec/lib/parser/defs_spec.rb +247 -0
  67. data/spec/lib/parser/dot2_spec.rb +29 -0
  68. data/spec/lib/parser/dot3_spec.rb +29 -0
  69. data/spec/lib/parser/dregx_spec.rb +127 -0
  70. data/spec/lib/parser/dstr_spec.rb +453 -0
  71. data/spec/lib/parser/dsym_spec.rb +31 -0
  72. data/spec/lib/parser/dxstr_spec.rb +31 -0
  73. data/spec/lib/parser/ensure_spec.rb +279 -0
  74. data/spec/lib/parser/false_spec.rb +12 -0
  75. data/spec/lib/parser/flip2_spec.rb +138 -0
  76. data/spec/lib/parser/flip3_spec.rb +100 -0
  77. data/spec/lib/parser/for_spec.rb +279 -0
  78. data/spec/lib/parser/gasgn_spec.rb +34 -0
  79. data/spec/lib/parser/gvar_spec.rb +33 -0
  80. data/spec/lib/parser/hash_spec.rb +77 -0
  81. data/spec/lib/parser/iasgn_spec.rb +54 -0
  82. data/spec/lib/parser/if_spec.rb +439 -0
  83. data/spec/lib/parser/iter_spec.rb +2582 -0
  84. data/spec/lib/parser/lasgn_spec.rb +1066 -0
  85. data/spec/lib/parser/lit_spec.rb +75 -0
  86. data/spec/lib/parser/masgn_spec.rb +1970 -0
  87. data/spec/lib/parser/match2_spec.rb +47 -0
  88. data/spec/lib/parser/match3_spec.rb +54 -0
  89. data/spec/lib/parser/match_spec.rb +19 -0
  90. data/spec/lib/parser/module_spec.rb +102 -0
  91. data/spec/lib/parser/nil_spec.rb +13 -0
  92. data/spec/lib/parser/not_spec.rb +39 -0
  93. data/spec/lib/parser/nth_ref_spec.rb +12 -0
  94. data/spec/lib/parser/op_asgn_spec.rb +619 -0
  95. data/spec/lib/parser/or_spec.rb +155 -0
  96. data/spec/lib/parser/postexe_spec.rb +31 -0
  97. data/spec/lib/parser/regex_spec.rb +52 -0
  98. data/spec/lib/parser/rescue_spec.rb +1028 -0
  99. data/spec/lib/parser/return_spec.rb +151 -0
  100. data/spec/lib/parser/sclass_spec.rb +172 -0
  101. data/spec/lib/parser/str_spec.rb +162 -0
  102. data/spec/lib/parser/super_spec.rb +276 -0
  103. data/spec/lib/parser/true_spec.rb +12 -0
  104. data/spec/lib/parser/undef_spec.rb +222 -0
  105. data/spec/lib/parser/until_spec.rb +286 -0
  106. data/spec/lib/parser/valias_spec.rb +12 -0
  107. data/spec/lib/parser/while_spec.rb +458 -0
  108. data/spec/lib/parser/xstr_spec.rb +12 -0
  109. data/spec/lib/parser/yield_spec.rb +202 -0
  110. data/spec/lib/parser/zsuper_spec.rb +101 -0
  111. data/spec/matchers/parse_as.rb +27 -0
  112. data/spec/spec_helper.rb +10 -0
  113. metadata +168 -0
@@ -0,0 +1,460 @@
1
+ require File.join(File.dirname(__FILE__), 'ast')
2
+
3
+ module Melbourne
4
+
5
+ # Exception that is raised whenever Melbourne encounters anything it cannot parse.
6
+ # When this exception is raised, the parsed code is most likely not syntactically valid.
7
+ #
8
+ class ParserError < Exception; end
9
+
10
+ class Parser
11
+ def process_parse_error(message, column, line, source)
12
+ @exc = SyntaxError.from message, column, line, source, @name
13
+ end
14
+
15
+ def process_dangling_node
16
+ raise ParserError.new('Processing called but node was NULL')
17
+ # TODO: output info about the current AST node
18
+ end
19
+
20
+ # This method is analogous to #method_missing. It is called
21
+ # if there is no processing method defined for a node.
22
+ def process_missing_node(line, node_name, node_type)
23
+ raise ParserError.new("Unhandled node #{node_name} (#{node_type})")
24
+ end
25
+
26
+ # Processing methods
27
+
28
+ def process_alias(line, to, from)
29
+ AST::Alias.new line, to, from
30
+ end
31
+
32
+ def process_and(line, left, right)
33
+ AST::And.new line, left, right
34
+ end
35
+
36
+ def process_args(line, args, defaults, splat)
37
+ AST::FormalArguments.new line, args, defaults, splat
38
+ end
39
+
40
+ def process_argscat(line, array, rest)
41
+ AST::ConcatArgs.new line, array, rest
42
+ end
43
+
44
+ def process_argspush(line, arguments, value)
45
+ AST::PushArgs.new line, arguments, value
46
+ end
47
+
48
+ def process_array(line, array)
49
+ AST::ArrayLiteral.new line, array
50
+ end
51
+
52
+ def process_attrasgn(line, receiver, name, arguments)
53
+ if name == :[]=
54
+ AST::ElementAssignment.new line, receiver, arguments
55
+ else
56
+ AST::AttributeAssignment.new line, receiver, name, arguments
57
+ end
58
+ end
59
+
60
+ def process_back_ref(line, ref)
61
+ AST::BackRef.new line, ref
62
+ end
63
+
64
+ def process_begin(line, body)
65
+ AST::Begin.new line, body
66
+ end
67
+
68
+ def process_block(line, array)
69
+ AST::Block.new line, array
70
+ end
71
+
72
+ def process_block_arg(line, name)
73
+ AST::BlockArgument.new line, name
74
+ end
75
+
76
+ def process_block_pass(line, method_send, body)
77
+ node = AST::BlockPass.new line, body
78
+ if method_send
79
+ method_send.block = node
80
+ method_send
81
+ else
82
+ node
83
+ end
84
+ end
85
+
86
+ def process_break(line, value)
87
+ AST::Break.new line, value
88
+ end
89
+
90
+ def process_call(line, receiver, name, arguments)
91
+ if arguments
92
+ AST::SendWithArguments.new line, receiver, name, arguments
93
+ else
94
+ AST::Send.new line, receiver, name
95
+ end
96
+ end
97
+
98
+ def process_case(line, receiver, whens, else_body)
99
+ if receiver
100
+ AST::ReceiverCase.new line, receiver, whens, else_body
101
+ else
102
+ AST::Case.new line, whens, else_body
103
+ end
104
+ end
105
+
106
+ def process_cdecl(line, expr, value)
107
+ AST::ConstSet.new line, expr, value
108
+ end
109
+
110
+ def process_class(line, name, superclass, body)
111
+ AST::Class.new line, name, superclass, body
112
+ end
113
+
114
+ def process_colon2(line, outer, name)
115
+ if outer
116
+ AST::ConstAccess.new line, outer, name
117
+ else
118
+ AST::ConstFind.new line, name
119
+ end
120
+ end
121
+
122
+ def process_colon3(line, name)
123
+ AST::ConstAtTop.new line, name
124
+ end
125
+
126
+ def process_const(line, name)
127
+ AST::ConstFind.new line, name
128
+ end
129
+
130
+ def process_cvar(line, name)
131
+ AST::ClassVariableAccess.new line, name
132
+ end
133
+
134
+ def process_cvasgn(line, name, value)
135
+ AST::ClassVariableAssignment.new line, name, value
136
+ end
137
+
138
+ def process_cvdecl(line, name, value)
139
+ AST::ClassVariableAssignment.new line, name, value
140
+ end
141
+
142
+ def process_data(line, data)
143
+ AST::EndData.new line, data
144
+ end
145
+
146
+ def process_defined(line, expr)
147
+ AST::Defined.new line, expr
148
+ end
149
+
150
+ def process_defn(line, name, body)
151
+ AST::Define.new line, name, body
152
+ end
153
+
154
+ def process_defs(line, receiver, name, body)
155
+ AST::DefineSingleton.new line, receiver, name, body
156
+ end
157
+
158
+ def process_dot2(line, start, finish)
159
+ AST::Range.new line, start, finish
160
+ end
161
+
162
+ def process_dot3(line, start, finish)
163
+ AST::RangeExclude.new line, start, finish
164
+ end
165
+
166
+ def process_dregx(line, str, array, flags)
167
+ AST::DynamicRegex.new line, str, array, flags
168
+ end
169
+
170
+ def process_dregx_once(line, str, array, flags)
171
+ AST::DynamicOnceRegex.new line, str, array, flags
172
+ end
173
+
174
+ def process_dstr(line, str, array)
175
+ AST::DynamicString.new line, str, array
176
+ end
177
+
178
+ def process_dsym(line, str, array)
179
+ AST::DynamicSymbol.new line, str, array
180
+ end
181
+
182
+ def process_dxstr(line, str, array)
183
+ AST::DynamicExecuteString.new line, str, array
184
+ end
185
+
186
+ def process_ensure(line, body, ensr)
187
+ AST::Ensure.new line, body, ensr
188
+ end
189
+
190
+ def process_evstr(line, value)
191
+ if value
192
+ AST::ToString.new line, value
193
+ else
194
+ AST::StringLiteral.new line, ""
195
+ end
196
+ end
197
+
198
+ def process_false(line)
199
+ AST::False.new line
200
+ end
201
+
202
+ def process_fcall(line, name, arguments)
203
+ receiver = AST::Self.new line
204
+
205
+ if arguments
206
+ AST::SendWithArguments.new line, receiver, name, arguments, true
207
+ else
208
+ AST::Send.new line, receiver, name, true
209
+ end
210
+ end
211
+
212
+ def process_file(line)
213
+ AST::File.new line
214
+ end
215
+
216
+ def process_fixnum(line, value)
217
+ AST::FixnumLiteral.new line, value
218
+ end
219
+
220
+ def process_flip2(line, start, finish)
221
+ AST::Flip2.new line, start, finish
222
+ end
223
+
224
+ def process_flip3(line, start, finish)
225
+ AST::Flip3.new line, start, finish
226
+ end
227
+
228
+ def process_float(line, str)
229
+ AST::Float.new line, str
230
+ end
231
+
232
+ def process_for(line, iter, arguments, body)
233
+ method_send = AST::Send.new line, iter, :each
234
+ method_send.block = AST::For.new line, arguments, body
235
+ method_send
236
+ end
237
+
238
+ def process_gasgn(line, name, expr)
239
+ AST::GlobalVariableAssignment.new line, name, expr
240
+ end
241
+
242
+ def process_gvar(line, name)
243
+ AST::GlobalVariableAccess.new line, name
244
+ end
245
+
246
+ def process_hash(line, array)
247
+ AST::HashLiteral.new line, array
248
+ end
249
+
250
+ def process_iasgn(line, name, value)
251
+ AST::InstanceVariableAssignment.new line, name, value
252
+ end
253
+
254
+ def process_if(line, cond, body, else_body)
255
+ AST::If.new line, cond, body, else_body
256
+ end
257
+
258
+ def process_iter(line, method_send, arguments, body)
259
+ method_send.block = AST::Iter.new line, arguments, body
260
+ method_send
261
+ end
262
+
263
+ def process_ivar(line, name)
264
+ AST::InstanceVariableAccess.new line, name
265
+ end
266
+
267
+ def process_lasgn(line, name, value)
268
+ AST::LocalVariableAssignment.new line, name, value
269
+ end
270
+
271
+ def process_lit(line, sym)
272
+ AST::SymbolLiteral.new line, sym
273
+ end
274
+
275
+ def process_lvar(line, name)
276
+ AST::LocalVariableAccess.new line, name
277
+ end
278
+
279
+ def process_masgn(line, left, right, splat)
280
+ AST::MAsgn.new line, left, right, splat
281
+ end
282
+
283
+ def process_match(line, pattern, flags)
284
+ AST::Match.new line, pattern, flags
285
+ end
286
+
287
+ def process_match2(line, pattern, value)
288
+ AST::Match2.new line, pattern, value
289
+ end
290
+
291
+ def process_match3(line, pattern, value)
292
+ AST::Match3.new line, pattern, value
293
+ end
294
+
295
+ def process_module(line, name, body)
296
+ AST::Module.new line, name, body
297
+ end
298
+
299
+ def process_negate(line, value)
300
+ AST::Negate.new line, value
301
+ end
302
+
303
+ def process_next(line, value)
304
+ AST::Next.new line, value
305
+ end
306
+
307
+ def process_nil(line)
308
+ AST::Nil.new line
309
+ end
310
+
311
+ def process_not(line, value)
312
+ AST::Not.new line, value
313
+ end
314
+
315
+ def process_nth_ref(line, ref)
316
+ AST::NthRef.new line, ref
317
+ end
318
+
319
+ def process_number(line, base, str)
320
+ value = str.to_i base
321
+ case value
322
+ when Fixnum
323
+ AST::FixnumLiteral.new line, value
324
+ when Bignum
325
+ AST::NumberLiteral.new line, value
326
+ end
327
+ end
328
+
329
+ def process_op_asgn1(line, receiver, index, op, value)
330
+ AST::OpAssign1.new line, receiver, index, op, value
331
+ end
332
+
333
+ def process_op_asgn2(line, receiver, name, op, value)
334
+ AST::OpAssign2.new line, receiver, name, op, value
335
+ end
336
+
337
+ def process_op_asgn_and(line, var, value)
338
+ AST::OpAssignAnd.new line, var, value
339
+ end
340
+
341
+ def process_op_asgn_or(line, var, value)
342
+ AST::OpAssignOr.new line, var, value
343
+ end
344
+
345
+ def process_or(line, left, right)
346
+ AST::Or.new line, left, right
347
+ end
348
+
349
+ def process_postexe(line)
350
+ AST::Send.new line, AST::Self.new(line), :at_exit, true
351
+ end
352
+
353
+ def process_redo(line)
354
+ AST::Redo.new line
355
+ end
356
+
357
+ def process_regex(line, str, flags)
358
+ AST::RegexLiteral.new line, str, flags
359
+ end
360
+
361
+ def process_resbody(line, conditions, body, nxt)
362
+ AST::RescueCondition.new line, conditions, body, nxt
363
+ end
364
+
365
+ def process_rescue(line, body, rescue_body, else_body)
366
+ AST::Rescue.new line, body, rescue_body, else_body
367
+ end
368
+
369
+ def process_retry(line)
370
+ AST::Retry.new line
371
+ end
372
+
373
+ def process_return(line, value)
374
+ AST::Return.new line, value
375
+ end
376
+
377
+ def process_sclass(line, receiver, body)
378
+ AST::SClass.new line, receiver, body
379
+ end
380
+
381
+ def process_scope(line, body)
382
+ if body.kind_of? AST::Block
383
+ body
384
+ elsif body
385
+ AST::Block.new line, [body]
386
+ end
387
+ end
388
+
389
+ def process_self(line)
390
+ AST::Self.new line
391
+ end
392
+
393
+ def process_splat(line, expr)
394
+ AST::SplatValue.new line, expr
395
+ end
396
+
397
+ def process_str(line, str)
398
+ AST::StringLiteral.new line, str
399
+ end
400
+
401
+ def process_super(line, args)
402
+ AST::Super.new line, args
403
+ end
404
+
405
+ def process_svalue(line, expr)
406
+ AST::SValue.new line, expr
407
+ end
408
+
409
+ def process_to_ary(line, expr)
410
+ AST::ToArray.new line, expr
411
+ end
412
+
413
+ def process_true(line)
414
+ AST::True.new line
415
+ end
416
+
417
+ def process_undef(line, sym)
418
+ AST::Undef.new line, sym
419
+ end
420
+
421
+ def process_until(line, cond, body, check_first)
422
+ AST::Until.new line, cond, body, check_first
423
+ end
424
+
425
+ def process_vcall(line, name)
426
+ receiver = AST::Self.new line
427
+
428
+ AST::Send.new line, receiver, name, true
429
+ end
430
+
431
+ def process_valias(line, to, from)
432
+ AST::VAlias.new line, to, from
433
+ end
434
+
435
+ def process_when(line, conditions, body)
436
+ AST::When.new line, conditions, body
437
+ end
438
+
439
+ def process_while(line, cond, body, check_first)
440
+ AST::While.new line, cond, body, check_first
441
+ end
442
+
443
+ def process_xstr(line, str)
444
+ AST::ExecuteString.new line, str
445
+ end
446
+
447
+ def process_yield(line, arguments, unwrap)
448
+ AST::Yield.new line, arguments, unwrap
449
+ end
450
+
451
+ def process_zarray(line)
452
+ AST::EmptyArray.new line
453
+ end
454
+
455
+ def process_zsuper(line)
456
+ AST::ZSuper.new line
457
+ end
458
+ end
459
+
460
+ end
data/lib/melbourne.rb ADDED
@@ -0,0 +1,46 @@
1
+ base = File.dirname(__FILE__)
2
+
3
+ require File.join(base, 'ext/melbourne')
4
+ require File.join(base, 'melbourne/parser')
5
+ require File.join(base, 'melbourne/processor')
6
+
7
+ module Melbourne #:nodoc:
8
+ end
9
+
10
+ class String
11
+
12
+ # Creates an AST for a +String+ containing Ruby source code.
13
+ #
14
+ # === Example
15
+ #
16
+ # 'class Test; end'.to_ast # => <AST::Class:0x1017800f8...
17
+ #
18
+ # === Arguments
19
+ #
20
+ # * +name+: the name of the source (this is usuall the name of the file the code was read from); defaults to <tt>(eval)</tt>
21
+ # * +line+: the starting line (if it's not 1 for some reason); defaults to <tt>1</tt>
22
+ #
23
+ def to_ast(name = '(eval)', line = 1)
24
+ Melbourne::Parser.parse_string(self, name, line)
25
+ end
26
+
27
+ end
28
+
29
+ class File
30
+
31
+ # Creates an AST for Ruby source code read from a file.
32
+ #
33
+ # === Example
34
+ #
35
+ # File.to_ast('user.rb') # => <AST::Class:0x1017800f8...
36
+ #
37
+ # === Arguments
38
+ #
39
+ # * +name+: the name of the file to read the source code from.
40
+ # * +line+: the starting line (if it's not 1 for some reason); defaults to <tt>1</tt>
41
+ #
42
+ def self.to_ast(name, line = 1)
43
+ Melbourne::Parser.parse_file(name, line)
44
+ end
45
+
46
+ end
@@ -0,0 +1,15 @@
1
+ module Melbourne
2
+
3
+ module AST
4
+
5
+ class Node
6
+
7
+ def reduced_graph
8
+ ReducedGraph.new(self).to_hash
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,64 @@
1
+ module Melbourne
2
+
3
+ module AST
4
+
5
+ class ReducedGraph
6
+
7
+ def initialize(ast)
8
+ @graph = {}
9
+ graph_node(ast)
10
+ end
11
+
12
+ def to_hash
13
+ @graph
14
+ end
15
+
16
+ private
17
+
18
+ def graph_node(node, parent = @graph)
19
+ return if node.kind_of?(Nil)
20
+ name = format_class_name(node.class)
21
+ parent[name] = {}
22
+
23
+ node.instance_variables.each do |instance_variable|
24
+ next if instance_variable == '@compiler'
25
+ value = node.instance_variable_get(instance_variable)
26
+ graph_instance_variable(instance_variable, value, parent[name])
27
+ end
28
+ end
29
+
30
+ def graph_instance_variable(variable, value, parent)
31
+ if value.kind_of?(Node)
32
+ graph_node(value, parent[variable.to_sym] = {})
33
+ elsif value.kind_of?(Array)
34
+ parent = parent[variable.to_sym] = []
35
+ value.each do |element|
36
+ if element.kind_of?(Node)
37
+ graph_node(element, (parent << {}).last)
38
+ else
39
+ parent << format_value(element)
40
+ end
41
+ end
42
+ else
43
+ parent[variable.to_sym] = format_value(value)
44
+ end
45
+ end
46
+
47
+ def format_value(value)
48
+ case value
49
+ when NilClass, TrueClass, FalseClass, Symbol, Fixnum
50
+ value
51
+ else
52
+ value.to_s.empty? ? :'<blank>' : value.to_s.to_sym
53
+ end
54
+ end
55
+
56
+ def format_class_name(klass)
57
+ klass.to_s.split('::').last.downcase.to_sym
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,97 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Melbourne::Parser do
4
+
5
+ it 'should correctly parse "class X; alias :y :x; end"' do
6
+ ruby = <<-ruby
7
+ class X
8
+ alias :y :x
9
+ end
10
+ ruby
11
+ ast = {:class=>
12
+ {:@superclass=>{},
13
+ :@body=>
14
+ {:classscope=>
15
+ {:@body=>
16
+ {:block=>
17
+ {:@array=>
18
+ [{:alias=>
19
+ {:@line=>2,
20
+ :@to=>{:symbolliteral=>{:@line=>2, :@value=>:y}},
21
+ :@from=>{:symbolliteral=>{:@line=>2, :@value=>:x}}}}],
22
+ :@line=>3}},
23
+ :@name=>:X,
24
+ :@line=>1}},
25
+ :@name=>{:classname=>{:@superclass=>{}, :@name=>:X, :@line=>1}},
26
+ :@line=>1}}
27
+
28
+ ruby.should parse_as(ast)
29
+ end
30
+
31
+ it 'should correctly parse "class X; alias y x; end"' do
32
+ ruby = <<-ruby
33
+ class X
34
+ alias y x
35
+ end
36
+ ruby
37
+ ast = {:class=>
38
+ {:@superclass=>{},
39
+ :@body=>
40
+ {:classscope=>
41
+ {:@body=>
42
+ {:block=>
43
+ {:@array=>
44
+ [{:alias=>
45
+ {:@line=>2,
46
+ :@to=>{:symbolliteral=>{:@line=>2, :@value=>:y}},
47
+ :@from=>{:symbolliteral=>{:@line=>2, :@value=>:x}}}}],
48
+ :@line=>3}},
49
+ :@name=>:X,
50
+ :@line=>1}},
51
+ :@name=>{:classname=>{:@superclass=>{}, :@name=>:X, :@line=>1}},
52
+ :@line=>1}}
53
+
54
+ ruby.should parse_as(ast)
55
+ end
56
+
57
+ it 'should correctly parse "class X; alias :"y#{1}" :"x#{2}"; end"' do
58
+ ruby = <<-ruby
59
+ class X
60
+ alias :"y\#{1}" :"x\#{2}"
61
+ end
62
+ ruby
63
+ ast = {:class=>
64
+ {:@superclass=>{},
65
+ :@body=>
66
+ {:classscope=>
67
+ {:@body=>
68
+ {:block=>
69
+ {:@array=>
70
+ [{:alias=>
71
+ {:@line=>2,
72
+ :@to=>
73
+ {:dynamicsymbol=>
74
+ {:@string=>:y,
75
+ :@array=>
76
+ [{:tostring=>
77
+ {:@line=>2,
78
+ :@value=>{:fixnumliteral=>{:@line=>2, :@value=>1}}}}],
79
+ :@line=>2}},
80
+ :@from=>
81
+ {:dynamicsymbol=>
82
+ {:@string=>:x,
83
+ :@array=>
84
+ [{:tostring=>
85
+ {:@line=>2,
86
+ :@value=>{:fixnumliteral=>{:@line=>2, :@value=>2}}}}],
87
+ :@line=>2}}}}],
88
+ :@line=>3}},
89
+ :@name=>:X,
90
+ :@line=>1}},
91
+ :@name=>{:classname=>{:@superclass=>{}, :@name=>:X, :@line=>1}},
92
+ :@line=>1}}
93
+
94
+ ruby.should parse_as(ast)
95
+ end
96
+
97
+ end