rdoc-f95 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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