Top Level Namespace

Defined Under Namespace

Classes: DSL, Ripper

Instance Method Summary collapse

Instance Method Details

#check_arity(h) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
# File 'tools/generate.rb', line 151

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



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'tools/generate.rb', line 92

def generate_eventids1(ids)
  buf = "".dup
  buf << %Q[#include "ruby/ruby.h"\n]
  buf << %Q[#include "eventids1.h"\n]
  buf << %Q[\n]
  buf << %Q[struct ripper_parser_ids ripper_parser_ids;\n]
  buf << %Q[\n]
  buf << %Q[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[#define intern_sym(name) ID2SYM(rb_intern_const(name))\n]
  buf << %Q[\n]
  buf << %Q[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_eventids1_h(ids) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'tools/generate.rb', line 73

def generate_eventids1_h(ids)
  buf = "".dup
  buf << %Q[#ifndef RIPPER_EVENTIDS1\n]
  buf << %Q[#define RIPPER_EVENTIDS1\n]
  buf << %Q[\n]
  buf << %Q[#define RIPPER_ID(n) ripper_parser_ids.id_ ## n\n]
  buf << %Q[void ripper_init_eventids1(void);\n]
  buf << %Q[void ripper_init_eventids1_table(VALUE self);\n]
  buf << %Q[\n]
  buf << %Q[struct ripper_parser_ids {\n]
  ids.each do |id, arity|
    buf << %Q[    ID id_#{id};\n]
  end
  buf << %Q[};\n]
  buf << %Q[\n]
  buf << %Q[#endif /* RIPPER_EVENTIDS1 */\n]
  buf << %Q[\n]
end

#generate_eventids2_table(ids) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'tools/generate.rb', line 122

def generate_eventids2_table(ids)
  buf = "".dup
  buf << %Q[#include "ruby/ruby.h"\n]
  buf << %Q[\n]
  buf << %Q[#define intern_sym(name) ID2SYM(rb_intern_const(name))\n]
  buf << %Q[\n]
  buf << %Q[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 << %Q[\n]
  buf << %Q[#define RIPPER_EVENTIDS2_TABLE_SIZE #{ids.size}\n]
  buf
end

#generate_line(f, out) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'tools/preproc.rb', line 56

def generate_line(f, out)
  while line = f.gets
    case
    when gen = DSL.line?(line, f.lineno)
      out << gen.generate << "\n"
    when line.start_with?("%%")
      out << "%%\n"
      break
    else
      out << yield(line)
    end
  end
end

#grammar(f, out) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'tools/preproc.rb', line 87

def grammar(f, out)
  generate_line(f, out) do |line|
    case line
    when %r</\*%%%\*/>
      "#if 0\n"
    when %r</\*%>
      "#endif\n"
    when %r<%\*/>
      "\n"
    else
      line
    end
  end
end

#mainObject



7
8
9
10
11
12
13
14
15
16
# File 'extconf.rb', line 7

def main
  $objs = %w(eventids1.o eventids2.o ripper.o ripper_init.o)
  $distcleanfiles.concat %w(ripper.y ripper.c eventids1.c eventids1.h eventids2table.c ripper_init.c)
  $cleanfiles.concat %w(ripper.E ripper.output y.output .eventids2-check)
  $defs << '-DRIPPER'
  $defs << '-DRIPPER_DEBUG' if $debug
  $VPATH << '$(topdir)' << '$(top_srcdir)'
  $INCFLAGS << ' -I$(topdir) -I$(top_srcdir)'
  create_makefile 'ripper'
end

#prelude(f, out) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'tools/preproc.rb', line 70

def prelude(f, out)
  @exprs = {}
  generate_line(f, out) do |line|
    if (/^enum lex_state_(?:bits|e) \{/ =~ line)..(/^\}/ =~ line)
      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
    line
  end
end

#process(f, out, path, template) ⇒ Object



48
49
50
51
52
# File 'tools/preproc.rb', line 48

def process(f, out, path, template)
  prelude f, out
  grammar f, out
  usercode f, out, path, template
end

#read_ids1(path) ⇒ Object



142
143
144
# File 'tools/generate.rb', line 142

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

#read_ids1_with_locations(path) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'tools/generate.rb', line 165

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 gen = DSL.line?(line, f.lineno)
        gen.events.each do |event, arity|
          (h[event] ||= []).push [f.lineno, arity.to_i]
        end
      end
    end
  }
  h
end

#read_ids2(path) ⇒ Object



184
185
186
187
188
189
190
191
192
# File 'tools/generate.rb', line 184

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



146
147
148
149
# File 'tools/generate.rb', line 146

def strip_locations(h)
  h.map {|event, list| [event, list.first[1]] }\
      .sort_by {|event, arity| event.to_s }
end

#usage(msg) ⇒ Object



67
68
69
70
71
# File 'tools/generate.rb', line 67

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

#usercode(f, out, path, template) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'tools/preproc.rb', line 102

def usercode(f, out, path, template)
  require 'erb'
  lineno = nil
  src = nil
  compiler = ERB::Compiler.new('%-')
  compiler.put_cmd = compiler.insert_cmd = "out.<<"

  if template
    File.open(template) do |f|
      out.clear
      lineno = f.lineno
      src, = compiler.compile(f.read)
      path = template
    end
  else
    lineno = f.lineno
    src, = compiler.compile(f.read)
  end

  eval(src, binding, path, lineno)
end