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

Public Instance methods

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

[Source]

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

[Source]

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

[Source]

     # 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

[Source]

     # 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

[Validate]