Bug #6929 » 0001-Documentation-for-Ripper.patch
| ext/ripper/extconf.rb | ||
|---|---|---|
| require 'mkmf' | ||
| require 'rbconfig' | ||
| def main | ||
| def main # :nodoc: | ||
|   unless find_executable('bison') | ||
|     unless File.exist?('ripper.c') or File.exist?("#{$srcdir}/ripper.c") | ||
|       raise 'missing bison; abort' | ||
| ext/ripper/lib/ripper.rb | ||
|---|---|---|
| require 'ripper/lexer' | ||
| require 'ripper/filter' | ||
| require 'ripper/sexp' | ||
| # Ripper is a Ruby script parser. | ||
| # | ||
| # You can get information from the parser with event-based style. | ||
| # Information such as abstract syntax trees or simple lexical analysis of the | ||
| # Ruby program. | ||
| # | ||
| # == Usage | ||
| # | ||
| # Ripper provides an easy interface for parsing your program into a symbolic | ||
| # expression tree (or S-expression). | ||
| # | ||
| # Understanding the output of the parser may come as a challenge, it's | ||
| # recommended you use PP to format the output for legibility. | ||
| # | ||
| #   require 'ripper' | ||
| #   require 'pp' | ||
| # | ||
| #   pp Ripper.sexp('def hello(world); "Hello, #{world}!"; end') | ||
| #     #=> [:program, | ||
| #          [[:def, | ||
| #            [:@ident, "hello", [1, 4]], | ||
| #            [:paren, | ||
| #             [:params, [[:@ident, "world", [1, 10]]], nil, nil, nil, nil, nil, nil]], | ||
| #            [:bodystmt, | ||
| #             [[:void_stmt], | ||
| #              [:string_literal, | ||
| #               [:string_content, | ||
| #                [:@tstring_content, "Hello, ", [1, 19]], | ||
| #                [:string_embexpr, [[:var_ref, [:@ident, "world", [1, 28]]]]], | ||
| #                [:@tstring_content, "!", [1, 34]]]]], | ||
| #             nil, | ||
| #             nil, | ||
| #             nil]]]] | ||
| # | ||
| # You can see in the example above, the expression starts with +:program+. | ||
| # | ||
| # From here, a method definition at +:def+, followed by the method's identifier | ||
| # <code>:@ident</code>. After the method's identifier comes the parentheses | ||
| # +:paren+ and the method parameters under +:params+. | ||
| # | ||
| # Next is the method body, starting at +:bodystmt+ (+stmt+ meaning statement), | ||
| # which contains the full definition of the method. | ||
| # | ||
| # In our case, we're simply returning a String, so next we have the | ||
| # +:void_stmt+ followed by a +:string_literal+. | ||
| # | ||
| # Within our +:string_literal+ you'll notice two <code>@tstring_content</code>, | ||
| # this is the literal part for <code>Hello, </code> and <code>!</code>. Between | ||
| # the two <code>@tstring_content</code> statements is a +:string_embexpr+, | ||
| # where _embexpr_ is an embedded expression. Our expression consists of a local | ||
| # variable, or +var_ref+, with the identifier (<code>@ident</code>) of +world+. | ||
| # | ||
| # == Resources | ||
| # | ||
| # * {Ruby Inside}[http://www.rubyinside.com/using-ripper-to-see-how-ruby-is-parsing-your-code-5270.html] | ||
| # | ||
| # == Requirements | ||
| # | ||
| # * ruby 1.9 (support CVS HEAD only) | ||
| # * bison 1.28 or later (Other yaccs do not work) | ||
| # | ||
| # == License | ||
| # | ||
| #   Ruby License. | ||
| # | ||
| #                                                 Minero Aoki | ||
| #                                         aamine@loveruby.net | ||
| #                                       http://i.loveruby.net | ||
| class Ripper; end | ||
| ext/ripper/lib/ripper/core.rb | ||
|---|---|---|
| class Ripper | ||
|   # Parses Ruby program read from _src_. | ||
|   # _src_ must be a String or a IO or a object which has #gets method. | ||
|   # Parses the given Ruby program read from +src+. | ||
|   # +src+ must be a String or an IO or a object with a #gets method. | ||
|   def Ripper.parse(src, filename = '(ripper)', lineno = 1) | ||
|     new(src, filename, lineno).parse | ||
|   end | ||
| ... | ... | |
|   end | ||
|   # This method is called when weak warning is produced by the parser. | ||
|   # _fmt_ and _args_ is printf style. | ||
|   # +fmt+ and +args+ is printf style. | ||
|   def warn(fmt, *args) | ||
|   end | ||
|   # This method is called when strong warning is produced by the parser. | ||
|   # _fmt_ and _args_ is printf style. | ||
|   # +fmt+ and +args+ is printf style. | ||
|   def warning(fmt, *args) | ||
|   end | ||
| ext/ripper/lib/ripper/filter.rb | ||
|---|---|---|
| class Ripper | ||
|   # This class handles only scanner events, | ||
|   # and they are dispatched in the `right' order (same with input). | ||
|   # which are dispatched in the 'right' order (same with input). | ||
|   class Filter | ||
|     # Creates a new Ripper::Filter instance, passes parameters +src+, | ||
|     # +filename+, and +lineno+ to Ripper::Lexer.new | ||
|     # | ||
|     # The lexer is for internal use only. | ||
|     def initialize(src, filename = '-', lineno = 1) | ||
|       @__lexer = Lexer.new(src, filename, lineno) | ||
|       @__line = nil | ||
| ... | ... | |
|       @__col | ||
|     end | ||
|     # Starts parsing.  _init_ is a data accumulator. | ||
|     # It is passed to the next event handler (as of Enumerable#inject). | ||
|     # Starts the parser. | ||
|     # +init+ is a data accumulator and is passed to the next event handler (as | ||
|     # of Enumerable#inject). | ||
|     def parse(init = nil) | ||
|       data = init | ||
|       @__lexer.lex.each do |pos, event, tok| | ||
| ... | ... | |
|     private | ||
|     # This method is called when some event handler have not defined. | ||
|     # _event_ is :on_XXX, _token_ is scanned token, _data_ is a data | ||
|     # accumulator.  The return value of this method is passed to the | ||
|     # next event handler (as of Enumerable#inject). | ||
|     # This method is called when some event handler is undefined. | ||
|     # +event+ is :on_XXX, +token+ is the scanned token, and +data+ is a data | ||
|     # accumulator. | ||
|     # | ||
|     # The return value of this method is passed to the next event handler (as | ||
|     # of Enumerable#inject). | ||
|     def on_default(event, token, data) | ||
|       data | ||
|     end | ||
| ext/ripper/lib/ripper/lexer.rb | ||
|---|---|---|
| class Ripper | ||
|   # Tokenizes Ruby program and returns an Array of String. | ||
|   # Tokenizes the Ruby program and returns an Array of String. | ||
|   def Ripper.tokenize(src, filename = '-', lineno = 1) | ||
|     Lexer.new(src, filename, lineno).tokenize | ||
|   end | ||
|   # Tokenizes Ruby program and returns an Array of Array, | ||
|   # which is formatted like [[lineno, column], type, token]. | ||
|   # Tokenizes the Ruby program and returns an Array of an Array, | ||
|   # which is formatted like <code>[[lineno, column], type, token]</code>. | ||
|   # | ||
|   #   require 'ripper' | ||
|   #   require 'pp' | ||
| ... | ... | |
|   class TokenPattern   #:nodoc: | ||
|     class Error < ::StandardError; end | ||
|     class CompileError < Error; end | ||
|     class MatchError < Error; end | ||
|     class Error < ::StandardError # :nodoc: | ||
|     end | ||
|     class CompileError < Error # :nodoc: | ||
|     end | ||
|     class MatchError < Error # :nodoc: | ||
|     end | ||
|     class << self | ||
|       alias compile new | ||
| ... | ... | |
|       MAP[tok]  or raise CompileError, "unknown token: #{tok}" | ||
|     end | ||
|     class MatchData | ||
|     class MatchData # :nodoc: | ||
|       def initialize(tokens, match) | ||
|         @tokens = tokens | ||
|         @match = match | ||
| ext/ripper/lib/ripper/sexp.rb | ||
|---|---|---|
|   # [EXPERIMENTAL] | ||
|   # Parses +src+ and create S-exp tree. | ||
|   # Returns more readable tree rather than Ripper.sexp_raw. | ||
|   # This method is for mainly developer use. | ||
|   # This method is mainly for developer use. | ||
|   # | ||
|   #   require 'ripper' | ||
|   #   require 'pp' | ||
| ... | ... | |
|   # [EXPERIMENTAL] | ||
|   # Parses +src+ and create S-exp tree. | ||
|   # This method is for mainly developer use. | ||
|   # This method is mainly for developer use. | ||
|   # | ||
|   #   require 'ripper' | ||
|   #   require 'pp' | ||
| ext/ripper/tools/generate.rb | ||
|---|---|---|
| require 'optparse' | ||
| def main | ||
| def main # :nodoc: | ||
|   mode = nil | ||
|   ids1src = nil | ||
|   ids2src = nil | ||
| ... | ... | |
|   end | ||
| end | ||
| def usage(msg) | ||
| def usage(msg) # :nodoc: | ||
|   $stderr.puts msg | ||
|   $stderr.puts @parser.help | ||
|   exit false | ||
| end | ||
| def generate_eventids1(ids) | ||
| def generate_eventids1(ids) # :nodoc: | ||
|   buf = "" | ||
|   ids.each do |id, arity| | ||
|     buf << %Q[static ID ripper_id_#{id};\n] | ||
| ... | ... | |
|   buf | ||
| end | ||
| def generate_eventids2_table(ids) | ||
| def generate_eventids2_table(ids) # :nodoc: | ||
|   buf = "" | ||
|   buf << %Q[static void\n] | ||
|   buf << %Q[ripper_init_eventids2_table(VALUE self)\n] | ||
| ... | ... | |
|   buf | ||
| end | ||
| def read_ids1(path) | ||
| def read_ids1(path) # :nodoc: | ||
|   strip_locations(read_ids1_with_locations(path)) | ||
| end | ||
| def strip_locations(h) | ||
| def strip_locations(h) # :nodoc: | ||
|   h.map {|event, list| [event, list.first[1]] }\ | ||
|       .sort_by {|event, arity| event.to_s } | ||
| end | ||
| def check_arity(h) | ||
| def check_arity(h) # :nodoc: | ||
|   invalid = false | ||
|   h.each do |event, list| | ||
|     unless list.map {|line, arity| arity }.uniq.size == 1 | ||
| ... | ... | |
|   abort if invalid | ||
| end | ||
| def read_ids1_with_locations(path) | ||
| def read_ids1_with_locations(path) # :nodoc: | ||
|   h = {} | ||
|   File.open(path) {|f| | ||
|     f.each do |line| | ||
| ... | ... | |
|   h | ||
| end | ||
| def read_ids2(path) | ||
| def read_ids2(path) # :nodoc: | ||
|   File.open(path) {|f| | ||
|     return f.read.scan(/ripper_id_(\w+)/).flatten.uniq.sort | ||
|   } | ||
| ext/ripper/tools/preproc.rb | ||
|---|---|---|
| require 'optparse' | ||
| def main | ||
| def main # :nodoc: | ||
|   output = nil | ||
|   parser = OptionParser.new | ||
|   parser.banner = "Usage: #{File.basename($0)} [--output=PATH] <parse.y>" | ||
| ... | ... | |
|   end | ||
| end | ||
| def prelude(f, out) | ||
| def prelude(f, out) # :nodoc: | ||
|   while line = f.gets | ||
|     case line | ||
|     when %r</\*%%%\*/> | ||
| ... | ... | |
|   end | ||
| end | ||
| def grammar(f, out) | ||
| def grammar(f, out) # :nodoc: | ||
|   while line = f.gets | ||
|     case line | ||
|     when %r</\*%%%\*/> | ||
| ... | ... | |
|   end | ||
| end | ||
| def usercode(f, out) | ||
| def usercode(f, out) # :nodoc: | ||
|   while line = f.gets | ||
|     out << line | ||
|   end | ||