summaryrefslogtreecommitdiff
path: root/jni/ruby/ext/ripper/tools
diff options
context:
space:
mode:
authorJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-16 18:49:26 +0900
committerJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-30 00:39:06 +0900
commitfcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch)
tree64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/ext/ripper/tools
Fresh start
Diffstat (limited to 'jni/ruby/ext/ripper/tools')
-rwxr-xr-xjni/ruby/ext/ripper/tools/generate-param-macros.rb14
-rwxr-xr-xjni/ruby/ext/ripper/tools/generate.rb161
-rwxr-xr-xjni/ruby/ext/ripper/tools/preproc.rb91
-rwxr-xr-xjni/ruby/ext/ripper/tools/strip.rb12
4 files changed, 278 insertions, 0 deletions
diff --git a/jni/ruby/ext/ripper/tools/generate-param-macros.rb b/jni/ruby/ext/ripper/tools/generate-param-macros.rb
new file mode 100755
index 0000000..b19f6e8
--- /dev/null
+++ b/jni/ruby/ext/ripper/tools/generate-param-macros.rb
@@ -0,0 +1,14 @@
+off = true
+ARGF.each do |line|
+ case line
+ when /RIPPER_PARAMS_DECL_BEGIN/
+ off = false
+ when /RIPPER_PARAMS_DECL_END/
+ exit
+ when /ripper/
+ next if off
+ var = line.scan(/\w+/).last or next
+ base = var.sub(/ripper_/, '')
+ puts %"\#define #{base}\t\t(parser->ripper_#{base})"
+ end
+end
diff --git a/jni/ruby/ext/ripper/tools/generate.rb b/jni/ruby/ext/ripper/tools/generate.rb
new file mode 100755
index 0000000..d9c9ae1
--- /dev/null
+++ b/jni/ruby/ext/ripper/tools/generate.rb
@@ -0,0 +1,161 @@
+# $Id: generate.rb 48169 2014-10-28 02:53:24Z nobu $
+
+require 'optparse'
+
+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
+
+def usage(msg)
+ $stderr.puts msg
+ $stderr.puts @parser.help
+ exit false
+end
+
+def generate_eventids1(ids)
+ buf = ""
+ 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
+
+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[ 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
+
+def read_ids1(path)
+ strip_locations(read_ids1_with_locations(path))
+end
+
+def strip_locations(h)
+ h.map {|event, list| [event, list.first[1]] }\
+ .sort_by {|event, arity| event.to_s }
+end
+
+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
+
+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
+ end
+ }
+ h
+end
+
+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
+
+main
diff --git a/jni/ruby/ext/ripper/tools/preproc.rb b/jni/ruby/ext/ripper/tools/preproc.rb
new file mode 100755
index 0000000..b2c4461
--- /dev/null
+++ b/jni/ruby/ext/ripper/tools/preproc.rb
@@ -0,0 +1,91 @@
+# $Id: preproc.rb 25189 2009-10-02 12:04:37Z akr $
+
+require 'optparse'
+
+def main
+ output = nil
+ parser = OptionParser.new
+ parser.banner = "Usage: #{File.basename($0)} [--output=PATH] <parse.y>"
+ 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
+ $stderr.puts err.message
+ $stderr.puts parser.help
+ exit false
+ end
+ unless ARGV.size == 1
+ abort "wrong number of arguments (#{ARGV.size} for 1)"
+ end
+ out = ""
+ File.open(ARGV[0]) {|f|
+ prelude f, out
+ grammar f, out
+ usercode f, out
+ }
+ if output
+ File.open(output, 'w') {|f|
+ f.write out
+ }
+ else
+ print out
+ end
+end
+
+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
+
+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
+
+def usercode(f, out)
+ while line = f.gets
+ out << line
+ end
+end
+
+main
diff --git a/jni/ruby/ext/ripper/tools/strip.rb b/jni/ruby/ext/ripper/tools/strip.rb
new file mode 100755
index 0000000..99413c3
--- /dev/null
+++ b/jni/ruby/ext/ripper/tools/strip.rb
@@ -0,0 +1,12 @@
+last_is_void = false
+ARGF.each do |line|
+ if line.strip.empty?
+ #puts() unless last_is_void
+ last_is_void = true
+ elsif /\A\#/ === line
+ ;
+ else
+ print line
+ last_is_void = false
+ end
+end