rdoc 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rdoc might be problematic. Click here for more details.
- data/History.txt +13 -0
- data/Manifest.txt +61 -0
- data/README.txt +34 -0
- data/Rakefile +10 -0
- data/bin/rdoc +22 -0
- data/bin/ri +6 -0
- data/lib/rdoc.rb +277 -0
- data/lib/rdoc/code_objects.rb +776 -0
- data/lib/rdoc/diagram.rb +338 -0
- data/lib/rdoc/dot.rb +249 -0
- data/lib/rdoc/generator.rb +1048 -0
- data/lib/rdoc/generator/chm.rb +113 -0
- data/lib/rdoc/generator/chm/chm.rb +98 -0
- data/lib/rdoc/generator/html.rb +370 -0
- data/lib/rdoc/generator/html/hefss.rb +414 -0
- data/lib/rdoc/generator/html/html.rb +704 -0
- data/lib/rdoc/generator/html/kilmer.rb +418 -0
- data/lib/rdoc/generator/html/one_page_html.rb +121 -0
- data/lib/rdoc/generator/ri.rb +229 -0
- data/lib/rdoc/generator/xml.rb +120 -0
- data/lib/rdoc/generator/xml/rdf.rb +113 -0
- data/lib/rdoc/generator/xml/xml.rb +111 -0
- data/lib/rdoc/markup.rb +473 -0
- data/lib/rdoc/markup/attribute_manager.rb +274 -0
- data/lib/rdoc/markup/formatter.rb +14 -0
- data/lib/rdoc/markup/fragments.rb +337 -0
- data/lib/rdoc/markup/inline.rb +101 -0
- data/lib/rdoc/markup/lines.rb +152 -0
- data/lib/rdoc/markup/preprocess.rb +71 -0
- data/lib/rdoc/markup/to_flow.rb +185 -0
- data/lib/rdoc/markup/to_html.rb +353 -0
- data/lib/rdoc/markup/to_html_crossref.rb +86 -0
- data/lib/rdoc/markup/to_latex.rb +328 -0
- data/lib/rdoc/markup/to_test.rb +50 -0
- data/lib/rdoc/options.rb +616 -0
- data/lib/rdoc/parsers/parse_c.rb +775 -0
- data/lib/rdoc/parsers/parse_f95.rb +1841 -0
- data/lib/rdoc/parsers/parse_rb.rb +2584 -0
- data/lib/rdoc/parsers/parse_simple.rb +40 -0
- data/lib/rdoc/parsers/parserfactory.rb +99 -0
- data/lib/rdoc/rdoc.rb +277 -0
- data/lib/rdoc/ri.rb +4 -0
- data/lib/rdoc/ri/cache.rb +188 -0
- data/lib/rdoc/ri/descriptions.rb +150 -0
- data/lib/rdoc/ri/display.rb +274 -0
- data/lib/rdoc/ri/driver.rb +452 -0
- data/lib/rdoc/ri/formatter.rb +616 -0
- data/lib/rdoc/ri/paths.rb +102 -0
- data/lib/rdoc/ri/reader.rb +106 -0
- data/lib/rdoc/ri/util.rb +81 -0
- data/lib/rdoc/ri/writer.rb +68 -0
- data/lib/rdoc/stats.rb +25 -0
- data/lib/rdoc/template.rb +64 -0
- data/lib/rdoc/tokenstream.rb +33 -0
- data/test/test_rdoc_c_parser.rb +261 -0
- data/test/test_rdoc_markup.rb +613 -0
- data/test/test_rdoc_markup_attribute_manager.rb +224 -0
- data/test/test_rdoc_ri_attribute_formatter.rb +42 -0
- data/test/test_rdoc_ri_default_display.rb +295 -0
- data/test/test_rdoc_ri_formatter.rb +318 -0
- data/test/test_rdoc_ri_overstrike_formatter.rb +69 -0
- metadata +134 -0
@@ -0,0 +1,1841 @@
|
|
1
|
+
#= parse_f95.rb - Fortran95 Parser
|
2
|
+
#
|
3
|
+
#== Overview
|
4
|
+
#
|
5
|
+
#"parse_f95.rb" parses Fortran95 files with suffixes "f90", "F90", "f95"
|
6
|
+
#and "F95". Fortran95 files are expected to be conformed to Fortran95
|
7
|
+
#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 Fortran95 programs
|
15
|
+
#
|
16
|
+
#"parse_f95.rb" parses main programs, modules, subroutines, functions,
|
17
|
+
#derived-types, public variables, public constants,
|
18
|
+
#defined operators and defined assignments.
|
19
|
+
#These components are described in items of RDoc documentation, as follows.
|
20
|
+
#
|
21
|
+
#Files :: Files (same as Ruby)
|
22
|
+
#Classes :: Modules
|
23
|
+
#Methods :: Subroutines, functions, variables, constants, derived-types, defined operators, defined assignments
|
24
|
+
#Required files :: Files in which imported modules, external subroutines and external functions are defined.
|
25
|
+
#Included Modules :: List of imported modules
|
26
|
+
#Attributes :: List of derived-types, List of imported modules all of whose components are published again
|
27
|
+
#
|
28
|
+
#Components listed in 'Methods' (subroutines, functions, ...)
|
29
|
+
#defined in modules are described in the item of 'Classes'.
|
30
|
+
#On the other hand, components defined in main programs or
|
31
|
+
#as external procedures are described in the item of 'Files'.
|
32
|
+
#
|
33
|
+
#=== Components parsed by default
|
34
|
+
#
|
35
|
+
#By default, documentation on public components (subroutines, functions,
|
36
|
+
#variables, constants, derived-types, defined operators,
|
37
|
+
#defined assignments) are generated.
|
38
|
+
#With "--all" option, documentation on all components
|
39
|
+
#are generated (almost same as the Ruby parser).
|
40
|
+
#
|
41
|
+
#=== Information parsed automatically
|
42
|
+
#
|
43
|
+
#The following information is automatically parsed.
|
44
|
+
#
|
45
|
+
#* Types of arguments
|
46
|
+
#* Types of variables and constants
|
47
|
+
#* Types of variables in the derived types, and initial values
|
48
|
+
#* NAMELISTs and types of variables in them, and initial values
|
49
|
+
#
|
50
|
+
#Aliases by interface statement are described in the item of 'Methods'.
|
51
|
+
#
|
52
|
+
#Components which are imported from other modules and published again
|
53
|
+
#are described in the item of 'Methods'.
|
54
|
+
#
|
55
|
+
#=== Format of comment blocks
|
56
|
+
#
|
57
|
+
#Comment blocks should be written as follows.
|
58
|
+
#Comment blocks are considered to be ended when the line without '!'
|
59
|
+
#appears.
|
60
|
+
#The indentation is not necessary.
|
61
|
+
#
|
62
|
+
# ! (Top of file)
|
63
|
+
# !
|
64
|
+
# ! Comment blocks for the files.
|
65
|
+
# !
|
66
|
+
# !--
|
67
|
+
# ! The comment described in the part enclosed by
|
68
|
+
# ! "!--" and "!++" is ignored.
|
69
|
+
# !++
|
70
|
+
# !
|
71
|
+
# module hogehoge
|
72
|
+
# !
|
73
|
+
# ! Comment blocks for the modules (or the programs).
|
74
|
+
# !
|
75
|
+
#
|
76
|
+
# private
|
77
|
+
#
|
78
|
+
# logical :: a ! a private variable
|
79
|
+
# real, public :: b ! a public variable
|
80
|
+
# integer, parameter :: c = 0 ! a public constant
|
81
|
+
#
|
82
|
+
# public :: c
|
83
|
+
# public :: MULTI_ARRAY
|
84
|
+
# public :: hoge, foo
|
85
|
+
#
|
86
|
+
# type MULTI_ARRAY
|
87
|
+
# !
|
88
|
+
# ! Comment blocks for the derived-types.
|
89
|
+
# !
|
90
|
+
# real, pointer :: var(:) =>null() ! Comments block for the variables.
|
91
|
+
# integer :: num = 0
|
92
|
+
# end type MULTI_ARRAY
|
93
|
+
#
|
94
|
+
# contains
|
95
|
+
#
|
96
|
+
# subroutine hoge( in, & ! Comment blocks between continuation lines are ignored.
|
97
|
+
# & out )
|
98
|
+
# !
|
99
|
+
# ! Comment blocks for the subroutines or functions
|
100
|
+
# !
|
101
|
+
# character(*),intent(in):: in ! Comment blocks for the arguments.
|
102
|
+
# character(*),intent(out),allocatable,target :: in
|
103
|
+
# ! Comment blocks can be
|
104
|
+
# ! written under Fortran statements.
|
105
|
+
#
|
106
|
+
# character(32) :: file ! This comment parsed as a variable in below NAMELIST.
|
107
|
+
# integer :: id
|
108
|
+
#
|
109
|
+
# namelist /varinfo_nml/ file, id
|
110
|
+
# !
|
111
|
+
# ! Comment blocks for the NAMELISTs.
|
112
|
+
# ! Information about variables are described above.
|
113
|
+
# !
|
114
|
+
#
|
115
|
+
# ....
|
116
|
+
#
|
117
|
+
# end subroutine hoge
|
118
|
+
#
|
119
|
+
# integer function foo( in )
|
120
|
+
# !
|
121
|
+
# ! This part is considered as comment block.
|
122
|
+
#
|
123
|
+
# ! Comment blocks under blank lines are ignored.
|
124
|
+
# !
|
125
|
+
# integer, intent(in):: inA ! This part is considered as comment block.
|
126
|
+
#
|
127
|
+
# ! This part is ignored.
|
128
|
+
#
|
129
|
+
# end function foo
|
130
|
+
#
|
131
|
+
# subroutine hide( in, &
|
132
|
+
# & out ) !:nodoc:
|
133
|
+
# !
|
134
|
+
# ! If "!:nodoc:" is described at end-of-line in subroutine
|
135
|
+
# ! statement as above, the subroutine is ignored.
|
136
|
+
# ! This assignment can be used to modules, subroutines,
|
137
|
+
# ! functions, variables, constants, derived-types,
|
138
|
+
# ! defined operators, defined assignments,
|
139
|
+
# ! list of imported modules ("use" statement).
|
140
|
+
# !
|
141
|
+
#
|
142
|
+
# ....
|
143
|
+
#
|
144
|
+
# end subroutine hide
|
145
|
+
#
|
146
|
+
# end module hogehoge
|
147
|
+
#
|
148
|
+
|
149
|
+
|
150
|
+
require "rdoc/code_objects"
|
151
|
+
|
152
|
+
module RDoc
|
153
|
+
|
154
|
+
class Token
|
155
|
+
|
156
|
+
NO_TEXT = "??".freeze
|
157
|
+
|
158
|
+
def initialize(line_no, char_no)
|
159
|
+
@line_no = line_no
|
160
|
+
@char_no = char_no
|
161
|
+
@text = NO_TEXT
|
162
|
+
end
|
163
|
+
# Because we're used in contexts that expect to return a token,
|
164
|
+
# we set the text string and then return ourselves
|
165
|
+
def set_text(text)
|
166
|
+
@text = text
|
167
|
+
self
|
168
|
+
end
|
169
|
+
|
170
|
+
attr_reader :line_no, :char_no, :text
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
# See rdoc/parsers/parse_f95.rb
|
175
|
+
|
176
|
+
class Fortran95parser
|
177
|
+
|
178
|
+
extend ParserFactory
|
179
|
+
parse_files_matching(/\.((f|F)9(0|5)|F)$/)
|
180
|
+
|
181
|
+
@@external_aliases = []
|
182
|
+
@@public_methods = []
|
183
|
+
|
184
|
+
# "false":: Comments are below source code
|
185
|
+
# "true" :: Comments are upper source code
|
186
|
+
COMMENTS_ARE_UPPER = false
|
187
|
+
|
188
|
+
# Internal alias message
|
189
|
+
INTERNAL_ALIAS_MES = "Alias for"
|
190
|
+
|
191
|
+
# External alias message
|
192
|
+
EXTERNAL_ALIAS_MES = "The entity is"
|
193
|
+
|
194
|
+
# prepare to parse a Fortran 95 file
|
195
|
+
def initialize(top_level, file_name, body, options, stats)
|
196
|
+
@body = body
|
197
|
+
@stats = stats
|
198
|
+
@file_name = file_name
|
199
|
+
@options = options
|
200
|
+
@top_level = top_level
|
201
|
+
@progress = $stderr unless options.quiet
|
202
|
+
end
|
203
|
+
|
204
|
+
# devine code constructs
|
205
|
+
def scan
|
206
|
+
|
207
|
+
# remove private comment
|
208
|
+
remaining_code = remove_private_comments(@body)
|
209
|
+
|
210
|
+
# continuation lines are united to one line
|
211
|
+
remaining_code = united_to_one_line(remaining_code)
|
212
|
+
|
213
|
+
# semicolons are replaced to line feed
|
214
|
+
remaining_code = semicolon_to_linefeed(remaining_code)
|
215
|
+
|
216
|
+
# collect comment for file entity
|
217
|
+
whole_comment, remaining_code = collect_first_comment(remaining_code)
|
218
|
+
@top_level.comment = whole_comment
|
219
|
+
|
220
|
+
# String "remaining_code" is converted to Array "remaining_lines"
|
221
|
+
remaining_lines = remaining_code.split("\n")
|
222
|
+
|
223
|
+
# "module" or "program" parts are parsed (new)
|
224
|
+
#
|
225
|
+
level_depth = 0
|
226
|
+
block_searching_flag = nil
|
227
|
+
block_searching_lines = []
|
228
|
+
pre_comment = []
|
229
|
+
module_program_trailing = ""
|
230
|
+
module_program_name = ""
|
231
|
+
other_block_level_depth = 0
|
232
|
+
other_block_searching_flag = nil
|
233
|
+
remaining_lines.collect!{|line|
|
234
|
+
if !block_searching_flag && !other_block_searching_flag
|
235
|
+
if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i
|
236
|
+
block_searching_flag = :module
|
237
|
+
block_searching_lines << line
|
238
|
+
module_program_name = $1
|
239
|
+
module_program_trailing = find_comments($2)
|
240
|
+
next false
|
241
|
+
elsif line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
|
242
|
+
line =~ /^\s*?\w/ && !block_start?(line)
|
243
|
+
block_searching_flag = :program
|
244
|
+
block_searching_lines << line
|
245
|
+
module_program_name = $1 || ""
|
246
|
+
module_program_trailing = find_comments($2)
|
247
|
+
next false
|
248
|
+
|
249
|
+
elsif block_start?(line)
|
250
|
+
other_block_searching_flag = true
|
251
|
+
next line
|
252
|
+
|
253
|
+
elsif line =~ /^\s*?!\s?(.*)/
|
254
|
+
pre_comment << line
|
255
|
+
next line
|
256
|
+
else
|
257
|
+
pre_comment = []
|
258
|
+
next line
|
259
|
+
end
|
260
|
+
elsif other_block_searching_flag
|
261
|
+
other_block_level_depth += 1 if block_start?(line)
|
262
|
+
other_block_level_depth -= 1 if block_end?(line)
|
263
|
+
if other_block_level_depth < 0
|
264
|
+
other_block_level_depth = 0
|
265
|
+
other_block_searching_flag = nil
|
266
|
+
end
|
267
|
+
next line
|
268
|
+
end
|
269
|
+
|
270
|
+
block_searching_lines << line
|
271
|
+
level_depth += 1 if block_start?(line)
|
272
|
+
level_depth -= 1 if block_end?(line)
|
273
|
+
if level_depth >= 0
|
274
|
+
next false
|
275
|
+
end
|
276
|
+
|
277
|
+
# "module_program_code" is formatted.
|
278
|
+
# ":nodoc:" flag is checked.
|
279
|
+
#
|
280
|
+
module_program_code = block_searching_lines.join("\n")
|
281
|
+
module_program_code = remove_empty_head_lines(module_program_code)
|
282
|
+
if module_program_trailing =~ /^:nodoc:/
|
283
|
+
# next loop to search next block
|
284
|
+
level_depth = 0
|
285
|
+
block_searching_flag = false
|
286
|
+
block_searching_lines = []
|
287
|
+
pre_comment = []
|
288
|
+
next false
|
289
|
+
end
|
290
|
+
|
291
|
+
# NormalClass is created, and added to @top_level
|
292
|
+
#
|
293
|
+
if block_searching_flag == :module
|
294
|
+
module_name = module_program_name
|
295
|
+
module_code = module_program_code
|
296
|
+
module_trailing = module_program_trailing
|
297
|
+
progress "m"
|
298
|
+
@stats.num_modules += 1
|
299
|
+
f9x_module = @top_level.add_module NormalClass, module_name
|
300
|
+
f9x_module.record_location @top_level
|
301
|
+
|
302
|
+
f9x_comment = COMMENTS_ARE_UPPER ?
|
303
|
+
find_comments(pre_comment.join("\n")) + "\n" + module_trailing :
|
304
|
+
module_trailing + "\n" + find_comments(module_code.sub(/^.*$\n/i, ''))
|
305
|
+
f9x_module.comment = f9x_comment
|
306
|
+
parse_program_or_module(f9x_module, module_code)
|
307
|
+
|
308
|
+
TopLevel.all_files.each do |name, toplevel|
|
309
|
+
if toplevel.include_includes?(module_name, @options.ignore_case)
|
310
|
+
if !toplevel.include_requires?(@file_name, @options.ignore_case)
|
311
|
+
toplevel.add_require(Require.new(@file_name, ""))
|
312
|
+
end
|
313
|
+
end
|
314
|
+
toplevel.each_classmodule{|m|
|
315
|
+
if m.include_includes?(module_name, @options.ignore_case)
|
316
|
+
if !m.include_requires?(@file_name, @options.ignore_case)
|
317
|
+
m.add_require(Require.new(@file_name, ""))
|
318
|
+
end
|
319
|
+
end
|
320
|
+
}
|
321
|
+
end
|
322
|
+
elsif block_searching_flag == :program
|
323
|
+
program_name = module_program_name
|
324
|
+
program_code = module_program_code
|
325
|
+
program_trailing = module_program_trailing
|
326
|
+
progress "p"
|
327
|
+
program_comment = COMMENTS_ARE_UPPER ?
|
328
|
+
find_comments(pre_comment.join("\n")) + "\n" + program_trailing :
|
329
|
+
program_trailing + "\n" + find_comments(program_code.sub(/^.*$\n/i, ''))
|
330
|
+
program_comment = "\n\n= <i>Program</i> <tt>#{program_name}</tt>\n\n" \
|
331
|
+
+ program_comment
|
332
|
+
@top_level.comment << program_comment
|
333
|
+
parse_program_or_module(@top_level, program_code, :private)
|
334
|
+
end
|
335
|
+
|
336
|
+
# next loop to search next block
|
337
|
+
level_depth = 0
|
338
|
+
block_searching_flag = false
|
339
|
+
block_searching_lines = []
|
340
|
+
pre_comment = []
|
341
|
+
next false
|
342
|
+
}
|
343
|
+
|
344
|
+
remaining_lines.delete_if{ |line|
|
345
|
+
line == false
|
346
|
+
}
|
347
|
+
|
348
|
+
# External subprograms and functions are parsed
|
349
|
+
#
|
350
|
+
parse_program_or_module(@top_level, remaining_lines.join("\n"),
|
351
|
+
:public, true)
|
352
|
+
|
353
|
+
@top_level
|
354
|
+
end # End of scan
|
355
|
+
|
356
|
+
private
|
357
|
+
|
358
|
+
def parse_program_or_module(container, code,
|
359
|
+
visibility=:public, external=nil)
|
360
|
+
return unless container
|
361
|
+
return unless code
|
362
|
+
remaining_lines = code.split("\n")
|
363
|
+
remaining_code = "#{code}"
|
364
|
+
|
365
|
+
#
|
366
|
+
# Parse variables before "contains" in module
|
367
|
+
#
|
368
|
+
level_depth = 0
|
369
|
+
before_contains_lines = []
|
370
|
+
before_contains_code = nil
|
371
|
+
before_contains_flag = nil
|
372
|
+
remaining_lines.each{ |line|
|
373
|
+
if !before_contains_flag
|
374
|
+
if line =~ /^\s*?module\s+\w+\s*?(!.*?)?$/i
|
375
|
+
before_contains_flag = true
|
376
|
+
end
|
377
|
+
else
|
378
|
+
break if line =~ /^\s*?contains\s*?(!.*?)?$/i
|
379
|
+
level_depth += 1 if block_start?(line)
|
380
|
+
level_depth -= 1 if block_end?(line)
|
381
|
+
break if level_depth < 0
|
382
|
+
before_contains_lines << line
|
383
|
+
end
|
384
|
+
}
|
385
|
+
before_contains_code = before_contains_lines.join("\n")
|
386
|
+
if before_contains_code
|
387
|
+
before_contains_code.gsub!(/^\s*?interface\s+.*?\s+end\s+interface.*?$/im, "")
|
388
|
+
before_contains_code.gsub!(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
|
389
|
+
end
|
390
|
+
|
391
|
+
#
|
392
|
+
# Parse global "use"
|
393
|
+
#
|
394
|
+
use_check_code = "#{before_contains_code}"
|
395
|
+
cascaded_modules_list = []
|
396
|
+
while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
|
397
|
+
use_check_code = $~.pre_match
|
398
|
+
use_check_code << $~.post_match
|
399
|
+
used_mod_name = $1.strip.chomp
|
400
|
+
used_list = $2 || ""
|
401
|
+
used_trailing = $3 || ""
|
402
|
+
next if used_trailing =~ /!:nodoc:/
|
403
|
+
if !container.include_includes?(used_mod_name, @options.ignore_case)
|
404
|
+
progress "."
|
405
|
+
container.add_include Include.new(used_mod_name, "")
|
406
|
+
end
|
407
|
+
if ! (used_list =~ /\,\s*?only\s*?:/i )
|
408
|
+
cascaded_modules_list << "\#" + used_mod_name
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
#
|
413
|
+
# Parse public and private, and store information.
|
414
|
+
# This information is used when "add_method" and
|
415
|
+
# "set_visibility_for" are called.
|
416
|
+
#
|
417
|
+
visibility_default, visibility_info =
|
418
|
+
parse_visibility(remaining_lines.join("\n"), visibility, container)
|
419
|
+
@@public_methods.concat visibility_info
|
420
|
+
if visibility_default == :public
|
421
|
+
if !cascaded_modules_list.empty?
|
422
|
+
cascaded_modules =
|
423
|
+
Attr.new("Cascaded Modules",
|
424
|
+
"Imported modules all of whose components are published again",
|
425
|
+
"",
|
426
|
+
cascaded_modules_list.join(", "))
|
427
|
+
container.add_attribute(cascaded_modules)
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
#
|
432
|
+
# Check rename elements
|
433
|
+
#
|
434
|
+
use_check_code = "#{before_contains_code}"
|
435
|
+
while use_check_code =~ /^\s*?use\s+(\w+)\s*?\,(.+)$/i
|
436
|
+
use_check_code = $~.pre_match
|
437
|
+
use_check_code << $~.post_match
|
438
|
+
used_mod_name = $1.strip.chomp
|
439
|
+
used_elements = $2.sub(/\s*?only\s*?:\s*?/i, '')
|
440
|
+
used_elements.split(",").each{ |used|
|
441
|
+
if /\s*?(\w+)\s*?=>\s*?(\w+)\s*?/ =~ used
|
442
|
+
local = $1
|
443
|
+
org = $2
|
444
|
+
@@public_methods.collect!{ |pub_meth|
|
445
|
+
if local == pub_meth["name"] ||
|
446
|
+
local.upcase == pub_meth["name"].upcase &&
|
447
|
+
@options.ignore_case
|
448
|
+
pub_meth["name"] = org
|
449
|
+
pub_meth["local_name"] = local
|
450
|
+
end
|
451
|
+
pub_meth
|
452
|
+
}
|
453
|
+
end
|
454
|
+
}
|
455
|
+
end
|
456
|
+
|
457
|
+
#
|
458
|
+
# Parse private "use"
|
459
|
+
#
|
460
|
+
use_check_code = remaining_lines.join("\n")
|
461
|
+
while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
|
462
|
+
use_check_code = $~.pre_match
|
463
|
+
use_check_code << $~.post_match
|
464
|
+
used_mod_name = $1.strip.chomp
|
465
|
+
used_trailing = $3 || ""
|
466
|
+
next if used_trailing =~ /!:nodoc:/
|
467
|
+
if !container.include_includes?(used_mod_name, @options.ignore_case)
|
468
|
+
progress "."
|
469
|
+
container.add_include Include.new(used_mod_name, "")
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
container.each_includes{ |inc|
|
474
|
+
TopLevel.all_files.each do |name, toplevel|
|
475
|
+
indicated_mod = toplevel.find_symbol(inc.name,
|
476
|
+
nil, @options.ignore_case)
|
477
|
+
if indicated_mod
|
478
|
+
indicated_name = indicated_mod.parent.file_relative_name
|
479
|
+
if !container.include_requires?(indicated_name, @options.ignore_case)
|
480
|
+
container.add_require(Require.new(indicated_name, ""))
|
481
|
+
end
|
482
|
+
break
|
483
|
+
end
|
484
|
+
end
|
485
|
+
}
|
486
|
+
|
487
|
+
#
|
488
|
+
# Parse derived-types definitions
|
489
|
+
#
|
490
|
+
derived_types_comment = ""
|
491
|
+
remaining_code = remaining_lines.join("\n")
|
492
|
+
while remaining_code =~ /^\s*?
|
493
|
+
type[\s\,]+(public|private)?\s*?(::)?\s*?
|
494
|
+
(\w+)\s*?(!.*?)?$
|
495
|
+
(.*?)
|
496
|
+
^\s*?end\s+type.*?$
|
497
|
+
/imx
|
498
|
+
remaining_code = $~.pre_match
|
499
|
+
remaining_code << $~.post_match
|
500
|
+
typename = $3.chomp.strip
|
501
|
+
type_elements = $5 || ""
|
502
|
+
type_code = remove_empty_head_lines($&)
|
503
|
+
type_trailing = find_comments($4)
|
504
|
+
next if type_trailing =~ /^:nodoc:/
|
505
|
+
type_visibility = $1
|
506
|
+
type_comment = COMMENTS_ARE_UPPER ?
|
507
|
+
find_comments($~.pre_match) + "\n" + type_trailing :
|
508
|
+
type_trailing + "\n" + find_comments(type_code.sub(/^.*$\n/i, ''))
|
509
|
+
type_element_visibility_public = true
|
510
|
+
type_code.split("\n").each{ |line|
|
511
|
+
if /^\s*?private\s*?$/ =~ line
|
512
|
+
type_element_visibility_public = nil
|
513
|
+
break
|
514
|
+
end
|
515
|
+
} if type_code
|
516
|
+
|
517
|
+
args_comment = ""
|
518
|
+
type_args_info = nil
|
519
|
+
|
520
|
+
if @options.show_all
|
521
|
+
args_comment = find_arguments(nil, type_code, true)
|
522
|
+
else
|
523
|
+
type_public_args_list = []
|
524
|
+
type_args_info = definition_info(type_code)
|
525
|
+
type_args_info.each{ |arg|
|
526
|
+
arg_is_public = type_element_visibility_public
|
527
|
+
arg_is_public = true if arg.include_attr?("public")
|
528
|
+
arg_is_public = nil if arg.include_attr?("private")
|
529
|
+
type_public_args_list << arg.varname if arg_is_public
|
530
|
+
}
|
531
|
+
args_comment = find_arguments(type_public_args_list, type_code)
|
532
|
+
end
|
533
|
+
|
534
|
+
type = AnyMethod.new("type #{typename}", typename)
|
535
|
+
type.singleton = false
|
536
|
+
type.params = ""
|
537
|
+
type.comment = "<b><em> Derived Type </em></b> :: <tt></tt>\n"
|
538
|
+
type.comment << args_comment if args_comment
|
539
|
+
type.comment << type_comment if type_comment
|
540
|
+
progress "t"
|
541
|
+
@stats.num_methods += 1
|
542
|
+
container.add_method type
|
543
|
+
|
544
|
+
set_visibility(container, typename, visibility_default, @@public_methods)
|
545
|
+
|
546
|
+
if type_visibility
|
547
|
+
type_visibility.gsub!(/\s/,'')
|
548
|
+
type_visibility.gsub!(/\,/,'')
|
549
|
+
type_visibility.gsub!(/:/,'')
|
550
|
+
type_visibility.downcase!
|
551
|
+
if type_visibility == "public"
|
552
|
+
container.set_visibility_for([typename], :public)
|
553
|
+
elsif type_visibility == "private"
|
554
|
+
container.set_visibility_for([typename], :private)
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
check_public_methods(type, container.name)
|
559
|
+
|
560
|
+
if @options.show_all
|
561
|
+
derived_types_comment << ", " unless derived_types_comment.empty?
|
562
|
+
derived_types_comment << typename
|
563
|
+
else
|
564
|
+
if type.visibility == :public
|
565
|
+
derived_types_comment << ", " unless derived_types_comment.empty?
|
566
|
+
derived_types_comment << typename
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
end
|
571
|
+
|
572
|
+
if !derived_types_comment.empty?
|
573
|
+
derived_types_table =
|
574
|
+
Attr.new("Derived Types", "Derived_Types", "",
|
575
|
+
derived_types_comment)
|
576
|
+
container.add_attribute(derived_types_table)
|
577
|
+
end
|
578
|
+
|
579
|
+
#
|
580
|
+
# move interface scope
|
581
|
+
#
|
582
|
+
interface_code = ""
|
583
|
+
while remaining_code =~ /^\s*?
|
584
|
+
interface(
|
585
|
+
\s+\w+ |
|
586
|
+
\s+operator\s*?\(.*?\) |
|
587
|
+
\s+assignment\s*?\(\s*?=\s*?\)
|
588
|
+
)?\s*?$
|
589
|
+
(.*?)
|
590
|
+
^\s*?end\s+interface.*?$
|
591
|
+
/imx
|
592
|
+
interface_code << remove_empty_head_lines($&) + "\n"
|
593
|
+
remaining_code = $~.pre_match
|
594
|
+
remaining_code << $~.post_match
|
595
|
+
end
|
596
|
+
|
597
|
+
#
|
598
|
+
# Parse global constants or variables in modules
|
599
|
+
#
|
600
|
+
const_var_defs = definition_info(before_contains_code)
|
601
|
+
const_var_defs.each{|defitem|
|
602
|
+
next if defitem.nodoc
|
603
|
+
const_or_var_type = "Variable"
|
604
|
+
const_or_var_progress = "v"
|
605
|
+
if defitem.include_attr?("parameter")
|
606
|
+
const_or_var_type = "Constant"
|
607
|
+
const_or_var_progress = "c"
|
608
|
+
end
|
609
|
+
const_or_var = AnyMethod.new(const_or_var_type, defitem.varname)
|
610
|
+
const_or_var.singleton = false
|
611
|
+
const_or_var.params = ""
|
612
|
+
self_comment = find_arguments([defitem.varname], before_contains_code)
|
613
|
+
const_or_var.comment = "<b><em>" + const_or_var_type + "</em></b> :: <tt></tt>\n"
|
614
|
+
const_or_var.comment << self_comment if self_comment
|
615
|
+
progress const_or_var_progress
|
616
|
+
@stats.num_methods += 1
|
617
|
+
container.add_method const_or_var
|
618
|
+
|
619
|
+
set_visibility(container, defitem.varname, visibility_default, @@public_methods)
|
620
|
+
|
621
|
+
if defitem.include_attr?("public")
|
622
|
+
container.set_visibility_for([defitem.varname], :public)
|
623
|
+
elsif defitem.include_attr?("private")
|
624
|
+
container.set_visibility_for([defitem.varname], :private)
|
625
|
+
end
|
626
|
+
|
627
|
+
check_public_methods(const_or_var, container.name)
|
628
|
+
|
629
|
+
} if const_var_defs
|
630
|
+
|
631
|
+
remaining_lines = remaining_code.split("\n")
|
632
|
+
|
633
|
+
# "subroutine" or "function" parts are parsed (new)
|
634
|
+
#
|
635
|
+
level_depth = 0
|
636
|
+
block_searching_flag = nil
|
637
|
+
block_searching_lines = []
|
638
|
+
pre_comment = []
|
639
|
+
procedure_trailing = ""
|
640
|
+
procedure_name = ""
|
641
|
+
procedure_params = ""
|
642
|
+
procedure_prefix = ""
|
643
|
+
procedure_result_arg = ""
|
644
|
+
procedure_type = ""
|
645
|
+
contains_lines = []
|
646
|
+
contains_flag = nil
|
647
|
+
remaining_lines.collect!{|line|
|
648
|
+
if !block_searching_flag
|
649
|
+
# subroutine
|
650
|
+
if line =~ /^\s*?
|
651
|
+
(recursive|pure|elemental)?\s*?
|
652
|
+
subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
|
653
|
+
/ix
|
654
|
+
block_searching_flag = :subroutine
|
655
|
+
block_searching_lines << line
|
656
|
+
|
657
|
+
procedure_name = $2.chomp.strip
|
658
|
+
procedure_params = $3 || ""
|
659
|
+
procedure_prefix = $1 || ""
|
660
|
+
procedure_trailing = $4 || "!"
|
661
|
+
next false
|
662
|
+
|
663
|
+
# function
|
664
|
+
elsif line =~ /^\s*?
|
665
|
+
(recursive|pure|elemental)?\s*?
|
666
|
+
(
|
667
|
+
character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
668
|
+
| type\s*?\([\w\s]+?\)\s+
|
669
|
+
| integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
670
|
+
| real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
671
|
+
| double\s+precision\s+
|
672
|
+
| logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
673
|
+
| complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
674
|
+
)?
|
675
|
+
function\s+(\w+)\s*?
|
676
|
+
(\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
|
677
|
+
/ix
|
678
|
+
block_searching_flag = :function
|
679
|
+
block_searching_lines << line
|
680
|
+
|
681
|
+
procedure_prefix = $1 || ""
|
682
|
+
procedure_type = $2 ? $2.chomp.strip : nil
|
683
|
+
procedure_name = $8.chomp.strip
|
684
|
+
procedure_params = $9 || ""
|
685
|
+
procedure_result_arg = $11 ? $11.chomp.strip : procedure_name
|
686
|
+
procedure_trailing = $12 || "!"
|
687
|
+
next false
|
688
|
+
elsif line =~ /^\s*?!\s?(.*)/
|
689
|
+
pre_comment << line
|
690
|
+
next line
|
691
|
+
else
|
692
|
+
pre_comment = []
|
693
|
+
next line
|
694
|
+
end
|
695
|
+
end
|
696
|
+
contains_flag = true if line =~ /^\s*?contains\s*?(!.*?)?$/
|
697
|
+
block_searching_lines << line
|
698
|
+
contains_lines << line if contains_flag
|
699
|
+
|
700
|
+
level_depth += 1 if block_start?(line)
|
701
|
+
level_depth -= 1 if block_end?(line)
|
702
|
+
if level_depth >= 0
|
703
|
+
next false
|
704
|
+
end
|
705
|
+
|
706
|
+
# "procedure_code" is formatted.
|
707
|
+
# ":nodoc:" flag is checked.
|
708
|
+
#
|
709
|
+
procedure_code = block_searching_lines.join("\n")
|
710
|
+
procedure_code = remove_empty_head_lines(procedure_code)
|
711
|
+
if procedure_trailing =~ /^!:nodoc:/
|
712
|
+
# next loop to search next block
|
713
|
+
level_depth = 0
|
714
|
+
block_searching_flag = nil
|
715
|
+
block_searching_lines = []
|
716
|
+
pre_comment = []
|
717
|
+
procedure_trailing = ""
|
718
|
+
procedure_name = ""
|
719
|
+
procedure_params = ""
|
720
|
+
procedure_prefix = ""
|
721
|
+
procedure_result_arg = ""
|
722
|
+
procedure_type = ""
|
723
|
+
contains_lines = []
|
724
|
+
contains_flag = nil
|
725
|
+
next false
|
726
|
+
end
|
727
|
+
|
728
|
+
# AnyMethod is created, and added to container
|
729
|
+
#
|
730
|
+
subroutine_function = nil
|
731
|
+
if block_searching_flag == :subroutine
|
732
|
+
subroutine_prefix = procedure_prefix
|
733
|
+
subroutine_name = procedure_name
|
734
|
+
subroutine_params = procedure_params
|
735
|
+
subroutine_trailing = procedure_trailing
|
736
|
+
subroutine_code = procedure_code
|
737
|
+
|
738
|
+
subroutine_comment = COMMENTS_ARE_UPPER ?
|
739
|
+
pre_comment.join("\n") + "\n" + subroutine_trailing :
|
740
|
+
subroutine_trailing + "\n" + subroutine_code.sub(/^.*$\n/i, '')
|
741
|
+
subroutine = AnyMethod.new("subroutine", subroutine_name)
|
742
|
+
parse_subprogram(subroutine, subroutine_params,
|
743
|
+
subroutine_comment, subroutine_code,
|
744
|
+
before_contains_code, nil, subroutine_prefix)
|
745
|
+
progress "s"
|
746
|
+
@stats.num_methods += 1
|
747
|
+
container.add_method subroutine
|
748
|
+
subroutine_function = subroutine
|
749
|
+
|
750
|
+
elsif block_searching_flag == :function
|
751
|
+
function_prefix = procedure_prefix
|
752
|
+
function_type = procedure_type
|
753
|
+
function_name = procedure_name
|
754
|
+
function_params_org = procedure_params
|
755
|
+
function_result_arg = procedure_result_arg
|
756
|
+
function_trailing = procedure_trailing
|
757
|
+
function_code_org = procedure_code
|
758
|
+
|
759
|
+
function_comment = COMMENTS_ARE_UPPER ?
|
760
|
+
pre_comment.join("\n") + "\n" + function_trailing :
|
761
|
+
function_trailing + "\n " + function_code_org.sub(/^.*$\n/i, '')
|
762
|
+
|
763
|
+
function_code = "#{function_code_org}"
|
764
|
+
if function_type
|
765
|
+
function_code << "\n" + function_type + " :: " + function_result_arg
|
766
|
+
end
|
767
|
+
|
768
|
+
function_params =
|
769
|
+
function_params_org.sub(/^\(/, "\(#{function_result_arg}, ")
|
770
|
+
|
771
|
+
function = AnyMethod.new("function", function_name)
|
772
|
+
parse_subprogram(function, function_params,
|
773
|
+
function_comment, function_code,
|
774
|
+
before_contains_code, true, function_prefix)
|
775
|
+
|
776
|
+
# Specific modification due to function
|
777
|
+
function.params.sub!(/\(\s*?#{function_result_arg}\s*?,\s*?/, "\( ")
|
778
|
+
function.params << " result(" + function_result_arg + ")"
|
779
|
+
function.start_collecting_tokens
|
780
|
+
function.add_token Token.new(1,1).set_text(function_code_org)
|
781
|
+
|
782
|
+
progress "f"
|
783
|
+
@stats.num_methods += 1
|
784
|
+
container.add_method function
|
785
|
+
subroutine_function = function
|
786
|
+
|
787
|
+
end
|
788
|
+
|
789
|
+
# The visibility of procedure is specified
|
790
|
+
#
|
791
|
+
set_visibility(container, procedure_name,
|
792
|
+
visibility_default, @@public_methods)
|
793
|
+
|
794
|
+
# The alias for this procedure from external modules
|
795
|
+
#
|
796
|
+
check_external_aliases(procedure_name,
|
797
|
+
subroutine_function.params,
|
798
|
+
subroutine_function.comment, subroutine_function) if external
|
799
|
+
check_public_methods(subroutine_function, container.name)
|
800
|
+
|
801
|
+
|
802
|
+
# contains_lines are parsed as private procedures
|
803
|
+
if contains_flag
|
804
|
+
parse_program_or_module(container,
|
805
|
+
contains_lines.join("\n"), :private)
|
806
|
+
end
|
807
|
+
|
808
|
+
# next loop to search next block
|
809
|
+
level_depth = 0
|
810
|
+
block_searching_flag = nil
|
811
|
+
block_searching_lines = []
|
812
|
+
pre_comment = []
|
813
|
+
procedure_trailing = ""
|
814
|
+
procedure_name = ""
|
815
|
+
procedure_params = ""
|
816
|
+
procedure_prefix = ""
|
817
|
+
procedure_result_arg = ""
|
818
|
+
contains_lines = []
|
819
|
+
contains_flag = nil
|
820
|
+
next false
|
821
|
+
} # End of remaining_lines.collect!{|line|
|
822
|
+
|
823
|
+
# Array remains_lines is converted to String remains_code again
|
824
|
+
#
|
825
|
+
remaining_code = remaining_lines.join("\n")
|
826
|
+
|
827
|
+
#
|
828
|
+
# Parse interface
|
829
|
+
#
|
830
|
+
interface_scope = false
|
831
|
+
generic_name = ""
|
832
|
+
interface_code.split("\n").each{ |line|
|
833
|
+
if /^\s*?
|
834
|
+
interface(
|
835
|
+
\s+\w+|
|
836
|
+
\s+operator\s*?\(.*?\)|
|
837
|
+
\s+assignment\s*?\(\s*?=\s*?\)
|
838
|
+
)?
|
839
|
+
\s*?(!.*?)?$
|
840
|
+
/ix =~ line
|
841
|
+
generic_name = $1 ? $1.strip.chomp : nil
|
842
|
+
interface_trailing = $2 || "!"
|
843
|
+
interface_scope = true
|
844
|
+
interface_scope = false if interface_trailing =~ /!:nodoc:/
|
845
|
+
# if generic_name =~ /operator\s*?\((.*?)\)/i
|
846
|
+
# operator_name = $1
|
847
|
+
# if operator_name && !operator_name.empty?
|
848
|
+
# generic_name = "#{operator_name}"
|
849
|
+
# end
|
850
|
+
# end
|
851
|
+
# if generic_name =~ /assignment\s*?\((.*?)\)/i
|
852
|
+
# assignment_name = $1
|
853
|
+
# if assignment_name && !assignment_name.empty?
|
854
|
+
# generic_name = "#{assignment_name}"
|
855
|
+
# end
|
856
|
+
# end
|
857
|
+
end
|
858
|
+
if /^\s*?end\s+interface/i =~ line
|
859
|
+
interface_scope = false
|
860
|
+
generic_name = nil
|
861
|
+
end
|
862
|
+
# internal alias
|
863
|
+
if interface_scope && /^\s*?module\s+procedure\s+(.*?)(!.*?)?$/i =~ line
|
864
|
+
procedures = $1.strip.chomp
|
865
|
+
procedures_trailing = $2 || "!"
|
866
|
+
next if procedures_trailing =~ /!:nodoc:/
|
867
|
+
procedures.split(",").each{ |proc|
|
868
|
+
proc.strip!
|
869
|
+
proc.chomp!
|
870
|
+
next if generic_name == proc || !generic_name
|
871
|
+
old_meth = container.find_symbol(proc, nil, @options.ignore_case)
|
872
|
+
next if !old_meth
|
873
|
+
nolink = old_meth.visibility == :private ? true : nil
|
874
|
+
nolink = nil if @options.show_all
|
875
|
+
new_meth =
|
876
|
+
initialize_external_method(generic_name, proc,
|
877
|
+
old_meth.params, nil,
|
878
|
+
old_meth.comment,
|
879
|
+
old_meth.clone.token_stream[0].text,
|
880
|
+
true, nolink)
|
881
|
+
new_meth.singleton = old_meth.singleton
|
882
|
+
|
883
|
+
progress "i"
|
884
|
+
@stats.num_methods += 1
|
885
|
+
container.add_method new_meth
|
886
|
+
|
887
|
+
set_visibility(container, generic_name, visibility_default, @@public_methods)
|
888
|
+
|
889
|
+
check_public_methods(new_meth, container.name)
|
890
|
+
|
891
|
+
}
|
892
|
+
end
|
893
|
+
|
894
|
+
# external aliases
|
895
|
+
if interface_scope
|
896
|
+
# subroutine
|
897
|
+
proc = nil
|
898
|
+
params = nil
|
899
|
+
procedures_trailing = nil
|
900
|
+
if line =~ /^\s*?
|
901
|
+
(recursive|pure|elemental)?\s*?
|
902
|
+
subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
|
903
|
+
/ix
|
904
|
+
proc = $2.chomp.strip
|
905
|
+
generic_name = proc unless generic_name
|
906
|
+
params = $3 || ""
|
907
|
+
procedures_trailing = $4 || "!"
|
908
|
+
|
909
|
+
# function
|
910
|
+
elsif line =~ /^\s*?
|
911
|
+
(recursive|pure|elemental)?\s*?
|
912
|
+
(
|
913
|
+
character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
914
|
+
| type\s*?\([\w\s]+?\)\s+
|
915
|
+
| integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
916
|
+
| real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
917
|
+
| double\s+precision\s+
|
918
|
+
| logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
919
|
+
| complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
920
|
+
)?
|
921
|
+
function\s+(\w+)\s*?
|
922
|
+
(\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
|
923
|
+
/ix
|
924
|
+
proc = $8.chomp.strip
|
925
|
+
generic_name = proc unless generic_name
|
926
|
+
params = $9 || ""
|
927
|
+
procedures_trailing = $12 || "!"
|
928
|
+
else
|
929
|
+
next
|
930
|
+
end
|
931
|
+
next if procedures_trailing =~ /!:nodoc:/
|
932
|
+
indicated_method = nil
|
933
|
+
indicated_file = nil
|
934
|
+
TopLevel.all_files.each do |name, toplevel|
|
935
|
+
indicated_method = toplevel.find_local_symbol(proc, @options.ignore_case)
|
936
|
+
indicated_file = name
|
937
|
+
break if indicated_method
|
938
|
+
end
|
939
|
+
|
940
|
+
if indicated_method
|
941
|
+
external_method =
|
942
|
+
initialize_external_method(generic_name, proc,
|
943
|
+
indicated_method.params,
|
944
|
+
indicated_file,
|
945
|
+
indicated_method.comment)
|
946
|
+
|
947
|
+
progress "e"
|
948
|
+
@stats.num_methods += 1
|
949
|
+
container.add_method external_method
|
950
|
+
set_visibility(container, generic_name, visibility_default, @@public_methods)
|
951
|
+
if !container.include_requires?(indicated_file, @options.ignore_case)
|
952
|
+
container.add_require(Require.new(indicated_file, ""))
|
953
|
+
end
|
954
|
+
check_public_methods(external_method, container.name)
|
955
|
+
|
956
|
+
else
|
957
|
+
@@external_aliases << {
|
958
|
+
"new_name" => generic_name,
|
959
|
+
"old_name" => proc,
|
960
|
+
"file_or_module" => container,
|
961
|
+
"visibility" => find_visibility(container, generic_name, @@public_methods) || visibility_default
|
962
|
+
}
|
963
|
+
end
|
964
|
+
end
|
965
|
+
|
966
|
+
} if interface_code # End of interface_code.split("\n").each ...
|
967
|
+
|
968
|
+
#
|
969
|
+
# Already imported methods are removed from @@public_methods.
|
970
|
+
# Remainders are assumed to be imported from other modules.
|
971
|
+
#
|
972
|
+
@@public_methods.delete_if{ |method| method["entity_is_discovered"]}
|
973
|
+
|
974
|
+
@@public_methods.each{ |pub_meth|
|
975
|
+
next unless pub_meth["file_or_module"].name == container.name
|
976
|
+
pub_meth["used_modules"].each{ |used_mod|
|
977
|
+
TopLevel.all_classes_and_modules.each{ |modules|
|
978
|
+
if modules.name == used_mod ||
|
979
|
+
modules.name.upcase == used_mod.upcase &&
|
980
|
+
@options.ignore_case
|
981
|
+
modules.method_list.each{ |meth|
|
982
|
+
if meth.name == pub_meth["name"] ||
|
983
|
+
meth.name.upcase == pub_meth["name"].upcase &&
|
984
|
+
@options.ignore_case
|
985
|
+
new_meth = initialize_public_method(meth,
|
986
|
+
modules.name)
|
987
|
+
if pub_meth["local_name"]
|
988
|
+
new_meth.name = pub_meth["local_name"]
|
989
|
+
end
|
990
|
+
progress "e"
|
991
|
+
@stats.num_methods += 1
|
992
|
+
container.add_method new_meth
|
993
|
+
end
|
994
|
+
}
|
995
|
+
end
|
996
|
+
}
|
997
|
+
}
|
998
|
+
}
|
999
|
+
|
1000
|
+
container
|
1001
|
+
end # End of parse_program_or_module
|
1002
|
+
|
1003
|
+
#
|
1004
|
+
# Parse arguments, comment, code of subroutine and function.
|
1005
|
+
# Return AnyMethod object.
|
1006
|
+
#
|
1007
|
+
def parse_subprogram(subprogram, params, comment, code,
|
1008
|
+
before_contains=nil, function=nil, prefix=nil)
|
1009
|
+
subprogram.singleton = false
|
1010
|
+
prefix = "" if !prefix
|
1011
|
+
arguments = params.sub(/\(/, "").sub(/\)/, "").split(",") if params
|
1012
|
+
args_comment, params_opt =
|
1013
|
+
find_arguments(arguments, code.sub(/^s*?contains\s*?(!.*?)?$.*/im, ""),
|
1014
|
+
nil, nil, true)
|
1015
|
+
params_opt = "( " + params_opt + " ) " if params_opt
|
1016
|
+
subprogram.params = params_opt || ""
|
1017
|
+
namelist_comment = find_namelists(code, before_contains)
|
1018
|
+
|
1019
|
+
block_comment = find_comments comment
|
1020
|
+
if function
|
1021
|
+
subprogram.comment = "<b><em> Function </em></b> :: <em>#{prefix}</em>\n"
|
1022
|
+
else
|
1023
|
+
subprogram.comment = "<b><em> Subroutine </em></b> :: <em>#{prefix}</em>\n"
|
1024
|
+
end
|
1025
|
+
subprogram.comment << args_comment if args_comment
|
1026
|
+
subprogram.comment << block_comment if block_comment
|
1027
|
+
subprogram.comment << namelist_comment if namelist_comment
|
1028
|
+
|
1029
|
+
# For output source code
|
1030
|
+
subprogram.start_collecting_tokens
|
1031
|
+
subprogram.add_token Token.new(1,1).set_text(code)
|
1032
|
+
|
1033
|
+
subprogram
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
#
|
1037
|
+
# Collect comment for file entity
|
1038
|
+
#
|
1039
|
+
def collect_first_comment(body)
|
1040
|
+
comment = ""
|
1041
|
+
not_comment = ""
|
1042
|
+
comment_start = false
|
1043
|
+
comment_end = false
|
1044
|
+
body.split("\n").each{ |line|
|
1045
|
+
if comment_end
|
1046
|
+
not_comment << line
|
1047
|
+
not_comment << "\n"
|
1048
|
+
elsif /^\s*?!\s?(.*)$/i =~ line
|
1049
|
+
comment_start = true
|
1050
|
+
comment << $1
|
1051
|
+
comment << "\n"
|
1052
|
+
elsif /^\s*?$/i =~ line
|
1053
|
+
comment_end = true if comment_start && COMMENTS_ARE_UPPER
|
1054
|
+
else
|
1055
|
+
comment_end = true
|
1056
|
+
not_comment << line
|
1057
|
+
not_comment << "\n"
|
1058
|
+
end
|
1059
|
+
}
|
1060
|
+
return comment, not_comment
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
|
1064
|
+
# Return comments of definitions of arguments
|
1065
|
+
#
|
1066
|
+
# If "all" argument is true, information of all arguments are returned.
|
1067
|
+
# If "modified_params" is true, list of arguments are decorated,
|
1068
|
+
# for exameple, optional arguments are parenthetic as "[arg]".
|
1069
|
+
#
|
1070
|
+
def find_arguments(args, text, all=nil, indent=nil, modified_params=nil)
|
1071
|
+
return unless args || all
|
1072
|
+
indent = "" unless indent
|
1073
|
+
args = ["all"] if all
|
1074
|
+
params = "" if modified_params
|
1075
|
+
comma = ""
|
1076
|
+
return unless text
|
1077
|
+
args_rdocforms = "\n"
|
1078
|
+
remaining_lines = "#{text}"
|
1079
|
+
definitions = definition_info(remaining_lines)
|
1080
|
+
args.each{ |arg|
|
1081
|
+
arg.strip!
|
1082
|
+
arg.chomp!
|
1083
|
+
definitions.each { |defitem|
|
1084
|
+
if arg == defitem.varname.strip.chomp || all
|
1085
|
+
args_rdocforms << <<-"EOF"
|
1086
|
+
|
1087
|
+
#{indent}<tt><b>#{defitem.varname.chomp.strip}#{defitem.arraysuffix}</b> #{defitem.inivalue}</tt> ::
|
1088
|
+
#{indent} <tt>#{defitem.types.chomp.strip}</tt>
|
1089
|
+
EOF
|
1090
|
+
if !defitem.comment.chomp.strip.empty?
|
1091
|
+
comment = ""
|
1092
|
+
defitem.comment.split("\n").each{ |line|
|
1093
|
+
comment << " " + line + "\n"
|
1094
|
+
}
|
1095
|
+
args_rdocforms << <<-"EOF"
|
1096
|
+
|
1097
|
+
#{indent} <tt></tt> ::
|
1098
|
+
#{indent} <tt></tt>
|
1099
|
+
#{indent} #{comment.chomp.strip}
|
1100
|
+
EOF
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
if modified_params
|
1104
|
+
if defitem.include_attr?("optional")
|
1105
|
+
params << "#{comma}[#{arg}]"
|
1106
|
+
else
|
1107
|
+
params << "#{comma}#{arg}"
|
1108
|
+
end
|
1109
|
+
comma = ", "
|
1110
|
+
end
|
1111
|
+
end
|
1112
|
+
}
|
1113
|
+
}
|
1114
|
+
if modified_params
|
1115
|
+
return args_rdocforms, params
|
1116
|
+
else
|
1117
|
+
return args_rdocforms
|
1118
|
+
end
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
# Return comments of definitions of namelists
|
1122
|
+
#
|
1123
|
+
def find_namelists(text, before_contains=nil)
|
1124
|
+
return nil if !text
|
1125
|
+
result = ""
|
1126
|
+
lines = "#{text}"
|
1127
|
+
before_contains = "" if !before_contains
|
1128
|
+
while lines =~ /^\s*?namelist\s+\/\s*?(\w+)\s*?\/([\s\w\,]+)$/i
|
1129
|
+
lines = $~.post_match
|
1130
|
+
nml_comment = COMMENTS_ARE_UPPER ?
|
1131
|
+
find_comments($~.pre_match) : find_comments($~.post_match)
|
1132
|
+
nml_name = $1
|
1133
|
+
nml_args = $2.split(",")
|
1134
|
+
result << "\n\n=== NAMELIST <tt><b>" + nml_name + "</tt></b>\n\n"
|
1135
|
+
result << nml_comment + "\n" if nml_comment
|
1136
|
+
if lines.split("\n")[0] =~ /^\//i
|
1137
|
+
lines = "namelist " + lines
|
1138
|
+
end
|
1139
|
+
result << find_arguments(nml_args, "#{text}" + "\n" + before_contains)
|
1140
|
+
end
|
1141
|
+
return result
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
#
|
1145
|
+
# Comments just after module or subprogram, or arguments are
|
1146
|
+
# returnd. If "COMMENTS_ARE_UPPER" is true, comments just before
|
1147
|
+
# modules or subprograms are returnd
|
1148
|
+
#
|
1149
|
+
def find_comments text
|
1150
|
+
return "" unless text
|
1151
|
+
lines = text.split("\n")
|
1152
|
+
lines.reverse! if COMMENTS_ARE_UPPER
|
1153
|
+
comment_block = Array.new
|
1154
|
+
lines.each do |line|
|
1155
|
+
break if line =~ /^\s*?\w/ || line =~ /^\s*?$/
|
1156
|
+
if COMMENTS_ARE_UPPER
|
1157
|
+
comment_block.unshift line.sub(/^\s*?!\s?/,"")
|
1158
|
+
else
|
1159
|
+
comment_block.push line.sub(/^\s*?!\s?/,"")
|
1160
|
+
end
|
1161
|
+
end
|
1162
|
+
nice_lines = comment_block.join("\n").split "\n\s*?\n"
|
1163
|
+
nice_lines[0] ||= ""
|
1164
|
+
nice_lines.shift
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
def progress(char)
|
1168
|
+
unless @options.quiet
|
1169
|
+
@progress.print(char)
|
1170
|
+
@progress.flush
|
1171
|
+
end
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
#
|
1175
|
+
# Create method for internal alias
|
1176
|
+
#
|
1177
|
+
def initialize_public_method(method, parent)
|
1178
|
+
return if !method || !parent
|
1179
|
+
|
1180
|
+
new_meth = AnyMethod.new("External Alias for module", method.name)
|
1181
|
+
new_meth.singleton = method.singleton
|
1182
|
+
new_meth.params = method.params.clone
|
1183
|
+
new_meth.comment = remove_trailing_alias(method.comment.clone)
|
1184
|
+
new_meth.comment << "\n\n#{EXTERNAL_ALIAS_MES} #{parent.strip.chomp}\##{method.name}"
|
1185
|
+
|
1186
|
+
return new_meth
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
#
|
1190
|
+
# Create method for external alias
|
1191
|
+
#
|
1192
|
+
# If argument "internal" is true, file is ignored.
|
1193
|
+
#
|
1194
|
+
def initialize_external_method(new, old, params, file, comment, token=nil,
|
1195
|
+
internal=nil, nolink=nil)
|
1196
|
+
return nil unless new || old
|
1197
|
+
|
1198
|
+
if internal
|
1199
|
+
external_alias_header = "#{INTERNAL_ALIAS_MES} "
|
1200
|
+
external_alias_text = external_alias_header + old
|
1201
|
+
elsif file
|
1202
|
+
external_alias_header = "#{EXTERNAL_ALIAS_MES} "
|
1203
|
+
external_alias_text = external_alias_header + file + "#" + old
|
1204
|
+
else
|
1205
|
+
return nil
|
1206
|
+
end
|
1207
|
+
external_meth = AnyMethod.new(external_alias_text, new)
|
1208
|
+
external_meth.singleton = false
|
1209
|
+
external_meth.params = params
|
1210
|
+
external_comment = remove_trailing_alias(comment) + "\n\n" if comment
|
1211
|
+
external_meth.comment = external_comment || ""
|
1212
|
+
if nolink && token
|
1213
|
+
external_meth.start_collecting_tokens
|
1214
|
+
external_meth.add_token Token.new(1,1).set_text(token)
|
1215
|
+
else
|
1216
|
+
external_meth.comment << external_alias_text
|
1217
|
+
end
|
1218
|
+
|
1219
|
+
return external_meth
|
1220
|
+
end
|
1221
|
+
|
1222
|
+
|
1223
|
+
|
1224
|
+
#
|
1225
|
+
# Parse visibility
|
1226
|
+
#
|
1227
|
+
def parse_visibility(code, default, container)
|
1228
|
+
result = []
|
1229
|
+
visibility_default = default || :public
|
1230
|
+
|
1231
|
+
used_modules = []
|
1232
|
+
container.includes.each{|i| used_modules << i.name} if container
|
1233
|
+
|
1234
|
+
remaining_code = code.gsub(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
|
1235
|
+
remaining_code.split("\n").each{ |line|
|
1236
|
+
if /^\s*?private\s*?$/ =~ line
|
1237
|
+
visibility_default = :private
|
1238
|
+
break
|
1239
|
+
end
|
1240
|
+
} if remaining_code
|
1241
|
+
|
1242
|
+
remaining_code.split("\n").each{ |line|
|
1243
|
+
if /^\s*?private\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
|
1244
|
+
methods = $2.sub(/!.*$/, '')
|
1245
|
+
methods.split(",").each{ |meth|
|
1246
|
+
meth.sub!(/!.*$/, '')
|
1247
|
+
meth.gsub!(/:/, '')
|
1248
|
+
result << {
|
1249
|
+
"name" => meth.chomp.strip,
|
1250
|
+
"visibility" => :private,
|
1251
|
+
"used_modules" => used_modules.clone,
|
1252
|
+
"file_or_module" => container,
|
1253
|
+
"entity_is_discovered" => nil,
|
1254
|
+
"local_name" => nil
|
1255
|
+
}
|
1256
|
+
}
|
1257
|
+
elsif /^\s*?public\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
|
1258
|
+
methods = $2.sub(/!.*$/, '')
|
1259
|
+
methods.split(",").each{ |meth|
|
1260
|
+
meth.sub!(/!.*$/, '')
|
1261
|
+
meth.gsub!(/:/, '')
|
1262
|
+
result << {
|
1263
|
+
"name" => meth.chomp.strip,
|
1264
|
+
"visibility" => :public,
|
1265
|
+
"used_modules" => used_modules.clone,
|
1266
|
+
"file_or_module" => container,
|
1267
|
+
"entity_is_discovered" => nil,
|
1268
|
+
"local_name" => nil
|
1269
|
+
}
|
1270
|
+
}
|
1271
|
+
end
|
1272
|
+
} if remaining_code
|
1273
|
+
|
1274
|
+
if container
|
1275
|
+
result.each{ |vis_info|
|
1276
|
+
vis_info["parent"] = container.name
|
1277
|
+
}
|
1278
|
+
end
|
1279
|
+
|
1280
|
+
return visibility_default, result
|
1281
|
+
end
|
1282
|
+
|
1283
|
+
#
|
1284
|
+
# Set visibility
|
1285
|
+
#
|
1286
|
+
# "subname" element of "visibility_info" is deleted.
|
1287
|
+
#
|
1288
|
+
def set_visibility(container, subname, visibility_default, visibility_info)
|
1289
|
+
return unless container || subname || visibility_default || visibility_info
|
1290
|
+
not_found = true
|
1291
|
+
visibility_info.collect!{ |info|
|
1292
|
+
if info["name"] == subname ||
|
1293
|
+
@options.ignore_case && info["name"].upcase == subname.upcase
|
1294
|
+
if info["file_or_module"].name == container.name
|
1295
|
+
container.set_visibility_for([subname], info["visibility"])
|
1296
|
+
info["entity_is_discovered"] = true
|
1297
|
+
not_found = false
|
1298
|
+
end
|
1299
|
+
end
|
1300
|
+
info
|
1301
|
+
}
|
1302
|
+
if not_found
|
1303
|
+
return container.set_visibility_for([subname], visibility_default)
|
1304
|
+
else
|
1305
|
+
return container
|
1306
|
+
end
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
#
|
1310
|
+
# Find visibility
|
1311
|
+
#
|
1312
|
+
def find_visibility(container, subname, visibility_info)
|
1313
|
+
return nil if !subname || !visibility_info
|
1314
|
+
visibility_info.each{ |info|
|
1315
|
+
if info["name"] == subname ||
|
1316
|
+
@options.ignore_case && info["name"].upcase == subname.upcase
|
1317
|
+
if info["parent"] == container.name
|
1318
|
+
return info["visibility"]
|
1319
|
+
end
|
1320
|
+
end
|
1321
|
+
}
|
1322
|
+
return nil
|
1323
|
+
end
|
1324
|
+
|
1325
|
+
#
|
1326
|
+
# Check external aliases
|
1327
|
+
#
|
1328
|
+
def check_external_aliases(subname, params, comment, test=nil)
|
1329
|
+
@@external_aliases.each{ |alias_item|
|
1330
|
+
if subname == alias_item["old_name"] ||
|
1331
|
+
subname.upcase == alias_item["old_name"].upcase &&
|
1332
|
+
@options.ignore_case
|
1333
|
+
|
1334
|
+
new_meth = initialize_external_method(alias_item["new_name"],
|
1335
|
+
subname, params, @file_name,
|
1336
|
+
comment)
|
1337
|
+
new_meth.visibility = alias_item["visibility"]
|
1338
|
+
|
1339
|
+
progress "e"
|
1340
|
+
@stats.num_methods += 1
|
1341
|
+
alias_item["file_or_module"].add_method(new_meth)
|
1342
|
+
|
1343
|
+
if !alias_item["file_or_module"].include_requires?(@file_name, @options.ignore_case)
|
1344
|
+
alias_item["file_or_module"].add_require(Require.new(@file_name, ""))
|
1345
|
+
end
|
1346
|
+
end
|
1347
|
+
}
|
1348
|
+
end
|
1349
|
+
|
1350
|
+
#
|
1351
|
+
# Check public_methods
|
1352
|
+
#
|
1353
|
+
def check_public_methods(method, parent)
|
1354
|
+
return if !method || !parent
|
1355
|
+
@@public_methods.each{ |alias_item|
|
1356
|
+
parent_is_used_module = nil
|
1357
|
+
alias_item["used_modules"].each{ |used_module|
|
1358
|
+
if used_module == parent ||
|
1359
|
+
used_module.upcase == parent.upcase &&
|
1360
|
+
@options.ignore_case
|
1361
|
+
parent_is_used_module = true
|
1362
|
+
end
|
1363
|
+
}
|
1364
|
+
next if !parent_is_used_module
|
1365
|
+
|
1366
|
+
if method.name == alias_item["name"] ||
|
1367
|
+
method.name.upcase == alias_item["name"].upcase &&
|
1368
|
+
@options.ignore_case
|
1369
|
+
|
1370
|
+
new_meth = initialize_public_method(method, parent)
|
1371
|
+
if alias_item["local_name"]
|
1372
|
+
new_meth.name = alias_item["local_name"]
|
1373
|
+
end
|
1374
|
+
|
1375
|
+
progress "e"
|
1376
|
+
@stats.num_methods += 1
|
1377
|
+
alias_item["file_or_module"].add_method new_meth
|
1378
|
+
end
|
1379
|
+
}
|
1380
|
+
end
|
1381
|
+
|
1382
|
+
#
|
1383
|
+
# Continuous lines are united.
|
1384
|
+
#
|
1385
|
+
# Comments in continuous lines are removed.
|
1386
|
+
#
|
1387
|
+
def united_to_one_line(f90src)
|
1388
|
+
return "" unless f90src
|
1389
|
+
lines = f90src.split("\n")
|
1390
|
+
previous_continuing = false
|
1391
|
+
now_continuing = false
|
1392
|
+
body = ""
|
1393
|
+
lines.each{ |line|
|
1394
|
+
words = line.split("")
|
1395
|
+
next if words.empty? && previous_continuing
|
1396
|
+
commentout = false
|
1397
|
+
brank_flag = true ; brank_char = ""
|
1398
|
+
squote = false ; dquote = false
|
1399
|
+
ignore = false
|
1400
|
+
words.collect! { |char|
|
1401
|
+
if previous_continuing && brank_flag
|
1402
|
+
now_continuing = true
|
1403
|
+
ignore = true
|
1404
|
+
case char
|
1405
|
+
when "!" ; break
|
1406
|
+
when " " ; brank_char << char ; next ""
|
1407
|
+
when "&"
|
1408
|
+
brank_flag = false
|
1409
|
+
now_continuing = false
|
1410
|
+
next ""
|
1411
|
+
else
|
1412
|
+
brank_flag = false
|
1413
|
+
now_continuing = false
|
1414
|
+
ignore = false
|
1415
|
+
next brank_char + char
|
1416
|
+
end
|
1417
|
+
end
|
1418
|
+
ignore = false
|
1419
|
+
|
1420
|
+
if now_continuing
|
1421
|
+
next ""
|
1422
|
+
elsif !(squote) && !(dquote) && !(commentout)
|
1423
|
+
case char
|
1424
|
+
when "!" ; commentout = true ; next char
|
1425
|
+
when "\""; dquote = true ; next char
|
1426
|
+
when "\'"; squote = true ; next char
|
1427
|
+
when "&" ; now_continuing = true ; next ""
|
1428
|
+
else next char
|
1429
|
+
end
|
1430
|
+
elsif commentout
|
1431
|
+
next char
|
1432
|
+
elsif squote
|
1433
|
+
case char
|
1434
|
+
when "\'"; squote = false ; next char
|
1435
|
+
else next char
|
1436
|
+
end
|
1437
|
+
elsif dquote
|
1438
|
+
case char
|
1439
|
+
when "\""; dquote = false ; next char
|
1440
|
+
else next char
|
1441
|
+
end
|
1442
|
+
end
|
1443
|
+
}
|
1444
|
+
if !ignore && !previous_continuing || !brank_flag
|
1445
|
+
if previous_continuing
|
1446
|
+
body << words.join("")
|
1447
|
+
else
|
1448
|
+
body << "\n" + words.join("")
|
1449
|
+
end
|
1450
|
+
end
|
1451
|
+
previous_continuing = now_continuing ? true : nil
|
1452
|
+
now_continuing = nil
|
1453
|
+
}
|
1454
|
+
return body
|
1455
|
+
end
|
1456
|
+
|
1457
|
+
|
1458
|
+
#
|
1459
|
+
# Continuous line checker
|
1460
|
+
#
|
1461
|
+
def continuous_line?(line)
|
1462
|
+
continuous = false
|
1463
|
+
if /&\s*?(!.*)?$/ =~ line
|
1464
|
+
continuous = true
|
1465
|
+
if comment_out?($~.pre_match)
|
1466
|
+
continuous = false
|
1467
|
+
end
|
1468
|
+
end
|
1469
|
+
return continuous
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
#
|
1473
|
+
# Comment out checker
|
1474
|
+
#
|
1475
|
+
def comment_out?(line)
|
1476
|
+
return nil unless line
|
1477
|
+
commentout = false
|
1478
|
+
squote = false ; dquote = false
|
1479
|
+
line.split("").each { |char|
|
1480
|
+
if !(squote) && !(dquote)
|
1481
|
+
case char
|
1482
|
+
when "!" ; commentout = true ; break
|
1483
|
+
when "\""; dquote = true
|
1484
|
+
when "\'"; squote = true
|
1485
|
+
else next
|
1486
|
+
end
|
1487
|
+
elsif squote
|
1488
|
+
case char
|
1489
|
+
when "\'"; squote = false
|
1490
|
+
else next
|
1491
|
+
end
|
1492
|
+
elsif dquote
|
1493
|
+
case char
|
1494
|
+
when "\""; dquote = false
|
1495
|
+
else next
|
1496
|
+
end
|
1497
|
+
end
|
1498
|
+
}
|
1499
|
+
return commentout
|
1500
|
+
end
|
1501
|
+
|
1502
|
+
#
|
1503
|
+
# Semicolons are replaced to line feed.
|
1504
|
+
#
|
1505
|
+
def semicolon_to_linefeed(text)
|
1506
|
+
return "" unless text
|
1507
|
+
lines = text.split("\n")
|
1508
|
+
lines.collect!{ |line|
|
1509
|
+
words = line.split("")
|
1510
|
+
commentout = false
|
1511
|
+
squote = false ; dquote = false
|
1512
|
+
words.collect! { |char|
|
1513
|
+
if !(squote) && !(dquote) && !(commentout)
|
1514
|
+
case char
|
1515
|
+
when "!" ; commentout = true ; next char
|
1516
|
+
when "\""; dquote = true ; next char
|
1517
|
+
when "\'"; squote = true ; next char
|
1518
|
+
when ";" ; "\n"
|
1519
|
+
else next char
|
1520
|
+
end
|
1521
|
+
elsif commentout
|
1522
|
+
next char
|
1523
|
+
elsif squote
|
1524
|
+
case char
|
1525
|
+
when "\'"; squote = false ; next char
|
1526
|
+
else next char
|
1527
|
+
end
|
1528
|
+
elsif dquote
|
1529
|
+
case char
|
1530
|
+
when "\""; dquote = false ; next char
|
1531
|
+
else next char
|
1532
|
+
end
|
1533
|
+
end
|
1534
|
+
}
|
1535
|
+
words.join("")
|
1536
|
+
}
|
1537
|
+
return lines.join("\n")
|
1538
|
+
end
|
1539
|
+
|
1540
|
+
#
|
1541
|
+
# Which "line" is start of block (module, program, block data,
|
1542
|
+
# subroutine, function) statement ?
|
1543
|
+
#
|
1544
|
+
def block_start?(line)
|
1545
|
+
return nil if !line
|
1546
|
+
|
1547
|
+
if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i ||
|
1548
|
+
line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
|
1549
|
+
line =~ /^\s*?block\s+data(\s+\w+)?\s*?(!.*?)?$/i ||
|
1550
|
+
line =~ \
|
1551
|
+
/^\s*?
|
1552
|
+
(recursive|pure|elemental)?\s*?
|
1553
|
+
subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
|
1554
|
+
/ix ||
|
1555
|
+
line =~ \
|
1556
|
+
/^\s*?
|
1557
|
+
(recursive|pure|elemental)?\s*?
|
1558
|
+
(
|
1559
|
+
character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
1560
|
+
| type\s*?\([\w\s]+?\)\s+
|
1561
|
+
| integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
1562
|
+
| real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
1563
|
+
| double\s+precision\s+
|
1564
|
+
| logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
1565
|
+
| complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
|
1566
|
+
)?
|
1567
|
+
function\s+(\w+)\s*?
|
1568
|
+
(\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
|
1569
|
+
/ix
|
1570
|
+
return true
|
1571
|
+
end
|
1572
|
+
|
1573
|
+
return nil
|
1574
|
+
end
|
1575
|
+
|
1576
|
+
#
|
1577
|
+
# Which "line" is end of block (module, program, block data,
|
1578
|
+
# subroutine, function) statement ?
|
1579
|
+
#
|
1580
|
+
def block_end?(line)
|
1581
|
+
return nil if !line
|
1582
|
+
|
1583
|
+
if line =~ /^\s*?end\s*?(!.*?)?$/i ||
|
1584
|
+
line =~ /^\s*?end\s+module(\s+\w+)?\s*?(!.*?)?$/i ||
|
1585
|
+
line =~ /^\s*?end\s+program(\s+\w+)?\s*?(!.*?)?$/i ||
|
1586
|
+
line =~ /^\s*?end\s+block\s+data(\s+\w+)?\s*?(!.*?)?$/i ||
|
1587
|
+
line =~ /^\s*?end\s+subroutine(\s+\w+)?\s*?(!.*?)?$/i ||
|
1588
|
+
line =~ /^\s*?end\s+function(\s+\w+)?\s*?(!.*?)?$/i
|
1589
|
+
return true
|
1590
|
+
end
|
1591
|
+
|
1592
|
+
return nil
|
1593
|
+
end
|
1594
|
+
|
1595
|
+
#
|
1596
|
+
# Remove "Alias for" in end of comments
|
1597
|
+
#
|
1598
|
+
def remove_trailing_alias(text)
|
1599
|
+
return "" if !text
|
1600
|
+
lines = text.split("\n").reverse
|
1601
|
+
comment_block = Array.new
|
1602
|
+
checked = false
|
1603
|
+
lines.each do |line|
|
1604
|
+
if !checked
|
1605
|
+
if /^\s?#{INTERNAL_ALIAS_MES}/ =~ line ||
|
1606
|
+
/^\s?#{EXTERNAL_ALIAS_MES}/ =~ line
|
1607
|
+
checked = true
|
1608
|
+
next
|
1609
|
+
end
|
1610
|
+
end
|
1611
|
+
comment_block.unshift line
|
1612
|
+
end
|
1613
|
+
nice_lines = comment_block.join("\n")
|
1614
|
+
nice_lines ||= ""
|
1615
|
+
return nice_lines
|
1616
|
+
end
|
1617
|
+
|
1618
|
+
# Empty lines in header are removed
|
1619
|
+
def remove_empty_head_lines(text)
|
1620
|
+
return "" unless text
|
1621
|
+
lines = text.split("\n")
|
1622
|
+
header = true
|
1623
|
+
lines.delete_if{ |line|
|
1624
|
+
header = false if /\S/ =~ line
|
1625
|
+
header && /^\s*?$/ =~ line
|
1626
|
+
}
|
1627
|
+
lines.join("\n")
|
1628
|
+
end
|
1629
|
+
|
1630
|
+
|
1631
|
+
# header marker "=", "==", ... are removed
|
1632
|
+
def remove_header_marker(text)
|
1633
|
+
return text.gsub(/^\s?(=+)/, '<tt></tt>\1')
|
1634
|
+
end
|
1635
|
+
|
1636
|
+
def remove_private_comments(body)
|
1637
|
+
body.gsub!(/^\s*!--\s*?$.*?^\s*!\+\+\s*?$/m, '')
|
1638
|
+
return body
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
|
1642
|
+
#
|
1643
|
+
# Information of arguments of subroutines and functions in Fortran95
|
1644
|
+
#
|
1645
|
+
class Fortran95Definition
|
1646
|
+
|
1647
|
+
# Name of variable
|
1648
|
+
#
|
1649
|
+
attr_reader :varname
|
1650
|
+
|
1651
|
+
# Types of variable
|
1652
|
+
#
|
1653
|
+
attr_reader :types
|
1654
|
+
|
1655
|
+
# Initial Value
|
1656
|
+
#
|
1657
|
+
attr_reader :inivalue
|
1658
|
+
|
1659
|
+
# Suffix of array
|
1660
|
+
#
|
1661
|
+
attr_reader :arraysuffix
|
1662
|
+
|
1663
|
+
# Comments
|
1664
|
+
#
|
1665
|
+
attr_accessor :comment
|
1666
|
+
|
1667
|
+
# Flag of non documentation
|
1668
|
+
#
|
1669
|
+
attr_accessor :nodoc
|
1670
|
+
|
1671
|
+
def initialize(varname, types, inivalue, arraysuffix, comment,
|
1672
|
+
nodoc=false)
|
1673
|
+
@varname = varname
|
1674
|
+
@types = types
|
1675
|
+
@inivalue = inivalue
|
1676
|
+
@arraysuffix = arraysuffix
|
1677
|
+
@comment = comment
|
1678
|
+
@nodoc = nodoc
|
1679
|
+
end
|
1680
|
+
|
1681
|
+
def to_s
|
1682
|
+
return <<-EOF
|
1683
|
+
<Fortran95Definition:
|
1684
|
+
varname=#{@varname}, types=#{types},
|
1685
|
+
inivalue=#{@inivalue}, arraysuffix=#{@arraysuffix}, nodoc=#{@nodoc},
|
1686
|
+
comment=
|
1687
|
+
#{@comment}
|
1688
|
+
>
|
1689
|
+
EOF
|
1690
|
+
end
|
1691
|
+
|
1692
|
+
#
|
1693
|
+
# If attr is included, true is returned
|
1694
|
+
#
|
1695
|
+
def include_attr?(attr)
|
1696
|
+
return if !attr
|
1697
|
+
@types.split(",").each{ |type|
|
1698
|
+
return true if type.strip.chomp.upcase == attr.strip.chomp.upcase
|
1699
|
+
}
|
1700
|
+
return nil
|
1701
|
+
end
|
1702
|
+
|
1703
|
+
end # End of Fortran95Definition
|
1704
|
+
|
1705
|
+
#
|
1706
|
+
# Parse string argument "text", and Return Array of
|
1707
|
+
# Fortran95Definition object
|
1708
|
+
#
|
1709
|
+
def definition_info(text)
|
1710
|
+
return nil unless text
|
1711
|
+
lines = "#{text}"
|
1712
|
+
defs = Array.new
|
1713
|
+
comment = ""
|
1714
|
+
trailing_comment = ""
|
1715
|
+
under_comment_valid = false
|
1716
|
+
lines.split("\n").each{ |line|
|
1717
|
+
if /^\s*?!\s?(.*)/ =~ line
|
1718
|
+
if COMMENTS_ARE_UPPER
|
1719
|
+
comment << remove_header_marker($1)
|
1720
|
+
comment << "\n"
|
1721
|
+
elsif defs[-1] && under_comment_valid
|
1722
|
+
defs[-1].comment << "\n"
|
1723
|
+
defs[-1].comment << remove_header_marker($1)
|
1724
|
+
end
|
1725
|
+
next
|
1726
|
+
elsif /^\s*?$/ =~ line
|
1727
|
+
comment = ""
|
1728
|
+
under_comment_valid = false
|
1729
|
+
next
|
1730
|
+
end
|
1731
|
+
type = ""
|
1732
|
+
characters = ""
|
1733
|
+
if line =~ /^\s*?
|
1734
|
+
(
|
1735
|
+
character\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
|
1736
|
+
| type\s*?\([\w\s]+?\)[\s\,]*
|
1737
|
+
| integer\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
|
1738
|
+
| real\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
|
1739
|
+
| double\s+precision[\s\,]*
|
1740
|
+
| logical\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
|
1741
|
+
| complex\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
|
1742
|
+
)
|
1743
|
+
(.*?::)?
|
1744
|
+
(.+)$
|
1745
|
+
/ix
|
1746
|
+
characters = $8
|
1747
|
+
type = $1
|
1748
|
+
type << $7.gsub(/::/, '').gsub(/^\s*?\,/, '') if $7
|
1749
|
+
else
|
1750
|
+
under_comment_valid = false
|
1751
|
+
next
|
1752
|
+
end
|
1753
|
+
squote = false ; dquote = false ; bracket = 0
|
1754
|
+
iniflag = false; commentflag = false
|
1755
|
+
varname = "" ; arraysuffix = "" ; inivalue = ""
|
1756
|
+
start_pos = defs.size
|
1757
|
+
characters.split("").each { |char|
|
1758
|
+
if !(squote) && !(dquote) && bracket <= 0 && !(iniflag) && !(commentflag)
|
1759
|
+
case char
|
1760
|
+
when "!" ; commentflag = true
|
1761
|
+
when "(" ; bracket += 1 ; arraysuffix = char
|
1762
|
+
when "\""; dquote = true
|
1763
|
+
when "\'"; squote = true
|
1764
|
+
when "=" ; iniflag = true ; inivalue << char
|
1765
|
+
when ","
|
1766
|
+
defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
|
1767
|
+
varname = "" ; arraysuffix = "" ; inivalue = ""
|
1768
|
+
under_comment_valid = true
|
1769
|
+
when " " ; next
|
1770
|
+
else ; varname << char
|
1771
|
+
end
|
1772
|
+
elsif commentflag
|
1773
|
+
comment << remove_header_marker(char)
|
1774
|
+
trailing_comment << remove_header_marker(char)
|
1775
|
+
elsif iniflag
|
1776
|
+
if dquote
|
1777
|
+
case char
|
1778
|
+
when "\"" ; dquote = false ; inivalue << char
|
1779
|
+
else ; inivalue << char
|
1780
|
+
end
|
1781
|
+
elsif squote
|
1782
|
+
case char
|
1783
|
+
when "\'" ; squote = false ; inivalue << char
|
1784
|
+
else ; inivalue << char
|
1785
|
+
end
|
1786
|
+
elsif bracket > 0
|
1787
|
+
case char
|
1788
|
+
when "(" ; bracket += 1 ; inivalue << char
|
1789
|
+
when ")" ; bracket -= 1 ; inivalue << char
|
1790
|
+
else ; inivalue << char
|
1791
|
+
end
|
1792
|
+
else
|
1793
|
+
case char
|
1794
|
+
when ","
|
1795
|
+
defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
|
1796
|
+
varname = "" ; arraysuffix = "" ; inivalue = ""
|
1797
|
+
iniflag = false
|
1798
|
+
under_comment_valid = true
|
1799
|
+
when "(" ; bracket += 1 ; inivalue << char
|
1800
|
+
when "\""; dquote = true ; inivalue << char
|
1801
|
+
when "\'"; squote = true ; inivalue << char
|
1802
|
+
when "!" ; commentflag = true
|
1803
|
+
else ; inivalue << char
|
1804
|
+
end
|
1805
|
+
end
|
1806
|
+
elsif !(squote) && !(dquote) && bracket > 0
|
1807
|
+
case char
|
1808
|
+
when "(" ; bracket += 1 ; arraysuffix << char
|
1809
|
+
when ")" ; bracket -= 1 ; arraysuffix << char
|
1810
|
+
else ; arraysuffix << char
|
1811
|
+
end
|
1812
|
+
elsif squote
|
1813
|
+
case char
|
1814
|
+
when "\'"; squote = false ; inivalue << char
|
1815
|
+
else ; inivalue << char
|
1816
|
+
end
|
1817
|
+
elsif dquote
|
1818
|
+
case char
|
1819
|
+
when "\""; dquote = false ; inivalue << char
|
1820
|
+
else ; inivalue << char
|
1821
|
+
end
|
1822
|
+
end
|
1823
|
+
}
|
1824
|
+
defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
|
1825
|
+
if trailing_comment =~ /^:nodoc:/
|
1826
|
+
defs[start_pos..-1].collect!{ |defitem|
|
1827
|
+
defitem.nodoc = true
|
1828
|
+
}
|
1829
|
+
end
|
1830
|
+
varname = "" ; arraysuffix = "" ; inivalue = ""
|
1831
|
+
comment = ""
|
1832
|
+
under_comment_valid = true
|
1833
|
+
trailing_comment = ""
|
1834
|
+
}
|
1835
|
+
return defs
|
1836
|
+
end
|
1837
|
+
|
1838
|
+
|
1839
|
+
end # class Fortran95parser
|
1840
|
+
|
1841
|
+
end # module RDoc
|