Extended maintenance of Ruby versions 1.8.7 and 1.9.2 will end on July 31, 2014. Read more

In Files

  • ripper/tools/generate.rb
  • ripper/tools/preproc.rb

Object

Public Instance Methods

check_arity(h) click to toggle source
 
               # File ripper/tools/generate.rb, line 120
def check_arity(h)
  invalid = false
  h.each do |event, list|
    unless list.map {|line, arity| arity }.uniq.size == 1
      invalid = true
      locations = list.map {|line, a| "#{line}:#{a}" }.join(', ')
      $stderr.puts "arity crash [event=#{event}]: #{locations}"
    end
  end
  abort if invalid
end
            
generate_eventids1(ids) click to toggle source
 
               # File ripper/tools/generate.rb, line 70
def generate_eventids1(ids)
  buf = ""
  ids.each do |id, arity|
    buf << %Q[static ID ripper_id_#{id};\n]
  end
  buf << %Q[\n]
  buf << %Q[static void\n]
  buf << %Q[ripper_init_eventids1(VALUE self)\n]
  buf << %Q[{\n]
  buf << %Q[    VALUE h;\n]
  buf << %Q[    ID id;\n]
  ids.each do |id, arity|
    buf << %Q[    ripper_id_#{id} = rb_intern_const("on_#{id}");\n]
  end
  buf << %Q[\n]
  buf << %Q[    h = rb_hash_new();\n]
  buf << %Q[    rb_define_const(self, "PARSER_EVENT_TABLE", h);\n]
  ids.each do |id, arity|
    buf << %Q[    id = rb_intern_const("#{id}");\n]
    buf << %Q[    rb_hash_aset(h, ID2SYM(id), INT2NUM(#{arity}));\n]
  end
  buf << %Q[}\n]
  buf
end
            
generate_eventids2_table(ids) click to toggle source
 
               # File ripper/tools/generate.rb, line 95
def generate_eventids2_table(ids)
  buf = ""
  buf << %Q[static void\n]
  buf << %Q[ripper_init_eventids2_table(VALUE self)\n]
  buf << %Q[{\n]
  buf << %Q[    VALUE h = rb_hash_new();\n]
  buf << %Q[    ID id;\n]
  buf << %Q[    rb_define_const(self, "SCANNER_EVENT_TABLE", h);\n]
  ids.each do |id|
    buf << %Q[    id = rb_intern_const("#{id}");\n]
    buf << %Q[    rb_hash_aset(h, ID2SYM(id), INT2NUM(1));\n]
  end
  buf << %Q[}\n]
  buf
end
            
grammar(f, out) click to toggle source
 
               # File ripper/tools/preproc.rb, line 63
def grammar(f, out)
  while line = f.gets
    case line
    when %r</\*%%%\*/>
      out << '#if 0' << $/
    when %r</\*%c%\*/>
      out << '/*' << $/
    when %r</\*%c>
      out << '*/' << $/
    when %r</\*%>
      out << '#endif' << $/
    when %r<%\*/>
      out << $/
    when /\A%%/
      out << '%%' << $/
      return
    else
      out << line
    end
  end
end
            
main() click to toggle source
 
               # File ripper/tools/generate.rb, line 5
def main
  mode = nil
  ids1src = nil
  ids2src = nil
  template = nil
  output = nil

  parser = @parser = OptionParser.new
  parser.banner = "Usage: #{File.basename($0)} --mode=MODE [--ids1src=PATH] [--ids2src=PATH] [--output=PATH]"
  parser.on('--mode=MODE', 'check, eventids1, or eventids2table.') {|m|
    mode = m
  }
  parser.on('--ids1src=PATH', 'A source file of event-IDs 1 (parse.y).') {|path|
    ids1src = path
  }
  parser.on('--ids2src=PATH', 'A source file of event-IDs 2 (eventids2.c).') {|path|
    ids2src = path
  }
  parser.on('--output=PATH', 'An output file.') {|path|
    output = path
  }
  parser.on('--help', 'Prints this message and quit.') {
    puts parser.help
    exit true
  }
  begin
    parser.parse!
  rescue OptionParser::ParseError => err
    usage err.message
  end
  usage 'no mode given' unless mode
  case mode
  when 'check'
    usage 'no --ids1src' unless ids1src
    usage 'no --ids2src' unless ids2src
    h = read_ids1_with_locations(ids1src)
    check_arity h
    ids2 = read_ids2(ids2src)
    common = h.keys & ids2
    unless common.empty?
      abort "event crash: #{common.join(' ')}"
    end
    exit 0
  when 'eventids1'
    usage 'no --ids1src' unless ids1src
    result = generate_eventids1(read_ids1(ids1src))
  when 'eventids2table'
    usage 'no --ids2src' unless ids2src
    result = generate_eventids2_table(read_ids2(ids2src))
  end
  if output
    File.open(output, 'w') {|f|
      f.write result
    }
  else
    puts result
  end
end
            
prelude(f, out) click to toggle source
 
               # File ripper/tools/preproc.rb, line 41
def prelude(f, out)
  while line = f.gets
    case line
    when %r</\*%%%\*/>
      out << '/*' << $/
    when %r</\*%>
      out << '*/' << $/
    when %r<%\*/>
      out << $/
    when /\A%%/
      out << '%%' << $/
      return
    when /\A%token/
      out << line.sub(/<\w+>/, '<val>')
    when /\A%type/
      out << line.sub(/<\w+>/, '<val>')
    else
      out << line
    end
  end
end
            
read_ids1(path) click to toggle source
 
               # File ripper/tools/generate.rb, line 111
def read_ids1(path)
  strip_locations(read_ids1_with_locations(path))
end
            
read_ids1_with_locations(path) click to toggle source
 
               # File ripper/tools/generate.rb, line 132
def read_ids1_with_locations(path)
  h = {}
  File.open(path) {|f|
    f.each do |line|
      next if /\A\#\s*define\s+s?dispatch/ =~ line
      next if /ripper_dispatch/ =~ line
      line.scan(/dispatch(\d)\((\w+)/) do |arity, event|
        (h[event] ||= []).push [f.lineno, arity.to_i]
      end
    end
  }
  h
end
            
read_ids2(path) click to toggle source
 
               # File ripper/tools/generate.rb, line 146
def read_ids2(path)
  File.open(path) {|f|
    return f.read.scan(/ripper_id_(\w+)/).flatten.uniq.sort
  }
end
            
strip_locations(h) click to toggle source
 
               # File ripper/tools/generate.rb, line 115
def strip_locations(h)
  h.map {|event, list| [event, list.first[1]] }       .sort_by {|event, arity| event.to_s }
end
            
usage(msg) click to toggle source
 
               # File ripper/tools/generate.rb, line 64
def usage(msg)
  $stderr.puts msg
  $stderr.puts @parser.help
  exit false
end
            
usercode(f, out) click to toggle source
 
               # File ripper/tools/preproc.rb, line 85
def usercode(f, out)
  while line = f.gets
    out << line
  end
end
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus