Class Fortran90Dependency::Fortran90DependencyEntry
In: f90depend.rb
Parent: Object

Methods

Attributes

file  [R] 
modules  [R] 
uses  [R] 

Public Class methods

引数 file には Fortran 90/95 ファイル名を与える. ファイルが存在しない場合, エラーを返す.

strictly に true を与えると Fortran 90/95 ファイル内の 継続行マーカ "&" や 改行マーカ ";" に関しても正しく 解析しますが, 実行時間が大幅に増えます.

[Source]

     # 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

Public Instance methods

引数 body で与えられる Fortran90/95 ソースコード内で 定義される module 名を取り出す.

[Source]

     # 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 文を取り出す.

[Source]

     # 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.

[Source]

     # 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

[Source]

     # 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

[Validate]