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 130 130: def initialize(file, strictly=nil) 131: @file = file 132: if !(file =~ /\.f9(0|5)$/i) 133: $stderr.print "\n Warning: \"#{file}\" is not recognized as a Fortran 90/95 file.\n" + 134: " Please rename a suffix of this file to .f90 etc.\n" 135: return nil 136: end 137: 138: body = File.open(@file, 'r') {|f| f.read} 139: if strictly 140: body = united_to_one_line(body) 141: body = semicolon_to_linefeed(body) 142: end 143: @modules = find_modules(body) 144: @uses = find_uses(body) 145: @uses.collect!{|use_item| 146: if @modules.include?(use_item) 147: nil 148: else 149: use_item 150: end 151: } 152: @uses.delete_if{|use_item| !use_item } 153: end
引数 body で与えられる Fortran90/95 ソースコード内で 定義される module 名を取り出す.
# File f90depend.rb, line 161 161: def find_modules(body) 162: modules = [] 163: body.split("\n").each{ |line| 164: if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i 165: modules << $1 166: end 167: } 168: return modules 169: end
引数 body で与えられる Fortran90/95 ソースコード内で 定義される use 文を取り出す.
# File f90depend.rb, line 175 175: def find_uses(body) 176: uses = [] 177: body.split("\n").each{ |line| 178: if line =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i 179: uses << $1 180: end 181: } 182: return uses.uniq 183: end
RDoc Fortran 90/95 解析機能強化版 の Fortran 95 パーサから移植 したメソッド.
Semicolons are replaced to line feed.
# File f90depend.rb, line 194 194: def semicolon_to_linefeed(text) 195: return "" unless text 196: lines = text.split("\n") 197: lines.collect!{ |line| 198: indent_space = "" 199: if line =~ /^(\s+)/ 200: indent_space = $1 201: end 202: words = line.split("") 203: commentout = false 204: squote = false ; dquote = false 205: words.collect! { |char| 206: if !(squote) && !(dquote) && !(commentout) 207: case char 208: when "!" ; commentout = true ; next char 209: when "\""; dquote = true ; next char 210: when "\'"; squote = true ; next char 211: when ";" ; "\n"+indent_space 212: else next char 213: end 214: elsif commentout 215: next char 216: elsif squote 217: case char 218: when "\'"; squote = false ; next char 219: else next char 220: end 221: elsif dquote 222: case char 223: when "\""; dquote = false ; next char 224: else next char 225: end 226: end 227: } 228: words.join("") 229: } 230: return lines.join("\n") 231: 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 254 254: def united_to_one_line(f90src, delete_space=true) 255: return "" unless f90src 256: lines = f90src.split("\n") 257: previous_continuing = false 258: now_continuing = false 259: body = "" 260: lines.each{ |line| 261: words = line.split("") 262: next if words.empty? && previous_continuing 263: commentout = false 264: brank_flag = true ; brank_char = "" 265: squote = false ; dquote = false 266: ignore = false 267: words.collect! { |char| 268: if previous_continuing && brank_flag 269: now_continuing = true 270: ignore = true 271: case char 272: when "!" ; break 273: when " " ; brank_char << char ; next "" 274: when "&" 275: brank_flag = false 276: now_continuing = false 277: next "" 278: else 279: brank_flag = false 280: now_continuing = false 281: ignore = false 282: next brank_char + char 283: end 284: end 285: ignore = false 286: 287: if now_continuing 288: next "" 289: elsif !(squote) && !(dquote) && !(commentout) 290: case char 291: when "!" ; commentout = true ; next char 292: when "\""; dquote = true ; next char 293: when "\'"; squote = true ; next char 294: when "&" ; now_continuing = true ; next "" 295: else next char 296: end 297: elsif commentout 298: next char 299: elsif squote 300: case char 301: when "\'"; squote = false ; next char 302: else next char 303: end 304: elsif dquote 305: case char 306: when "\""; dquote = false ; next char 307: else next char 308: end 309: end 310: } 311: if !ignore && !previous_continuing || !brank_flag 312: if previous_continuing 313: if delete_space 314: joined_words = words.join("") 315: body = body.rstrip + " " + joined_words.lstrip 316: else 317: body << words.join("") 318: end 319: else 320: body << "\n" + words.join("") 321: end 322: end 323: previous_continuing = now_continuing ? true : nil 324: now_continuing = nil 325: } 326: return body 327: end