method
parse_program_or_module
v1_8_7_330 -
Show latest stable
-
0 notes -
Class: RDoc::Fortran95parser
- 1_8_6_287 (0)
- 1_8_7_72 (0)
- 1_8_7_330 (0)
- 1_9_1_378
- 1_9_2_180
- 1_9_3_125
- 1_9_3_392
- 2_1_10
- 2_2_9
- 2_4_6
- 2_5_5
- 2_6_3
- What's this?
parse_program_or_module(container, code, visibility=:public, external=nil)
private
Hide source
# File lib/rdoc/parsers/parse_f95.rb, line 358 def parse_program_or_module(container, code, visibility=:public, external=nil) return unless container return unless code remaining_lines = code.split("\n") remaining_code = "#{code}" # # Parse variables before "contains" in module # level_depth = 0 before_contains_lines = [] before_contains_code = nil before_contains_flag = nil remaining_lines.each{ |line| if !before_contains_flag if line =~ /^\s*?module\s+\w+\s*?(!.*?)?$/i before_contains_flag = true end else break if line =~ /^\s*?contains\s*?(!.*?)?$/i level_depth += 1 if block_start?(line) level_depth -= 1 if block_end?(line) break if level_depth < 0 before_contains_lines << line end } before_contains_code = before_contains_lines.join("\n") if before_contains_code before_contains_code.gsub!(/^\s*?interface\s+.*?\s+end\s+interface.*?$/im, "") before_contains_code.gsub!(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "") end # # Parse global "use" # use_check_code = "#{before_contains_code}" cascaded_modules_list = [] while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i use_check_code = $~.pre_match use_check_code << $~.post_match used_mod_name = $1.strip.chomp used_list = $2 || "" used_trailing = $3 || "" next if used_trailing =~ /!:nodoc:/ if !container.include_includes?(used_mod_name, @options.ignore_case) progress "." container.add_include Include.new(used_mod_name, "") end if ! (used_list =~ /\,\s*?only\s*?:/i ) cascaded_modules_list << "\#" + used_mod_name end end # # Parse public and private, and store information. # This information is used when "add_method" and # "set_visibility_for" are called. # visibility_default, visibility_info = parse_visibility(remaining_lines.join("\n"), visibility, container) @@public_methods.concat visibility_info if visibility_default == :public if !cascaded_modules_list.empty? cascaded_modules = Attr.new("Cascaded Modules", "Imported modules all of whose components are published again", "", cascaded_modules_list.join(", ")) container.add_attribute(cascaded_modules) end end # # Check rename elements # use_check_code = "#{before_contains_code}" while use_check_code =~ /^\s*?use\s+(\w+)\s*?\,(.+)$/i use_check_code = $~.pre_match use_check_code << $~.post_match used_mod_name = $1.strip.chomp used_elements = $2.sub(/\s*?only\s*?:\s*?/i, '') used_elements.split(",").each{ |used| if /\s*?(\w+)\s*?=>\s*?(\w+)\s*?/ =~ used local = $1 org = $2 @@public_methods.collect!{ |pub_meth| if local == pub_meth["name"] || local.upcase == pub_meth["name"].upcase && @options.ignore_case pub_meth["name"] = org pub_meth["local_name"] = local end pub_meth } end } end # # Parse private "use" # use_check_code = remaining_lines.join("\n") while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i use_check_code = $~.pre_match use_check_code << $~.post_match used_mod_name = $1.strip.chomp used_trailing = $3 || "" next if used_trailing =~ /!:nodoc:/ if !container.include_includes?(used_mod_name, @options.ignore_case) progress "." container.add_include Include.new(used_mod_name, "") end end container.each_includes{ |inc| TopLevel.all_files.each do |name, toplevel| indicated_mod = toplevel.find_symbol(inc.name, nil, @options.ignore_case) if indicated_mod indicated_name = indicated_mod.parent.file_relative_name if !container.include_requires?(indicated_name, @options.ignore_case) container.add_require(Require.new(indicated_name, "")) end break end end } # # Parse derived-types definitions # derived_types_comment = "" remaining_code = remaining_lines.join("\n") while remaining_code =~ /^\s*? type[\s\,]+(public|private)?\s*?(::)?\s*? (\w+)\s*?(!.*?)?$ (.*?) ^\s*?end\s+type.*?$ /imx remaining_code = $~.pre_match remaining_code << $~.post_match typename = $3.chomp.strip type_elements = $5 || "" type_code = remove_empty_head_lines($&) type_trailing = find_comments($4) next if type_trailing =~ /^:nodoc:/ type_visibility = $1 type_comment = COMMENTS_ARE_UPPER ? find_comments($~.pre_match) + "\n" + type_trailing : type_trailing + "\n" + find_comments(type_code.sub(/^.*$\n/i, '')) type_element_visibility_public = true type_code.split("\n").each{ |line| if /^\s*?private\s*?$/ =~ line type_element_visibility_public = nil break end } if type_code args_comment = "" type_args_info = nil if @options.show_all args_comment = find_arguments(nil, type_code, true) else type_public_args_list = [] type_args_info = definition_info(type_code) type_args_info.each{ |arg| arg_is_public = type_element_visibility_public arg_is_public = true if arg.include_attr?("public") arg_is_public = nil if arg.include_attr?("private") type_public_args_list << arg.varname if arg_is_public } args_comment = find_arguments(type_public_args_list, type_code) end type = AnyMethod.new("type #{typename}", typename) type.singleton = false type.params = "" type.comment = "<b><em> Derived Type </em></b> :: <tt></tt>\n" type.comment << args_comment if args_comment type.comment << type_comment if type_comment progress "t" @stats.num_methods += 1 container.add_method type set_visibility(container, typename, visibility_default, @@public_methods) if type_visibility type_visibility.gsub!(/\s/,'') type_visibility.gsub!(/\,/,'') type_visibility.gsub!(/:/,'') type_visibility.downcase! if type_visibility == "public" container.set_visibility_for([typename], :public) elsif type_visibility == "private" container.set_visibility_for([typename], :private) end end check_public_methods(type, container.name) if @options.show_all derived_types_comment << ", " unless derived_types_comment.empty? derived_types_comment << typename else if type.visibility == :public derived_types_comment << ", " unless derived_types_comment.empty? derived_types_comment << typename end end end if !derived_types_comment.empty? derived_types_table = Attr.new("Derived Types", "Derived_Types", "", derived_types_comment) container.add_attribute(derived_types_table) end # # move interface scope # interface_code = "" while remaining_code =~ /^\s*? interface( \s+\w+ | \s+operator\s*?\(.*?\) | \s+assignment\s*?\(\s*?=\s*?\) )?\s*?$ (.*?) ^\s*?end\s+interface.*?$ /imx interface_code << remove_empty_head_lines($&) + "\n" remaining_code = $~.pre_match remaining_code << $~.post_match end # # Parse global constants or variables in modules # const_var_defs = definition_info(before_contains_code) const_var_defs.each{|defitem| next if defitem.nodoc const_or_var_type = "Variable" const_or_var_progress = "v" if defitem.include_attr?("parameter") const_or_var_type = "Constant" const_or_var_progress = "c" end const_or_var = AnyMethod.new(const_or_var_type, defitem.varname) const_or_var.singleton = false const_or_var.params = "" self_comment = find_arguments([defitem.varname], before_contains_code) const_or_var.comment = "<b><em>" + const_or_var_type + "</em></b> :: <tt></tt>\n" const_or_var.comment << self_comment if self_comment progress const_or_var_progress @stats.num_methods += 1 container.add_method const_or_var set_visibility(container, defitem.varname, visibility_default, @@public_methods) if defitem.include_attr?("public") container.set_visibility_for([defitem.varname], :public) elsif defitem.include_attr?("private") container.set_visibility_for([defitem.varname], :private) end check_public_methods(const_or_var, container.name) } if const_var_defs remaining_lines = remaining_code.split("\n") # "subroutine" or "function" parts are parsed (new) # level_depth = 0 block_searching_flag = nil block_searching_lines = [] pre_comment = [] procedure_trailing = "" procedure_name = "" procedure_params = "" procedure_prefix = "" procedure_result_arg = "" procedure_type = "" contains_lines = [] contains_flag = nil remaining_lines.collect!{|line| if !block_searching_flag # subroutine if line =~ /^\s*? (recursive|pure|elemental)?\s*? subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$ /ix block_searching_flag = :subroutine block_searching_lines << line procedure_name = $2.chomp.strip procedure_params = $3 || "" procedure_prefix = $1 || "" procedure_trailing = $4 || "!" next false # function elsif line =~ /^\s*? (recursive|pure|elemental)?\s*? ( character\s*?(\([\w\s\=\(\)\*]+?\))?\s+ | type\s*?\([\w\s]+?\)\s+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+ | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+ | double\s+precision\s+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+ )? function\s+(\w+)\s*? (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$ /ix block_searching_flag = :function block_searching_lines << line procedure_prefix = $1 || "" procedure_type = $2 ? $2.chomp.strip : nil procedure_name = $8.chomp.strip procedure_params = $9 || "" procedure_result_arg = $11 ? $11.chomp.strip : procedure_name procedure_trailing = $12 || "!" next false elsif line =~ /^\s*?!\s?(.*)/ pre_comment << line next line else pre_comment = [] next line end end contains_flag = true if line =~ /^\s*?contains\s*?(!.*?)?$/ block_searching_lines << line contains_lines << line if contains_flag level_depth += 1 if block_start?(line) level_depth -= 1 if block_end?(line) if level_depth >= 0 next false end # "procedure_code" is formatted. # ":nodoc:" flag is checked. # procedure_code = block_searching_lines.join("\n") procedure_code = remove_empty_head_lines(procedure_code) if procedure_trailing =~ /^!:nodoc:/ # next loop to search next block level_depth = 0 block_searching_flag = nil block_searching_lines = [] pre_comment = [] procedure_trailing = "" procedure_name = "" procedure_params = "" procedure_prefix = "" procedure_result_arg = "" procedure_type = "" contains_lines = [] contains_flag = nil next false end # AnyMethod is created, and added to container # subroutine_function = nil if block_searching_flag == :subroutine subroutine_prefix = procedure_prefix subroutine_name = procedure_name subroutine_params = procedure_params subroutine_trailing = procedure_trailing subroutine_code = procedure_code subroutine_comment = COMMENTS_ARE_UPPER ? pre_comment.join("\n") + "\n" + subroutine_trailing : subroutine_trailing + "\n" + subroutine_code.sub(/^.*$\n/i, '') subroutine = AnyMethod.new("subroutine", subroutine_name) parse_subprogram(subroutine, subroutine_params, subroutine_comment, subroutine_code, before_contains_code, nil, subroutine_prefix) progress "s" @stats.num_methods += 1 container.add_method subroutine subroutine_function = subroutine elsif block_searching_flag == :function function_prefix = procedure_prefix function_type = procedure_type function_name = procedure_name function_params_org = procedure_params function_result_arg = procedure_result_arg function_trailing = procedure_trailing function_code_org = procedure_code function_comment = COMMENTS_ARE_UPPER ? pre_comment.join("\n") + "\n" + function_trailing : function_trailing + "\n " + function_code_org.sub(/^.*$\n/i, '') function_code = "#{function_code_org}" if function_type function_code << "\n" + function_type + " :: " + function_result_arg end function_params = function_params_org.sub(/^\(/, "\(#{function_result_arg}, ") function = AnyMethod.new("function", function_name) parse_subprogram(function, function_params, function_comment, function_code, before_contains_code, true, function_prefix) # Specific modification due to function function.params.sub!(/\(\s*?#{function_result_arg}\s*?,\s*?/, "\( ") function.params << " result(" + function_result_arg + ")" function.start_collecting_tokens function.add_token Token.new(1,1).set_text(function_code_org) progress "f" @stats.num_methods += 1 container.add_method function subroutine_function = function end # The visibility of procedure is specified # set_visibility(container, procedure_name, visibility_default, @@public_methods) # The alias for this procedure from external modules # check_external_aliases(procedure_name, subroutine_function.params, subroutine_function.comment, subroutine_function) if external check_public_methods(subroutine_function, container.name) # contains_lines are parsed as private procedures if contains_flag parse_program_or_module(container, contains_lines.join("\n"), :private) end # next loop to search next block level_depth = 0 block_searching_flag = nil block_searching_lines = [] pre_comment = [] procedure_trailing = "" procedure_name = "" procedure_params = "" procedure_prefix = "" procedure_result_arg = "" contains_lines = [] contains_flag = nil next false } # End of remaining_lines.collect!{|line| # Array remains_lines is converted to String remains_code again # remaining_code = remaining_lines.join("\n") # # Parse interface # interface_scope = false generic_name = "" interface_code.split("\n").each{ |line| if /^\s*? interface( \s+\w+| \s+operator\s*?\(.*?\)| \s+assignment\s*?\(\s*?=\s*?\) )? \s*?(!.*?)?$ /ix =~ line generic_name = $1 ? $1.strip.chomp : nil interface_trailing = $2 || "!" interface_scope = true interface_scope = false if interface_trailing =~ /!:nodoc:/ # if generic_name =~ /operator\s*?\((.*?)\)/i # operator_name = $1 # if operator_name && !operator_name.empty? # generic_name = "#{operator_name}" # end # end # if generic_name =~ /assignment\s*?\((.*?)\)/i # assignment_name = $1 # if assignment_name && !assignment_name.empty? # generic_name = "#{assignment_name}" # end # end end if /^\s*?end\s+interface/i =~ line interface_scope = false generic_name = nil end # internal alias if interface_scope && /^\s*?module\s+procedure\s+(.*?)(!.*?)?$/i =~ line procedures = $1.strip.chomp procedures_trailing = $2 || "!" next if procedures_trailing =~ /!:nodoc:/ procedures.split(",").each{ |proc| proc.strip! proc.chomp! next if generic_name == proc || !generic_name old_meth = container.find_symbol(proc, nil, @options.ignore_case) next if !old_meth nolink = old_meth.visibility == :private ? true : nil nolink = nil if @options.show_all new_meth = initialize_external_method(generic_name, proc, old_meth.params, nil, old_meth.comment, old_meth.clone.token_stream[0].text, true, nolink) new_meth.singleton = old_meth.singleton progress "i" @stats.num_methods += 1 container.add_method new_meth set_visibility(container, generic_name, visibility_default, @@public_methods) check_public_methods(new_meth, container.name) } end # external aliases if interface_scope # subroutine proc = nil params = nil procedures_trailing = nil if line =~ /^\s*? (recursive|pure|elemental)?\s*? subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$ /ix proc = $2.chomp.strip generic_name = proc unless generic_name params = $3 || "" procedures_trailing = $4 || "!" # function elsif line =~ /^\s*? (recursive|pure|elemental)?\s*? ( character\s*?(\([\w\s\=\(\)\*]+?\))?\s+ | type\s*?\([\w\s]+?\)\s+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+ | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+ | double\s+precision\s+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+ )? function\s+(\w+)\s*? (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$ /ix proc = $8.chomp.strip generic_name = proc unless generic_name params = $9 || "" procedures_trailing = $12 || "!" else next end next if procedures_trailing =~ /!:nodoc:/ indicated_method = nil indicated_file = nil TopLevel.all_files.each do |name, toplevel| indicated_method = toplevel.find_local_symbol(proc, @options.ignore_case) indicated_file = name break if indicated_method end if indicated_method external_method = initialize_external_method(generic_name, proc, indicated_method.params, indicated_file, indicated_method.comment) progress "e" @stats.num_methods += 1 container.add_method external_method set_visibility(container, generic_name, visibility_default, @@public_methods) if !container.include_requires?(indicated_file, @options.ignore_case) container.add_require(Require.new(indicated_file, "")) end check_public_methods(external_method, container.name) else @@external_aliases << { "new_name" => generic_name, "old_name" => proc, "file_or_module" => container, "visibility" => find_visibility(container, generic_name, @@public_methods) || visibility_default } end end } if interface_code # End of interface_code.split("\n").each ... # # Already imported methods are removed from @@public_methods. # Remainders are assumed to be imported from other modules. # @@public_methods.delete_if{ |method| method["entity_is_discovered"]} @@public_methods.each{ |pub_meth| next unless pub_meth["file_or_module"].name == container.name pub_meth["used_modules"].each{ |used_mod| TopLevel.all_classes_and_modules.each{ |modules| if modules.name == used_mod || modules.name.upcase == used_mod.upcase && @options.ignore_case modules.method_list.each{ |meth| if meth.name == pub_meth["name"] || meth.name.upcase == pub_meth["name"].upcase && @options.ignore_case new_meth = initialize_public_method(meth, modules.name) if pub_meth["local_name"] new_meth.name = pub_meth["local_name"] end progress "e" @stats.num_methods += 1 container.add_method new_meth end } end } } } container end