| 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