rdoc-f95 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +79 -0
  3. data/PostInstall.txt +7 -0
  4. data/README.rdoc +147 -0
  5. data/Rakefile +28 -0
  6. data/bin/rdoc-f95 +70 -0
  7. data/lib/rdoc-f95.rb +306 -0
  8. data/lib/rdoc-f95/code_objects.rb +776 -0
  9. data/lib/rdoc-f95/diagram.rb +342 -0
  10. data/lib/rdoc-f95/dot.rb +249 -0
  11. data/lib/rdoc-f95/generator.rb +1088 -0
  12. data/lib/rdoc-f95/generator/chm.rb +113 -0
  13. data/lib/rdoc-f95/generator/chm/chm.rb +98 -0
  14. data/lib/rdoc-f95/generator/html.rb +370 -0
  15. data/lib/rdoc-f95/generator/html/hefss.rb +414 -0
  16. data/lib/rdoc-f95/generator/html/html.rb +708 -0
  17. data/lib/rdoc-f95/generator/html/kilmer.rb +418 -0
  18. data/lib/rdoc-f95/generator/html/one_page_html.rb +121 -0
  19. data/lib/rdoc-f95/generator/ri.rb +229 -0
  20. data/lib/rdoc-f95/generator/xhtml.rb +106 -0
  21. data/lib/rdoc-f95/generator/xhtml/ctop.xsl +1318 -0
  22. data/lib/rdoc-f95/generator/xhtml/mathml.xsl +42 -0
  23. data/lib/rdoc-f95/generator/xhtml/pmathml.xsl +612 -0
  24. data/lib/rdoc-f95/generator/xhtml/pmathmlcss.xsl +872 -0
  25. data/lib/rdoc-f95/generator/xhtml/xhtml.rb +732 -0
  26. data/lib/rdoc-f95/generator/xml.rb +120 -0
  27. data/lib/rdoc-f95/generator/xml/rdf.rb +113 -0
  28. data/lib/rdoc-f95/generator/xml/xml.rb +111 -0
  29. data/lib/rdoc-f95/install.rb +166 -0
  30. data/lib/rdoc-f95/markup.rb +506 -0
  31. data/lib/rdoc-f95/markup/formatter.rb +14 -0
  32. data/lib/rdoc-f95/markup/fragments.rb +337 -0
  33. data/lib/rdoc-f95/markup/inline.rb +361 -0
  34. data/lib/rdoc-f95/markup/install.rb +57 -0
  35. data/lib/rdoc-f95/markup/lines.rb +152 -0
  36. data/lib/rdoc-f95/markup/mathml_wrapper.rb +91 -0
  37. data/lib/rdoc-f95/markup/preprocess.rb +71 -0
  38. data/lib/rdoc-f95/markup/sample/rdoc2latex.rb +16 -0
  39. data/lib/rdoc-f95/markup/sample/sample.rb +42 -0
  40. data/lib/rdoc-f95/markup/to_flow.rb +185 -0
  41. data/lib/rdoc-f95/markup/to_html.rb +357 -0
  42. data/lib/rdoc-f95/markup/to_html_crossref.rb +123 -0
  43. data/lib/rdoc-f95/markup/to_latex.rb +328 -0
  44. data/lib/rdoc-f95/markup/to_test.rb +50 -0
  45. data/lib/rdoc-f95/markup/to_xhtml_texparser.rb +234 -0
  46. data/lib/rdoc-f95/options.rb +745 -0
  47. data/lib/rdoc-f95/parsers/parse_c.rb +775 -0
  48. data/lib/rdoc-f95/parsers/parse_f95.rb +2499 -0
  49. data/lib/rdoc-f95/parsers/parse_rb.rb +2587 -0
  50. data/lib/rdoc-f95/parsers/parse_simple.rb +39 -0
  51. data/lib/rdoc-f95/parsers/parserfactory.rb +99 -0
  52. data/lib/rdoc-f95/ri.rb +2 -0
  53. data/lib/rdoc-f95/ri/cache.rb +188 -0
  54. data/lib/rdoc-f95/ri/descriptions.rb +147 -0
  55. data/lib/rdoc-f95/ri/display.rb +244 -0
  56. data/lib/rdoc-f95/ri/driver.rb +435 -0
  57. data/lib/rdoc-f95/ri/formatter.rb +603 -0
  58. data/lib/rdoc-f95/ri/paths.rb +105 -0
  59. data/lib/rdoc-f95/ri/reader.rb +106 -0
  60. data/lib/rdoc-f95/ri/util.rb +81 -0
  61. data/lib/rdoc-f95/ri/writer.rb +64 -0
  62. data/lib/rdoc-f95/stats.rb +23 -0
  63. data/lib/rdoc-f95/template.rb +64 -0
  64. data/lib/rdoc-f95/tokenstream.rb +33 -0
  65. data/lib/rdoc-f95/usage.rb +210 -0
  66. data/script/console +10 -0
  67. data/script/destroy +14 -0
  68. data/script/generate +14 -0
  69. data/test/test_helper.rb +3 -0
  70. data/test/test_rdoc-f95.rb +11 -0
  71. metadata +156 -0
@@ -0,0 +1,2499 @@
1
+ #= parse_f95.rb - Fortran 90/95 Parser
2
+ #
3
+ #== Overview
4
+ #
5
+ #"parse_f95.rb" parses Fortran 90/95 files with suffixes "f90", "F90", "f95"
6
+ #and "F95". These files are expected to conform to Fortran 90 or
7
+ #Fortran 95 standards.
8
+ #
9
+ #== Rules
10
+ #
11
+ #Fundamental rules are same as that of the Ruby parser.
12
+ #But comment markers are '!' not '#'.
13
+ #
14
+ #=== Correspondence between RDoc documentation and Fortran 90/95 programs
15
+ #
16
+ #"parse_f95.rb" parses entities of Fortran 90/95 standards, or main programs,
17
+ #modules, subroutines, functions, derived types, public variables,
18
+ #public constants, defined operators and defined assignments.
19
+ #These entities are described in items of RDoc documentation, as follows.
20
+ #
21
+ #Files :: Files (same as Ruby)
22
+ #Classes :: Modules, list of NAMELIST group names
23
+ #Methods :: Main programs, subroutines, functions, variables, constants,
24
+ # derived types, defined operators, defined assignments,
25
+ # NAMELIST group names
26
+ #Required files :: Files in which imported modules, external subroutines
27
+ # and external functions are defined.
28
+ #Included Modules :: List of imported modules
29
+ #Attributes :: List of derived types, List of imported modules all of
30
+ # whose components are published again
31
+ #
32
+ #Entities listed in 'Methods' (subroutines, functions, ...)
33
+ #defined in modules are described in the item of 'Classes'.
34
+ #On the other hand, defined in main programs or
35
+ #as external procedures are described in the item of 'Files'.
36
+ #Main programs are described in the item of 'Files', too.
37
+ #
38
+ #=== Parsed entities
39
+ #
40
+ #Documentation on public entities (main programs,
41
+ #subroutines, functions, variables, constants,
42
+ #derived types, defined operators,
43
+ #defined assignments, NAMELIST group names) are generated.
44
+ #With "--all" option, documentation on all entities
45
+ #are generated (almost same as the Ruby parser).
46
+ #
47
+ #
48
+ #=== Parsed information
49
+ #
50
+ #The following information is automatically parsed.
51
+ #
52
+ #* Data types and attributes of arguments of functions and subprograms
53
+ #* Data types and attributes of public variables and public constants
54
+ #* Data types, initial values, and attributes of variables in the derived types
55
+ #* Data types, initial values, and attributes of variables declared in NAMELIST statement
56
+ #
57
+ #Only attributes specified in type declaration statements are parsed.
58
+ #Attributes specified in POINTER, TARGET, ALLOCATE, INTENT, OPTIONAL, SAVE
59
+ #statements are not parsed.
60
+ #
61
+ #Aliases declared by INTERFACE statements are described in the item
62
+ #of 'Methods'.
63
+ #
64
+ #Entities which are imported from other modules and published again
65
+ #are described in the item of 'Methods'.
66
+ #
67
+ #
68
+ #=== Format of comment blocks
69
+ #
70
+ #Comment blocks should be written as follows.
71
+ #Comment blocks are considered to be ended when the line without '!'
72
+ #appears.
73
+ #The indentation is not necessary.
74
+ #
75
+ # ! (Top of file)
76
+ # !
77
+ # ! Comment blocks for the files.
78
+ # !
79
+ # !--
80
+ # ! The comment described in the part enclosed by
81
+ # ! "!--" and "!++" is ignored.
82
+ # !++
83
+ # !
84
+ # module hogehoge
85
+ # !
86
+ # ! Comment blocks for the modules (or the main programs).
87
+ # !
88
+ #
89
+ # private
90
+ #
91
+ # logical :: a ! a private variable
92
+ # real, public :: b ! a public variable
93
+ # integer, parameter :: c = 0 ! a public constant
94
+ #
95
+ # public :: c
96
+ # public :: MULTI_ARRAY
97
+ # public :: hoge, foo
98
+ #
99
+ # type MULTI_ARRAY
100
+ # !
101
+ # ! Comment blocks for the derived types.
102
+ # !
103
+ # real, pointer :: var(:) =>null() ! Comments block for the variables.
104
+ # integer :: num = 0
105
+ # end type MULTI_ARRAY
106
+ #
107
+ # contains
108
+ #
109
+ # subroutine hoge( in, & ! Comment blocks between continuation lines are ignored.
110
+ # & out )
111
+ # !
112
+ # ! Comment blocks for the subroutines or functions
113
+ # !
114
+ # character(*),intent(in):: in ! Comment blocks for the arguments.
115
+ # character(*),intent(out),allocatable,target :: in
116
+ # ! Comment blocks can be
117
+ # ! written under Fortran statements.
118
+ #
119
+ # character(32) :: file ! This comment parsed as a variable in below NAMELIST.
120
+ # integer :: id
121
+ #
122
+ # namelist /varinfo_nml/ file, id
123
+ # !
124
+ # ! Comment blocks for the NAMELIST statement.
125
+ # ! Information about variables are described above.
126
+ # !
127
+ #
128
+ # ....
129
+ #
130
+ # end subroutine hoge
131
+ #
132
+ # integer function foo( in )
133
+ # !
134
+ # ! This part is considered as comment block.
135
+ #
136
+ # ! Comment blocks under blank lines are ignored.
137
+ # !
138
+ # integer, intent(in):: inA ! This part is considered as comment block.
139
+ #
140
+ # ! This part is ignored.
141
+ #
142
+ # end function foo
143
+ #
144
+ # subroutine hide( in, &
145
+ # & out ) !:nodoc:
146
+ # !
147
+ # ! If '!:nodoc:' is described at end-of-line in SUBROUTINE
148
+ # ! statement as above, the subroutine is ignored.
149
+ # ! This assignment can be used to main programs, modules,
150
+ # ! subroutines, functions, variables, constants, derived types,
151
+ # ! defined operators, defined assignments,
152
+ # ! list of imported modules (USE statement).
153
+ # !
154
+ #
155
+ # ....
156
+ #
157
+ # end subroutine hide
158
+ #
159
+ # end module hogehoge
160
+ #
161
+ #
162
+ #=== The sequence of displayed entities
163
+ #
164
+ #Entities listed in 'Files' and 'Classes' are displayed in
165
+ #ASCII order usually (in particular, A...Z, a...z, ...).
166
+ #Entities with the same names declared by INTERFACE statements
167
+ #are ordered by argument keywords or contents in comment blocks.
168
+ #
169
+ #If you want to order entities manually, describe a comment
170
+ #like '<b><tt>!:doc-priority 100:</tt></b>' at end-of-line in
171
+ #the statement of the entities.
172
+ #`100` represents priority. Priority level is specified as follows.
173
+ #(Default number is '50').
174
+ #
175
+ #Integer of 0 or less :: Entities are displayed at the head of the document. Entities with more small number go upstairs.
176
+ #Integer from 1 to 99 :: Priority within entities with the same names. Entities with more small number go upstairs.
177
+ #Integer of 100 or more :: Entities are displayed at the foot of the document. Entities with more large number go downstairs.
178
+ #
179
+ #An example is showed as follows. When 'doc-priority' is written as
180
+ #a following example, a sequence of displayed entities is
181
+ #
182
+ #* top_display, generic_name_procedures (an original entity: bottom_display),
183
+ # generic_name_procedures (an original entity: top_display), bottom_display.
184
+ #
185
+ #On the other hand, if 'doc-priority' is not written, the sequence become
186
+ #
187
+ #* bottom_display, generic_name_procedures (an original entity: top_display),
188
+ # generic_name_procedures (an original entity: bottom_display), top_display.
189
+ #
190
+ #The details are given in the following example.
191
+ #
192
+ # module sample1
193
+ # :
194
+ # interface generic_name_procedures
195
+ # !
196
+ # ! This INTERFACE statement redefines "top_display" and
197
+ # ! "bottom_display" as an generic name "generic_name_procedures".
198
+ # !
199
+ # ! RDoc orders two "generic_name_procedures" by argument keywords
200
+ # ! essentially. Therefore "generic_name_procedures" that
201
+ # ! the original entity is "top_display" is displayed above because
202
+ # ! an argument keyword of the procedure begins 'c'.
203
+ # ! (The name of the original entity is ignored).
204
+ # !
205
+ # ! In the following example, because 'doc-priority' is written,
206
+ # ! "generic_name_procedures" that
207
+ # ! the original entity is "bottom_display" is displayed above because
208
+ # ! the numerical value is smaller.
209
+ # !
210
+ # module procedure bottom_display !:doc-priority 40:
211
+ # module procedure top_display !:doc-priority 60:
212
+ # end interface
213
+ # :
214
+ # contains
215
+ # :
216
+ # subroutine top_display(arg) !:doc-priority -10:
217
+ # !
218
+ # ! In a normal situation, this entity is displayed below 'bottom_display'.
219
+ # ! But because priority is -10, this entity is displayed above.
220
+ # !
221
+ # ....
222
+ # end subroutine top_display
223
+ #
224
+ # subroutine bottom_display(arg) !:doc-priority 110:
225
+ # !
226
+ # ! In a normal situation, this entity is displayed above 'top_display'.
227
+ # ! But because priority is 110, this entity is displayed below.
228
+ # !
229
+ # ....
230
+ # end subroutine bottom_display
231
+ # :
232
+ # end module sample1
233
+ #
234
+ #
235
+
236
+ require "rdoc-f95/code_objects"
237
+
238
+ module RDocF95
239
+
240
+ class Token
241
+
242
+ NO_TEXT = "??".freeze
243
+
244
+ def initialize(line_no, char_no)
245
+ @line_no = line_no
246
+ @char_no = char_no
247
+ @text = NO_TEXT
248
+ end
249
+ # Because we're used in contexts that expect to return a token,
250
+ # we set the text string and then return ourselves
251
+ def set_text(text)
252
+ @text = text
253
+ self
254
+ end
255
+
256
+ attr_reader :line_no, :char_no, :text
257
+
258
+ end
259
+
260
+
261
+ # Extend Context class for parse_f95.rb
262
+ # Original class is defined in code_objects.rb.
263
+ # * The case of names of classes or modules or methods are ignored
264
+ # * Includes modules can be refered.
265
+
266
+ class Context
267
+
268
+ def add_method(a_method)
269
+ if !(a_method.visibility == :public) &&
270
+ !(a_method.visibility == :private) &&
271
+ !(a_method.visibility == :protected)
272
+ a_method.visibility = @visibility
273
+ end
274
+ puts "Adding #{a_method.visibility} method #{a_method.name} to #@name" if $DEBUG_RDOC
275
+ add_to(@method_list, a_method)
276
+ end
277
+
278
+ def add_alias(an_alias, ignore_case=nil)
279
+ meth = find_instance_method_named(an_alias.old_name, ignore_case)
280
+ if meth
281
+ new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
282
+ new_meth.is_alias_for = meth
283
+ new_meth.singleton = meth.singleton
284
+ new_meth.params = meth.params
285
+ new_meth.comment = "Alias for \##{meth.name}"
286
+ meth.add_alias(new_meth)
287
+ add_method(new_meth)
288
+ else
289
+ add_to(@aliases, an_alias)
290
+ end
291
+ end
292
+
293
+ # Find a named module
294
+ def find_module_named(name, ignore_case=nil)
295
+ res = nil
296
+ if !ignore_case
297
+ return self if self.name == name
298
+ else
299
+ return self if self.name.upcase == name.upcase
300
+ end
301
+ if !ignore_case
302
+ res = @modules[name] || @classes[name]
303
+ else
304
+ @modules.each{ |n, v|
305
+ if n.upcase == name.upcase
306
+ res = v ; break
307
+ end
308
+ }
309
+ @classes.each{ |n, v|
310
+ if n.upcase == name.upcase
311
+ res = v ; break
312
+ end
313
+ } if !res
314
+ end
315
+ return res if res
316
+ find_enclosing_module_named(name, ignore_case)
317
+ end
318
+
319
+ # find a module at a higher scope
320
+ def find_enclosing_module_named(name, ignore_case=nil)
321
+ parent && parent.find_module_named(name, ignore_case)
322
+ end
323
+
324
+ def each_includes
325
+ @includes.each {|i| yield i}
326
+ end
327
+
328
+ # Look up the given filename.
329
+ def find_file(file, method=nil, ignore_case=nil)
330
+ find_file_named(file, method, ignore_case)
331
+ end
332
+
333
+ # Look up the given symbol. If method is non-nil, then
334
+ # we assume the symbol references a module that
335
+ # contains that method
336
+ def find_symbol(symbol, method=nil, ignore_case=nil)
337
+ result = nil
338
+ case symbol
339
+ when /^::(.*)/
340
+ result = toplevel.find_symbol($1, nil, ignore_case)
341
+ when /::/
342
+ modules = symbol.split(/::/)
343
+ unless modules.empty?
344
+ module_name = modules.shift
345
+ result = find_module_named(module_name, ignore_case)
346
+ if result
347
+ modules.each do |module_name|
348
+ result = result.find_module_named(module_name, ignore_case)
349
+ break unless result
350
+ end
351
+ end
352
+ end
353
+ else
354
+ # if a method is specified, then we're definitely looking for
355
+ # a module, otherwise it could be any symbol
356
+ if method
357
+ result = find_module_named(symbol, ignore_case)
358
+ else
359
+ result = find_local_symbol(symbol, ignore_case)
360
+ if result.nil?
361
+ if symbol =~ /^[A-Z]/ ||
362
+ symbol =~ /^[A-Za-z]/ && ignore_case
363
+ result = parent
364
+ while result && result.name != symbol
365
+ result = result.parent
366
+ end
367
+ end
368
+ end
369
+ end
370
+ end
371
+ if result && method
372
+ if !result.respond_to?(:find_local_symbol)
373
+ p result.name
374
+ p method
375
+ fail
376
+ end
377
+ result = result.find_local_symbol(method, ignore_case)
378
+ end
379
+ result
380
+ end
381
+
382
+ def find_local_symbol(symbol, ignore_case=nil)
383
+ res = find_method_named(symbol, ignore_case) ||
384
+ find_constant_named(symbol, ignore_case) ||
385
+ find_attribute_named(symbol, ignore_case) ||
386
+ find_module_named(symbol, ignore_case)
387
+ end
388
+
389
+ def include_requires?(name, ignore_case=nil)
390
+ if self.kind_of? TopLevel
391
+ self.requires.each{|r|
392
+ if r.name == name ||
393
+ r.name.upcase == name.upcase && ignore_case
394
+ return true
395
+ end
396
+ }
397
+ return false
398
+ else
399
+ parent.include_requires?(name)
400
+ end
401
+ end
402
+
403
+ def include_includes?(name, ignore_case=nil)
404
+ self.includes.each{|i|
405
+ if i.name == name ||
406
+ i.name.upcase == name.upcase && ignore_case
407
+ return true
408
+ end
409
+ }
410
+ return false
411
+ end
412
+
413
+ # Find a named method, or return nil
414
+ def find_method_named(name, ignore_case=nil)
415
+ if !ignore_case
416
+ @method_list.find {|meth| meth.name == name}
417
+ else
418
+ @method_list.find {|meth| meth.name.upcase == name.upcase}
419
+ end
420
+ end
421
+
422
+ # Find a named instance method, or return nil
423
+ def find_instance_method_named(name, ignore_case=nil)
424
+ if !ignore_case
425
+ @method_list.find {|meth| meth.name == name && !meth.singleton}
426
+ else
427
+ @method_list.find {|meth|
428
+ meth.name.upcase == name.upcase && !meth.singleton
429
+ }
430
+ end
431
+ end
432
+
433
+ # Find a named constant, or return nil
434
+ def find_constant_named(name, ignore_case=nil)
435
+ if !ignore_case
436
+ @constants.find {|m| m.name == name}
437
+ else
438
+ @constants.find {|m| m.name.upcase == name.upcase}
439
+ end
440
+ end
441
+
442
+ # Find a named attribute, or return nil
443
+ def find_attribute_named(name, ignore_case=nil)
444
+ if !ignore_case
445
+ @attributes.find {|m| m.name == name}
446
+ else
447
+ @attributes.find {|m| m.name.upcase == name.upcase}
448
+ end
449
+ end
450
+
451
+ end
452
+
453
+
454
+
455
+ # Extend TopLevel class for parse_f95.rb.
456
+ # Original class is defined in code_objects.rb.
457
+ # * Cross-reference of files are enabled
458
+ # * The case of names of classes or modules or methods are ignored
459
+
460
+ class TopLevel
461
+ @@all_files = {}
462
+
463
+ def TopLevel::reset
464
+ @@all_classes = {}
465
+ @@all_modules = {}
466
+ @@all_files = {}
467
+ end
468
+
469
+ def initialize(file_name)
470
+ super()
471
+ @name = "TopLevel"
472
+ @file_relative_name = file_name
473
+ @file_absolute_name = file_name
474
+ @file_stat = File.stat(file_name)
475
+ @diagram = nil
476
+ @@all_files[file_name] = self
477
+ end
478
+
479
+ def TopLevel.all_files
480
+ @@all_files
481
+ end
482
+
483
+ def find_local_symbol(symbol, ignore_case=nil)
484
+ find_class_or_module_named(symbol, ignore_case) || super
485
+ end
486
+
487
+ def find_class_or_module_named(symbol, ignore_case=nil)
488
+ if !ignore_case
489
+ @@all_classes.each_value {|c| return c if c.name == symbol}
490
+ @@all_modules.each_value {|m| return m if m.name == symbol}
491
+ else
492
+ @@all_classes.each_value {|c| return c if c.name.upcase == symbol.upcase}
493
+ @@all_modules.each_value {|m| return m if m.name.upcase == symbol.upcase}
494
+ end
495
+ nil
496
+ end
497
+
498
+ # Find a named module
499
+ def find_module_named(name, ignore_case=nil)
500
+ find_class_or_module_named(name, ignore_case) || find_enclosing_module_named(name, ignore_case)
501
+ end
502
+
503
+ # Find a named file
504
+ def find_file_named(name, method=nil, ignore_case=nil)
505
+ return nil unless name
506
+ result = nil
507
+ @@all_files.each{|file_name, toplevel|
508
+ result = toplevel if file_name == name
509
+ }
510
+ dir = File.dirname(@file_relative_name)
511
+ @@all_files.each{|file_name, toplevel|
512
+ if /^#{dir}\/(.*)/ =~ file_name
513
+ result = toplevel if $1 == name
514
+ end
515
+ }
516
+ if result
517
+ if method
518
+ result_method = result.find_local_symbol(method, ignore_case)
519
+ return result_method
520
+ else
521
+ return result
522
+ end
523
+ else
524
+ return nil
525
+ end
526
+ end
527
+
528
+ end
529
+
530
+
531
+ # Extend ClassModule class for parse_f95.rb
532
+ # Original class is defined in code_objects.rb.
533
+ # * The case of names of classes or modules or methods are ignored
534
+
535
+ class ClassModule
536
+ def find_file_named(name, method=nil, ignore_case=nil)
537
+ parent.find_file_named(name, method, ignore_case)
538
+ end
539
+ end
540
+
541
+ # Extend AnyMethod class for parse_f95.rb
542
+ # Original class is defined in code_objects.rb.
543
+ # * A method "<=>" is modified.
544
+
545
+ class AnyMethod < CodeObject
546
+
547
+ attr_reader :doc_priority
548
+
549
+ def initialize(text, name)
550
+ super()
551
+ @text = text
552
+ @name = name
553
+ @token_stream = nil
554
+ @visibility = :public
555
+ @dont_rename_initialize = false
556
+ @block_params = nil
557
+ @aliases = []
558
+ @is_alias_for = nil
559
+ @comment = ""
560
+ @call_seq = nil
561
+ @doc_priority = 50
562
+ end
563
+
564
+ def set_priority(doc_priority)
565
+ if doc_priority.class.to_s == 'Fixnum'
566
+ @doc_priority = doc_priority
567
+ end
568
+ end
569
+
570
+ def <=>(other)
571
+ if @doc_priority < 1 && other.doc_priority < 1
572
+ t = @doc_priority <=> other.doc_priority
573
+ return t if t != 0
574
+ elsif @doc_priority < 1 && other.doc_priority >= 1
575
+ return -1
576
+ elsif @doc_priority >= 1 && other.doc_priority < 1
577
+ return 1
578
+ end
579
+
580
+ if @doc_priority > 99 && other.doc_priority > 99
581
+ t = @doc_priority <=> other.doc_priority
582
+ return t if t != 0
583
+ elsif @doc_priority > 99 && other.doc_priority <= 99
584
+ return 1
585
+ elsif @doc_priority <= 99 && other.doc_priority > 99
586
+ return -1
587
+ end
588
+
589
+ t = @name <=> other.name
590
+ return t if t != 0
591
+ t = @doc_priority <=> other.doc_priority
592
+ return t if t != 0
593
+ t = @params <=> other.params
594
+ return t if t != 0
595
+ t = @comment <=> other.comment
596
+ end
597
+ end
598
+
599
+
600
+ #See rdoc/parsers/parse_f95.rb
601
+ #
602
+ class Fortran95parser
603
+
604
+ extend ParserFactory
605
+ parse_files_matching(/\.((f|F)9(0|5)|F)$/)
606
+
607
+ @@external_aliases = []
608
+ @@public_methods = []
609
+
610
+ # "false":: Comments are below source code
611
+ # "true" :: Comments are upper source code
612
+ COMMENTS_ARE_UPPER = false
613
+
614
+ # Internal alias message
615
+ INTERNAL_ALIAS_MES = "Alias for"
616
+
617
+ # External alias message
618
+ EXTERNAL_ALIAS_MES = "Original external subprogram is"
619
+
620
+ # Provided modules message
621
+ PROVIDED_MODULES_MES = "This file provides the following module"
622
+
623
+ # Repository of NAMELIST statements
624
+ NAMELIST_REPOSITORY_NAME = "NAMELIST"
625
+
626
+ # Ignored marker
627
+ IGNORED_MARKER_REGEXP = /^:nodoc:/
628
+
629
+ # Document priority marker
630
+ DOC_PRIORITY_REGEXP = /^:doc\-priority\s+([\-\+]?\d+):\s*/
631
+
632
+ # prepare to parse a Fortran 95 file
633
+ def initialize(top_level, file_name, body, options, stats)
634
+ @body = body
635
+ @stats = stats
636
+ @file_name = file_name
637
+ @options = options
638
+ @top_level = top_level
639
+ @progress = $stderr unless options.quiet
640
+
641
+ begin
642
+ @options_ignore_case = options.ignore_case
643
+ rescue
644
+ @options_ignore_case = true
645
+ end
646
+
647
+ end
648
+
649
+ # devine code constructs
650
+ def scan
651
+
652
+ # remove private comment
653
+ remaining_code = remove_private_comments(@body)
654
+
655
+ # continuation lines are united to one line
656
+ remaining_code = united_to_one_line(remaining_code)
657
+
658
+ # semicolons are replaced to line feed
659
+ remaining_code = semicolon_to_linefeed(remaining_code)
660
+
661
+ # collect comment for file entity
662
+ whole_comment, remaining_code = collect_first_comment(remaining_code)
663
+ @top_level.comment = whole_comment
664
+
665
+ # String "remaining_code" is converted to Array "remaining_lines"
666
+ remaining_lines = remaining_code.split("\n")
667
+
668
+ # "module" or "program" parts are parsed (new)
669
+ #
670
+ level_depth = 0
671
+ block_searching_flag = nil
672
+ block_searching_lines = []
673
+ pre_comment = []
674
+ module_program_trailing = ""
675
+ module_program_name = ""
676
+ other_block_level_depth = 0
677
+ other_block_searching_flag = nil
678
+ remaining_lines.collect!{|line|
679
+ if !block_searching_flag && !other_block_searching_flag
680
+ if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i
681
+ block_searching_flag = :module
682
+ block_searching_lines << line
683
+ module_program_name = $1
684
+ module_program_trailing = find_comments($2)
685
+ next false
686
+ elsif line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
687
+ line =~ /^\s*?\w/ && !block_start?(line)
688
+ block_searching_flag = :program
689
+ block_searching_lines << line
690
+ module_program_name = $1 || ""
691
+ module_program_trailing = find_comments($2)
692
+ next false
693
+
694
+ elsif block_start?(line)
695
+ other_block_searching_flag = true
696
+ next line
697
+
698
+ elsif line =~ /^\s*?!\s?(.*)/
699
+ pre_comment << line
700
+ next line
701
+ else
702
+ pre_comment = []
703
+ next line
704
+ end
705
+ elsif other_block_searching_flag
706
+ other_block_level_depth += 1 if block_start?(line)
707
+ other_block_level_depth -= 1 if block_end?(line)
708
+ if other_block_level_depth < 0
709
+ other_block_level_depth = 0
710
+ other_block_searching_flag = nil
711
+ end
712
+ next line
713
+ end
714
+
715
+ block_searching_lines << line
716
+ level_depth += 1 if block_start?(line)
717
+ level_depth -= 1 if block_end?(line)
718
+ if level_depth >= 0
719
+ next false
720
+ end
721
+
722
+ # "module_program_code" is formatted.
723
+ # ":nodoc:" flag is checked.
724
+ #
725
+ module_program_code = block_searching_lines.join("\n")
726
+ module_program_code = remove_empty_head_lines(module_program_code)
727
+ if module_program_trailing =~ IGNORED_MARKER_REGEXP
728
+ # next loop to search next block
729
+ level_depth = 0
730
+ block_searching_flag = false
731
+ block_searching_lines = []
732
+ pre_comment = []
733
+ next false
734
+ end
735
+
736
+ # NormalClass is created, and added to @top_level
737
+ #
738
+ if block_searching_flag == :module
739
+ module_name = module_program_name
740
+ module_code = module_program_code
741
+ module_trailing = module_program_trailing
742
+ progress "m"
743
+ @stats.num_modules += 1
744
+ f9x_module = @top_level.add_module NormalClass, module_name
745
+ f9x_module.record_location @top_level
746
+
747
+ #
748
+ # Add provided modules information to @top_level comment
749
+ #
750
+ provided_modules = []
751
+ provided_mes_line_num = nil
752
+ top_level_comment_lines = []
753
+ line_num = 0
754
+ @top_level.comment.split("\n").each{|line|
755
+ top_level_comment_lines << line
756
+ line_num += 1
757
+ next if line.empty?
758
+ if !provided_mes_line_num && /^\s?#{PROVIDED_MODULES_MES}/ =~ line
759
+ provided_mes_line_num = line_num
760
+ next
761
+ end
762
+ if provided_mes_line_num
763
+ if /^\s?\*\s+<b>(\w+)<\/b>/ =~ line
764
+ provided_modules << $1
765
+ else
766
+ provided_mes_line_num = nil
767
+ end
768
+ end
769
+ }
770
+ line_num = 0
771
+ if provided_mes_line_num
772
+ top_level_comment_lines.collect!{ |line|
773
+ line_num += 1
774
+ if line_num < provided_mes_line_num
775
+ line
776
+ else
777
+ nil
778
+ end
779
+ }
780
+ top_level_comment_lines.delete_if{|line| !line }
781
+ end
782
+ top_level_comment_lines << "\n" + PROVIDED_MODULES_MES + "."
783
+ if provided_mes_line_num
784
+ top_level_comment_lines[-1].sub!(/\.$/, '')
785
+ top_level_comment_lines[-1] << "s."
786
+ end
787
+ provided_modules.each{ |mod|
788
+ top_level_comment_lines << "* <b>" + mod + "</b>"
789
+ }
790
+ top_level_comment_lines << "* <b>" + module_name + "</b>"
791
+ @top_level.comment = top_level_comment_lines.join("\n")
792
+
793
+ #
794
+ # Information about the module is parsed
795
+ #
796
+ f9x_comment = COMMENTS_ARE_UPPER ? find_comments(pre_comment.join("\n")) +
797
+ "\n" + module_trailing : module_trailing + "\n" +
798
+ find_comments(module_code.sub(/^.*$\n/i, ''))
799
+ f9x_module.comment = f9x_comment
800
+ parse_program_or_module(f9x_module, module_code)
801
+
802
+ TopLevel.all_files.each do |name, toplevel|
803
+ if toplevel.include_includes?(module_name, @options_ignore_case)
804
+ if !toplevel.include_requires?(@file_name, @options_ignore_case)
805
+ toplevel.add_require(Require.new(@file_name, ""))
806
+ end
807
+ end
808
+ toplevel.each_classmodule{|m|
809
+ if m.include_includes?(module_name, @options_ignore_case)
810
+ if !m.include_requires?(@file_name, @options_ignore_case)
811
+ m.add_require(Require.new(@file_name, ""))
812
+ end
813
+ end
814
+ }
815
+ end
816
+
817
+ namelist_comment =
818
+ find_namelists(f9x_module, before_contains(module_code))
819
+ f9x_module.comment << namelist_comment if namelist_comment
820
+
821
+ elsif block_searching_flag == :program
822
+ program_name = module_program_name
823
+ program_name = "main_program" if program_name.empty?
824
+ program_code = module_program_code
825
+ program_trailing = module_program_trailing
826
+ program_priority, program_trailing = doc_priority_from_trailing(program_trailing)
827
+
828
+ program_comment = COMMENTS_ARE_UPPER ? find_comments(pre_comment.join("\n")) +
829
+ "\n" + program_trailing : program_trailing + "\n" +
830
+ find_comments(program_code.sub(/^.*$\n/i, ''))
831
+
832
+ progress "p"
833
+ @stats.num_methods += 1
834
+ f9x_mainprogram = AnyMethod.new("main_program", program_name)
835
+ f9x_mainprogram.singleton = false
836
+ f9x_mainprogram.comment = "<b><em> Main Program </em></b> :: <tt></tt>\n"
837
+ f9x_mainprogram.comment << program_comment
838
+ f9x_mainprogram.params = ""
839
+ f9x_mainprogram.set_priority(program_priority) if program_priority
840
+
841
+ # For output source code
842
+ f9x_mainprogram.start_collecting_tokens
843
+ f9x_mainprogram.add_token Token.new(1,1).set_text(program_code)
844
+
845
+ @top_level.add_method f9x_mainprogram
846
+ parse_program_or_module(@top_level, program_code, :private)
847
+
848
+ namelist_comment = find_namelists(f9x_mainprogram, program_code)
849
+ f9x_mainprogram.comment << namelist_comment if namelist_comment
850
+ end
851
+
852
+ # next loop to search next block
853
+ level_depth = 0
854
+ block_searching_flag = false
855
+ block_searching_lines = []
856
+ pre_comment = []
857
+ next false
858
+ }
859
+
860
+ remaining_lines.delete_if{ |line|
861
+ line == false
862
+ }
863
+
864
+ # External subprograms and functions are parsed
865
+ #
866
+ parse_program_or_module(@top_level, remaining_lines.join("\n"),
867
+ :public, true)
868
+
869
+ @top_level
870
+ end # End of scan
871
+
872
+ private
873
+
874
+ def parse_program_or_module(container, code,
875
+ visibility=:public, external=nil)
876
+ return unless container
877
+ return unless code
878
+ remaining_lines = code.split("\n")
879
+ remaining_code = "#{code}"
880
+
881
+ #
882
+ # Parse variables before "contains" in module
883
+ #
884
+ before_contains_code = before_contains(remaining_code)
885
+
886
+ #
887
+ # Parse global "use"
888
+ #
889
+ use_check_code = "#{before_contains_code}"
890
+ cascaded_modules_list = []
891
+ while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
892
+ use_check_code = $~.pre_match
893
+ use_check_code << $~.post_match
894
+ used_mod_name = $1.strip.chomp
895
+ used_list = $2 || ""
896
+ used_trailing = $3 || ""
897
+ next if used_trailing.sub(/^!/, '') =~ IGNORED_MARKER_REGEXP
898
+ if !container.include_includes?(used_mod_name, @options_ignore_case)
899
+ progress "."
900
+ container.add_include Include.new(used_mod_name, "")
901
+ end
902
+ if ! (used_list =~ /\,\s*?only\s*?:/i )
903
+ cascaded_modules_list << "\#" + used_mod_name
904
+ end
905
+ end
906
+
907
+ #
908
+ # Parse public and private, and store information.
909
+ # This information is used when "add_method" and
910
+ # "set_visibility_for" are called.
911
+ #
912
+ visibility_default, visibility_info =
913
+ parse_visibility(remaining_lines.join("\n"), visibility, container)
914
+ @@public_methods.concat visibility_info
915
+ if visibility_default == :public
916
+ if !cascaded_modules_list.empty?
917
+ cascaded_modules =
918
+ Attr.new("Cascaded Modules",
919
+ "Imported modules all of whose components are published again",
920
+ "",
921
+ cascaded_modules_list.join(", "))
922
+ container.add_attribute(cascaded_modules)
923
+ end
924
+ end
925
+
926
+ #
927
+ # Check rename elements
928
+ #
929
+ use_check_code = "#{before_contains_code}"
930
+ while use_check_code =~ /^\s*?use\s+(\w+)\s*?\,(.+)$/i
931
+ use_check_code = $~.pre_match
932
+ use_check_code << $~.post_match
933
+ used_mod_name = $1.strip.chomp
934
+ used_elements = $2.sub(/\s*?only\s*?:\s*?/i, '')
935
+ used_elements.split(",").each{ |used|
936
+ if /\s*?(\w+)\s*?=>\s*?(\w+)\s*?/ =~ used
937
+ local = $1
938
+ org = $2
939
+ @@public_methods.collect!{ |pub_meth|
940
+ if local == pub_meth["name"] ||
941
+ local.upcase == pub_meth["name"].upcase &&
942
+ @options_ignore_case
943
+ pub_meth["name"] = org
944
+ pub_meth["local_name"] = local
945
+ end
946
+ pub_meth
947
+ }
948
+ end
949
+ }
950
+ end
951
+
952
+ #
953
+ # Parse private "use"
954
+ #
955
+ use_check_code = remaining_lines.join("\n")
956
+ while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
957
+ use_check_code = $~.pre_match
958
+ use_check_code << $~.post_match
959
+ used_mod_name = $1.strip.chomp
960
+ used_trailing = $3 || ""
961
+ next if used_trailing.sub(/^!/, '') =~ IGNORED_MARKER_REGEXP
962
+ if !container.include_includes?(used_mod_name, @options_ignore_case)
963
+ progress "."
964
+ container.add_include Include.new(used_mod_name, "")
965
+ end
966
+ end
967
+
968
+ container.each_includes{ |inc|
969
+ TopLevel.all_files.each do |name, toplevel|
970
+ indicated_mod = toplevel.find_symbol(inc.name,
971
+ nil, @options_ignore_case)
972
+ if indicated_mod
973
+ indicated_name = indicated_mod.parent.file_relative_name
974
+ if !container.include_requires?(indicated_name, @options_ignore_case)
975
+ container.add_require(Require.new(indicated_name, ""))
976
+ end
977
+ break
978
+ end
979
+ end
980
+ }
981
+
982
+ #
983
+ # Parse derived types definitions
984
+ #
985
+ derived_types_comment = ""
986
+ remaining_code = remaining_lines.join("\n")
987
+ while remaining_code =~ /^\s*?
988
+ type[\s\,]+(public|private)?\s*?(::)?\s*?
989
+ (\w+)\s*?(!.*?)?$
990
+ (.*?)
991
+ ^\s*?end\s+type.*?$
992
+ /imx
993
+ remaining_code = $~.pre_match
994
+ remaining_code << $~.post_match
995
+ typename = $3.chomp.strip
996
+ type_elements = $5 || ""
997
+ type_code = remove_empty_head_lines($&)
998
+ type_trailing = find_comments($4)
999
+ type_visibility = $1
1000
+ pre_match = $~.pre_match
1001
+ next if type_trailing =~ IGNORED_MARKER_REGEXP
1002
+ type_priority, type_trailing = doc_priority_from_trailing(type_trailing)
1003
+ type_comment = COMMENTS_ARE_UPPER ?
1004
+ find_comments(pre_match) + "\n" + type_trailing :
1005
+ type_trailing + "\n" + find_comments(type_code.sub(/^.*$\n/i, ''))
1006
+ type_element_visibility_public = true
1007
+ type_code.split("\n").each{ |line|
1008
+ if /^\s*?private\s*?$/ =~ line
1009
+ type_element_visibility_public = nil
1010
+ break
1011
+ end
1012
+ } if type_code
1013
+
1014
+ args_comment = ""
1015
+ type_args_info = nil
1016
+
1017
+ if @options.show_all
1018
+ args_comment = find_arguments(nil, type_code, true)
1019
+ else
1020
+ type_public_args_list = []
1021
+ type_args_info = definition_info(type_code)
1022
+ type_args_info.each{ |arg|
1023
+ arg_is_public = type_element_visibility_public
1024
+ arg_is_public = true if arg.include_attr?("public")
1025
+ arg_is_public = nil if arg.include_attr?("private")
1026
+ type_public_args_list << arg.varname if arg_is_public
1027
+ }
1028
+ args_comment = find_arguments(type_public_args_list, type_code)
1029
+ end
1030
+
1031
+ type = AnyMethod.new("type #{typename}", typename)
1032
+ type.singleton = false
1033
+ type.params = ""
1034
+ type.comment = "<b><em> Derived Type </em></b> :: <tt></tt>\n"
1035
+ type.comment << args_comment if args_comment
1036
+ type.comment << type_comment if type_comment
1037
+ type.set_priority(type_priority) if type_priority
1038
+ progress "t"
1039
+ @stats.num_methods += 1
1040
+ container.add_method type
1041
+
1042
+ set_visibility(container, typename, visibility_default, @@public_methods)
1043
+
1044
+ if type_visibility
1045
+ type_visibility.gsub!(/\s/,'')
1046
+ type_visibility.gsub!(/\,/,'')
1047
+ type_visibility.gsub!(/:/,'')
1048
+ type_visibility.downcase!
1049
+ if type_visibility == "public"
1050
+ container.set_visibility_for([typename], :public)
1051
+ elsif type_visibility == "private"
1052
+ container.set_visibility_for([typename], :private)
1053
+ end
1054
+ end
1055
+
1056
+ check_public_methods(type, container.name)
1057
+
1058
+ if @options.show_all
1059
+ derived_types_comment << ", " unless derived_types_comment.empty?
1060
+ derived_types_comment << typename
1061
+ else
1062
+ if type.visibility == :public
1063
+ derived_types_comment << ", " unless derived_types_comment.empty?
1064
+ derived_types_comment << typename
1065
+ end
1066
+ end
1067
+
1068
+ end
1069
+
1070
+ if !derived_types_comment.empty?
1071
+ derived_types_table =
1072
+ Attr.new("Derived Types", "Derived_Types", "",
1073
+ derived_types_comment)
1074
+ container.add_attribute(derived_types_table)
1075
+ end
1076
+
1077
+ #
1078
+ # move interface scope
1079
+ #
1080
+ interface_code = ""
1081
+ while remaining_code =~ /^\s*?
1082
+ interface(
1083
+ \s+\w+ |
1084
+ \s+operator\s*?\(.*?\) |
1085
+ \s+assignment\s*?\(\s*?=\s*?\)
1086
+ )?\s*?$
1087
+ (.*?)
1088
+ ^\s*?end\s+interface.*?$
1089
+ /imx
1090
+ interface_code << remove_empty_head_lines($&) + "\n"
1091
+ remaining_code = $~.pre_match
1092
+ remaining_code << $~.post_match
1093
+ end
1094
+
1095
+ #
1096
+ # Parse global constants or variables in modules
1097
+ #
1098
+ const_var_defs = definition_info(before_contains_code)
1099
+ const_var_defs.each{|defitem|
1100
+ next if defitem.nodoc
1101
+ const_or_var_type = "Variable"
1102
+ const_or_var_progress = "v"
1103
+ if defitem.include_attr?("parameter")
1104
+ const_or_var_type = "Constant"
1105
+ const_or_var_progress = "c"
1106
+ end
1107
+ const_or_var = AnyMethod.new(const_or_var_type, defitem.varname)
1108
+ const_or_var.set_priority(defitem.doc_priority) if defitem.doc_priority
1109
+ const_or_var.singleton = false
1110
+ const_or_var.params = ""
1111
+ self_comment = find_arguments([defitem.varname], before_contains_code)
1112
+ const_or_var.comment = "<b><em>" + const_or_var_type + "</em></b> :: <tt></tt>\n"
1113
+ const_or_var.comment << self_comment if self_comment
1114
+ progress const_or_var_progress
1115
+ @stats.num_methods += 1
1116
+ container.add_method const_or_var
1117
+
1118
+ set_visibility(container, defitem.varname, visibility_default, @@public_methods)
1119
+
1120
+ if defitem.include_attr?("public")
1121
+ container.set_visibility_for([defitem.varname], :public)
1122
+ elsif defitem.include_attr?("private")
1123
+ container.set_visibility_for([defitem.varname], :private)
1124
+ end
1125
+
1126
+ check_public_methods(const_or_var, container.name)
1127
+
1128
+ } if const_var_defs
1129
+
1130
+ remaining_lines = remaining_code.split("\n")
1131
+
1132
+ # "subroutine" or "function" parts are parsed (new)
1133
+ #
1134
+ level_depth = 0
1135
+ block_searching_flag = nil
1136
+ block_searching_lines = []
1137
+ pre_comment = []
1138
+ procedure_trailing = ""
1139
+ procedure_name = ""
1140
+ procedure_params = ""
1141
+ procedure_prefix = ""
1142
+ procedure_result_arg = ""
1143
+ procedure_type = ""
1144
+ contains_lines = []
1145
+ contains_flag = nil
1146
+ remaining_lines.collect!{|line|
1147
+ if !block_searching_flag
1148
+ # subroutine
1149
+ if line =~ /^\s*?
1150
+ (recursive|pure|elemental)?\s*?
1151
+ subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
1152
+ /ix
1153
+ block_searching_flag = :subroutine
1154
+ block_searching_lines << line
1155
+
1156
+ procedure_name = $2.chomp.strip
1157
+ procedure_params = $3 || ""
1158
+ procedure_prefix = $1 || ""
1159
+ procedure_trailing = $4 || "!"
1160
+ next false
1161
+
1162
+ # function
1163
+ elsif line =~ /^\s*?
1164
+ (recursive|pure|elemental)?\s*?
1165
+ (
1166
+ character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1167
+ | type\s*?\([\w\s]+?\)\s+
1168
+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1169
+ | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1170
+ | double\s+precision\s+
1171
+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1172
+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1173
+ )?
1174
+ function\s+(\w+)\s*?
1175
+ (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
1176
+ /ix
1177
+ block_searching_flag = :function
1178
+ block_searching_lines << line
1179
+
1180
+ procedure_prefix = $1 || ""
1181
+ procedure_type = $2 ? $2.chomp.strip : nil
1182
+ procedure_name = $8.chomp.strip
1183
+ procedure_params = $9 || ""
1184
+ procedure_result_arg = $11 ? $11.chomp.strip : procedure_name
1185
+ procedure_trailing = $12 || "!"
1186
+ next false
1187
+ elsif line =~ /^\s*?!\s?(.*)/
1188
+ pre_comment << line
1189
+ next line
1190
+ else
1191
+ pre_comment = []
1192
+ next line
1193
+ end
1194
+ end
1195
+ contains_flag = true if line =~ /^\s*?contains\s*?(!.*?)?$/
1196
+ block_searching_lines << line
1197
+ contains_lines << line if contains_flag
1198
+
1199
+ level_depth += 1 if block_start?(line)
1200
+ level_depth -= 1 if block_end?(line)
1201
+ if level_depth >= 0
1202
+ next false
1203
+ end
1204
+
1205
+ # "procedure_code" is formatted.
1206
+ # ":nodoc:" flag is checked.
1207
+ #
1208
+ procedure_code = block_searching_lines.join("\n")
1209
+ procedure_code = remove_empty_head_lines(procedure_code)
1210
+ if procedure_trailing.sub(/^!/, '') =~ IGNORED_MARKER_REGEXP
1211
+ # next loop to search next block
1212
+ level_depth = 0
1213
+ block_searching_flag = nil
1214
+ block_searching_lines = []
1215
+ pre_comment = []
1216
+ procedure_trailing = ""
1217
+ procedure_name = ""
1218
+ procedure_params = ""
1219
+ procedure_prefix = ""
1220
+ procedure_result_arg = ""
1221
+ procedure_type = ""
1222
+ contains_lines = []
1223
+ contains_flag = nil
1224
+ next false
1225
+ end
1226
+
1227
+ # AnyMethod is created, and added to container
1228
+ #
1229
+ subroutine_function = nil
1230
+ if block_searching_flag == :subroutine
1231
+ subroutine_prefix = procedure_prefix
1232
+ subroutine_name = procedure_name
1233
+ subroutine_params = procedure_params
1234
+ subroutine_trailing = procedure_trailing
1235
+ subroutine_code = procedure_code
1236
+ subroutine_priority, subroutine_trailing = doc_priority_from_trailing(subroutine_trailing)
1237
+
1238
+ subroutine_comment = COMMENTS_ARE_UPPER ?
1239
+ pre_comment.join("\n") + "\n" + subroutine_trailing :
1240
+ subroutine_trailing + "\n" + subroutine_code.sub(/^.*$\n/i, '')
1241
+ subroutine = AnyMethod.new("subroutine", subroutine_name)
1242
+ parse_subprogram(subroutine, subroutine_params,
1243
+ subroutine_comment, subroutine_code,
1244
+ before_contains_code, nil, subroutine_prefix)
1245
+ subroutine.set_priority(subroutine_priority) if subroutine_priority
1246
+ progress "s"
1247
+ @stats.num_methods += 1
1248
+ container.add_method subroutine
1249
+ subroutine_function = subroutine
1250
+
1251
+ namelist_comment =
1252
+ find_namelists(subroutine, subroutine_code, before_contains_code)
1253
+ subroutine.comment << namelist_comment if namelist_comment
1254
+
1255
+ elsif block_searching_flag == :function
1256
+ function_prefix = procedure_prefix
1257
+ function_type = procedure_type
1258
+ function_name = procedure_name
1259
+ function_params_org = procedure_params
1260
+ function_result_arg = procedure_result_arg
1261
+ function_trailing = procedure_trailing
1262
+ function_code_org = procedure_code
1263
+ function_priority, function_trailing = doc_priority_from_trailing(function_trailing)
1264
+
1265
+ function_comment = COMMENTS_ARE_UPPER ?
1266
+ pre_comment.join("\n") + "\n" + function_trailing :
1267
+ function_trailing + "\n " + function_code_org.sub(/^.*$\n/i, '')
1268
+
1269
+ function_code = "#{function_code_org}"
1270
+ if function_type
1271
+ function_code << "\n" + function_type + " :: " + function_result_arg
1272
+ end
1273
+
1274
+ if function_params_org =~ /^\s*\(\s*\)\s*$/
1275
+ function_params =
1276
+ function_params_org.sub(/^\(/, "\(#{function_result_arg}")
1277
+ else
1278
+ function_params =
1279
+ function_params_org.sub(/^\(/, "\(#{function_result_arg}, ")
1280
+ end
1281
+
1282
+ function = AnyMethod.new("function", function_name)
1283
+ parse_subprogram(function, function_params,
1284
+ function_comment, function_code,
1285
+ before_contains_code, true, function_prefix)
1286
+ function.set_priority(function_priority) if function_priority
1287
+
1288
+ # Specific modification due to function
1289
+ function.params.sub!(/\(\s*?#{function_result_arg}\s*?,?\s*?/, "\( ")
1290
+ function.params << " result(" + function_result_arg + ")"
1291
+ function.start_collecting_tokens
1292
+ function.add_token Token.new(1,1).set_text(function_code_org)
1293
+
1294
+ progress "f"
1295
+ @stats.num_methods += 1
1296
+ container.add_method function
1297
+ subroutine_function = function
1298
+
1299
+ namelist_comment =
1300
+ find_namelists(function, function_code, before_contains_code)
1301
+ function.comment << namelist_comment if namelist_comment
1302
+
1303
+ end
1304
+
1305
+ # The visibility of procedure is specified
1306
+ #
1307
+ set_visibility(container, procedure_name,
1308
+ visibility_default, @@public_methods)
1309
+
1310
+ # The alias for this procedure from external modules
1311
+ #
1312
+ check_external_aliases(procedure_name,
1313
+ subroutine_function.params,
1314
+ subroutine_function.comment, subroutine_function) if external
1315
+ check_public_methods(subroutine_function, container.name)
1316
+
1317
+
1318
+ # contains_lines are parsed as private procedures
1319
+ if contains_flag
1320
+ parse_program_or_module(container,
1321
+ contains_lines.join("\n"), :private)
1322
+ end
1323
+
1324
+ # next loop to search next block
1325
+ level_depth = 0
1326
+ block_searching_flag = nil
1327
+ block_searching_lines = []
1328
+ pre_comment = []
1329
+ procedure_trailing = ""
1330
+ procedure_name = ""
1331
+ procedure_params = ""
1332
+ procedure_prefix = ""
1333
+ procedure_result_arg = ""
1334
+ contains_lines = []
1335
+ contains_flag = nil
1336
+ next false
1337
+ } # End of remaining_lines.collect!{|line|
1338
+
1339
+ # Array remains_lines is converted to String remains_code again
1340
+ #
1341
+ remaining_code = remaining_lines.join("\n")
1342
+
1343
+ #
1344
+ # Parse interface
1345
+ #
1346
+ interface_scope = false
1347
+ generic_name = ""
1348
+ interface_code.split("\n").each{ |line|
1349
+ if /^\s*?
1350
+ interface(
1351
+ \s+\w+|
1352
+ \s+operator\s*?\(.*?\)|
1353
+ \s+assignment\s*?\(\s*?=\s*?\)
1354
+ )?
1355
+ \s*?(!.*?)?$
1356
+ /ix =~ line
1357
+ generic_name = $1 ? $1.strip.chomp : nil
1358
+ interface_trailing = $2 || "!"
1359
+ interface_scope = true
1360
+ interface_scope = false if interface_trailing.sub(/^!/, '') =~ IGNORED_MARKER_REGEXP
1361
+ # if generic_name =~ /operator\s*?\((.*?)\)/i
1362
+ # operator_name = $1
1363
+ # if operator_name && !operator_name.empty?
1364
+ # generic_name = "#{operator_name}"
1365
+ # end
1366
+ # end
1367
+ # if generic_name =~ /assignment\s*?\((.*?)\)/i
1368
+ # assignment_name = $1
1369
+ # if assignment_name && !assignment_name.empty?
1370
+ # generic_name = "#{assignment_name}"
1371
+ # end
1372
+ # end
1373
+ end
1374
+ if /^\s*?end\s+interface/i =~ line
1375
+ interface_scope = false
1376
+ generic_name = nil
1377
+ end
1378
+ # internal alias
1379
+ if interface_scope && /^\s*?module\s+procedure\s+(.*?)(!.*?)?$/i =~ line
1380
+ procedures = $1.strip.chomp
1381
+ procedures_trailing = $2 || "!"
1382
+ next if procedures_trailing.sub(/^!/, '') =~ IGNORED_MARKER_REGEXP
1383
+ procedures_priority, procedures_trailing = doc_priority_from_trailing(procedures_trailing)
1384
+
1385
+ procedures.split(",").each{ |proc|
1386
+ proc.strip!
1387
+ proc.chomp!
1388
+ next if generic_name == proc || !generic_name
1389
+ old_meth = container.find_symbol(proc, nil, @options_ignore_case)
1390
+ next if !old_meth
1391
+ nolink = old_meth.visibility == :private ? true : nil
1392
+ nolink = nil if @options.show_all
1393
+ new_meth =
1394
+ initialize_external_method(generic_name, proc,
1395
+ old_meth.params, nil,
1396
+ old_meth.comment,
1397
+ old_meth.clone.token_stream[0].text,
1398
+ true, nolink)
1399
+ new_meth.singleton = old_meth.singleton
1400
+ new_meth.set_priority(procedures_priority) if procedures_priority
1401
+
1402
+ progress "i"
1403
+ @stats.num_methods += 1
1404
+ container.add_method new_meth
1405
+
1406
+ set_visibility(container, generic_name, visibility_default, @@public_methods)
1407
+
1408
+ check_public_methods(new_meth, container.name)
1409
+
1410
+ }
1411
+ end
1412
+
1413
+ # external aliases
1414
+ if interface_scope
1415
+ # subroutine
1416
+ proc = nil
1417
+ params = nil
1418
+ procedures_trailing = nil
1419
+ if line =~ /^\s*?
1420
+ (recursive|pure|elemental)?\s*?
1421
+ subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
1422
+ /ix
1423
+ proc = $2.chomp.strip
1424
+ proc_name = generic_name || proc
1425
+ params = $3 || ""
1426
+ procedures_trailing = $4 || "!"
1427
+
1428
+ # function
1429
+ elsif line =~ /^\s*?
1430
+ (recursive|pure|elemental)?\s*?
1431
+ (
1432
+ character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1433
+ | type\s*?\([\w\s]+?\)\s+
1434
+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1435
+ | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1436
+ | double\s+precision\s+
1437
+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1438
+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1439
+ )?
1440
+ function\s+(\w+)\s*?
1441
+ (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
1442
+ /ix
1443
+ proc = $8.chomp.strip
1444
+ proc_name = generic_name || proc
1445
+ params = $9 || ""
1446
+ procedures_trailing = $12 || "!"
1447
+ else
1448
+ next
1449
+ end
1450
+ next if procedures_trailing.sub(/^!/, '') =~ IGNORED_MARKER_REGEXP
1451
+ procedures_priority, procedures_trailing = doc_priority_from_trailing(procedures_trailing)
1452
+ indicated_method = nil
1453
+ indicated_file = nil
1454
+ TopLevel.all_files.each do |name, toplevel|
1455
+ indicated_method = toplevel.find_local_symbol(proc, @options_ignore_case)
1456
+ indicated_file = name
1457
+ break if indicated_method
1458
+ end
1459
+
1460
+ if indicated_method
1461
+ external_method =
1462
+ initialize_external_method(proc_name, proc,
1463
+ indicated_method.params,
1464
+ indicated_file,
1465
+ indicated_method.comment)
1466
+ external_method.set_priority(procedures_priority) if procedures_priority
1467
+
1468
+ progress "e"
1469
+ @stats.num_methods += 1
1470
+ container.add_method external_method
1471
+ set_visibility(container, proc_name, visibility_default, @@public_methods)
1472
+ if !container.include_requires?(indicated_file, @options_ignore_case)
1473
+ container.add_require(Require.new(indicated_file, ""))
1474
+ end
1475
+ check_public_methods(external_method, container.name)
1476
+
1477
+ else
1478
+ @@external_aliases << {
1479
+ "new_name" => proc_name,
1480
+ "old_name" => proc,
1481
+ "file_or_module" => container,
1482
+ "visibility" => find_visibility(container, proc_name, @@public_methods) || visibility_default,
1483
+ "doc_priority" => procedures_priority
1484
+ }
1485
+ end
1486
+ end
1487
+
1488
+ } if interface_code # End of interface_code.split("\n").each ...
1489
+
1490
+ #
1491
+ # Already imported methods are removed from @@public_methods.
1492
+ # Remainders are assumed to be imported from other modules.
1493
+ #
1494
+ @@public_methods.delete_if{ |method| method["entity_is_discovered"]}
1495
+
1496
+ @@public_methods.each{ |pub_meth|
1497
+ next unless pub_meth["file_or_module"].name == container.name
1498
+ pub_meth["used_modules"].each{ |used_mod|
1499
+ TopLevel.all_classes_and_modules.each{ |modules|
1500
+ if modules.name == used_mod ||
1501
+ modules.name.upcase == used_mod.upcase &&
1502
+ @options_ignore_case
1503
+ modules.method_list.each{ |meth|
1504
+ if meth.name == pub_meth["name"] ||
1505
+ meth.name.upcase == pub_meth["name"].upcase &&
1506
+ @options_ignore_case
1507
+ new_meth = initialize_public_method(meth,
1508
+ modules.name)
1509
+ if pub_meth["local_name"]
1510
+ new_meth.name = pub_meth["local_name"]
1511
+ end
1512
+ progress "e"
1513
+ @stats.num_methods += 1
1514
+ container.add_method new_meth
1515
+ end
1516
+ }
1517
+ end
1518
+ }
1519
+ }
1520
+ }
1521
+
1522
+ container
1523
+ end # End of parse_program_or_module
1524
+
1525
+ #
1526
+ # Parse arguments, comment, code of subroutine and function.
1527
+ # Return AnyMethod object.
1528
+ #
1529
+ def parse_subprogram(subprogram, params, comment, code,
1530
+ before_contains=nil, function=nil, prefix=nil)
1531
+ subprogram.singleton = false
1532
+ prefix = "" if !prefix
1533
+ arguments = params.sub(/\(/, "").sub(/\)/, "").split(",") if params
1534
+ args_comment, params_opt =
1535
+ find_arguments(arguments, code.sub(/^s*?contains\s*?(!.*?)?$.*/im, ""),
1536
+ nil, nil, true)
1537
+ params_opt = "( " + params_opt + " ) " if params_opt
1538
+ subprogram.params = params_opt || ""
1539
+
1540
+ block_comment = find_comments comment
1541
+ if function
1542
+ subprogram.comment = "<b><em> Function </em></b> :: <em>#{prefix}</em>\n"
1543
+ else
1544
+ subprogram.comment = "<b><em> Subroutine </em></b> :: <em>#{prefix}</em>\n"
1545
+ end
1546
+ subprogram.comment << args_comment if args_comment
1547
+ subprogram.comment << block_comment if block_comment
1548
+
1549
+ # For output source code
1550
+ subprogram.start_collecting_tokens
1551
+ subprogram.add_token Token.new(1,1).set_text(code)
1552
+
1553
+ subprogram
1554
+ end
1555
+
1556
+ def doc_priority_from_trailing(trailing)
1557
+ prefix = ''
1558
+ if trailing =~ /^(\s*!)(.*)$/
1559
+ prefix = $1
1560
+ trailing = $2
1561
+ end
1562
+ if trailing =~ DOC_PRIORITY_REGEXP
1563
+ priority = $1.to_i
1564
+ trailing.sub!(DOC_PRIORITY_REGEXP, '')
1565
+ else
1566
+ priority = false
1567
+ end
1568
+ trailing = prefix + trailing
1569
+ return priority, trailing
1570
+ end
1571
+
1572
+ #
1573
+ # Return lines before "contains" statement in modules.
1574
+ # "interface", "type" statements are removed.
1575
+ #
1576
+ def before_contains(code)
1577
+ level_depth = 0
1578
+ before_contains_lines = []
1579
+ before_contains_code = nil
1580
+ before_contains_flag = nil
1581
+ code.split("\n").each{ |line|
1582
+ if !before_contains_flag
1583
+ if line =~ /^\s*?module\s+\w+\s*?(!.*?)?$/i
1584
+ before_contains_flag = true
1585
+ end
1586
+ else
1587
+ break if line =~ /^\s*?contains\s*?(!.*?)?$/i
1588
+ level_depth += 1 if block_start?(line)
1589
+ level_depth -= 1 if block_end?(line)
1590
+ break if level_depth < 0
1591
+ before_contains_lines << line
1592
+ end
1593
+
1594
+ }
1595
+ before_contains_code = before_contains_lines.join("\n")
1596
+ if before_contains_code
1597
+ before_contains_code.gsub!(/^\s*?interface\s+.*?\s+end\s+interface.*?$/im, "")
1598
+ before_contains_code.gsub!(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
1599
+ end
1600
+
1601
+ before_contains_code
1602
+ end
1603
+
1604
+ #
1605
+ # Collect comment for file entity
1606
+ #
1607
+ def collect_first_comment(body)
1608
+ comment = ""
1609
+ not_comment = ""
1610
+ comment_start = false
1611
+ comment_end = false
1612
+ body.split("\n").each{ |line|
1613
+ if comment_end
1614
+ not_comment << line
1615
+ not_comment << "\n"
1616
+ elsif /^\s*?!\s?(.*)$/i =~ line
1617
+ comment_start = true
1618
+ comment << $1
1619
+ comment << "\n"
1620
+ elsif /^\s*?$/i =~ line
1621
+ comment_end = true if comment_start && COMMENTS_ARE_UPPER
1622
+ else
1623
+ comment_end = true
1624
+ not_comment << line
1625
+ not_comment << "\n"
1626
+ end
1627
+ }
1628
+ return comment, not_comment
1629
+ end
1630
+
1631
+
1632
+ # Return comments of definitions of arguments
1633
+ #
1634
+ # If "all" argument is true, information of all arguments are returned.
1635
+ # If "modified_params" is true, list of arguments are decorated,
1636
+ # for exameple, optional arguments are parenthetic as "[arg]".
1637
+ #
1638
+ def find_arguments(args, text, all=nil, indent=nil, modified_params=nil)
1639
+ return unless args || all
1640
+ indent = "" unless indent
1641
+ args = ["all"] if all
1642
+ params = "" if modified_params
1643
+ comma = ""
1644
+ return unless text
1645
+ args_rdocforms = "\n"
1646
+ remaining_lines = "#{text}"
1647
+ definitions = definition_info(remaining_lines)
1648
+ args.each{ |arg|
1649
+ arg.strip!
1650
+ arg.chomp!
1651
+ definitions.each { |defitem|
1652
+ if arg == defitem.varname.strip.chomp || all
1653
+ args_rdocforms << <<-"EOF"
1654
+
1655
+ #{indent}<b><tt>#{defitem.varname.chomp.strip}#{defitem.arraysuffix} </tt></b> <tt> #{defitem.inivalue}</tt> ::
1656
+ #{indent} <tt>#{defitem.types.chomp.strip}</tt>
1657
+ EOF
1658
+ if !defitem.comment.chomp.strip.empty?
1659
+ comment = ""
1660
+ defitem.comment.split("\n").each{ |line|
1661
+ comment << " " + line + "\n"
1662
+ }
1663
+ args_rdocforms << <<-"EOF"
1664
+
1665
+ #{indent} <tt></tt> ::
1666
+ #{indent} <tt></tt>
1667
+ #{indent} #{comment.chomp.strip}
1668
+ EOF
1669
+ end
1670
+
1671
+ if modified_params
1672
+ if defitem.include_attr?("optional")
1673
+ params << "#{comma}[#{arg}]"
1674
+ else
1675
+ params << "#{comma}#{arg}"
1676
+ end
1677
+ comma = ", "
1678
+ end
1679
+ end
1680
+ }
1681
+ }
1682
+ if modified_params
1683
+ return args_rdocforms, params
1684
+ else
1685
+ return args_rdocforms
1686
+ end
1687
+ end
1688
+
1689
+ #
1690
+ # Add namelist information to Repository (dummy module of each
1691
+ # @top_level) of NAMELIST statements.
1692
+ # And return comments about namelist group names
1693
+ #
1694
+ def find_namelists(container, text, before_contains=nil)
1695
+ return nil if !text
1696
+ top_level = find_toplevel(container)
1697
+
1698
+ if text =~ /^\s*?namelist\s+\/\s*?(\w+)\s*?\/([\s\w\,]+)(!.*?)?$/i
1699
+ if top_level.include_includes?(NAMELIST_REPOSITORY_NAME)
1700
+ namelist_module =
1701
+ top_level.find_module_named(NAMELIST_REPOSITORY_NAME)
1702
+ else
1703
+ namelist_module =
1704
+ top_level.add_module NormalClass, NAMELIST_REPOSITORY_NAME
1705
+ namelist_module.record_location top_level
1706
+ namelist_module.comment = <<-"EOF"
1707
+ This is not a module but a repository of NAMELIST group names declared
1708
+ in all Fortran 90/95 files
1709
+ EOF
1710
+ end
1711
+ else
1712
+ return ""
1713
+ end
1714
+
1715
+ nml_group_name_lists = []
1716
+ lines = "#{text}"
1717
+ before_contains = "" if !before_contains
1718
+ while lines =~ /^\s*?namelist\s+\/\s*?(\w+)\s*?\/([\s\w\,]+)(!.*?)?$/i
1719
+ lines = $~.post_match
1720
+ pre_match = $~.pre_match ; post_match = $~.post_match
1721
+ nml_group_name = $1
1722
+ trailing_comment = $3 || ""
1723
+ nml_vars_list = $2.split(",")
1724
+ nml_comment = COMMENTS_ARE_UPPER ?
1725
+ find_comments(pre_match.sub(/\n$/, '')) :
1726
+ find_comments(trailing_comment + post_match)
1727
+ if lines.split("\n")[0] =~ /^\//i
1728
+ lines = "namelist " + lines
1729
+ end
1730
+
1731
+ nml_meth = AnyMethod.new("NAMELIST", nml_group_name)
1732
+ nml_meth.singleton = false
1733
+ nml_meth.params = "( " + nml_vars_list.join(", ") + " )"
1734
+ nml_meth.comment = "<b><em> NAMELIST </em></b> :: <tt></tt>\n"
1735
+ nml_meth.comment << find_arguments(nml_vars_list, "#{text}" + "\n" + before_contains)
1736
+ nml_meth.comment << "\n" + nml_comment if nml_comment
1737
+ if container.parent.parent
1738
+ parent_object = container.parent.name
1739
+ else
1740
+ parent_object = container.parent.file_relative_name
1741
+ end
1742
+ nml_meth.comment << "\n\nThis namelist group name is input/output in "
1743
+ nml_meth.comment << parent_object + "#" + container.name
1744
+
1745
+ progress "n"
1746
+ @stats.num_methods += 1
1747
+ namelist_module.add_method nml_meth
1748
+
1749
+ nml_group_name_lists << NAMELIST_REPOSITORY_NAME + "#" + nml_group_name
1750
+ end
1751
+
1752
+ if !nml_group_name_lists.empty?
1753
+ comments_in_procedures = "\n\nThis procedure input/output "
1754
+ comments_in_procedures << nml_group_name_lists.join(", ") + " . "
1755
+ else
1756
+ comments_in_procedures = ""
1757
+ end
1758
+
1759
+ comments_in_procedures
1760
+ end
1761
+
1762
+ #
1763
+ # Return toplevel class of container
1764
+ #
1765
+ def find_toplevel(container)
1766
+ top_level = container
1767
+ while top_level.parent
1768
+ top_level = top_level.parent
1769
+ end
1770
+ top_level
1771
+ end
1772
+
1773
+ #
1774
+ # Comments just after module or subprogram, or arguments are
1775
+ # returnd. If "COMMENTS_ARE_UPPER" is true, comments just before
1776
+ # modules or subprograms are returnd
1777
+ #
1778
+ def find_comments text
1779
+ return "" unless text
1780
+ lines = text.split("\n")
1781
+ lines.reverse! if COMMENTS_ARE_UPPER
1782
+ comment_block = Array.new
1783
+ lines.each do |line|
1784
+ break if line =~ /^\s*?\w/ || line =~ /^\s*?$/
1785
+ if COMMENTS_ARE_UPPER
1786
+ comment_block.unshift line.sub(/^\s*?!\s?/,"")
1787
+ else
1788
+ comment_block.push line.sub(/^\s*?!\s?/,"")
1789
+ end
1790
+ end
1791
+ nice_lines = comment_block.join("\n").split "\n\s*?\n"
1792
+ nice_lines[0] ||= ""
1793
+ nice_lines.shift
1794
+ end
1795
+
1796
+ def progress(char)
1797
+ unless @options.quiet
1798
+ @progress.print(char)
1799
+ @progress.flush
1800
+ end
1801
+ end
1802
+
1803
+ #
1804
+ # Create method for internal alias
1805
+ #
1806
+ def initialize_public_method(method, parent)
1807
+ return if !method || !parent
1808
+
1809
+ new_meth = AnyMethod.new("External Alias for module", method.name)
1810
+ new_meth.singleton = method.singleton
1811
+ new_meth.params = method.params.clone
1812
+ new_meth.comment = remove_trailing_alias(method.comment.clone)
1813
+ new_meth.comment << "\n\n#{EXTERNAL_ALIAS_MES} #{parent.strip.chomp}\##{method.name}"
1814
+
1815
+ return new_meth
1816
+ end
1817
+
1818
+ #
1819
+ # Create method for external alias
1820
+ #
1821
+ # If argument "internal" is true, file is ignored.
1822
+ #
1823
+ def initialize_external_method(new, old, params, file, comment, token=nil,
1824
+ internal=nil, nolink=nil)
1825
+ return nil unless new || old
1826
+
1827
+ if internal
1828
+ external_alias_header = "#{INTERNAL_ALIAS_MES} "
1829
+ external_alias_text = external_alias_header + old
1830
+ elsif file
1831
+ external_alias_header = "#{EXTERNAL_ALIAS_MES} "
1832
+ external_alias_text = external_alias_header + file + "#" + old
1833
+ else
1834
+ return nil
1835
+ end
1836
+ external_meth = AnyMethod.new(external_alias_text, new)
1837
+ external_meth.singleton = false
1838
+ external_meth.params = params
1839
+ external_comment = remove_trailing_alias(comment) + "\n\n" if comment
1840
+ external_meth.comment = external_comment || ""
1841
+ if nolink && token
1842
+ external_meth.start_collecting_tokens
1843
+ external_meth.add_token Token.new(1,1).set_text(token)
1844
+ else
1845
+ external_meth.comment << external_alias_text
1846
+ end
1847
+
1848
+ return external_meth
1849
+ end
1850
+
1851
+
1852
+
1853
+ #
1854
+ # Parse visibility
1855
+ #
1856
+ def parse_visibility(code, default, container)
1857
+ result = []
1858
+ visibility_default = default || :public
1859
+
1860
+ used_modules = []
1861
+ container.includes.each{|i| used_modules << i.name} if container
1862
+
1863
+ remaining_code = code.gsub(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
1864
+ remaining_code.split("\n").each{ |line|
1865
+ if /^\s*?private\s*?$/ =~ line
1866
+ visibility_default = :private
1867
+ break
1868
+ end
1869
+ } if remaining_code
1870
+
1871
+ remaining_code.split("\n").each{ |line|
1872
+ if /^\s*?private\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
1873
+ methods = $2.sub(/!.*$/, '')
1874
+ methods.split(",").each{ |meth|
1875
+ meth.sub!(/!.*$/, '')
1876
+ meth.gsub!(/:/, '')
1877
+ result << {
1878
+ "name" => meth.chomp.strip,
1879
+ "visibility" => :private,
1880
+ "used_modules" => used_modules.clone,
1881
+ "file_or_module" => container,
1882
+ "entity_is_discovered" => nil,
1883
+ "local_name" => nil
1884
+ }
1885
+ }
1886
+ elsif /^\s*?public\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
1887
+ methods = $2.sub(/!.*$/, '')
1888
+ methods.split(",").each{ |meth|
1889
+ meth.sub!(/!.*$/, '')
1890
+ meth.gsub!(/:/, '')
1891
+ result << {
1892
+ "name" => meth.chomp.strip,
1893
+ "visibility" => :public,
1894
+ "used_modules" => used_modules.clone,
1895
+ "file_or_module" => container,
1896
+ "entity_is_discovered" => nil,
1897
+ "local_name" => nil
1898
+ }
1899
+ }
1900
+ end
1901
+ } if remaining_code
1902
+
1903
+ if container
1904
+ result.each{ |vis_info|
1905
+ vis_info["parent"] = container.name
1906
+ }
1907
+ end
1908
+
1909
+ return visibility_default, result
1910
+ end
1911
+
1912
+ #
1913
+ # Set visibility
1914
+ #
1915
+ # "subname" element of "visibility_info" is deleted.
1916
+ #
1917
+ def set_visibility(container, subname, visibility_default, visibility_info)
1918
+ return unless container || subname || visibility_default || visibility_info
1919
+ not_found = true
1920
+ visibility_info.collect!{ |info|
1921
+ if info["name"] == subname ||
1922
+ @options_ignore_case && info["name"].upcase == subname.upcase
1923
+ if info["file_or_module"].name == container.name
1924
+ container.set_visibility_for([subname], info["visibility"])
1925
+ info["entity_is_discovered"] = true
1926
+ not_found = false
1927
+ end
1928
+ end
1929
+ info
1930
+ }
1931
+ if not_found
1932
+ return container.set_visibility_for([subname], visibility_default)
1933
+ else
1934
+ return container
1935
+ end
1936
+ end
1937
+
1938
+ #
1939
+ # Find visibility
1940
+ #
1941
+ def find_visibility(container, subname, visibility_info)
1942
+ return nil if !subname || !visibility_info
1943
+ visibility_info.each{ |info|
1944
+ if info["name"] == subname ||
1945
+ @options_ignore_case && info["name"].upcase == subname.upcase
1946
+ if info["parent"] == container.name
1947
+ return info["visibility"]
1948
+ end
1949
+ end
1950
+ }
1951
+ return nil
1952
+ end
1953
+
1954
+ #
1955
+ # Check external aliases
1956
+ #
1957
+ def check_external_aliases(subname, params, comment, test=nil)
1958
+ @@external_aliases.each{ |alias_item|
1959
+ if subname == alias_item["old_name"] ||
1960
+ subname.upcase == alias_item["old_name"].upcase &&
1961
+ @options_ignore_case
1962
+
1963
+ new_meth = initialize_external_method(alias_item["new_name"],
1964
+ subname, params, @file_name,
1965
+ comment)
1966
+ new_meth.visibility = alias_item["visibility"]
1967
+ new_meth.set_priority(alias_item["doc_priority"]) if alias_item["doc_priority"]
1968
+
1969
+ progress "e"
1970
+ @stats.num_methods += 1
1971
+ alias_item["file_or_module"].add_method(new_meth)
1972
+
1973
+ if !alias_item["file_or_module"].include_requires?(@file_name, @options_ignore_case)
1974
+ alias_item["file_or_module"].add_require(Require.new(@file_name, ""))
1975
+ end
1976
+ end
1977
+ }
1978
+ end
1979
+
1980
+ #
1981
+ # Check public_methods
1982
+ #
1983
+ def check_public_methods(method, parent)
1984
+ return if !method || !parent
1985
+ @@public_methods.each{ |alias_item|
1986
+ parent_is_used_module = nil
1987
+ alias_item["used_modules"].each{ |used_module|
1988
+ if used_module == parent ||
1989
+ used_module.upcase == parent.upcase &&
1990
+ @options_ignore_case
1991
+ parent_is_used_module = true
1992
+ end
1993
+ }
1994
+ next if !parent_is_used_module
1995
+
1996
+ if method.name == alias_item["name"] ||
1997
+ method.name.upcase == alias_item["name"].upcase &&
1998
+ @options_ignore_case
1999
+
2000
+ new_meth = initialize_public_method(method, parent)
2001
+ if alias_item["local_name"]
2002
+ new_meth.name = alias_item["local_name"]
2003
+ end
2004
+
2005
+ progress "e"
2006
+ @stats.num_methods += 1
2007
+ alias_item["file_or_module"].add_method new_meth
2008
+ end
2009
+ }
2010
+ end
2011
+
2012
+ #
2013
+ # Continuous lines are united.
2014
+ #
2015
+ # Comments in continuous lines are removed.
2016
+ # If delete_space=false, spaces around "&" are not deleted.
2017
+ #
2018
+ # Example
2019
+ #
2020
+ # before
2021
+ #
2022
+ # subroutine func(a, b, c, d, e, & ! ignored comments
2023
+ # & f, g, h) ! valid comments
2024
+ #
2025
+ # after
2026
+ #
2027
+ # subroutine func(a, b, c, d, e, f, g, h) ! valid comments
2028
+ #
2029
+ def united_to_one_line(f90src, delete_space=true)
2030
+ return "" unless f90src
2031
+ lines = f90src.split("\n")
2032
+ previous_continuing = false
2033
+ now_continuing = false
2034
+ body = ""
2035
+ squote = false ; dquote = false
2036
+ lines.each{ |line|
2037
+ words = line.split("")
2038
+ next if words.empty? && previous_continuing
2039
+ commentout = false
2040
+ brank_flag = true ; brank_char = ""
2041
+ ignore = false
2042
+ words.collect! { |char|
2043
+ if previous_continuing && brank_flag
2044
+ now_continuing = true
2045
+ ignore = true
2046
+ case char
2047
+ when "!" ; break
2048
+ when " " ; brank_char << char ; next ""
2049
+ when "&"
2050
+ brank_flag = false
2051
+ now_continuing = false
2052
+ next ""
2053
+ else
2054
+ brank_flag = false
2055
+ now_continuing = false
2056
+ ignore = false
2057
+ next brank_char + char
2058
+ end
2059
+ end
2060
+ ignore = false
2061
+
2062
+ if now_continuing && !(squote) && !(dquote)
2063
+ next ""
2064
+ elsif !(squote) && !(dquote) && !(commentout)
2065
+ case char
2066
+ when "!" ; commentout = true ; next char
2067
+ when "\""; dquote = true ; next char
2068
+ when "\'"; squote = true ; next char
2069
+ when "&" ; now_continuing = true ; next ""
2070
+ else next char
2071
+ end
2072
+ elsif commentout
2073
+ next char
2074
+ elsif squote
2075
+ case char
2076
+ when "\'"; squote = false ; now_continuing = false ; next char
2077
+ when "&" ; now_continuing = true ; next ""
2078
+ else next char
2079
+ end
2080
+ elsif dquote
2081
+ case char
2082
+ when "\""; dquote = false ; now_continuing = false ; next char
2083
+ when "&" ; now_continuing = true ; next ""
2084
+ else next char
2085
+ end
2086
+ end
2087
+ }
2088
+ if !ignore && !previous_continuing || !brank_flag
2089
+ if previous_continuing
2090
+ if delete_space
2091
+ joined_words = words.join("")
2092
+ body = body.rstrip + " " + joined_words.lstrip
2093
+ else
2094
+ body << words.join("")
2095
+ end
2096
+ else
2097
+ body << "\n" + words.join("")
2098
+ end
2099
+ end
2100
+ previous_continuing = now_continuing ? true : false
2101
+ now_continuing = false
2102
+ }
2103
+ return body
2104
+ end
2105
+
2106
+
2107
+ #
2108
+ # Continuous line checker
2109
+ #
2110
+ def continuous_line?(line)
2111
+ continuous = false
2112
+ if /&\s*?(!.*)?$/ =~ line
2113
+ continuous = true
2114
+ if comment_out?($~.pre_match)
2115
+ continuous = false
2116
+ end
2117
+ end
2118
+ return continuous
2119
+ end
2120
+
2121
+ #
2122
+ # Comment out checker
2123
+ #
2124
+ def comment_out?(line)
2125
+ return nil unless line
2126
+ commentout = false
2127
+ squote = false ; dquote = false
2128
+ line.split("").each { |char|
2129
+ if !(squote) && !(dquote)
2130
+ case char
2131
+ when "!" ; commentout = true ; break
2132
+ when "\""; dquote = true
2133
+ when "\'"; squote = true
2134
+ else next
2135
+ end
2136
+ elsif squote
2137
+ case char
2138
+ when "\'"; squote = false
2139
+ else next
2140
+ end
2141
+ elsif dquote
2142
+ case char
2143
+ when "\""; dquote = false
2144
+ else next
2145
+ end
2146
+ end
2147
+ }
2148
+ return commentout
2149
+ end
2150
+
2151
+ #
2152
+ # Semicolons are replaced to line feed.
2153
+ #
2154
+ def semicolon_to_linefeed(text)
2155
+ return "" unless text
2156
+ lines = text.split("\n")
2157
+ lines.collect!{ |line|
2158
+ indent_space = ""
2159
+ if line =~ /^(\s+)/
2160
+ indent_space = $1
2161
+ end
2162
+ words = line.split("")
2163
+ commentout = false
2164
+ squote = false ; dquote = false
2165
+ words.collect! { |char|
2166
+ if !(squote) && !(dquote) && !(commentout)
2167
+ case char
2168
+ when "!" ; commentout = true ; next char
2169
+ when "\""; dquote = true ; next char
2170
+ when "\'"; squote = true ; next char
2171
+ when ";" ; "\n"+indent_space
2172
+ else next char
2173
+ end
2174
+ elsif commentout
2175
+ next char
2176
+ elsif squote
2177
+ case char
2178
+ when "\'"; squote = false ; next char
2179
+ else next char
2180
+ end
2181
+ elsif dquote
2182
+ case char
2183
+ when "\""; dquote = false ; next char
2184
+ else next char
2185
+ end
2186
+ end
2187
+ }
2188
+ words.join("")
2189
+ }
2190
+ return lines.join("\n")
2191
+ end
2192
+
2193
+ #
2194
+ # Which "line" is start of block (module, program, block data,
2195
+ # subroutine, function) statement ?
2196
+ #
2197
+ def block_start?(line)
2198
+ return nil if !line
2199
+
2200
+ if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i ||
2201
+ line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
2202
+ line =~ /^\s*?block\s+data(\s+\w+)?\s*?(!.*?)?$/i ||
2203
+ line =~ \
2204
+ /^\s*?
2205
+ (recursive|pure|elemental)?\s*?
2206
+ subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
2207
+ /ix ||
2208
+ line =~ \
2209
+ /^\s*?
2210
+ (recursive|pure|elemental)?\s*?
2211
+ (
2212
+ character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
2213
+ | type\s*?\([\w\s]+?\)\s+
2214
+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
2215
+ | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
2216
+ | double\s+precision\s+
2217
+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
2218
+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
2219
+ )?
2220
+ function\s+(\w+)\s*?
2221
+ (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
2222
+ /ix
2223
+ return true
2224
+ end
2225
+
2226
+ return nil
2227
+ end
2228
+
2229
+ #
2230
+ # Which "line" is end of block (module, program, block data,
2231
+ # subroutine, function) statement ?
2232
+ #
2233
+ def block_end?(line)
2234
+ return nil if !line
2235
+
2236
+ if line =~ /^\s*?end\s*?(!.*?)?$/i ||
2237
+ line =~ /^\s*?end\s+module(\s+\w+)?\s*?(!.*?)?$/i ||
2238
+ line =~ /^\s*?end\s+program(\s+\w+)?\s*?(!.*?)?$/i ||
2239
+ line =~ /^\s*?end\s+block\s+data(\s+\w+)?\s*?(!.*?)?$/i ||
2240
+ line =~ /^\s*?end\s+subroutine(\s+\w+)?\s*?(!.*?)?$/i ||
2241
+ line =~ /^\s*?end\s+function(\s+\w+)?\s*?(!.*?)?$/i
2242
+ return true
2243
+ end
2244
+
2245
+ return nil
2246
+ end
2247
+
2248
+ #
2249
+ # Remove "Alias for" in end of comments
2250
+ #
2251
+ def remove_trailing_alias(text)
2252
+ return "" if !text
2253
+ lines = text.split("\n").reverse
2254
+ comment_block = Array.new
2255
+ checked = false
2256
+ lines.each do |line|
2257
+ if !checked
2258
+ if /^\s?#{INTERNAL_ALIAS_MES}/ =~ line ||
2259
+ /^\s?#{EXTERNAL_ALIAS_MES}/ =~ line
2260
+ checked = true
2261
+ next
2262
+ end
2263
+ end
2264
+ comment_block.unshift line
2265
+ end
2266
+ nice_lines = comment_block.join("\n")
2267
+ nice_lines ||= ""
2268
+ return nice_lines
2269
+ end
2270
+
2271
+ # Empty lines in header are removed
2272
+ def remove_empty_head_lines(text)
2273
+ return "" unless text
2274
+ lines = text.split("\n")
2275
+ header = true
2276
+ lines.delete_if{ |line|
2277
+ header = false if /\S/ =~ line
2278
+ header && /^\s*?$/ =~ line
2279
+ }
2280
+ lines.join("\n")
2281
+ end
2282
+
2283
+
2284
+ # header marker "=", "==", ... are removed
2285
+ def remove_header_marker(text)
2286
+ return text.gsub(/^\s?(=+)/, '<tt></tt>\1')
2287
+ end
2288
+
2289
+ def remove_private_comments(body)
2290
+ body.gsub!(/^(\s*)!--\s*?$.*?^\s*!\+\+\s*?$/m, '\\1!')
2291
+ return body
2292
+ end
2293
+
2294
+
2295
+ #
2296
+ # Information of arguments of subroutines and functions in Fortran95
2297
+ #
2298
+ class Fortran95Definition
2299
+
2300
+ # Name of variable
2301
+ attr_reader :varname
2302
+
2303
+ # Types of variable
2304
+ attr_reader :types
2305
+
2306
+ # Initial Value
2307
+ attr_reader :inivalue
2308
+
2309
+ # Suffix of array
2310
+ attr_reader :arraysuffix
2311
+
2312
+ # Comments
2313
+ attr_accessor :comment
2314
+
2315
+ # Flag of non documentation
2316
+ attr_accessor :nodoc
2317
+
2318
+ # Priority of documentation
2319
+ attr_accessor :doc_priority
2320
+
2321
+ def initialize(varname, types, inivalue, arraysuffix, comment,
2322
+ nodoc=false, doc_priority=50)
2323
+ @varname = varname
2324
+ @types = types
2325
+ @inivalue = inivalue
2326
+ @arraysuffix = arraysuffix
2327
+ @comment = comment
2328
+ @nodoc = nodoc
2329
+ @doc_priority = doc_priority
2330
+ end
2331
+
2332
+ def to_s
2333
+ return <<-EOF
2334
+ <Fortran95Definition:
2335
+ varname=#{@varname}, types=#{types},
2336
+ inivalue=#{@inivalue}, arraysuffix=#{@arraysuffix}, nodoc=#{@nodoc},
2337
+ comment=
2338
+ #{@comment}
2339
+ >
2340
+ EOF
2341
+ end
2342
+
2343
+ #
2344
+ # If attr is included, true is returned
2345
+ #
2346
+ def include_attr?(attr)
2347
+ return if !attr
2348
+ @types.split(",").each{ |type|
2349
+ return true if type.strip.chomp.upcase == attr.strip.chomp.upcase
2350
+ }
2351
+ return nil
2352
+ end
2353
+
2354
+ end # End of Fortran95Definition
2355
+
2356
+ #
2357
+ # Parse string argument "text", and Return Array of
2358
+ # Fortran95Definition object
2359
+ #
2360
+ def definition_info(text)
2361
+ return nil unless text
2362
+ lines = "#{text}"
2363
+ defs = Array.new
2364
+ comment = ""
2365
+ trailing_comment = ""
2366
+ under_comment_valid = false
2367
+ lines.split("\n").each{ |line|
2368
+ if /^\s*?!\s?(.*)/ =~ line
2369
+ if COMMENTS_ARE_UPPER
2370
+ comment << remove_header_marker($1)
2371
+ comment << "\n"
2372
+ elsif defs[-1] && under_comment_valid
2373
+ defs[-1].comment << "\n"
2374
+ defs[-1].comment << remove_header_marker($1)
2375
+ end
2376
+ next
2377
+ elsif /^\s*?$/ =~ line
2378
+ comment = ""
2379
+ under_comment_valid = false
2380
+ next
2381
+ end
2382
+ type = ""
2383
+ characters = ""
2384
+ if line =~ /^\s*?
2385
+ (
2386
+ character\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
2387
+ | type\s*?\([\w\s]+?\)[\s\,]*
2388
+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
2389
+ | real\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
2390
+ | double\s+precision[\s\,]*
2391
+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
2392
+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
2393
+ )
2394
+ (.*?::)?
2395
+ (.+)$
2396
+ /ix
2397
+ characters = $8
2398
+ type = $1
2399
+ type << $7.gsub(/::/, '').gsub(/^\s*?\,/, '') if $7
2400
+ else
2401
+ under_comment_valid = false
2402
+ next
2403
+ end
2404
+ squote = false ; dquote = false ; bracket = 0
2405
+ iniflag = false; commentflag = false
2406
+ varname = "" ; arraysuffix = "" ; inivalue = ""
2407
+ start_pos = defs.size
2408
+ characters.split("").each { |char|
2409
+ if !(squote) && !(dquote) && bracket <= 0 && !(iniflag) && !(commentflag)
2410
+ case char
2411
+ when "!" ; commentflag = true
2412
+ when "(" ; bracket += 1 ; arraysuffix = char
2413
+ when "\""; dquote = true
2414
+ when "\'"; squote = true
2415
+ when "=" ; iniflag = true ; inivalue << char
2416
+ when ","
2417
+ defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
2418
+ varname = "" ; arraysuffix = "" ; inivalue = ""
2419
+ under_comment_valid = true
2420
+ when " " ; next
2421
+ else ; varname << char
2422
+ end
2423
+ elsif commentflag
2424
+ comment << remove_header_marker(char)
2425
+ trailing_comment << remove_header_marker(char)
2426
+ elsif iniflag
2427
+ if dquote
2428
+ case char
2429
+ when "\"" ; dquote = false ; inivalue << char
2430
+ else ; inivalue << char
2431
+ end
2432
+ elsif squote
2433
+ case char
2434
+ when "\'" ; squote = false ; inivalue << char
2435
+ else ; inivalue << char
2436
+ end
2437
+ elsif bracket > 0
2438
+ case char
2439
+ when "(" ; bracket += 1 ; inivalue << char
2440
+ when ")" ; bracket -= 1 ; inivalue << char
2441
+ else ; inivalue << char
2442
+ end
2443
+ else
2444
+ case char
2445
+ when ","
2446
+ defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
2447
+ varname = "" ; arraysuffix = "" ; inivalue = ""
2448
+ iniflag = false
2449
+ under_comment_valid = true
2450
+ when "(" ; bracket += 1 ; inivalue << char
2451
+ when "\""; dquote = true ; inivalue << char
2452
+ when "\'"; squote = true ; inivalue << char
2453
+ when "!" ; commentflag = true
2454
+ else ; inivalue << char
2455
+ end
2456
+ end
2457
+ elsif !(squote) && !(dquote) && bracket > 0
2458
+ case char
2459
+ when "(" ; bracket += 1 ; arraysuffix << char
2460
+ when ")" ; bracket -= 1 ; arraysuffix << char
2461
+ else ; arraysuffix << char
2462
+ end
2463
+ elsif squote
2464
+ case char
2465
+ when "\'"; squote = false ; inivalue << char
2466
+ else ; inivalue << char
2467
+ end
2468
+ elsif dquote
2469
+ case char
2470
+ when "\""; dquote = false ; inivalue << char
2471
+ else ; inivalue << char
2472
+ end
2473
+ end
2474
+ }
2475
+ defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
2476
+ if trailing_comment =~ IGNORED_MARKER_REGEXP
2477
+ defs[start_pos..-1].collect!{ |defitem|
2478
+ defitem.nodoc = true
2479
+ }
2480
+ end
2481
+ if trailing_comment =~ DOC_PRIORITY_REGEXP
2482
+ doc_priority = $1.to_i
2483
+ defs[start_pos..-1].collect!{ |defitem|
2484
+ defitem.doc_priority = doc_priority
2485
+ defitem.comment.sub!(DOC_PRIORITY_REGEXP, '')
2486
+ }
2487
+ end
2488
+ varname = "" ; arraysuffix = "" ; inivalue = ""
2489
+ comment = ""
2490
+ under_comment_valid = true
2491
+ trailing_comment = ""
2492
+ }
2493
+ return defs
2494
+ end
2495
+
2496
+
2497
+ end # class Fortran95parser
2498
+
2499
+ end # module RDocF95