method
parse_program_or_module
v1_9_1_378 -
Show latest stable
- Class:
RDoc::Parser::F95
parse_program_or_module(container, code, visibility=:public, external=nil)private
No documentation available.
# File lib/rdoc/parser/f95.rb, line 354
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*?(!.*?)?$/
before_contains_flag = true
end
else
break if line =~ /^\s*?contains\s*?(!.*?)?$/
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.*?$/m, "")
before_contains_code.gsub!(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/m, "")
end
#
# Parse global "use"
#
use_check_code = "#{before_contains_code}"
cascaded_modules_list = []
while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/
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 "." # HACK what stats thingy does this correspond to?
container.add_include Include.new(used_mod_name, "")
end
if ! (used_list =~ /\,\s*?only\s*?:/ )
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*?\,(.+)$/
use_check_code = $~.pre_match
use_check_code << $~.post_match
used_mod_name = $1.strip.chomp
used_elements = $2.sub(/\s*?only\s*?:\s*?/, '')
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+)(.*?)(!.*?)?$/
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 "." # HACK what stats thingy does this correspond to?
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.*?$
/mx
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/, ''))
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
@stats.add_method type
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.*?$
/mx
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
@stats.add_method const_or_var_progress
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*?(!.*?)?$
/x
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*?(!.*?)?$
/x
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/, '')
subroutine = AnyMethod.new("subroutine", subroutine_name)
parse_subprogram(subroutine, subroutine_params,
subroutine_comment, subroutine_code,
before_contains_code, nil, subroutine_prefix)
@stats.add_method subroutine
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/, '')
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)
@stats.add_method function
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*?(!.*?)?$
/x =~ 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/ =~ line
interface_scope = false
generic_name = nil
end
# internal alias
if interface_scope && /^\s*?module\s+procedure\s+(.*?)(!.*?)?$/ =~ 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
@stats.add_method new_meth
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*?(!.*?)?$
/x
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*?(!.*?)?$
/x
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)
@stats.add_method external_method
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
@stats.add_method new_meth
container.add_method new_meth
end
}
end
}
}
}
container
end