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