def merge_adjacent_comment_lines(lines): """Given a list of numered Fortran source code lines, i.e., pairs of the form (n, code_line) where n is a line number and code_line is a line of code, merge_adjacent_comment_lines() merges sequences of lines that are indicated to be comment lines. """ i = 0 while i < len(lines) - 1: lnum, line = lines[i] if line_is_comment(line): j = i + 1 while j < len(lines) and line_is_comment(lines[j][1]): line += lines[j][1] lines.pop(j) # pop() removes a line so lines[j] now refers to the next line lines[i] = (lnum, line) i += 1 return lines
def separate_trailing_comments(lines: List[str]) -> List[Tuple[int, str]]: """Given a list of Fortran source code linesseparate_trailing_comments() removes partial-line comments and returns the resulting list of lines. """ i = 0 while i < len(lines): code_line = lines[i] if not line_is_comment(code_line): (code_part, comment_part) = split_trailing_comment(code_line) if comment_part is not None: lines[i] = code_part i += 1 return lines
def type_of_line(line): """Given a line of code, type_of_line() returns a string indicating what kind of code it is.""" if line_is_comment(line): return "comment" elif line_is_executable(line): return "exec_stmt" elif line_is_pgm_unit_end(line): return "pgm_unit_end" else: if line_is_pgm_unit_start(line): return "pgm_unit_start" else: return "other"
def merge_continued_lines(lines): """Given a list of numered Fortran source code lines, i.e., pairs of the form (n, code_line) where n is a line number and code_line is a line of code, merge_continued_lines() merges sequences of lines that are indicated to be continuation lines. """ # Before a continuation line L1 is merged with the line L0 before it (and # presumably the one L1 is continuing), ensure that L0 is not a comment. # If L0 is a comment, swap L0 and L1. chg = True while chg: chg = False i = 0 while i < len(lines) - 1: ln0, ln1 = lines[i], lines[i + 1] if line_is_comment(ln0[1]) and line_is_continuation(ln1[1]): # swap the code portions of lines[i] and lines[i+1] lines[i], lines[i + 1] = (ln0[0], ln1[1]), (ln1[0], ln0[1]) chg = True i += 1 # Merge continuation lines chg = True while chg: chg = False i = 0 while i < len(lines): line = lines[i] if line_is_continuation(line[1]): assert i > 0 (prev_linenum, prev_line_code) = lines[i - 1] curr_line_code = line[1].lstrip()[ 1: ] # remove continuation char merged_code = prev_line_code.rstrip() + curr_line_code.lstrip() lines[i - 1] = (prev_linenum, merged_code) lines.pop(i) chg = True i += 1 return lines
def separate_trailing_comments(lines: List[str]) -> List[Tuple[int, str]]: """Given a list of numbered Fortran source code lines, i.e., pairs of the form (n, code_line) where n is a line number and code_line is a line of code, separate_trailing_comments() behaves as follows: for each pair (n, code_line) where code_line can be broken into two parts -- a code portion code_part and a trailing comment portion comment_part, such that code_part and comment_part are both non-empty, it replaces the pair (n, code_line) by two pairs (n, comment_part) and (n, code_part). The return value is the resulting list of numbered lines. """ i = 0 while i < len(lines): (n, code_line) = lines[i] if not line_is_comment(code_line): (code_part, comment_part) = split_trailing_comment(code_line) if comment_part is not None: lines[i] = (n, comment_part) lines.insert(i + 1, (n, code_part)) i += 1 return lines
def merge_continued_lines(lines): """Given a list of numered Fortran source code lines, i.e., pairs of the form (n, code_line) where n is a line number and code_line is a line of code, merge_continued_lines() merges sequences of lines that are indicated to be continuation lines. """ # Before a continuation line L1 is merged with the line L0 before it (and # presumably the one L1 is continuing), ensure that L0 is not a comment. # If L0 is a comment, swap L0 and L1. chg = True swaps = set() while chg: chg = False i = 0 while i < len(lines) - 1: ln0, ln1 = lines[i], lines[i + 1] if (line_is_comment(ln0[1]) and line_is_continuation(ln1[1])) \ or (line_is_continued(ln0[1]) and line_is_comment(ln1[1])): if (i, i + 1) not in swaps: # swap the code portions of lines[i] and lines[i+1] lines[i], lines[i + 1] = (ln0[0], ln1[1]), (ln1[0], ln0[1]) swaps.add((i, i + 1)) # to prevent infinite loops else: # If we get here, there is a pair of adjacent lines that # are about to go into an infinite swap sequence; one of them # must be a comment. We delete the comment. if line_is_comment(ln0[1]): lines.pop(i) else: assert line_is_comment(ln1[1]) lines.pop(i + 1) chg = True i += 1 # Merge continuation lines chg = True while chg: chg = False i = 0 while i < len(lines): line = lines[i] if line_is_continuation(line[1]): assert i > 0 (prev_linenum, prev_line_code) = lines[i - 1] curr_line_code = line[1].lstrip()[ 1:] # remove continuation char merged_code = prev_line_code.rstrip() + \ " " + \ curr_line_code.lstrip() + \ "\n" lines[i - 1] = (prev_linenum, merged_code) lines.pop(i) chg = True elif line_is_continued(line[1]): assert i < len(lines) - 1 # there must be a next line (next_linenum, next_line_code) = lines[i + 1] curr_line_code = line[1].rstrip()[:-1].rstrip( ) # remove continuation char merged_code = curr_line_code + " " + next_line_code.lstrip() lines[i] = (i, merged_code) lines.pop(i + 1) chg = True i += 1 return lines
def get_comments(src_file_name: str): curr_comment = [] curr_fn, prev_fn, curr_marker = None, None, None in_neck = False comments = OrderedDict() lineno = 1 comments["$file_head"] = None comments["$file_foot"] = None _, f_ext = os.path.splitext(src_file_name) with open(src_file_name, "r", encoding="latin-1") as f: for line in f: if line_is_comment(line) or line.strip() == "": curr_comment.append(line) else: if comments["$file_head"] is None: comments["$file_head"] = curr_comment f_start, f_name_maybe = line_starts_subpgm(line) if f_start: f_name = f_name_maybe prev_fn = curr_fn curr_fn = f_name if prev_fn is not None: comments[prev_fn]["foot"] = curr_comment comments[curr_fn] = init_comment_map( curr_comment, [], [], OrderedDict()) curr_comment = [] in_neck = True elif line_ends_subpgm(line): curr_comment = [] elif line_is_continuation(line, f_ext): lineno += 1 continue else: if in_neck: comments[curr_fn]["neck"] = curr_comment in_neck = False curr_comment = [] else: match = re.match(RE_INTERNAL_COMMENT_MARKER, line) if match != None: curr_marker = match.group(1) curr_comment = [] elif curr_marker != None: comments[curr_fn]["internal"][ curr_marker] = curr_comment curr_marker = None curr_comment = [] lineno += 1 # if there's a comment at the very end of the file, make it the foot # comment of curr_fn if curr_comment != [] and comments.get(curr_fn): comments[curr_fn]["foot"] = curr_comment comments["$file_foot"] = curr_comment if comments["$file_head"] is None: comments["$file_head"] = [] if comments["$file_foot"] is None: comments["$file_foot"] = [] return comments
def discard_comments(lines): return [ line for line in lines if not (line_is_comment(line) or line.strip() == "") ]