Top Level Namespace

Defined Under Namespace

Classes: DSL, Ripper

Instance Method Summary collapse

Instance Method Details

#check_arity(h) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
# File '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) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File '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) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
# File '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) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File '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 << "\n"
    when %r</\*%%%\*/>
      out << "#if 0\n"
    when %r</\*%>
      out << "#endif\n"
    when %r<%\*/>
      out << "\n"
    when /\A%%/
      out << "%%\n"
      return
    else
      out << line
    end
  end
end

#mainObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'extconf.rb', line 7

def main
  yacc = ENV["YACC"] || "bison"

  unless find_executable(yacc)
    unless File.exist?('ripper.c') or File.exist?("#{$srcdir}/ripper.c")
      raise 'missing bison; abort'
    end
  end
  $objs = %w(ripper.o)
  $cleanfiles.concat %w(ripper.y ripper.c ripper.E ripper.output y.output eventids1.c eventids2table.c .eventids2-check)
  $defs << '-DRIPPER'
  $defs << '-DRIPPER_DEBUG' if $debug
  $VPATH << '$(topdir)' << '$(top_srcdir)'
  $INCFLAGS << ' -I$(topdir) -I$(top_srcdir)'
  create_makefile 'ripper' do |conf|
    conf << "BISON = #{yacc}"
  end
end

#prelude(f, out) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'tools/preproc.rb', line 42

def prelude(f, out)
  @exprs = {}
  lex_state_def = false
  while line = f.gets
    case line
    when /\A%%/
      out << "%%\n"
      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) ⇒ Object



117
118
119
# File 'tools/generate.rb', line 117

def read_ids1(path)
  strip_locations(read_ids1_with_locations(path))
end

#read_ids1_with_locations(path) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File '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) ⇒ Object



161
162
163
164
165
166
167
168
169
# File '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) ⇒ Object



121
122
123
124
# File '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) ⇒ Object



64
65
66
67
68
# File 'tools/generate.rb', line 64

def usage(msg)
  $stderr.puts msg
  $stderr.puts @parser.help
  exit false
end

#usercode(f, out) ⇒ Object



98
99
100
101
102
103
104
105
# File '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