Tôi e rằng các cụm từ thông dụng sẽ không đưa bạn đi rất xa. Xem xét ví dụ các biểu thức sau (cũng là Ruby hợp lệ)
"(foo.bar.size.split('.')).last"
"(foo.bar.size.split '.').last"
"(foo.bar.size.split '(.) . .(). .').last"
Vấn đề là danh sách các cuộc gọi thực sự là một cây gọi. Giải pháp đơn giản nhất trong tầm nhìn có lẽ là sử dụng một phân tích cú pháp Ruby và chuyển đổi cây phân tích cú pháp theo yêu cầu của bạn (trong ví dụ này, chúng tôi đang đệ quy giảm dần vào cây gọi, thu thập các cuộc gọi vào một danh sách):
# gem install ruby_parser
# gem install awesome_print
require 'ruby_parser'
require 'ap'
def calls_as_list code
tree = RubyParser.new.parse(code)
t = tree
calls = []
while t
# gather arguments if present
args = nil
if t[3][0] == :arglist
args = t[3][1..-1].to_a
end
# append all information to our list
calls << [t[2].to_s, args]
# descend to next call
t = t[1]
end
calls.reverse
end
p calls_as_list "foo.bar.size.split('.').last"
#=> [["foo", []], ["bar", []], ["size", []], ["split", [[:str, "."]]], ["last", []]]
p calls_as_list "puts 3, 4"
#=> [["puts", [[:lit, 3], [:lit, 4]]]]
Và để hiển thị cây phân tích cú pháp của bất kỳ đầu vào:
ap RubyParser.new.parse("puts 3, 4")
Nó không phải là dễ dàng như bạn nghĩ. – sawa
@sawa: bạn đã đóng một câu hỏi bởi vì bạn nghĩ rằng nó quá khó? – iconoclast
@iconoclast Tôi không nhớ, nhưng không phải vì lý do bạn nghĩ. – sawa