Class | Fortran90Dependency::Fortran90DependencyEntry |
In: |
f90depend.rb
|
Parent: | Object |
file | [R] | |
modules | [R] | |
uses | [R] |
引数 file には Fortran 90/95 ファイル名を与える. ファイルが存在しない場合, エラーを返す.
strictly に true を与えると Fortran 90/95 ファイル内の 継続行マーカ "&" や 改行マーカ ";" に関しても正しく 解析しますが, 実行時間が大幅に増えます.
# File f90depend.rb, line 113 113: def initialize(file, strictly=nil) 114: @file = file 115: if !(file =~ /\.f9(0|5)$/i) 116: $stderr.print "\n Warning: \"#{file}\" is not recognized as a Fortran 90/95 file.\n" + 117: " Please rename a suffix of this file to .f90 etc.\n" 118: return nil 119: end 120: 121: body = File.open(@file, 'r') {|f| f.read} 122: if strictly 123: body = united_to_one_line(body) 124: body = semicolon_to_linefeed(body) 125: end 126: @modules = find_modules(body) 127: @uses = find_uses(body) 128: @uses.collect!{|use_item| 129: if @modules.include?(use_item) 130: nil 131: else 132: use_item 133: end 134: } 135: @uses.delete_if{|use_item| !use_item } 136: end
引数 body で与えられる Fortran90/95 ソースコード内で 定義される module 名を取り出す.
# File f90depend.rb, line 144 144: def find_modules(body) 145: modules = [] 146: body.split("\n").each{ |line| 147: if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i 148: modules << $1 149: end 150: } 151: return modules 152: end
引数 body で与えられる Fortran90/95 ソースコード内で 定義される use 文を取り出す.
# File f90depend.rb, line 158 158: def find_uses(body) 159: uses = [] 160: body.split("\n").each{ |line| 161: if line =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i 162: uses << $1 163: end 164: } 165: return uses.uniq 166: end
RDoc Fortran 90/95 解析機能強化版 の Fortran 95 パーサから移植 したメソッド.
Semicolons are replaced to line feed.
# File f90depend.rb, line 177 177: def semicolon_to_linefeed(text) 178: return "" unless text 179: lines = text.split("\n") 180: lines.collect!{ |line| 181: indent_space = "" 182: if line =~ /^(\s+)/ 183: indent_space = $1 184: end 185: words = line.split("") 186: commentout = false 187: squote = false ; dquote = false 188: words.collect! { |char| 189: if !(squote) && !(dquote) && !(commentout) 190: case char 191: when "!" ; commentout = true ; next char 192: when "\""; dquote = true ; next char 193: when "\'"; squote = true ; next char 194: when ";" ; "\n"+indent_space 195: else next char 196: end 197: elsif commentout 198: next char 199: elsif squote 200: case char 201: when "\'"; squote = false ; next char 202: else next char 203: end 204: elsif dquote 205: case char 206: when "\""; dquote = false ; next char 207: else next char 208: end 209: end 210: } 211: words.join("") 212: } 213: return lines.join("\n") 214: end
RDoc Fortran 90/95 解析機能強化版 の Fortran 95 パーサから移植 したメソッド.
Continuous lines are united.
Comments in continuous lines are removed. If delete_space=false, spaces around "&" are not deleted.
Example
before
subroutine func(a, b, c, d, e, & ! ignored comments & f, g, h) ! valid comments
after
subroutine func(a, b, c, d, e, f, g, h) ! valid comments
# File f90depend.rb, line 237 237: def united_to_one_line(f90src, delete_space=true) 238: return "" unless f90src 239: lines = f90src.split("\n") 240: previous_continuing = false 241: now_continuing = false 242: body = "" 243: lines.each{ |line| 244: words = line.split("") 245: next if words.empty? && previous_continuing 246: commentout = false 247: brank_flag = true ; brank_char = "" 248: squote = false ; dquote = false 249: ignore = false 250: words.collect! { |char| 251: if previous_continuing && brank_flag 252: now_continuing = true 253: ignore = true 254: case char 255: when "!" ; break 256: when " " ; brank_char << char ; next "" 257: when "&" 258: brank_flag = false 259: now_continuing = false 260: next "" 261: else 262: brank_flag = false 263: now_continuing = false 264: ignore = false 265: next brank_char + char 266: end 267: end 268: ignore = false 269: 270: if now_continuing 271: next "" 272: elsif !(squote) && !(dquote) && !(commentout) 273: case char 274: when "!" ; commentout = true ; next char 275: when "\""; dquote = true ; next char 276: when "\'"; squote = true ; next char 277: when "&" ; now_continuing = true ; next "" 278: else next char 279: end 280: elsif commentout 281: next char 282: elsif squote 283: case char 284: when "\'"; squote = false ; next char 285: else next char 286: end 287: elsif dquote 288: case char 289: when "\""; dquote = false ; next char 290: else next char 291: end 292: end 293: } 294: if !ignore && !previous_continuing || !brank_flag 295: if previous_continuing 296: if delete_space 297: joined_words = words.join("") 298: body = body.rstrip + " " + joined_words.lstrip 299: else 300: body << words.join("") 301: end 302: else 303: body << "\n" + words.join("") 304: end 305: end 306: previous_continuing = now_continuing ? true : nil 307: now_continuing = nil 308: } 309: return body 310: end