diff options
| author | Daniel Bovensiepen <[email protected]> | 2013-06-23 17:37:39 +0800 |
|---|---|---|
| committer | Daniel Bovensiepen <[email protected]> | 2013-06-23 17:37:39 +0800 |
| commit | 52336e540819730ac95b817bcd0e788e92780eb2 (patch) | |
| tree | 984828a77acbccd63b2ec30b3e372ef3e8183eec /doc/language/mrbdoc/lib/mrbdoc_analyze.rb | |
| parent | 0a8381b7a06aa7d10a218b82c132d6060626aaf2 (diff) | |
| download | mruby-52336e540819730ac95b817bcd0e788e92780eb2.tar.gz mruby-52336e540819730ac95b817bcd0e788e92780eb2.zip | |
Add mrbdoc - first draft
Diffstat (limited to 'doc/language/mrbdoc/lib/mrbdoc_analyze.rb')
| -rw-r--r-- | doc/language/mrbdoc/lib/mrbdoc_analyze.rb | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/doc/language/mrbdoc/lib/mrbdoc_analyze.rb b/doc/language/mrbdoc/lib/mrbdoc_analyze.rb new file mode 100644 index 000000000..88b42fc69 --- /dev/null +++ b/doc/language/mrbdoc/lib/mrbdoc_analyze.rb @@ -0,0 +1,215 @@ +class MRBDoc + SRC_DIR = 'src' + MRBLIB_DIR = 'mrblib' + + def analyze_code dir, &block + @mrb_files = {} + @dir = File.expand_path(dir) + + block.call "MRBDOC\tStart Analyzing Source of #{@dir}" + + analyze(dir) do |progress| + block.call progress + end + + block.call "MRBDOC\tFinish Analyzing Source" + end + + def each_file(&block); @mrb_files.each {|k,v| block.call k,v}; end + + def find_c_func(c_func_name) + each_file do |file_name, file| + c_func = file.c_funcs(c_func_name) + return c_func unless c_func.nil? + end + {} + end + + def find_c_file(rb_obj_name, c_func_name) + last_file_name_match = '' + each_file do |file_name, file| + c_func = file.c_funcs(c_func_name) + if c_func and file.rb_class(rb_obj_name) or file.rb_module(rb_obj_name) + return file_name + elsif c_func + last_file_name_match = file_name + end + end + last_file_name_match + end + + def find_c_file_by_class(name) + each_file do |file_name, file| + rb_class = file.rb_class(name) + return file_name unless rb_class.nil? + end + 'nil' + end + + def find_c_file_by_module(name) + each_file do |file_name, file| + rb_module = file.rb_module(name) + return file_name unless rb_module.nil? + end + 'nil' + end + + private + + def analyze dir, &block + collect_all_files dir, &block + end + + def collect_all_files dir, &block + l = lambda {|f| block.call " - #{f.name}"} + collect_files(src_code_dir(dir), /\.c$/, &l) + collect_files(mrb_code_dir(dir), /\.rb$/, &l) + end + + def collect_files dir, rxp, &block + Dir.foreach(dir) do |file| + next unless file =~ rxp + + file_path = "#{dir}/#{file}" + mrb_file = MRBFile.new "#{file_path}" + @mrb_files["#{file_path}"] = mrb_file + + block.call mrb_file + end + end + + def src_code_dir dir; File.expand_path SRC_DIR, dir; end + def mrb_code_dir dir; File.expand_path MRBLIB_DIR, dir; end +end + +class MRBFile + attr_reader :name + attr_reader :file + + def initialize mrb_file + @file = mrb_file + @name = File.basename file + @c_funcs = {} + @rb_class_c_def = {} + @rb_method_c_def = {} + @rb_class_method_c_def = {} + @rb_module_c_def = {} + @last_line = nil + @assignments = {} + + analyze + end + + def each_class &block + @rb_class_c_def.each do |class_name, class_hsh| + block.call class_name, class_hsh + end + end + + def each_method name, &block + @rb_method_c_def.each do |met_name, met_hsh| + met_name_tmp = met_name.sub /^#{name}_/, '' + block.call met_name_tmp, met_hsh if met_hsh[:rb_class] == name + end + end + + def each_class_method name, &block + @rb_class_method_c_def.each do |met_name, met_hsh| + met_name_tmp = met_name.sub /^#{name}_/, '' + block.call met_name_tmp, met_hsh if met_hsh[:rb_class] == name + end + end + + def each_module &block + @rb_module_c_def.each_key do |module_name| + block.call module_name + end + end + + def each_core_object &block + each_class {|n| block.call n} + each_module {|n| block.call n} + end + + def c_funcs c_func_name; @c_funcs[c_func_name]; end + def rb_class rb_class_name; @rb_class_c_def[rb_class_name]; end + def rb_module rb_module_name; @rb_module_c_def[rb_module_name]; end + + private + + def analyze + File.open(file).each_line.each_with_index do |line, idx| + line_no = idx.succ + if c_file? + analyze_c_line line, line_no + elsif rb_file? + analyze_rb_line line, line_no + else + raise ArgumentError.new "#{file} is a not supported file type" + end + @last_line = line.strip + end + end + + def c_file?; (name =~ /\.c$/); end + def rb_file?; (name =~ /\.rb$/); end + + RXP_C_VAR = /\s*([^\s]*?)\s*?/ + RXP_C_STR = /\s*?\"(.*?)\"\s*?/ + #RXP_C_ISO = /\s*\;\s*[\/\*]*\s*.*?([15\.]{0,3}[0-9\.]*)\s*[\\\\\*]*/ + RXP_C_ISO = /\s*;\s*[\/\*]*[\sa-zA-Z]*([\d\.]*)[\sa-zA-Z]*[\*\/]*/ + + def analyze_c_line line, line_no + case line.strip + when /^([a-zA-Z\_][a-zA-Z\_0-9]*?)\((.*?)\)\s*?$/ + # assuming c method definition + @c_funcs[$1] = {:line_no => line_no, :args => $2, :return => @last_line} + when /mrb_define_class\(.*?\,#{RXP_C_STR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/ + # assuming ruby class definition in c + class_name = $1.clone + iso = $3.clone + iso.strip! + @rb_class_c_def[class_name] = {:c_object => $2, :iso => iso} + assigns = line.split '=' + if assigns.size > 1 + assigns[0..-2].each do |v| + @assignments[v.strip] = class_name + end + end + when /mrb_define_module\(.*?\,#{RXP_C_STR}\)#{RXP_C_ISO}/ + # assuming ruby class definition in c + module_name = $1.clone + iso = $2.clone + iso.strip! + @rb_module_c_def[module_name] = {:iso => iso} + assigns = line.split '=' + if assigns.size > 1 + assigns[0..-2].each do |v| + @assignments[v.strip] = module_name + end + end + when /mrb_define_method\(.*?\,#{RXP_C_VAR}\,#{RXP_C_STR}\,#{RXP_C_VAR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/ + # assuming ruby method definition in c + name = $1.clone + name = resolve_obj(name) + iso = $5.clone + iso.strip! + @rb_method_c_def["#{name}_#{$2}"] = {:c_func => $3, :args => $4, :rb_class => name, :iso => iso} + when /mrb_define_class_method\(.*?\,#{RXP_C_VAR}\,#{RXP_C_STR}\,#{RXP_C_VAR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/ + # assuming ruby class method definition in c + class_name = $1.clone + class_name = resolve_obj(class_name) + iso = $5.clone + iso.strip! + @rb_class_method_c_def["#{class_name}_#{$2}"] = {:c_func => $3, :args => $4, :rb_class => class_name, :iso => iso} + end + end + + def analyze_rb_line line, line_no + + end + + def resolve_obj c_var + @assignments[c_var] + end +end |
