| Class | Fortran90Dependency::Fortran90DependencyEntry |
| In: |
f90depend.rb
|
| Parent: | Object |
引数 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