Class: Object (Ruby 2.7.2)
Description: Class : Object - Ruby 2.7.2

### Home Classes Methods

### In Files

- ripper/ripper.c
- ripper/tools/dsl.rb
- ripper/tools/generate.rb
- ripper/tools/preproc.rb

### Parent

BasicObject

### Methods

- ::const_missing
- #add_event
- #check_arity
- #generate_eventids1
- #generate_eventids2_table
- #grammar
- #main
- #method_missing
- #new_var
- #opt_event
- #prelude
- #read_ids1
- #read_ids1_with_locations
- #read_ids2
- #strip_locations
- #usage
- #usercode

### Class/Module Index

Quicksearch

- DSL
- Object
- Ripper
- Ripper::Filter

No matching classes.

# Object

### Constants

SCRIPT_LINES__

  When a Hash is assigned to `SCRIPT_LINES__` the contents of files loaded after the assignment will be added as an Array of lines with the file name as the key.

### Public Class Methods

const_missing(name) click to toggle source

                   # File ripper/tools/dsl.rb, line 81
    def self.const_missing(name)
      name
    end

### Public Instance Methods

add_event(event, args, qundef_check = false) click to toggle source

                   # File ripper/tools/dsl.rb, line 56
    def add_event(event, args, qundef_check = false)
      event = event.to_s.sub(/!\z/, "")
      @events[event] = args.size
      vars = []
      args.each do |arg|
        vars << v = new_var
        @code << "#{ v }=#{ arg };"
      end
      v = new_var
      d = "dispatch#{ args.size }(#{ [event, *vars].join(",") })"
      d = "#{ vars.last }==Qundef ? #{ vars.first } : #{ d }" if qundef_check
      @code << "#{ v }=#{ d };"
      v
    end

check_arity(h) click to toggle source

                   # File ripper/tools/generate.rb, line 126
    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 = "".dup
      buf << %Q[static struct {\n]
      ids.each do |id, arity|
        buf << %Q[    ID id_#{id};\n]
      end
      buf << %Q[} ripper_parser_ids;\n]
      buf << %Q[\n]
      ids.each do |id, arity|
        buf << %Q[#define ripper_id_#{id} ripper_parser_ids.id_#{id}\n]
      end
      buf << %Q[\n]
      buf << %Q[static void\n]
      buf << %Q[ripper_init_eventids1(void)\n]
      buf << %Q[{\n]
      buf << %Q[#define set_id1(name) ripper_id_##name = rb_intern_const("on_"#name)\n]
      ids.each do |id, arity|
        buf << %Q[    set_id1(#{id});\n]
      end
      buf << %Q[}\n]
      buf << %Q[\n]
      buf << %Q[static void\n]
      buf << %Q[ripper_init_eventids1_table(VALUE self)\n]
      buf << %Q[{\n]
      buf << %Q[    VALUE h = rb_hash_new();\n]
      buf << %Q[    rb_define_const(self, "PARSER_EVENT_TABLE", h);\n]
      ids.each do |id, arity|
        buf << %Q[    rb_hash_aset(h, intern_sym("#{id}"), INT2FIX(#{arity}));\n]
      end
      buf << %Q[}\n]
      buf
    end

generate_eventids2_table(ids) click to toggle source

                   # File ripper/tools/generate.rb, line 103
    def generate_eventids2_table(ids)
      buf = "".dup
      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[    rb_define_const(self, "SCANNER_EVENT_TABLE", h);\n]
      ids.each do |id|
        buf << %Q[    rb_hash_aset(h, intern_sym("#{id}"), INT2FIX(1));\n]
      end
      buf << %Q[}\n]
      buf
    end

grammar(f, out) click to toggle source

                   # File ripper/tools/preproc.rb, line 78
    def grammar(f, out)
      while line = f.gets
        case line
        when %r</\*% *ripper(?:\[(.*?)\])?: *(.*?) *%\*/>
          out << DSL.new($2, ($1 || "").split(",")).generate << $/
        when %r</\*%%%\*/>
          out << '#if 0' << $/
        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 6
    def main
      mode = nil
      ids1src = nil
      ids2src = 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

method_missing(event, *args) click to toggle source

                   # File ripper/tools/dsl.rb, line 71
    def method_missing(event, *args)
      if event.to_s =~ /!\z/
        add_event(event, args)
      elsif args.empty? and /\Aid[A-Z_]/ =~ event.to_s
        event
      else
        "#{ event }(#{ args.join(", ") })"
      end
    end

new_var() click to toggle source

                   # File ripper/tools/dsl.rb, line 48
    def new_var
      "v#{ @vars += 1 }"
    end

opt_event(event, default, addend) click to toggle source

                   # File ripper/tools/dsl.rb, line 52
    def opt_event(event, default, addend)
      add_event(event, [default, addend], true)
    end

prelude(f, out) click to toggle source

                   # File ripper/tools/preproc.rb, line 42
    def prelude(f, out)
      @exprs = {}
      lex_state_def = false
      while line = f.gets
        case line
        when /\A%%/
          out << '%%' << $/
          return
        when /\A%token/
          out << line.sub(/<\w+>/, '<val>')
        when /\A%type/
          out << line.sub(/<\w+>/, '<val>')
        when /^enum lex_state_(?:bits|e) \{/
          lex_state_def = true
          out << line
        when /^\}/
          lex_state_def = false
          out << line
        else
          out << line
        end
        if lex_state_def
          case line
          when /^\s*(EXPR_\w+),\s+\/\*(.+)\*\//
            @exprs[$1.chomp("_bit")] = $2.strip
          when /^\s*(EXPR_\w+)\s+=\s+(.+)$/
            name = $1
            val = $2.chomp(",")
            @exprs[name] = "equals to " + (val.start_with?("(") ? "<tt>#{val}</tt>" : "+#{val}+")
          end
        end
      end
    end

read_ids1(path) click to toggle source

                   # File ripper/tools/generate.rb, line 117
    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 140
    def read_ids1_with_locations(path)
      h = {}
      File.open(path) {|f|
        f.each do |line|
          next if /\A\#\s*define\s+dispatch/ =~ line
          next if /ripper_dispatch/ =~ line
          line.scan(/\bdispatch(\d)\((\w+)/) do |arity, event|
            (h[event] ||= []).push [f.lineno, arity.to_i]
          end
          if line =~ %r</\*% *ripper(?:\[(.*?)\])?: *(.*?) *%\*/>
            gen = DSL.new($2, ($1 || "").split(","))
            gen.generate
            gen.events.each do |event, arity|
              (h[event] ||= []).push [f.lineno, arity.to_i]
            end
          end
        end
      }
      h
    end

read_ids2(path) click to toggle source

                   # File ripper/tools/generate.rb, line 161
    def read_ids2(path)
      src = File.open(path) {|f| f.read}
      ids2 = src.scan(/ID\s+ripper_id_(\w+)/).flatten.uniq.sort
      diff = src.scan(/set_id2\((\w+)\);/).flatten - ids2
      unless diff.empty?
        abort "missing scanner IDs: #{diff}"
      end
      return ids2
    end

strip_locations(h) click to toggle source

                   # File ripper/tools/generate.rb, line 121
    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 98
    def usercode(f, out)
      require 'erb'
      compiler = ERB::Compiler.new('%-')
      compiler.put_cmd = compiler.insert_cmd = "out.<<"
      lineno = f.lineno
      src, = compiler.compile(f.read)
      eval(src, binding, f.path, lineno)
    end