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.
- data/MIT-LICENSE +20 -0
- data/README.markdown +10 -0
- data/lib/core_ext/array/flush.rb +5 -0
- data/lib/core_ext/hash/delete_at.rb +5 -0
- data/lib/core_ext/object/meta_class.rb +5 -0
- data/lib/core_ext/object/try.rb +12 -0
- data/lib/erb/stripper.rb +48 -0
- data/lib/highlighters/ansi.rb +29 -0
- data/lib/ripper/event_log.rb +45 -0
- data/lib/ripper/ruby_builder.rb +168 -0
- data/lib/ripper/ruby_builder/buffer.rb +34 -0
- data/lib/ripper/ruby_builder/events/args.rb +40 -0
- data/lib/ripper/ruby_builder/events/array.rb +71 -0
- data/lib/ripper/ruby_builder/events/assignment.rb +55 -0
- data/lib/ripper/ruby_builder/events/block.rb +80 -0
- data/lib/ripper/ruby_builder/events/call.rb +123 -0
- data/lib/ripper/ruby_builder/events/case.rb +17 -0
- data/lib/ripper/ruby_builder/events/const.rb +47 -0
- data/lib/ripper/ruby_builder/events/for.rb +13 -0
- data/lib/ripper/ruby_builder/events/hash.rb +24 -0
- data/lib/ripper/ruby_builder/events/identifier.rb +41 -0
- data/lib/ripper/ruby_builder/events/if.rb +37 -0
- data/lib/ripper/ruby_builder/events/lexer.rb +159 -0
- data/lib/ripper/ruby_builder/events/literal.rb +47 -0
- data/lib/ripper/ruby_builder/events/method.rb +21 -0
- data/lib/ripper/ruby_builder/events/operator.rb +23 -0
- data/lib/ripper/ruby_builder/events/statements.rb +50 -0
- data/lib/ripper/ruby_builder/events/string.rb +117 -0
- data/lib/ripper/ruby_builder/events/symbol.rb +22 -0
- data/lib/ripper/ruby_builder/events/while.rb +27 -0
- data/lib/ripper/ruby_builder/queue.rb +33 -0
- data/lib/ripper/ruby_builder/stack.rb +125 -0
- data/lib/ripper/ruby_builder/token.rb +91 -0
- data/lib/ripper2ruby.rb +1 -0
- data/lib/ruby.rb +28 -0
- data/lib/ruby/aggregate.rb +71 -0
- data/lib/ruby/alternation/args.rb +25 -0
- data/lib/ruby/alternation/hash.rb +25 -0
- data/lib/ruby/alternation/list.rb +19 -0
- data/lib/ruby/args.rb +36 -0
- data/lib/ruby/array.rb +27 -0
- data/lib/ruby/assignment.rb +32 -0
- data/lib/ruby/assoc.rb +17 -0
- data/lib/ruby/block.rb +42 -0
- data/lib/ruby/call.rb +34 -0
- data/lib/ruby/case.rb +30 -0
- data/lib/ruby/const.rb +49 -0
- data/lib/ruby/for.rb +18 -0
- data/lib/ruby/hash.rb +14 -0
- data/lib/ruby/if.rb +35 -0
- data/lib/ruby/list.rb +40 -0
- data/lib/ruby/literal.rb +45 -0
- data/lib/ruby/method.rb +19 -0
- data/lib/ruby/node.rb +47 -0
- data/lib/ruby/node/composite.rb +68 -0
- data/lib/ruby/node/conversions.rb +66 -0
- data/lib/ruby/node/position.rb +35 -0
- data/lib/ruby/node/source.rb +29 -0
- data/lib/ruby/node/text.rb +121 -0
- data/lib/ruby/node/traversal.rb +82 -0
- data/lib/ruby/operator.rb +49 -0
- data/lib/ruby/params.rb +41 -0
- data/lib/ruby/statements.rb +45 -0
- data/lib/ruby/string.rb +40 -0
- data/lib/ruby/symbol.rb +27 -0
- data/lib/ruby/token.rb +51 -0
- data/lib/ruby/while.rb +32 -0
- data/test/all.rb +3 -0
- data/test/builder/stack_test.rb +67 -0
- data/test/builder/text_test.rb +118 -0
- data/test/context_test.rb +54 -0
- data/test/erb_stripper_test.rb +29 -0
- data/test/fixtures/all.rb.src +150 -0
- data/test/fixtures/source_1.rb +16 -0
- data/test/fixtures/source_2.rb +1 -0
- data/test/fixtures/stuff.rb +371 -0
- data/test/fixtures/template.html.erb +22 -0
- data/test/fixtures/tmp.rb +6 -0
- data/test/lib_test.rb +92 -0
- data/test/lib_test_helper.rb +103 -0
- data/test/libs.txt +227 -0
- data/test/nodes/args_test.rb +100 -0
- data/test/nodes/array_test.rb +141 -0
- data/test/nodes/assignment_test.rb +49 -0
- data/test/nodes/block_test.rb +125 -0
- data/test/nodes/call_test.rb +229 -0
- data/test/nodes/case_test.rb +68 -0
- data/test/nodes/comments_test.rb +25 -0
- data/test/nodes/const_test.rb +46 -0
- data/test/nodes/conversions_test.rb +9 -0
- data/test/nodes/for_test.rb +34 -0
- data/test/nodes/hash_test.rb +71 -0
- data/test/nodes/heredoc_test.rb +202 -0
- data/test/nodes/identifier_test.rb +51 -0
- data/test/nodes/if_test.rb +100 -0
- data/test/nodes/literals_test.rb +63 -0
- data/test/nodes/method_test.rb +92 -0
- data/test/nodes/namespaces_test.rb +65 -0
- data/test/nodes/node_test.rb +74 -0
- data/test/nodes/nodes_test.rb +23 -0
- data/test/nodes/operator_test.rb +241 -0
- data/test/nodes/separators_test.rb +97 -0
- data/test/nodes/statements_test.rb +70 -0
- data/test/nodes/string_test.rb +92 -0
- data/test/nodes/symbol_test.rb +57 -0
- data/test/nodes/unless_test.rb +42 -0
- data/test/nodes/until_test.rb +61 -0
- data/test/nodes/while_test.rb +71 -0
- data/test/test_helper.rb +51 -0
- data/test/traversal_test.rb +53 -0
- 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
|