mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
119 lines
2.8 KiB
Ruby
119 lines
2.8 KiB
Ruby
|
# 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
|