Class: Solid::Parser::Ripper
- Inherits:
-
Solid::Parser
- Object
- Solid::Parser
- Solid::Parser::Ripper
- Defined in:
- lib/solid/parser/ripper.rb
Constant Summary collapse
- REGEXP_FLAGS =
{ 'i' => Regexp::IGNORECASE, 'x' => Regexp::EXTENDED, 'm' => Regexp::MULTILINE, 'n' => Regexp::NOENCODING }
Constants inherited from Solid::Parser
Class Method Summary collapse
Instance Method Summary collapse
-
#dive_in ⇒ Object
Looks for a structure like [:program, [[:array, [#stuff#]]]] or [:program, [[:array, nil]]].
-
#handle_array(array) ⇒ Object
# [1] [[:@int, “1”, [1, 1]].
-
#handle_bare_assoc_hash(assoc_hash) ⇒ Object
# foo: 42 [[:assoc_new, [:@label, “foo:”, [1, 1]], [:@int, “42”, [1, 5]]]].
-
#handle_binary(left_operand, operator, right_operand) ⇒ Object
# 1 + 2 [:@int, “1”, [1, 0]], :*, [:@int, “2”, [1, 4]].
-
#handle_call(receiver_sexp, method_call, method_sexp) ⇒ Object
# myvar.length.
-
#handle_const(constant, lineno_column) ⇒ Object
# Spam “Spam”, [1, 23].
-
#handle_dot2(start_value, end_value) ⇒ Object
# 1..10 [[:@int, “1”, [1, 0]], [:@int, “10”, [1, 4]]].
-
#handle_dot3(start_value, end_value) ⇒ Object
# 1…10 [[:@int, “1”, [1, 0]], [:@int, “10”, [1, 4]]].
- #handle_dyna_symbol(string_content) ⇒ Object
-
#handle_float(float, lineno_column) ⇒ Object
# 4.2 “4.2”, [1, 2].
-
#handle_hash(hash) ⇒ Object
# 42 [:assoclist_from_args, [[:assoc_new, [:@label, “foo:”, [1, 2]], [:@int, “42”, [1, 7]]]]].
-
#handle_ident(identifier, lineno_column) ⇒ Object
# spam “spam”, [1, 23].
-
#handle_int(int, lineno_column) ⇒ Object
# 42 “42”, [1, 2].
-
#handle_kw(keyword, lineno_column) ⇒ Object
# true “true”, [1, 33].
-
#handle_label(label, lineno_column) ⇒ Object
# foo: “foo:”, [1, 2].
-
#handle_method_add_arg(call_sexp, args_sexp) ⇒ Object
# myvar.split(‘,’, 2).
-
#handle_paren(content) ⇒ Object
# (1) [[:@int, “42”, [1, 2]]].
-
#handle_regexp_literal(regexp_content, regexp_end) ⇒ Object
TODO: handle regexp interpolation.
- #handle_string_content(*parts) ⇒ Object
-
#handle_string_literal(string_content) ⇒ Object
# ‘mystring’ [:string_content, [:@tstring_content, “mystring”, [1, 14]]] TODO: handle string interpolation.
-
#handle_tstring_content(string_content, lineno_column) ⇒ Object
[:@tstring_content, “mystring”, [1, 14]].
-
#handle_unary(operator, operand) ⇒ Object
# !true [:!, [:var_ref, [:@kw, “true”, [1, 1]]]].
-
#handle_var_ref(var_ref) ⇒ Object
# spam [:@ident, “spam”, [1, 33]] or # true [:@kw, “true”, [1, 23]].
-
#handle_vcall(expression) ⇒ Object
# myvar.
-
#initialize(string) ⇒ Ripper
constructor
A new instance of Ripper.
- #instanciate_regexp(content, flags) ⇒ Object
-
#method_call_args(args_sexp) ⇒ Object
# args list: (‘,’, 2) [:arg_paren, [:args_add_block, [ [:string_literal, [:string_content, [:@tstring_content, “,”, [1, 14]]]], [:@int, “2”, [1, 18]] ], false]].
- #parse ⇒ Object
- #parse_one(argument) ⇒ Object
Constructor Details
#initialize(string) ⇒ Ripper
Returns a new instance of Ripper.
7 8 9 10 |
# File 'lib/solid/parser/ripper.rb', line 7 def initialize(string) @string = string @sexp = nil end |
Class Method Details
.parse(string) ⇒ Object
3 4 5 |
# File 'lib/solid/parser/ripper.rb', line 3 def self.parse(string) new(string).parse end |
Instance Method Details
#dive_in ⇒ Object
Looks for a structure like
- :program, [[:array, [#stuff#]]]
-
or
- :program, [[:array, nil]]
21 22 23 24 |
# File 'lib/solid/parser/ripper.rb', line 21 def dive_in @sexp = @sexp[1] @sexp = @sexp.first end |
#handle_array(array) ⇒ Object
# [1]
- [:@int, “1”, [1, 1]
115 116 117 |
# File 'lib/solid/parser/ripper.rb', line 115 def handle_array(array) LiteralArray.new((array || []).map(&method(:parse_one))) end |
#handle_bare_assoc_hash(assoc_hash) ⇒ Object
# foo: 42
- [:assoc_new, [:@label, “foo:”, [1, 1]], [:@int, “42”, [1, 5]]]
43 44 45 |
# File 'lib/solid/parser/ripper.rb', line 43 def (assoc_hash) LiteralHash.new assoc_hash.map {|(_, *key_value)| key_value.map(&method(:parse_one)) } end |
#handle_binary(left_operand, operator, right_operand) ⇒ Object
# 1 + 2
- :@int, “1”, [1, 0]], :*, [:@int, “2”, [1, 4]
108 109 110 111 |
# File 'lib/solid/parser/ripper.rb', line 108 def handle_binary(left_operand, operator, right_operand) receiver = parse_one(left_operand) MethodCall.new(receiver, operator, [parse_one(right_operand)]) end |
#handle_call(receiver_sexp, method_call, method_sexp) ⇒ Object
# myvar.length
- :var_ref, [:@ident, “myvar”, [1, 1]]
-
:“.”
- :@ident, “length”, [1, 7]
59 60 61 62 63 |
# File 'lib/solid/parser/ripper.rb', line 59 def handle_call(receiver_sexp, method_call, method_sexp) receiver = parse_one(receiver_sexp) method = method_sexp[1] MethodCall.new receiver, method, [] end |
#handle_const(constant, lineno_column) ⇒ Object
# Spam “Spam”, [1, 23]
198 199 200 |
# File 'lib/solid/parser/ripper.rb', line 198 def handle_const(constant, lineno_column) ContextVariable.new constant end |
#handle_dot2(start_value, end_value) ⇒ Object
# 1..10
- [:@int, “1”, [1, 0]], [:@int, “10”, [1, 4]]
127 128 129 |
# File 'lib/solid/parser/ripper.rb', line 127 def handle_dot2(start_value, end_value) LiteralRange.new(parse_one(start_value), parse_one(end_value), false) end |
#handle_dot3(start_value, end_value) ⇒ Object
# 1…10
- [:@int, “1”, [1, 0]], [:@int, “10”, [1, 4]]
133 134 135 |
# File 'lib/solid/parser/ripper.rb', line 133 def handle_dot3(start_value, end_value) LiteralRange.new(parse_one(start_value), parse_one(end_value), true) end |
#handle_dyna_symbol(string_content) ⇒ Object
153 154 155 |
# File 'lib/solid/parser/ripper.rb', line 153 def handle_dyna_symbol(string_content) Literal.new(string_content.first[1]) end |
#handle_float(float, lineno_column) ⇒ Object
# 4.2 “4.2”, [1, 2]
210 211 212 |
# File 'lib/solid/parser/ripper.rb', line 210 def handle_float(float, lineno_column) Literal.new float.to_f end |
#handle_hash(hash) ⇒ Object
# 42
- :assoclist_from_args, [[:assoc_new, [:@label, “foo:”, [1, 2]], [:@int, “42”, [1, 7]]]]
49 50 51 52 |
# File 'lib/solid/parser/ripper.rb', line 49 def handle_hash(hash) return LiteralHash.new({}) unless hash (hash.last) end |
#handle_ident(identifier, lineno_column) ⇒ Object
# spam “spam”, [1, 23]
192 193 194 |
# File 'lib/solid/parser/ripper.rb', line 192 def handle_ident(identifier, lineno_column) ContextVariable.new identifier end |
#handle_int(int, lineno_column) ⇒ Object
# 42 “42”, [1, 2]
204 205 206 |
# File 'lib/solid/parser/ripper.rb', line 204 def handle_int(int, lineno_column) Literal.new int.to_i end |
#handle_kw(keyword, lineno_column) ⇒ Object
# true “true”, [1, 33]
185 186 187 188 |
# File 'lib/solid/parser/ripper.rb', line 185 def handle_kw(keyword, lineno_column) raise Solid::SyntaxError, 'unknown Ripper sexp' unless KEYWORDS.has_key? keyword KEYWORDS[keyword] end |
#handle_label(label, lineno_column) ⇒ Object
# foo: “foo:”, [1, 2]
216 217 218 |
# File 'lib/solid/parser/ripper.rb', line 216 def handle_label(label, lineno_column) Literal.new label[0..-2].to_sym end |
#handle_method_add_arg(call_sexp, args_sexp) ⇒ Object
# myvar.split(‘,’, 2)
- :call, [:var_ref, [:@ident, “myvar”, [1, 1]]], :“.”, [:@ident, “split”, [1, 7]]
-
[:arg_paren, [:args_add_block, [
[:string_literal, [:string_content, [:@tstring_content, ",", [1, 14]]]], [:@int, "2", [1, 18]] ], false]]
80 81 82 83 84 |
# File 'lib/solid/parser/ripper.rb', line 80 def handle_method_add_arg(call_sexp, args_sexp) method_call = parse_one(call_sexp) method_call.arguments = method_call_args(args_sexp) method_call end |
#handle_paren(content) ⇒ Object
# (1)
- [:@int, “42”, [1, 2]]
121 122 123 |
# File 'lib/solid/parser/ripper.rb', line 121 def handle_paren(content) parse_one(content.first) end |
#handle_regexp_literal(regexp_content, regexp_end) ⇒ Object
TODO: handle regexp interpolation
179 180 181 |
# File 'lib/solid/parser/ripper.rb', line 179 def handle_regexp_literal(regexp_content, regexp_end) Literal.new instanciate_regexp(regexp_content.first[1], regexp_end[1][1..-1]) end |
#handle_string_content(*parts) ⇒ Object
144 145 146 |
# File 'lib/solid/parser/ripper.rb', line 144 def handle_string_content(*parts) parts.map(&method(:parse_one)).join end |
#handle_string_literal(string_content) ⇒ Object
# ‘mystring’
- :string_content, [:@tstring_content, “mystring”, [1, 14]]
-
TODO: handle string interpolation
140 141 142 |
# File 'lib/solid/parser/ripper.rb', line 140 def handle_string_literal(string_content) Literal.new(parse_one(string_content)) end |
#handle_tstring_content(string_content, lineno_column) ⇒ Object
- :@tstring_content, “mystring”, [1, 14]
149 150 151 |
# File 'lib/solid/parser/ripper.rb', line 149 def handle_tstring_content(string_content, lineno_column) string_content end |
#handle_unary(operator, operand) ⇒ Object
# !true
- :!, [:var_ref, [:@kw, “true”, [1, 1]]]
102 103 104 |
# File 'lib/solid/parser/ripper.rb', line 102 def handle_unary(operator, operand) MethodCall.new(parse_one(operand), operator, []) end |
#handle_var_ref(var_ref) ⇒ Object
# spam
- :@ident, “spam”, [1, 33]
-
or
# true
- :@kw, “true”, [1, 23]
37 38 39 |
# File 'lib/solid/parser/ripper.rb', line 37 def handle_var_ref(var_ref) parse_one(var_ref) end |
#handle_vcall(expression) ⇒ Object
# myvar
since 1.9.3
- :vcall, [:@ident, “myvar”, [1, 0]]
69 70 71 |
# File 'lib/solid/parser/ripper.rb', line 69 def handle_vcall(expression) parse_one(expression) end |
#instanciate_regexp(content, flags) ⇒ Object
164 165 166 167 168 169 170 |
# File 'lib/solid/parser/ripper.rb', line 164 def instanciate_regexp(content, flags) mode = 0 flags.each_char do |flag| mode |= REGEXP_FLAGS[flag] || 0 end Regexp.new(content, mode) end |
#method_call_args(args_sexp) ⇒ Object
# args list: (‘,’, 2) [:arg_paren, [:args_add_block, [
[:string_literal, [:string_content, [:@tstring_content, ",", [1, 14]]]],
[:@int, "2", [1, 18]]
], false]]
1 args list: ()
- :arg_paren, nil
94 95 96 97 98 |
# File 'lib/solid/parser/ripper.rb', line 94 def method_call_args(args_sexp) return [] if args_sexp[1].nil? args_sexp = args_sexp.last[1] args_sexp.map(&method(:parse_one)) end |
#parse ⇒ Object
12 13 14 15 16 |
# File 'lib/solid/parser/ripper.rb', line 12 def parse @sexp = ::Ripper.sexp(@string) dive_in or raise 'Ripper changed?' parse_one(@sexp) end |
#parse_one(argument) ⇒ Object
26 27 28 29 30 31 |
# File 'lib/solid/parser/ripper.rb', line 26 def parse_one(argument) type = argument.shift handler = "handle_#{type.to_s.sub('@', '')}" raise Solid::SyntaxError, "unknown Ripper type: #{type.inspect}" unless respond_to?(handler) public_send handler, *argument end |