| Class | RDoc::Fortran95parser |
| In: |
parsers/parse_f95.rb
|
| Parent: | Object |
See rdoc/parsers/parse_f95.rb
| COMMENTS_ARE_UPPER | = | false |
|
|||||
| INTERNAL_ALIAS_MES | = | "Alias for" | Internal alias message | |||||
| EXTERNAL_ALIAS_MES | = | "The entity is" | External alias message |
prepare to parse a Fortran 95 file
# File parsers/parse_f95.rb, line 397
397: def initialize(top_level, file_name, body, options, stats)
398: @body = body
399: @stats = stats
400: @file_name = file_name
401: @options = options
402: @top_level = top_level
403: @progress = $stderr unless options.quiet
404: end
Which "line" is end of block (module, program, block data, subroutine, function) statement ?
# File parsers/parse_f95.rb, line 1802
1802: def block_end?(line)
1803: return nil if !line
1804:
1805: if line =~ /^\s*?end\s*?(!.*?)?$/i ||
1806: line =~ /^\s*?end\s+module(\s+\w+)?\s*?(!.*?)?$/i ||
1807: line =~ /^\s*?end\s+program(\s+\w+)?\s*?(!.*?)?$/i ||
1808: line =~ /^\s*?end\s+block\s+data(\s+\w+)?\s*?(!.*?)?$/i ||
1809: line =~ /^\s*?end\s+subroutine(\s+\w+)?\s*?(!.*?)?$/i ||
1810: line =~ /^\s*?end\s+function(\s+\w+)?\s*?(!.*?)?$/i
1811: return true
1812: end
1813:
1814: return nil
1815: end
Which "line" is start of block (module, program, block data, subroutine, function) statement ?
# File parsers/parse_f95.rb, line 1766
1766: def block_start?(line)
1767: return nil if !line
1768:
1769: if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i ||
1770: line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
1771: line =~ /^\s*?block\s+data(\s+\w+)?\s*?(!.*?)?$/i ||
1772: line =~ \
1773: /^\s*?
1774: (recursive|pure|elemental)?\s*?
1775: subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
1776: /ix ||
1777: line =~ \
1778: /^\s*?
1779: (recursive|pure|elemental)?\s*?
1780: (
1781: character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1782: | type\s*?\([\w\s]+?\)\s+
1783: | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1784: | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1785: | double\s+precision\s+
1786: | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1787: | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1788: )?
1789: function\s+(\w+)\s*?
1790: (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
1791: /ix
1792: return true
1793: end
1794:
1795: return nil
1796: end
Check external aliases
subname というサブルーチン名, または関数名を持つファイルを 探査し, 存在する場合にはそのファイル内へメソッドを追加する.
# File parsers/parse_f95.rb, line 1545
1545: def check_external_aliases(subname, params, comment, test=nil)
1546: @@external_aliases.each{ |alias_item|
1547: if subname == alias_item["old_name"] ||
1548: subname.upcase == alias_item["old_name"].upcase &&
1549: @options.ignore_case
1550:
1551: new_meth = initialize_external_method(alias_item["new_name"],
1552: subname, params, @file_name,
1553: comment)
1554: new_meth.visibility = alias_item["visibility"]
1555:
1556: progress "e"
1557: @stats.num_methods += 1
1558: alias_item["file_or_module"].add_method(new_meth)
1559:
1560: if !alias_item["file_or_module"].include_requires?(@file_name, @options.ignore_case)
1561: alias_item["file_or_module"].add_require(Require.new(@file_name, ""))
1562: end
1563: end
1564: }
1565: end
Check public_methods
use したモジュールからそのまま引き継いで public として 公開する場合のチェックを行う. subname というサブルーチン名, または関数名を持つファイルを 探査し, 存在する場合にはそのファイル内へメソッドを追加する.
# File parsers/parse_f95.rb, line 1575
1575: def check_public_methods(method, parent)
1576: return if !method || !parent
1577: @@public_methods.each{ |alias_item|
1578: parent_is_used_module = nil
1579: alias_item["used_modules"].each{ |used_module|
1580: if used_module == parent ||
1581: used_module.upcase == parent.upcase &&
1582: @options.ignore_case
1583: parent_is_used_module = true
1584: end
1585: }
1586: next if !parent_is_used_module
1587:
1588: if method.name == alias_item["name"] ||
1589: method.name.upcase == alias_item["name"].upcase &&
1590: @options.ignore_case
1591:
1592: new_meth = initialize_public_method(method, parent)
1593: if alias_item["local_name"]
1594: new_meth.name = alias_item["local_name"]
1595: end
1596:
1597: progress "e"
1598: @stats.num_methods += 1
1599: alias_item["file_or_module"].add_method new_meth
1600: end
1601: }
1602: end
Collect comment for file entity
# File parsers/parse_f95.rb, line 1251
1251: def collect_first_comment(body)
1252: comment = ""
1253: not_comment = ""
1254: comment_start = false
1255: comment_end = false
1256: body.split("\n").each{ |line|
1257: if comment_end
1258: not_comment << line
1259: not_comment << "\n"
1260: elsif /^\s*?!\s?(.*)$/i =~ line
1261: comment_start = true
1262: comment << $1
1263: comment << "\n"
1264: elsif /^\s*?$/i =~ line
1265: comment_end = true if comment_start && COMMENTS_ARE_UPPER
1266: else
1267: comment_end = true
1268: not_comment << line
1269: not_comment << "\n"
1270: end
1271: }
1272: return comment, not_comment
1273: end
Comment out checker
# File parsers/parse_f95.rb, line 1697
1697: def comment_out?(line)
1698: return nil unless line
1699: commentout = false
1700: squote = false ; dquote = false
1701: line.split("").each { |char|
1702: if !(squote) && !(dquote)
1703: case char
1704: when "!" ; commentout = true ; break
1705: when "\""; dquote = true
1706: when "\'"; squote = true
1707: else next
1708: end
1709: elsif squote
1710: case char
1711: when "\'"; squote = false
1712: else next
1713: end
1714: elsif dquote
1715: case char
1716: when "\""; dquote = false
1717: else next
1718: end
1719: end
1720: }
1721: return commentout
1722: end
Continuous line checker
# File parsers/parse_f95.rb, line 1683
1683: def continuous_line?(line)
1684: continuous = false
1685: if /&\s*?(!.*)?$/ =~ line
1686: continuous = true
1687: if comment_out?($~.pre_match)
1688: continuous = false
1689: end
1690: end
1691: return continuous
1692: end
Parse string argument "text", and Return Array of Fortran95Definition object
# File parsers/parse_f95.rb, line 1938
1938: def definition_info(text)
1939: return nil unless text
1940: lines = "#{text}"
1941: defs = Array.new
1942: comment = ""
1943: trailing_comment = ""
1944: under_comment_valid = false
1945: lines.split("\n").each{ |line|
1946: if /^\s*?!\s?(.*)/ =~ line
1947: if COMMENTS_ARE_UPPER
1948: comment << remove_header_marker($1)
1949: comment << "\n"
1950: elsif defs[-1] && under_comment_valid
1951: defs[-1].comment << "\n"
1952: defs[-1].comment << remove_header_marker($1)
1953: end
1954: next
1955: elsif /^\s*?$/ =~ line
1956: comment = ""
1957: under_comment_valid = false
1958: next
1959: end
1960: type = ""
1961: characters = ""
1962: if line =~ /^\s*?
1963: (
1964: character\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
1965: | type\s*?\([\w\s]+?\)[\s\,]*
1966: | integer\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
1967: | real\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
1968: | double\s+precision[\s\,]*
1969: | logical\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
1970: | complex\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
1971: )
1972: (.*?::)?
1973: (.+)$
1974: /ix
1975: characters = $8
1976: type = $1
1977: type << $7.gsub(/::/, '').gsub(/^\s*?\,/, '') if $7
1978: else
1979: under_comment_valid = false
1980: next
1981: end
1982: squote = false ; dquote = false ; bracket = 0
1983: iniflag = false; commentflag = false
1984: varname = "" ; arraysuffix = "" ; inivalue = ""
1985: start_pos = defs.size
1986: characters.split("").each { |char|
1987: if !(squote) && !(dquote) && bracket <= 0 && !(iniflag) && !(commentflag)
1988: case char
1989: when "!" ; commentflag = true
1990: when "(" ; bracket += 1 ; arraysuffix = char
1991: when "\""; dquote = true
1992: when "\'"; squote = true
1993: when "=" ; iniflag = true ; inivalue << char
1994: when ","
1995: defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
1996: varname = "" ; arraysuffix = "" ; inivalue = ""
1997: under_comment_valid = true
1998: when " " ; next
1999: else ; varname << char
2000: end
2001: elsif commentflag
2002: comment << remove_header_marker(char)
2003: trailing_comment << remove_header_marker(char)
2004: elsif iniflag
2005: if dquote
2006: case char
2007: when "\"" ; dquote = false ; inivalue << char
2008: else ; inivalue << char
2009: end
2010: elsif squote
2011: case char
2012: when "\'" ; squote = false ; inivalue << char
2013: else ; inivalue << char
2014: end
2015: elsif bracket > 0
2016: case char
2017: when "(" ; bracket += 1 ; inivalue << char
2018: when ")" ; bracket -= 1 ; inivalue << char
2019: else ; inivalue << char
2020: end
2021: else
2022: case char
2023: when ","
2024: defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
2025: varname = "" ; arraysuffix = "" ; inivalue = ""
2026: iniflag = false
2027: under_comment_valid = true
2028: when "(" ; bracket += 1 ; inivalue << char
2029: when "\""; dquote = true ; inivalue << char
2030: when "\'"; squote = true ; inivalue << char
2031: when "!" ; commentflag = true
2032: else ; inivalue << char
2033: end
2034: end
2035: elsif !(squote) && !(dquote) && bracket > 0
2036: case char
2037: when "(" ; bracket += 1 ; arraysuffix << char
2038: when ")" ; bracket -= 1 ; arraysuffix << char
2039: else ; arraysuffix << char
2040: end
2041: elsif squote
2042: case char
2043: when "\'"; squote = false ; inivalue << char
2044: else ; inivalue << char
2045: end
2046: elsif dquote
2047: case char
2048: when "\""; dquote = false ; inivalue << char
2049: else ; inivalue << char
2050: end
2051: end
2052: }
2053: defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
2054: if trailing_comment =~ /^:nodoc:/
2055: defs[start_pos..-1].collect!{ |defitem|
2056: defitem.nodoc = true
2057: }
2058: end
2059: varname = "" ; arraysuffix = "" ; inivalue = ""
2060: comment = ""
2061: under_comment_valid = true
2062: trailing_comment = ""
2063: }
2064: return defs
2065: end
Return comments of definitions of arguments
If "all" argument is true, information of all arguments are returned. If "modified_params" is true, list of arguments are decorated, for exameple, optional arguments are parenthetic as "[arg]".
# File parsers/parse_f95.rb, line 1282
1282: def find_arguments(args, text, all=nil, indent=nil, modified_params=nil)
1283: return unless args || all
1284: indent = "" unless indent
1285: args = ["all"] if all
1286: params = "" if modified_params
1287: comma = ""
1288: return unless text
1289: args_rdocforms = "\n"
1290: remaining_lines = "#{text}"
1291: definitions = definition_info(remaining_lines)
1292: args.each{ |arg|
1293: arg.strip!
1294: arg.chomp!
1295: definitions.each { |defitem|
1296: if arg == defitem.varname.strip.chomp || all
1297: args_rdocforms << "\n\#{indent}<tt><b>\#{defitem.varname.chomp.strip}\#{defitem.arraysuffix} </b> \#{defitem.inivalue}</tt> ::\n\#{indent} <tt>\#{defitem.types.chomp.strip}</tt>\n"
1298: if !defitem.comment.chomp.strip.empty?
1299: comment = ""
1300: defitem.comment.split("\n").each{ |line|
1301: comment << " " + line + "\n"
1302: }
1303: args_rdocforms << "\n\#{indent} <tt></tt> ::\n\#{indent} <tt></tt>\n\#{indent} \#{comment.chomp.strip}\n"
1304: end
1305:
1306: if modified_params
1307: if defitem.include_attr?("optional")
1308: params << "#{comma}[#{arg}]"
1309: else
1310: params << "#{comma}#{arg}"
1311: end
1312: comma = ", "
1313: end
1314: end
1315: }
1316: }
1317: if modified_params
1318: return args_rdocforms, params
1319: else
1320: return args_rdocforms
1321: end
1322: end
Comments just after module or subprogram, or arguments are returnd. If "COMMENTS_ARE_UPPER" is true, comments just before modules or subprograms are returnd
# File parsers/parse_f95.rb, line 1363
1363: def find_comments text
1364: return "" unless text
1365: lines = text.split("\n")
1366: lines.reverse! if COMMENTS_ARE_UPPER
1367: comment_block = Array.new
1368: lines.each do |line|
1369: break if line =~ /^\s*?\w/ || line =~ /^\s*?$/
1370: if COMMENTS_ARE_UPPER
1371: comment_block.unshift line.sub(/^\s*?!\s?/,"")
1372: else
1373: comment_block.push line.sub(/^\s*?!\s?/,"")
1374: end
1375: end
1376: nice_lines = comment_block.join("\n").split "\n\s*?\n"
1377: nice_lines[0] ||= ""
1378: nice_lines.shift
1379: end
Return comments of definitions of namelists
# File parsers/parse_f95.rb, line 1337
1337: def find_namelists(text, before_contains=nil)
1338: return nil if !text
1339: result = ""
1340: lines = "#{text}"
1341: before_contains = "" if !before_contains
1342: while lines =~ /^\s*?namelist\s+\/\s*?(\w+)\s*?\/([\s\w\,]+)$/i
1343: lines = $~.post_match
1344: nml_comment = COMMENTS_ARE_UPPER ?
1345: find_comments($~.pre_match) : find_comments($~.post_match)
1346: nml_name = $1
1347: nml_args = $2.split(",")
1348: result << "\n\n=== NAMELIST <tt><b>" + nml_name + "</tt></b>\n\n"
1349: result << nml_comment + "\n" if nml_comment
1350: if lines.split("\n")[0] =~ /^\//i
1351: lines = "namelist " + lines
1352: end
1353: result << find_arguments(nml_args, "#{text}" + "\n" + before_contains)
1354: end
1355: return result
1356: end
Find visibility
# File parsers/parse_f95.rb, line 1526
1526: def find_visibility(container, subname, visibility_info)
1527: return nil if !subname || !visibility_info
1528: visibility_info.each{ |info|
1529: if info["name"] == subname ||
1530: @options.ignore_case && info["name"].upcase == subname.upcase
1531: if info["parent"] == container.name
1532: return info["visibility"]
1533: end
1534: end
1535: }
1536: return nil
1537: end
Create method for external alias
If argument "internal" is true, file is ignored.
# File parsers/parse_f95.rb, line 1408
1408: def initialize_external_method(new, old, params, file, comment, token=nil,
1409: internal=nil, nolink=nil)
1410: return nil unless new || old
1411:
1412: if internal
1413: external_alias_header = "#{INTERNAL_ALIAS_MES} "
1414: external_alias_text = external_alias_header + old
1415: elsif file
1416: external_alias_header = "#{EXTERNAL_ALIAS_MES} "
1417: external_alias_text = external_alias_header + file + "#" + old
1418: else
1419: return nil
1420: end
1421: external_meth = AnyMethod.new(external_alias_text, new)
1422: external_meth.singleton = false
1423: external_meth.params = params
1424: external_comment = remove_trailing_alias(comment) + "\n\n" if comment
1425: external_meth.comment = external_comment || ""
1426: if nolink && token
1427: external_meth.start_collecting_tokens
1428: external_meth.add_token Token.new(1,1).set_text(token)
1429: else
1430: external_meth.comment << external_alias_text
1431: end
1432:
1433: return external_meth
1434: end
Create method for internal alias
# File parsers/parse_f95.rb, line 1391
1391: def initialize_public_method(method, parent)
1392: return if !method || !parent
1393:
1394: new_meth = AnyMethod.new("External Alias for module", method.name)
1395: new_meth.singleton = method.singleton
1396: new_meth.params = method.params.clone
1397: new_meth.comment = remove_trailing_alias(method.comment.clone)
1398: new_meth.comment << "\n\n#{EXTERNAL_ALIAS_MES} #{parent.strip.chomp}\##{method.name}"
1399:
1400: return new_meth
1401: end
# File parsers/parse_f95.rb, line 563
563: def parse_program_or_module(container, code,
564: visibility=:public, external=nil)
565: return unless container
566: return unless code
567: remaining_lines = code.split("\n")
568: remaining_code = "#{code}"
569:
570: #
571: # Parse variables before "contains" in module
572: #
573: # namelist 変数の定義に使われたり, これ自体が定数, 変数
574: # 提供されるのに利用される. (変数や定数として利用される場合,
575: # これもメソッドとして提供する.
576: #
577: level_depth = 0
578: before_contains_lines = []
579: before_contains_code = nil
580: before_contains_flag = nil
581: remaining_lines.each{ |line|
582: if !before_contains_flag
583: if line =~ /^\s*?module\s+\w+\s*?(!.*?)?$/i
584: before_contains_flag = true
585: end
586: else
587: break if line =~ /^\s*?contains\s*?(!.*?)?$/i
588: level_depth += 1 if block_start?(line)
589: level_depth -= 1 if block_end?(line)
590: break if level_depth < 0
591: before_contains_lines << line
592: end
593: }
594: before_contains_code = before_contains_lines.join("\n")
595: if before_contains_code
596: before_contains_code.gsub!(/^\s*?interface\s+.*?\s+end\s+interface.*?$/im, "")
597: before_contains_code.gsub!(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
598: end
599:
600: #
601: # Parse global "use"
602: #
603: use_check_code = "#{before_contains_code}"
604: cascaded_modules_list = []
605: while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
606: use_check_code = $~.pre_match
607: use_check_code << $~.post_match
608: used_mod_name = $1.strip.chomp
609: used_list = $2 || ""
610: used_trailing = $3 || ""
611: next if used_trailing =~ /!:nodoc:/
612: if !container.include_includes?(used_mod_name, @options.ignore_case)
613: progress "."
614: container.add_include Include.new(used_mod_name, "")
615: end
616: if ! (used_list =~ /\,\s*?only\s*?:/i )
617: cascaded_modules_list << "\#" + used_mod_name
618: end
619: end
620:
621: #
622: # Parse public and private, and store information.
623: # This information is used when "add_method" and
624: # "set_visibility_for" are called.
625: #
626: visibility_default, visibility_info =
627: parse_visibility(remaining_lines.join("\n"), visibility, container)
628: @@public_methods.concat visibility_info
629: if visibility_default == :public
630: if !cascaded_modules_list.empty?
631: cascaded_modules =
632: Attr.new("Cascaded Modules",
633: "Imported modules all of whose components are published again",
634: "",
635: cascaded_modules_list.join(", "))
636: container.add_attribute(cascaded_modules)
637: end
638: end
639:
640: #
641: # Check rename elements
642: #
643: use_check_code = "#{before_contains_code}"
644: while use_check_code =~ /^\s*?use\s+(\w+)\s*?\,(.+)$/i
645: use_check_code = $~.pre_match
646: use_check_code << $~.post_match
647: used_mod_name = $1.strip.chomp
648: used_elements = $2.sub(/\s*?only\s*?:\s*?/i, '')
649: used_elements.split(",").each{ |used|
650: if /\s*?(\w+)\s*?=>\s*?(\w+)\s*?/ =~ used
651: local = $1
652: org = $2
653: @@public_methods.collect!{ |pub_meth|
654: if local == pub_meth["name"] ||
655: local.upcase == pub_meth["name"].upcase &&
656: @options.ignore_case
657: pub_meth["name"] = org
658: pub_meth["local_name"] = local
659: end
660: pub_meth
661: }
662: end
663: }
664: end
665:
666: #
667: # Parse private "use"
668: #
669: use_check_code = remaining_lines.join("\n")
670: while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
671: use_check_code = $~.pre_match
672: use_check_code << $~.post_match
673: used_mod_name = $1.strip.chomp
674: used_trailing = $3 || ""
675: next if used_trailing =~ /!:nodoc:/
676: if !container.include_includes?(used_mod_name, @options.ignore_case)
677: progress "."
678: container.add_include Include.new(used_mod_name, "")
679: end
680: end
681:
682: container.each_includes{ |inc|
683: TopLevel.all_files.each do |name, toplevel|
684: indicated_mod = toplevel.find_symbol(inc.name,
685: nil, @options.ignore_case)
686: if indicated_mod
687: indicated_name = indicated_mod.parent.file_relative_name
688: if !container.include_requires?(indicated_name, @options.ignore_case)
689: container.add_require(Require.new(indicated_name, ""))
690: end
691: break
692: end
693: end
694: }
695:
696: #
697: # Parse derived-types definitions
698: #
699: derived_types_comment = ""
700: remaining_code = remaining_lines.join("\n")
701: while remaining_code =~ /^\s*?
702: type[\s\,]+(public|private)?\s*?(::)?\s*?
703: (\w+)\s*?(!.*?)?$
704: (.*?)
705: ^\s*?end\s+type.*?$
706: /imx
707: remaining_code = $~.pre_match
708: remaining_code << $~.post_match
709: typename = $3.chomp.strip
710: type_elements = $5 || ""
711: type_code = remove_empty_head_lines($&)
712: type_trailing = find_comments($4)
713: next if type_trailing =~ /^:nodoc:/
714: type_visibility = $1
715: type_comment = COMMENTS_ARE_UPPER ?
716: find_comments($~.pre_match) + "\n" + type_trailing :
717: type_trailing + "\n" + find_comments(type_code.sub(/^.*$\n/i, ''))
718: type_element_visibility_public = true
719: type_code.split("\n").each{ |line|
720: if /^\s*?private\s*?$/ =~ line
721: type_element_visibility_public = nil
722: break
723: end
724: } if type_code
725:
726: args_comment = ""
727: type_args_info = nil
728:
729: if @options.show_all
730: args_comment = find_arguments(nil, type_code, true)
731: else
732: type_public_args_list = []
733: type_args_info = definition_info(type_code)
734: type_args_info.each{ |arg|
735: arg_is_public = type_element_visibility_public
736: arg_is_public = true if arg.include_attr?("public")
737: arg_is_public = nil if arg.include_attr?("private")
738: type_public_args_list << arg.varname if arg_is_public
739: }
740: args_comment = find_arguments(type_public_args_list, type_code)
741: end
742:
743: type = AnyMethod.new("type #{typename}", typename)
744: type.singleton = false
745: type.params = ""
746: type.comment = "<b><em> Derived Type </em></b> :: <tt></tt>\n"
747: type.comment << args_comment if args_comment
748: type.comment << type_comment if type_comment
749: progress "t"
750: @stats.num_methods += 1
751: container.add_method type
752:
753: set_visibility(container, typename, visibility_default, @@public_methods)
754:
755: if type_visibility
756: type_visibility.gsub!(/\s/,'')
757: type_visibility.gsub!(/\,/,'')
758: type_visibility.gsub!(/:/,'')
759: type_visibility.downcase!
760: if type_visibility == "public"
761: container.set_visibility_for([typename], :public)
762: elsif type_visibility == "private"
763: container.set_visibility_for([typename], :private)
764: end
765: end
766:
767: check_public_methods(type, container.name)
768:
769: if @options.show_all
770: derived_types_comment << ", " unless derived_types_comment.empty?
771: derived_types_comment << typename
772: else
773: if type.visibility == :public
774: derived_types_comment << ", " unless derived_types_comment.empty?
775: derived_types_comment << typename
776: end
777: end
778:
779: end
780:
781: if !derived_types_comment.empty?
782: derived_types_table =
783: Attr.new("Derived Types", "Derived_Types", "",
784: derived_types_comment)
785: container.add_attribute(derived_types_table)
786: end
787:
788: #
789: # move interface scope
790: #
791: interface_code = ""
792: while remaining_code =~ /^\s*?
793: interface(
794: \s+\w+ |
795: \s+operator\s*?\(.*?\) |
796: \s+assignment\s*?\(\s*?=\s*?\)
797: )?\s*?$
798: (.*?)
799: ^\s*?end\s+interface.*?$
800: /imx
801: interface_code << remove_empty_head_lines($&) + "\n"
802: remaining_code = $~.pre_match
803: remaining_code << $~.post_match
804: end
805:
806: #
807: # Parse global constants or variables in modules
808: #
809: const_var_defs = definition_info(before_contains_code)
810: const_var_defs.each{|defitem|
811: next if defitem.nodoc
812: const_or_var_type = "Variable"
813: const_or_var_progress = "v"
814: if defitem.include_attr?("parameter")
815: const_or_var_type = "Constant"
816: const_or_var_progress = "c"
817: end
818: const_or_var = AnyMethod.new(const_or_var_type, defitem.varname)
819: const_or_var.singleton = false
820: const_or_var.params = ""
821: self_comment = find_arguments([defitem.varname], before_contains_code)
822: const_or_var.comment = "<b><em>" + const_or_var_type + "</em></b> :: <tt></tt>\n"
823: const_or_var.comment << self_comment if self_comment
824: progress const_or_var_progress
825: @stats.num_methods += 1
826: container.add_method const_or_var
827:
828: set_visibility(container, defitem.varname, visibility_default, @@public_methods)
829:
830: if defitem.include_attr?("public")
831: container.set_visibility_for([defitem.varname], :public)
832: elsif defitem.include_attr?("private")
833: container.set_visibility_for([defitem.varname], :private)
834: end
835:
836: check_public_methods(const_or_var, container.name)
837:
838: } if const_var_defs
839:
840: remaining_lines = remaining_code.split("\n")
841:
842: # "subroutine" or "function" parts are parsed (new)
843: #
844: level_depth = 0
845: block_searching_flag = nil
846: block_searching_lines = []
847: pre_comment = []
848: procedure_trailing = ""
849: procedure_name = ""
850: procedure_params = ""
851: procedure_prefix = ""
852: procedure_result_arg = ""
853: procedure_type = ""
854: contains_lines = []
855: contains_flag = nil
856: remaining_lines.collect!{|line|
857: if !block_searching_flag
858: # subroutine
859: if line =~ /^\s*?
860: (recursive|pure|elemental)?\s*?
861: subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
862: /ix
863: block_searching_flag = :subroutine
864: block_searching_lines << line
865:
866: procedure_name = $2.chomp.strip
867: procedure_params = $3 || ""
868: procedure_prefix = $1 || ""
869: procedure_trailing = $4 || "!"
870: next false
871:
872: # function
873: elsif line =~ /^\s*?
874: (recursive|pure|elemental)?\s*?
875: (
876: character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
877: | type\s*?\([\w\s]+?\)\s+
878: | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
879: | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
880: | double\s+precision\s+
881: | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
882: | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
883: )?
884: function\s+(\w+)\s*?
885: (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
886: /ix
887: block_searching_flag = :function
888: block_searching_lines << line
889:
890: procedure_prefix = $1 || ""
891: procedure_type = $2 ? $2.chomp.strip : nil
892: procedure_name = $8.chomp.strip
893: procedure_params = $9 || ""
894: procedure_result_arg = $11 ? $11.chomp.strip : procedure_name
895: procedure_trailing = $12 || "!"
896: next false
897: elsif line =~ /^\s*?!\s?(.*)/
898: pre_comment << line
899: next line
900: else
901: pre_comment = []
902: next line
903: end
904: end
905: contains_flag = true if line =~ /^\s*?contains\s*?(!.*?)?$/
906: block_searching_lines << line
907: contains_lines << line if contains_flag
908:
909: level_depth += 1 if block_start?(line)
910: level_depth -= 1 if block_end?(line)
911: if level_depth >= 0
912: next false
913: end
914:
915: # "procedure_code" is formatted.
916: # ":nodoc:" flag is checked.
917: #
918: procedure_code = block_searching_lines.join("\n")
919: procedure_code = remove_empty_head_lines(procedure_code)
920: if procedure_trailing =~ /^!:nodoc:/
921: # next loop to search next block
922: level_depth = 0
923: block_searching_flag = nil
924: block_searching_lines = []
925: pre_comment = []
926: procedure_trailing = ""
927: procedure_name = ""
928: procedure_params = ""
929: procedure_prefix = ""
930: procedure_result_arg = ""
931: procedure_type = ""
932: contains_lines = []
933: contains_flag = nil
934: next false
935: end
936:
937: # AnyMethod is created, and added to container
938: #
939: subroutine_function = nil
940: if block_searching_flag == :subroutine
941: subroutine_prefix = procedure_prefix
942: subroutine_name = procedure_name
943: subroutine_params = procedure_params
944: subroutine_trailing = procedure_trailing
945: subroutine_code = procedure_code
946:
947: subroutine_comment = COMMENTS_ARE_UPPER ?
948: pre_comment.join("\n") + "\n" + subroutine_trailing :
949: subroutine_trailing + "\n" + subroutine_code.sub(/^.*$\n/i, '')
950: subroutine = AnyMethod.new("subroutine", subroutine_name)
951: parse_subprogram(subroutine, subroutine_params,
952: subroutine_comment, subroutine_code,
953: before_contains_code, nil, subroutine_prefix)
954: progress "s"
955: @stats.num_methods += 1
956: container.add_method subroutine
957: subroutine_function = subroutine
958:
959: elsif block_searching_flag == :function
960: function_prefix = procedure_prefix
961: function_type = procedure_type
962: function_name = procedure_name
963: function_params_org = procedure_params
964: function_result_arg = procedure_result_arg
965: function_trailing = procedure_trailing
966: function_code_org = procedure_code
967:
968: function_comment = COMMENTS_ARE_UPPER ?
969: pre_comment.join("\n") + "\n" + function_trailing :
970: function_trailing + "\n " + function_code_org.sub(/^.*$\n/i, '')
971:
972: function_code = "#{function_code_org}"
973: if function_type
974: function_code << "\n" + function_type + " :: " + function_result_arg
975: end
976:
977: function_params =
978: function_params_org.sub(/^\(/, "\(#{function_result_arg}, ")
979:
980: function = AnyMethod.new("function", function_name)
981: parse_subprogram(function, function_params,
982: function_comment, function_code,
983: before_contains_code, true, function_prefix)
984:
985: # Specific modification due to function
986: function.params.sub!(/\(\s*?#{function_result_arg}\s*?,\s*?/, "\( ")
987: function.params << " result(" + function_result_arg + ")"
988: function.start_collecting_tokens
989: function.add_token Token.new(1,1).set_text(function_code_org)
990:
991: progress "f"
992: @stats.num_methods += 1
993: container.add_method function
994: subroutine_function = function
995:
996: end
997:
998: # The visibility of procedure is specified
999: #
1000: set_visibility(container, procedure_name,
1001: visibility_default, @@public_methods)
1002:
1003: # The alias for this procedure from external modules
1004: #
1005: check_external_aliases(procedure_name,
1006: subroutine_function.params,
1007: subroutine_function.comment, subroutine_function) if external
1008: check_public_methods(subroutine_function, container.name)
1009:
1010:
1011: # contains_lines are parsed as private procedures
1012: if contains_flag
1013: parse_program_or_module(container,
1014: contains_lines.join("\n"), :private)
1015: end
1016:
1017: # next loop to search next block
1018: level_depth = 0
1019: block_searching_flag = nil
1020: block_searching_lines = []
1021: pre_comment = []
1022: procedure_trailing = ""
1023: procedure_name = ""
1024: procedure_params = ""
1025: procedure_prefix = ""
1026: procedure_result_arg = ""
1027: contains_lines = []
1028: contains_flag = nil
1029: next false
1030: } # End of remaining_lines.collect!{|line|
1031:
1032: # Array remains_lines is converted to String remains_code again
1033: #
1034: remaining_code = remaining_lines.join("\n")
1035:
1036: #
1037: # Parse interface
1038: #
1039: interface_scope = false
1040: generic_name = ""
1041: interface_code.split("\n").each{ |line|
1042: if /^\s*?
1043: interface(
1044: \s+\w+|
1045: \s+operator\s*?\(.*?\)|
1046: \s+assignment\s*?\(\s*?=\s*?\)
1047: )?
1048: \s*?(!.*?)?$
1049: /ix =~ line
1050: generic_name = $1 ? $1.strip.chomp : nil
1051: interface_trailing = $2 || "!"
1052: interface_scope = true
1053: interface_scope = false if interface_trailing =~ /!:nodoc:/
1054: # if generic_name =~ /operator\s*?\((.*?)\)/i
1055: # operator_name = $1
1056: # if operator_name && !operator_name.empty?
1057: # generic_name = "#{operator_name}"
1058: # end
1059: # end
1060: # if generic_name =~ /assignment\s*?\((.*?)\)/i
1061: # assignment_name = $1
1062: # if assignment_name && !assignment_name.empty?
1063: # generic_name = "#{assignment_name}"
1064: # end
1065: # end
1066: end
1067: if /^\s*?end\s+interface/i =~ line
1068: interface_scope = false
1069: generic_name = nil
1070: end
1071: # internal alias
1072: if interface_scope && /^\s*?module\s+procedure\s+(.*?)(!.*?)?$/i =~ line
1073: procedures = $1.strip.chomp
1074: procedures_trailing = $2 || "!"
1075: next if procedures_trailing =~ /!:nodoc:/
1076: procedures.split(",").each{ |proc|
1077: proc.strip!
1078: proc.chomp!
1079: next if generic_name == proc || !generic_name
1080: old_meth = container.find_symbol(proc, nil, @options.ignore_case)
1081: next if !old_meth
1082: nolink = old_meth.visibility == :private ? true : nil
1083: nolink = nil if @options.show_all
1084: new_meth =
1085: initialize_external_method(generic_name, proc,
1086: old_meth.params, nil,
1087: old_meth.comment,
1088: old_meth.clone.token_stream[0].text,
1089: true, nolink)
1090: new_meth.singleton = old_meth.singleton
1091:
1092: progress "i"
1093: @stats.num_methods += 1
1094: container.add_method new_meth
1095:
1096: set_visibility(container, generic_name, visibility_default, @@public_methods)
1097:
1098: check_public_methods(new_meth, container.name)
1099:
1100: }
1101: end
1102:
1103: # external aliases
1104: if interface_scope
1105: # subroutine
1106: proc = nil
1107: params = nil
1108: procedures_trailing = nil
1109: if line =~ /^\s*?
1110: (recursive|pure|elemental)?\s*?
1111: subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
1112: /ix
1113: proc = $2.chomp.strip
1114: generic_name = proc unless generic_name
1115: params = $3 || ""
1116: procedures_trailing = $4 || "!"
1117:
1118: # function
1119: elsif line =~ /^\s*?
1120: (recursive|pure|elemental)?\s*?
1121: (
1122: character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1123: | type\s*?\([\w\s]+?\)\s+
1124: | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1125: | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1126: | double\s+precision\s+
1127: | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1128: | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
1129: )?
1130: function\s+(\w+)\s*?
1131: (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
1132: /ix
1133: proc = $8.chomp.strip
1134: generic_name = proc unless generic_name
1135: params = $9 || ""
1136: procedures_trailing = $12 || "!"
1137: else
1138: next
1139: end
1140: next if procedures_trailing =~ /!:nodoc:/
1141: indicated_method = nil
1142: indicated_file = nil
1143: TopLevel.all_files.each do |name, toplevel|
1144: indicated_method = toplevel.find_local_symbol(proc, @options.ignore_case)
1145: indicated_file = name
1146: break if indicated_method
1147: end
1148:
1149: if indicated_method
1150: external_method =
1151: initialize_external_method(generic_name, proc,
1152: indicated_method.params,
1153: indicated_file,
1154: indicated_method.comment)
1155:
1156: progress "e"
1157: @stats.num_methods += 1
1158: container.add_method external_method
1159: set_visibility(container, generic_name, visibility_default, @@public_methods)
1160: if !container.include_requires?(indicated_file, @options.ignore_case)
1161: container.add_require(Require.new(indicated_file, ""))
1162: end
1163: check_public_methods(external_method, container.name)
1164:
1165: else
1166: @@external_aliases << {
1167: "new_name" => generic_name,
1168: "old_name" => proc,
1169: "file_or_module" => container,
1170: "visibility" => find_visibility(container, generic_name, @@public_methods) || visibility_default
1171: }
1172: end
1173: end
1174:
1175: } if interface_code # End of interface_code.split("\n").each ...
1176:
1177: #
1178: # Already imported methods are removed from @@public_methods.
1179: # Remainders are assumed to be imported from other modules.
1180: #
1181: # 既に参照済みのメソッドは @@public_methods から取り除く.
1182: # 残りは外部モジュールからの参照と仮定する.
1183: #
1184: @@public_methods.delete_if{ |method| method["entity_is_discovered"]}
1185:
1186: @@public_methods.each{ |pub_meth|
1187: next unless pub_meth["file_or_module"].name == container.name
1188: pub_meth["used_modules"].each{ |used_mod|
1189: TopLevel.all_classes_and_modules.each{ |modules|
1190: if modules.name == used_mod ||
1191: modules.name.upcase == used_mod.upcase &&
1192: @options.ignore_case
1193: modules.method_list.each{ |meth|
1194: if meth.name == pub_meth["name"] ||
1195: meth.name.upcase == pub_meth["name"].upcase &&
1196: @options.ignore_case
1197: new_meth = initialize_public_method(meth,
1198: modules.name)
1199: if pub_meth["local_name"]
1200: new_meth.name = pub_meth["local_name"]
1201: end
1202: progress "e"
1203: @stats.num_methods += 1
1204: container.add_method new_meth
1205: end
1206: }
1207: end
1208: }
1209: }
1210: }
1211:
1212: container
1213: end
Parse arguments, comment, code of subroutine and function. Return AnyMethod object.
# File parsers/parse_f95.rb, line 1219
1219: def parse_subprogram(subprogram, params, comment, code,
1220: before_contains=nil, function=nil, prefix=nil)
1221: subprogram.singleton = false
1222: prefix = "" if !prefix
1223: arguments = params.sub(/\(/, "").sub(/\)/, "").split(",") if params
1224: args_comment, params_opt =
1225: find_arguments(arguments, code.sub(/^s*?contains\s*?(!.*?)?$.*/im, ""),
1226: nil, nil, true)
1227: params_opt = "( " + params_opt + " ) " if params_opt
1228: subprogram.params = params_opt || ""
1229: namelist_comment = find_namelists(code, before_contains)
1230:
1231: block_comment = find_comments comment
1232: if function
1233: subprogram.comment = "<b><em> Function </em></b> :: <em>#{prefix}</em>\n"
1234: else
1235: subprogram.comment = "<b><em> Subroutine </em></b> :: <em>#{prefix}</em>\n"
1236: end
1237: subprogram.comment << args_comment if args_comment
1238: subprogram.comment << block_comment if block_comment
1239: subprogram.comment << namelist_comment if namelist_comment
1240:
1241: # For output source code
1242: subprogram.start_collecting_tokens
1243: subprogram.add_token Token.new(1,1).set_text(code)
1244:
1245: subprogram
1246: end
Parse visibility
# File parsers/parse_f95.rb, line 1441
1441: def parse_visibility(code, default, container)
1442: result = []
1443: visibility_default = default || :public
1444:
1445: used_modules = []
1446: container.includes.each{|i| used_modules << i.name} if container
1447:
1448: remaining_code = code.gsub(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
1449: remaining_code.split("\n").each{ |line|
1450: if /^\s*?private\s*?$/ =~ line
1451: visibility_default = :private
1452: break
1453: end
1454: } if remaining_code
1455:
1456: remaining_code.split("\n").each{ |line|
1457: if /^\s*?private\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
1458: methods = $2.sub(/!.*$/, '')
1459: methods.split(",").each{ |meth|
1460: meth.sub!(/!.*$/, '')
1461: meth.gsub!(/:/, '')
1462: result << {
1463: "name" => meth.chomp.strip,
1464: "visibility" => :private,
1465: "used_modules" => used_modules.clone,
1466: "file_or_module" => container,
1467: "entity_is_discovered" => nil,
1468: "local_name" => nil
1469: }
1470: }
1471: elsif /^\s*?public\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
1472: methods = $2.sub(/!.*$/, '')
1473: methods.split(",").each{ |meth|
1474: meth.sub!(/!.*$/, '')
1475: meth.gsub!(/:/, '')
1476: result << {
1477: "name" => meth.chomp.strip,
1478: "visibility" => :public,
1479: "used_modules" => used_modules.clone,
1480: "file_or_module" => container,
1481: "entity_is_discovered" => nil,
1482: "local_name" => nil
1483: }
1484: }
1485: end
1486: } if remaining_code
1487:
1488: if container
1489: result.each{ |vis_info|
1490: vis_info["parent"] = container.name
1491: }
1492: end
1493:
1494: return visibility_default, result
1495: end
# File parsers/parse_f95.rb, line 1381
1381: def progress(char)
1382: unless @options.quiet
1383: @progress.print(char)
1384: @progress.flush
1385: end
1386: end
Empty lines in header are removed
# File parsers/parse_f95.rb, line 1841
1841: def remove_empty_head_lines(text)
1842: return "" unless text
1843: lines = text.split("\n")
1844: header = true
1845: lines.delete_if{ |line|
1846: header = false if /\S/ =~ line
1847: header && /^\s*?$/ =~ line
1848: }
1849: lines.join("\n")
1850: end
header marker "=", "==", … are removed
# File parsers/parse_f95.rb, line 1854
1854: def remove_header_marker(text)
1855: return text.gsub(/^\s?(=+)/, '<tt></tt>\1')
1856: end
# File parsers/parse_f95.rb, line 1858
1858: def remove_private_comments(body)
1859: body.gsub!(/^\s*!--\s*?$.*?^\s*!\+\+\s*?$/m, '')
1860: return body
1861: end
Remove "Alias for" in end of comments
# File parsers/parse_f95.rb, line 1820
1820: def remove_trailing_alias(text)
1821: return "" if !text
1822: lines = text.split("\n").reverse
1823: comment_block = Array.new
1824: checked = false
1825: lines.each do |line|
1826: if !checked
1827: if /^\s?#{INTERNAL_ALIAS_MES}/ =~ line ||
1828: /^\s?#{EXTERNAL_ALIAS_MES}/ =~ line
1829: checked = true
1830: next
1831: end
1832: end
1833: comment_block.unshift line
1834: end
1835: nice_lines = comment_block.join("\n")
1836: nice_lines ||= ""
1837: return nice_lines
1838: end
devine code constructs
# File parsers/parse_f95.rb, line 407
407: def scan
408:
409: # remove private comment
410: remaining_code = remove_private_comments(@body)
411:
412: # continuation lines are united to one line
413: remaining_code = united_to_one_line(remaining_code)
414:
415: # semicolons are replaced to line feed
416: remaining_code = semicolon_to_linefeed(remaining_code)
417:
418: # collect comment for file entity
419: whole_comment, remaining_code = collect_first_comment(remaining_code)
420: @top_level.comment = whole_comment
421:
422: # String "remaining_code" is converted to Array "remaining_lines"
423: remaining_lines = remaining_code.split("\n")
424:
425: # "module" or "program" parts are parsed (new)
426: #
427: level_depth = 0
428: block_searching_flag = nil
429: block_searching_lines = []
430: pre_comment = []
431: module_program_trailing = ""
432: module_program_name = ""
433: other_block_level_depth = 0
434: other_block_searching_flag = nil
435: remaining_lines.collect!{|line|
436: if !block_searching_flag && !other_block_searching_flag
437: if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i
438: block_searching_flag = :module
439: block_searching_lines << line
440: module_program_name = $1
441: module_program_trailing = find_comments($2)
442: next false
443: elsif line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
444: line =~ /^\s*?\w/ && !block_start?(line)
445: block_searching_flag = :program
446: block_searching_lines << line
447: module_program_name = $1 || ""
448: module_program_trailing = find_comments($2)
449: next false
450:
451: elsif block_start?(line)
452: other_block_searching_flag = true
453: next line
454:
455: elsif line =~ /^\s*?!\s?(.*)/
456: pre_comment << line
457: next line
458: else
459: pre_comment = []
460: next line
461: end
462: elsif other_block_searching_flag
463: other_block_level_depth += 1 if block_start?(line)
464: other_block_level_depth -= 1 if block_end?(line)
465: if other_block_level_depth < 0
466: other_block_level_depth = 0
467: other_block_searching_flag = nil
468: end
469: next line
470: end
471:
472: block_searching_lines << line
473: level_depth += 1 if block_start?(line)
474: level_depth -= 1 if block_end?(line)
475: if level_depth >= 0
476: next false
477: end
478:
479: # "module_program_code" is formatted.
480: # ":nodoc:" flag is checked.
481: #
482: module_program_code = block_searching_lines.join("\n")
483: module_program_code = remove_empty_head_lines(module_program_code)
484: if module_program_trailing =~ /^:nodoc:/
485: # next loop to search next block
486: level_depth = 0
487: block_searching_flag = false
488: block_searching_lines = []
489: pre_comment = []
490: next false
491: end
492:
493: # NormalClass is created, and added to @top_level
494: #
495: if block_searching_flag == :module
496: module_name = module_program_name
497: module_code = module_program_code
498: module_trailing = module_program_trailing
499: progress "m"
500: @stats.num_modules += 1
501: f9x_module = @top_level.add_module NormalClass, module_name
502: f9x_module.record_location @top_level
503:
504: f9x_comment = COMMENTS_ARE_UPPER ?
505: find_comments(pre_comment.join("\n")) + "\n" + module_trailing :
506: module_trailing + "\n" + find_comments(module_code.sub(/^.*$\n/i, ''))
507: f9x_module.comment = f9x_comment
508: parse_program_or_module(f9x_module, module_code)
509:
510: TopLevel.all_files.each do |name, toplevel|
511: if toplevel.include_includes?(module_name, @options.ignore_case)
512: if !toplevel.include_requires?(@file_name, @options.ignore_case)
513: toplevel.add_require(Require.new(@file_name, ""))
514: end
515: end
516: toplevel.each_classmodule{|m|
517: if m.include_includes?(module_name, @options.ignore_case)
518: if !m.include_requires?(@file_name, @options.ignore_case)
519: m.add_require(Require.new(@file_name, ""))
520: end
521: end
522: }
523: end
524: elsif block_searching_flag == :program
525: program_name = module_program_name
526: program_code = module_program_code
527: program_trailing = module_program_trailing
528: progress "p"
529: program_comment = COMMENTS_ARE_UPPER ?
530: find_comments(pre_comment.join("\n")) + "\n" + program_trailing :
531: program_trailing + "\n" + find_comments(program_code.sub(/^.*$\n/i, ''))
532: program_comment = "\n\n= <i>Program</i> <tt>#{program_name}</tt>\n\n" \
533: + program_comment
534: @top_level.comment << program_comment
535: parse_program_or_module(@top_level, program_code, :private)
536: end
537:
538: # next loop to search next block
539: level_depth = 0
540: block_searching_flag = false
541: block_searching_lines = []
542: pre_comment = []
543: next false
544: }
545:
546: remaining_lines.delete_if{ |line|
547: line == false
548: }
549:
550: # External subprograms and functions are parsed
551: #
552: # 単一のファイル内において program や module に格納されない,
553: # 外部サブルーチン, 外部関数部分の解析.
554: #
555: parse_program_or_module(@top_level, remaining_lines.join("\n"),
556: :public, true)
557:
558: @top_level
559: end
Semicolons are replaced to line feed.
# File parsers/parse_f95.rb, line 1727
1727: def semicolon_to_linefeed(text)
1728: return "" unless text
1729: lines = text.split("\n")
1730: lines.collect!{ |line|
1731: words = line.split("")
1732: commentout = false
1733: squote = false ; dquote = false
1734: words.collect! { |char|
1735: if !(squote) && !(dquote) && !(commentout)
1736: case char
1737: when "!" ; commentout = true ; next char
1738: when "\""; dquote = true ; next char
1739: when "\'"; squote = true ; next char
1740: when ";" ; "\n"
1741: else next char
1742: end
1743: elsif commentout
1744: next char
1745: elsif squote
1746: case char
1747: when "\'"; squote = false ; next char
1748: else next char
1749: end
1750: elsif dquote
1751: case char
1752: when "\""; dquote = false ; next char
1753: else next char
1754: end
1755: end
1756: }
1757: words.join("")
1758: }
1759: return lines.join("\n")
1760: end
Set visibility
"subname" element of "visibility_info" is deleted.
# File parsers/parse_f95.rb, line 1502
1502: def set_visibility(container, subname, visibility_default, visibility_info)
1503: return unless container || subname || visibility_default || visibility_info
1504: not_found = true
1505: visibility_info.collect!{ |info|
1506: if info["name"] == subname ||
1507: @options.ignore_case && info["name"].upcase == subname.upcase
1508: if info["file_or_module"].name == container.name
1509: container.set_visibility_for([subname], info["visibility"])
1510: info["entity_is_discovered"] = true
1511: not_found = false
1512: end
1513: end
1514: info
1515: }
1516: if not_found
1517: return container.set_visibility_for([subname], visibility_default)
1518: else
1519: return container
1520: end
1521: end
Continuous lines are united.
Comments in continuous lines are removed.
# File parsers/parse_f95.rb, line 1609
1609: def united_to_one_line(f90src)
1610: return "" unless f90src
1611: lines = f90src.split("\n")
1612: previous_continuing = false
1613: now_continuing = false
1614: body = ""
1615: lines.each{ |line|
1616: words = line.split("")
1617: next if words.empty? && previous_continuing
1618: commentout = false
1619: brank_flag = true ; brank_char = ""
1620: squote = false ; dquote = false
1621: ignore = false
1622: words.collect! { |char|
1623: if previous_continuing && brank_flag
1624: now_continuing = true
1625: ignore = true
1626: case char
1627: when "!" ; break
1628: when " " ; brank_char << char ; next ""
1629: when "&"
1630: brank_flag = false
1631: now_continuing = false
1632: next ""
1633: else
1634: brank_flag = false
1635: now_continuing = false
1636: ignore = false
1637: next brank_char + char
1638: end
1639: end
1640: ignore = false
1641:
1642: if now_continuing
1643: next ""
1644: elsif !(squote) && !(dquote) && !(commentout)
1645: case char
1646: when "!" ; commentout = true ; next char
1647: when "\""; dquote = true ; next char
1648: when "\'"; squote = true ; next char
1649: when "&" ; now_continuing = true ; next ""
1650: else next char
1651: end
1652: elsif commentout
1653: next char
1654: elsif squote
1655: case char
1656: when "\'"; squote = false ; next char
1657: else next char
1658: end
1659: elsif dquote
1660: case char
1661: when "\""; dquote = false ; next char
1662: else next char
1663: end
1664: end
1665: }
1666: if !ignore && !previous_continuing || !brank_flag
1667: if previous_continuing
1668: body << words.join("")
1669: else
1670: body << "\n" + words.join("")
1671: end
1672: end
1673: previous_continuing = now_continuing ? true : nil
1674: now_continuing = nil
1675: }
1676: return body
1677: end