#!/usr/bin/env ruby # # c++2rb : partial conversion from C and C++ to Ruby # # Copyright (c) 2001 Issac Trotts # # Under the Ruby license # # TODO # - template functions # - template classes # - build a database of all the functions for a given class and # put them all in a single file as a post-processing step $type_re = '(void|char|short|int|long|float|double)' $map_re = '\bmap\s*<.*>' $list_re = '\blist\s*<.*>' $vector_re = '\bvector\s*<.*>' $token_re = '[a-zA-Z_][a-zA-Z0-9_]*' def do_generic_line(line, outfile) line.gsub!(/;/, '') line.gsub!(/#include\s+\<([^>.]+)(.h)?>/, 'require \'\1\'') line.gsub!(/\/, '') line.gsub!(/\\s*/, '') line.gsub!(/\\s*/, '') line.gsub!(/\\s*/, '') eval('line.gsub!(/#{$list_re}\s*(#{$token_re})/, \'\1 = []\')') eval('line.gsub!(/#{$vector_re}\s*(#{$token_re})/, \'\1 = []\')') eval('line.gsub!(/#{$map_re}\s*(#{$token_re})/, \'\1 = {}\')') line.gsub!(/push_back/, 'push') line.gsub!(/\/, 'self') line.gsub!(/\/, '"\n"') line.gsub!(/\<(public|protected|private)\>\s*\:/, '\1') # comments line.gsub!(/\/\//, '#') line.gsub!(/\{/, '') line.gsub!(/^(\s*)}/, '\1end') line.sub!(/(\S+)(\s*)}/, '\1\2; end') line.gsub!(/\/, 'when') line.gsub!(/\/, 'case') line.gsub!(/\/, 'else') line.gsub!(/\/, 'class') line.gsub!(/if\s*\(([^)]+)\)/, 'if \1') # inheritance line.gsub!(/:\s+(public|private|protected)/, '<') line.gsub!(/\-\>/, '.') # global functions with no args eval("line.sub!(/#{$type_re}\\s+(#{$token_re})\\s*\\(\\s*\\)/, "+ '\'def \2\')') # global functions with args eval("line.sub!(/#{$type_re}\\s+(#{$token_re})\\s*(\\(.*\\))\s*{?/, "+ '\'def \2\3\')') # constructors #if eval("line.gsub!(/(#{$token_re})::\\1(.*)/, 'class \\1; def initialize\\2')") #return #end #eval("gsub!(/#{token_re)::#{(token_re)}, 'class \\1; def initialize\\2')") # member functions with no args eval("line.sub!(/#{$type_re}\\s+(#{$token_re})::(#{$token_re})\\s*\\(\\s*\\)/, "+ '\'class \2; def \3 # FIXME: put another end at the end\')') # member functions with args eval("line.sub!(/#{$type_re}\\s+(#{$token_re})::(#{$token_re})\\s*\\((.*)\\)/, "+ '\'class \2; def \3 (\4) # FIXME: put another end at the end\')') # member function invocations with no args # member function invocations with args # for-loops... # using std::cout; --> cout = std::cout # using namespace X # namespaces line.gsub!(/namespace/, 'module') #eval("gsub!(/#{type_re}\s+#{token_re}/, 'TYPE VAR')") #eval("gsub!(/#{type_re}\\s*#{token_re}\\s*\\(\\s*\\)\\*;/, 'TYPE FUNC')") # functions # OpenGL calls (using the Ruby OpenGL extension) line.gsub!(/\bgl([a-zA-Z0-9]+)/, 'GL.\1') outfile.write(line) end def parse(filename) newname = filename+'.rb' $stdout.sync = true puts 'Creating '+newname infile = File.new(filename, 'r') outfile = File.new(newname, 'w') lines = infile.readlines() infile.close() mode = 'default' lines.each_with_index { |line, i| do_generic_line(line, outfile) #case mode #when 'class_decl' #when #else #mode = do_generic_line(line, outfile, mode) #end } end ARGV.each { |filename| parse(filename) } # TODO: THE NEW WAY: # step 1: gather namespace/class/struct/function/variable declarations/definitions # making a note of the file basename for each one # step 2: for each basename, create a ruby file containing the appropriate # contents