ripper2ruby 0.0.1

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 (111) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +10 -0
  3. data/lib/core_ext/array/flush.rb +5 -0
  4. data/lib/core_ext/hash/delete_at.rb +5 -0
  5. data/lib/core_ext/object/meta_class.rb +5 -0
  6. data/lib/core_ext/object/try.rb +12 -0
  7. data/lib/erb/stripper.rb +48 -0
  8. data/lib/highlighters/ansi.rb +29 -0
  9. data/lib/ripper/event_log.rb +45 -0
  10. data/lib/ripper/ruby_builder.rb +168 -0
  11. data/lib/ripper/ruby_builder/buffer.rb +34 -0
  12. data/lib/ripper/ruby_builder/events/args.rb +40 -0
  13. data/lib/ripper/ruby_builder/events/array.rb +71 -0
  14. data/lib/ripper/ruby_builder/events/assignment.rb +55 -0
  15. data/lib/ripper/ruby_builder/events/block.rb +80 -0
  16. data/lib/ripper/ruby_builder/events/call.rb +123 -0
  17. data/lib/ripper/ruby_builder/events/case.rb +17 -0
  18. data/lib/ripper/ruby_builder/events/const.rb +47 -0
  19. data/lib/ripper/ruby_builder/events/for.rb +13 -0
  20. data/lib/ripper/ruby_builder/events/hash.rb +24 -0
  21. data/lib/ripper/ruby_builder/events/identifier.rb +41 -0
  22. data/lib/ripper/ruby_builder/events/if.rb +37 -0
  23. data/lib/ripper/ruby_builder/events/lexer.rb +159 -0
  24. data/lib/ripper/ruby_builder/events/literal.rb +47 -0
  25. data/lib/ripper/ruby_builder/events/method.rb +21 -0
  26. data/lib/ripper/ruby_builder/events/operator.rb +23 -0
  27. data/lib/ripper/ruby_builder/events/statements.rb +50 -0
  28. data/lib/ripper/ruby_builder/events/string.rb +117 -0
  29. data/lib/ripper/ruby_builder/events/symbol.rb +22 -0
  30. data/lib/ripper/ruby_builder/events/while.rb +27 -0
  31. data/lib/ripper/ruby_builder/queue.rb +33 -0
  32. data/lib/ripper/ruby_builder/stack.rb +125 -0
  33. data/lib/ripper/ruby_builder/token.rb +91 -0
  34. data/lib/ripper2ruby.rb +1 -0
  35. data/lib/ruby.rb +28 -0
  36. data/lib/ruby/aggregate.rb +71 -0
  37. data/lib/ruby/alternation/args.rb +25 -0
  38. data/lib/ruby/alternation/hash.rb +25 -0
  39. data/lib/ruby/alternation/list.rb +19 -0
  40. data/lib/ruby/args.rb +36 -0
  41. data/lib/ruby/array.rb +27 -0
  42. data/lib/ruby/assignment.rb +32 -0
  43. data/lib/ruby/assoc.rb +17 -0
  44. data/lib/ruby/block.rb +42 -0
  45. data/lib/ruby/call.rb +34 -0
  46. data/lib/ruby/case.rb +30 -0
  47. data/lib/ruby/const.rb +49 -0
  48. data/lib/ruby/for.rb +18 -0
  49. data/lib/ruby/hash.rb +14 -0
  50. data/lib/ruby/if.rb +35 -0
  51. data/lib/ruby/list.rb +40 -0
  52. data/lib/ruby/literal.rb +45 -0
  53. data/lib/ruby/method.rb +19 -0
  54. data/lib/ruby/node.rb +47 -0
  55. data/lib/ruby/node/composite.rb +68 -0
  56. data/lib/ruby/node/conversions.rb +66 -0
  57. data/lib/ruby/node/position.rb +35 -0
  58. data/lib/ruby/node/source.rb +29 -0
  59. data/lib/ruby/node/text.rb +121 -0
  60. data/lib/ruby/node/traversal.rb +82 -0
  61. data/lib/ruby/operator.rb +49 -0
  62. data/lib/ruby/params.rb +41 -0
  63. data/lib/ruby/statements.rb +45 -0
  64. data/lib/ruby/string.rb +40 -0
  65. data/lib/ruby/symbol.rb +27 -0
  66. data/lib/ruby/token.rb +51 -0
  67. data/lib/ruby/while.rb +32 -0
  68. data/test/all.rb +3 -0
  69. data/test/builder/stack_test.rb +67 -0
  70. data/test/builder/text_test.rb +118 -0
  71. data/test/context_test.rb +54 -0
  72. data/test/erb_stripper_test.rb +29 -0
  73. data/test/fixtures/all.rb.src +150 -0
  74. data/test/fixtures/source_1.rb +16 -0
  75. data/test/fixtures/source_2.rb +1 -0
  76. data/test/fixtures/stuff.rb +371 -0
  77. data/test/fixtures/template.html.erb +22 -0
  78. data/test/fixtures/tmp.rb +6 -0
  79. data/test/lib_test.rb +92 -0
  80. data/test/lib_test_helper.rb +103 -0
  81. data/test/libs.txt +227 -0
  82. data/test/nodes/args_test.rb +100 -0
  83. data/test/nodes/array_test.rb +141 -0
  84. data/test/nodes/assignment_test.rb +49 -0
  85. data/test/nodes/block_test.rb +125 -0
  86. data/test/nodes/call_test.rb +229 -0
  87. data/test/nodes/case_test.rb +68 -0
  88. data/test/nodes/comments_test.rb +25 -0
  89. data/test/nodes/const_test.rb +46 -0
  90. data/test/nodes/conversions_test.rb +9 -0
  91. data/test/nodes/for_test.rb +34 -0
  92. data/test/nodes/hash_test.rb +71 -0
  93. data/test/nodes/heredoc_test.rb +202 -0
  94. data/test/nodes/identifier_test.rb +51 -0
  95. data/test/nodes/if_test.rb +100 -0
  96. data/test/nodes/literals_test.rb +63 -0
  97. data/test/nodes/method_test.rb +92 -0
  98. data/test/nodes/namespaces_test.rb +65 -0
  99. data/test/nodes/node_test.rb +74 -0
  100. data/test/nodes/nodes_test.rb +23 -0
  101. data/test/nodes/operator_test.rb +241 -0
  102. data/test/nodes/separators_test.rb +97 -0
  103. data/test/nodes/statements_test.rb +70 -0
  104. data/test/nodes/string_test.rb +92 -0
  105. data/test/nodes/symbol_test.rb +57 -0
  106. data/test/nodes/unless_test.rb +42 -0
  107. data/test/nodes/until_test.rb +61 -0
  108. data/test/nodes/while_test.rb +71 -0
  109. data/test/test_helper.rb +51 -0
  110. data/test/traversal_test.rb +53 -0
  111. metadata +163 -0
@@ -0,0 +1,159 @@
1
+ class Ripper
2
+ class RubyBuilder < Ripper::SexpBuilder
3
+ module Lexer
4
+ # unimplemented = :tlambda, :tlambeg
5
+
6
+ def on_parse_error(msg)
7
+ raise ParseError.new("#{filename}:#{position.row + 1}: #{msg}")
8
+ end
9
+
10
+ def on_param_error(param)
11
+ raise ParseError.new("#{filename}:#{position.row + 1}: syntax error, invalid parameter type: #{param.to_ruby}")
12
+ end
13
+
14
+ def on_ignored_nl(*args)
15
+ token = push(super)
16
+ on_heredoc_literal if end_heredoc?(token)
17
+ token
18
+ end
19
+
20
+ def on_nl(*args)
21
+ token = push(super)
22
+ on_heredoc_literal if end_heredoc?(token)
23
+ token
24
+ end
25
+
26
+ def on_comment(*args)
27
+ token = push(super)
28
+ on_heredoc_literal if end_heredoc?(token)
29
+ token
30
+ end
31
+
32
+ def on_sp(*args)
33
+ token = push(super)
34
+ on_heredoc_literal if end_heredoc?(token) # ripper counts \ + nl ("\\\n") as whitespace
35
+ token
36
+ end
37
+
38
+ def on_semicolon(*args)
39
+ push(super)
40
+ end
41
+
42
+ def on_period(*args)
43
+ push(super)
44
+ end
45
+
46
+ def on_comma(*args)
47
+ push(super)
48
+ end
49
+
50
+ def on_backtick(*args)
51
+ push(super)
52
+ end
53
+
54
+ def on_symbeg(*args)
55
+ push(super)
56
+ end
57
+
58
+ def on_tstring_beg(*args)
59
+ push(super)
60
+ end
61
+
62
+ def on_tstring_content(token)
63
+ push(super)
64
+ nil
65
+ end
66
+
67
+ def on_tstring_end(token)
68
+ push(super)
69
+ on_words_end(token) if closes_words?(token) # simulating on_words_end event
70
+ end
71
+
72
+ def on_qwords_beg(*args)
73
+ push(super)
74
+ end
75
+
76
+ def on_words_beg(*args)
77
+ push(super)
78
+ end
79
+
80
+ def on_words_sep(token)
81
+ token.each_char do |token|
82
+ case token
83
+ when "\n"
84
+ push([:@nl, token, position])
85
+ when /\s+/
86
+ push([:@sp, token, position])
87
+ else
88
+ push([:@words_end, token, position])
89
+ on_words_end(token) if closes_words?(token) # simulating on_words_end event
90
+ end
91
+ end
92
+ end
93
+
94
+ def on_embexpr_beg(*args)
95
+ push(super)
96
+ end
97
+
98
+ def on_embexpr_end(*args)
99
+ push(super)
100
+ end
101
+
102
+ def on_regexp_beg(*args)
103
+ push(super)
104
+ end
105
+
106
+ def on_regexp_end(*args)
107
+ push(super)
108
+ end
109
+
110
+ def on_lparen(*args)
111
+ push(super)
112
+ end
113
+
114
+ def on_rparen(*args)
115
+ push(super)
116
+ end
117
+
118
+ def on_lbracket(*args)
119
+ push(super)
120
+ end
121
+
122
+ def on_rbracket(*args)
123
+ push(super)
124
+ end
125
+
126
+ def on_lbrace(*args)
127
+ push(super)
128
+ end
129
+
130
+ def on_rbrace(*args)
131
+ push(super)
132
+ end
133
+
134
+ def on_op(*args)
135
+ push(super)
136
+ end
137
+
138
+ def on_embdoc(doc)
139
+ push([:@comment, doc, position])
140
+ end
141
+
142
+ def on_embdoc_beg(doc)
143
+ push([:@comment, doc, position])
144
+ end
145
+
146
+ def on_embdoc_end(doc)
147
+ push([:@comment, doc, position])
148
+ end
149
+
150
+ def on_embvar(*args)
151
+ push(super)
152
+ end
153
+
154
+ def on___end__(*args)
155
+ push(super)
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,47 @@
1
+ class Ripper
2
+ class RubyBuilder < Ripper::SexpBuilder
3
+ module Literal
4
+ @@tokens = %w(class module def do begin rescue ensure retry end
5
+ if unless then else elsif case when while until for in
6
+ not and or alias undef super yield return next redo break
7
+ defined? BEGIN END)
8
+
9
+ def on_kw(token)
10
+ if @@tokens.include?(token)
11
+ push(super) # these aren't passed to the next parser event, so we need them on the stack
12
+ else
13
+ push(super)
14
+ build_keyword(pop_token(:"@#{token}"))
15
+ end
16
+ end
17
+
18
+ def on_int(token)
19
+ push
20
+ Ruby::Integer.new(token, position, prolog)
21
+ end
22
+
23
+ def on_float(token)
24
+ push
25
+ Ruby::Float.new(token, position, prolog)
26
+ end
27
+
28
+ def on_dot2(left, right)
29
+ Ruby::Range.new(left, pop_token(:'@..'), right)
30
+ end
31
+
32
+ def on_dot3(left, right)
33
+ Ruby::Range.new(left, pop_token(:'@...'), right)
34
+ end
35
+
36
+ def on_CHAR(token)
37
+ push
38
+ Ruby::Char.new(token, position, prolog)
39
+ end
40
+
41
+ def on_label(label)
42
+ push
43
+ Ruby::Label.new(label, position, prolog)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ class Ripper
2
+ class RubyBuilder < Ripper::SexpBuilder
3
+ module Method
4
+ def on_def(identifier, params, body)
5
+ rdelim = pop_token(:@end)
6
+ # the identifier might be a keyword, e.g. def class; end. could even be def def; end
7
+ identifier = pop_identifier(identifier.type, :right => rdelim) if identifier.is_a?(Ripper::RubyBuilder::Token)
8
+ ldelim = pop_token(:@def, :pass => true)
9
+ Ruby::Method.new(nil, nil, identifier, params, body, ldelim, rdelim)
10
+ end
11
+
12
+ def on_defs(target, separator, identifier, params, body)
13
+ rdelim = pop_token(:@end)
14
+ ldelim = pop_token(:@def, :pass => true)
15
+ identifier = pop_identifier(identifier.type, :left => ldelim, :right => rdelim) if identifier.is_a?(Ripper::RubyBuilder::Token)
16
+ separator = pop_token(:@period, :'@::')
17
+ Ruby::Method.new(target, separator, identifier, params, body, ldelim, rdelim)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ class Ripper
2
+ class RubyBuilder < Ripper::SexpBuilder
3
+ module Operator
4
+ def on_unary(operator, operand)
5
+ operator = pop_unary_operator(:pass => true, :right => operand) # e.g. not(1)
6
+ ldelim = pop_token(:@lparen, :left => operator)
7
+ rdelim = pop_token(:@rparen, :left => operator) if ldelim
8
+ Ruby::Unary.new(operator, operand, ldelim, rdelim) if operator
9
+ end
10
+
11
+ def on_binary(left, operator, right)
12
+ operator = pop_token(:"@#{operator}", :pass => true, :right => right)
13
+ Ruby::Binary.new(operator, left, right) if operator
14
+ end
15
+
16
+ def on_ifop(condition, left, right)
17
+ operators = pop_ternary_operator(:left => condition, :right => left),
18
+ pop_ternary_operator(:left => left, :right => right)
19
+ Ruby::IfOp.new(condition, left, right, operators)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,50 @@
1
+ class Ripper
2
+ class RubyBuilder < Ripper::SexpBuilder
3
+ module Statements
4
+ def on_program(statements)
5
+ program = statements.to_program(src, filename, pop_end_data)
6
+ program << Ruby::Token.new('', position, prolog) unless stack.buffer.empty?
7
+ program
8
+ end
9
+
10
+ def on_body_stmt(body, rescue_block, else_block, ensure_block)
11
+ statements = [rescue_block, else_block, ensure_block].compact
12
+ body = body.to_chained_block(nil, statements) unless statements.empty?
13
+ body
14
+ end
15
+
16
+ def on_paren(node)
17
+ node = Ruby::Statements.new(node) unless node.is_a?(Ruby::ArgsList) || node.is_a?(Ruby::Params)
18
+ node.rdelim ||= pop_token(:@rparen)
19
+ node.ldelim ||= pop_token(:@lparen)
20
+ node
21
+ end
22
+
23
+ def on_stmts_add(target, statement)
24
+ on_words_end if statement.is_a?(Ruby::Array) && !string_stack.empty? # simulating on_words_end event
25
+ target.elements << statement if statement
26
+ target
27
+ end
28
+
29
+ def on_stmts_new
30
+ Ruby::Statements.new
31
+ end
32
+
33
+ def on_void_stmt
34
+ nil
35
+ end
36
+
37
+ def on_var_ref(ref)
38
+ ref.instance_of?(Ruby::Identifier) ? Ruby::Variable.new(ref.token, ref.position, ref.prolog) : ref
39
+ end
40
+
41
+ def on_const_ref(const)
42
+ const
43
+ end
44
+
45
+ def on_var_field(field)
46
+ field
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,117 @@
1
+ class Ripper
2
+ class RubyBuilder < Ripper::SexpBuilder
3
+ module String
4
+ def on_string_concat(*strings)
5
+ Ruby::StringConcat.new(strings)
6
+ end
7
+
8
+ def on_string_literal(string)
9
+ string_stack.pop if string == string_stack.last
10
+ string.rdelim = pop_token(:@tstring_end) if string.respond_to?(:rdelim)
11
+ string
12
+ end
13
+
14
+ def on_string_add(string, content)
15
+ content = pop_string_content unless content
16
+ target = heredoc? ? string_stack.last : string
17
+ target << content
18
+ string
19
+ end
20
+
21
+ def on_string_content(*args)
22
+ if token = pop_token(:@heredoc_beg)
23
+ Ruby::HeredocBegin.new(token.token, token.position, token.prolog)
24
+ else
25
+ string_stack << Ruby::String.new(nil, pop_token(:@tstring_beg))
26
+ string_stack.last
27
+ end
28
+ end
29
+
30
+ def on_xstring_literal(string, type = :@tstring_end)
31
+ string_stack.pop if string == string_stack.last
32
+ string.rdelim = pop_token(type) if string.respond_to?(:rdelim)
33
+ string
34
+ end
35
+
36
+ def on_regexp_literal(string, rdelim)
37
+ on_xstring_literal(string, rdelim.type)
38
+ end
39
+
40
+ def on_xstring_new(*args)
41
+ if token = pop_token(:@heredoc_beg)
42
+ Ruby::HeredocBegin.new(token.token, token.position, token.prolog)
43
+ else
44
+ ldelim = pop(:@symbeg, :@backtick, :@regexp_beg, :max => 1, :pass => true).first
45
+ string_stack << build_xstring(ldelim)
46
+ string_stack.last
47
+ end
48
+ end
49
+
50
+ def on_xstring_add(string, content)
51
+ on_string_add(string, content)
52
+ end
53
+
54
+ def on_word_new
55
+ Ruby::String.new
56
+ end
57
+
58
+ def on_word_add(string, word)
59
+ word = pop_string_content unless word
60
+ string << word
61
+ end
62
+
63
+ def on_heredoc_literal(*args)
64
+ string_stack.flush.each { |heredoc| push([:@heredoc, heredoc]) }
65
+ end
66
+
67
+ def on_heredoc_new
68
+ string_stack << Ruby::Heredoc.new
69
+ end
70
+
71
+ def on_heredoc_beg(*args)
72
+ token = push(super)
73
+ on_heredoc_new
74
+ end
75
+
76
+ def on_heredoc_end(token)
77
+ string_stack.last.rdelim = Ruby::Token.new(token, position)
78
+ nil
79
+ end
80
+
81
+ def on_string_embexpr(expression)
82
+ expression.ldelim = pop_token(:@embexpr_beg)
83
+ expression.rdelim = pop_token(:@rbrace)
84
+ expression
85
+ end
86
+
87
+ def on_string_dvar(variable)
88
+ variable = Ruby::DelimitedVariable.new(variable.to_identifier)
89
+ ldelim = pop_token(:@embvar)
90
+ variable.ldelim = ldelim
91
+ variable
92
+ end
93
+
94
+ protected
95
+
96
+ def heredocs
97
+ @heredoc ||= []
98
+ end
99
+
100
+ def heredoc?
101
+ string_stack.last.is_a?(Ruby::Heredoc)
102
+ end
103
+
104
+ def end_heredoc?(token)
105
+ extra_heredoc_stage? && extra_heredoc_char?(token)
106
+ end
107
+
108
+ def extra_heredoc_stage?
109
+ heredoc? && !!string_stack.last.rdelim
110
+ end
111
+
112
+ def extra_heredoc_char?(token)
113
+ token && (token.newline? || token.comment? || token.token == "\\\n")
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,22 @@
1
+ class Ripper
2
+ class RubyBuilder < Ripper::SexpBuilder
3
+ module Symbol
4
+ def on_symbol_literal(symbol)
5
+ symbol = pop_identifier(symbol.type) if symbol.try(:known?) # happens w/ symbols that are also keywords, e.g. :class
6
+ symbol
7
+ end
8
+
9
+ def on_symbol(token)
10
+ push
11
+ token = pop_identifier(token.type) if token.try(:known?)
12
+ Ruby::Symbol.new(token, pop_token(:@symbeg))
13
+ end
14
+
15
+ def on_dyna_symbol(symbol)
16
+ string_stack.pop if symbol == string_stack.last
17
+ symbol.rdelim = pop_token(:@tstring_end)
18
+ symbol
19
+ end
20
+ end
21
+ end
22
+ end