summaryrefslogtreecommitdiff
path: root/lib/rdoc/parsers/parse_f95.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rdoc/parsers/parse_f95.rb')
-rw-r--r--lib/rdoc/parsers/parse_f95.rb118
1 files changed, 118 insertions, 0 deletions
diff --git a/lib/rdoc/parsers/parse_f95.rb b/lib/rdoc/parsers/parse_f95.rb
new file mode 100644
index 0000000000..3adf29d933
--- /dev/null
+++ b/lib/rdoc/parsers/parse_f95.rb
@@ -0,0 +1,118 @@
+# Parse a Fortran 95 file.
+
+require "rdoc/code_objects"
+
+module RDoc
+
+ # See rdoc/parsers/parse_f95.rb
+
+ class Token
+
+ NO_TEXT = "??".freeze
+
+ def initialize(line_no, char_no)
+ @line_no = line_no
+ @char_no = char_no
+ @text = NO_TEXT
+ end
+ # Because we're used in contexts that expect to return a token,
+ # we set the text string and then return ourselves
+ def set_text(text)
+ @text = text
+ self
+ end
+
+ attr_reader :line_no, :char_no, :text
+
+ end
+
+ class Fortran95parser
+
+ extend ParserFactory
+ parse_files_matching(/\.(f9(0|5)|F)$/)
+
+ # prepare to parse a Fortran 95 file
+ def initialize(top_level, file_name, body, options)
+ @body = body
+ @options = options
+ @top_level = top_level
+ @progress = $stderr unless options.quiet
+ end
+
+ # devine code constructs
+ def scan
+
+ # modules and programs
+ if @body =~ /^(module|program)\s+(\w+)/i
+ progress "m"
+ f9x_module = @top_level.add_module NormalClass, $2
+ f9x_module.record_location @top_level
+ first_comment, second_comment = $`.gsub(/^!\s?/,"").split "\n\s*\n"
+ if second_comment
+ @top_level.comment = first_comment if first_comment
+ f9x_module.comment = second_comment
+ else
+ f9x_module.comment = first_comment if first_comment
+ end
+ end
+
+ # use modules
+ remaining_code = @body
+ while remaining_code =~ /^\s*use\s+(\w+)/i
+ remaining_code = $~.post_match
+ progress "."
+ f9x_module.add_include Include.new($1, "") if f9x_module
+ end
+
+ # subroutines
+ remaining_code = @body
+ while remaining_code =~ /^\s*subroutine\s+(\w+)\s*\((.*?)\)/im
+ remaining_code = $~.post_match
+ subroutine = AnyMethod.new("Text", $1)
+ subroutine.singleton = false
+
+ prematchText = $~.pre_match
+ params = $2
+ params.gsub!(/&/,'')
+ subroutine.params = params
+ comment = find_comments prematchText
+ subroutine.comment = comment if comment
+
+ subroutine.start_collecting_tokens
+ remaining_code =~ /^\s*end\s+subroutine/i
+ code = "subroutine #{subroutine.name} (#{subroutine.params})\n"
+ code += $~.pre_match
+ code += "\nend subroutine\n"
+ subroutine.add_token Token.new(1,1).set_text(code)
+
+ progress "s"
+ f9x_module.add_method subroutine if f9x_module
+ end
+
+ @top_level
+
+ end
+
+ def find_comments text
+ lines = text.split("\n").reverse
+ comment_block = Array.new
+ lines.each do |line|
+ break if line =~ /^\s*\w/
+ comment_block.unshift line.sub(/^!\s?/,"")
+ end
+ nice_lines = comment_block.join("\n").split "\n\s*\n"
+ nice_lines.shift
+ nice_lines.shift
+ nice_lines.shift
+ end
+
+ def progress(char)
+ unless @options.quiet
+ @progress.print(char)
+ @progress.flush
+ end
+ end
+
+ end # class Fortran95parser
+
+end # module RDoc