Exemplo n.º 1
0
 def create_object(json_obj, enc_obj=None):
     if enc_obj is not None:
         enc_scope_name = enc_obj.FQSN
     else:
         enc_scope_name = None
     if "mods" in json_obj:
         modifiers, dim_str, _ = map_keywords(json_obj["mods"])
     else:
         modifiers = []
         dim_str = None
     name = json_obj["name"]
     args = json_obj.get("args", "")
     if lowercase_intrinsics:
         name = name.lower()
         args = args.lower()
     if json_obj["type"] == 0:
         mod_tmp = fortran_module(none_file,
                                  0,
                                  name,
                                  enc_scope=enc_scope_name)
         if "use" in json_obj:
             mod_tmp.add_use(json_obj["use"], 0)
         return mod_tmp
     elif json_obj["type"] == 1:
         return fortran_subroutine(none_file,
                                   0,
                                   name,
                                   enc_scope=enc_scope_name,
                                   args=args)
     elif json_obj["type"] == 2:
         return fortran_function(
             none_file,
             0,
             name,
             enc_scope=enc_scope_name,
             args=args,
             return_type=[json_obj["return"], modifiers, dim_str])
     elif json_obj["type"] == 3:
         return fortran_obj(none_file, 0, name, json_obj["desc"], modifiers,
                            dim_str, enc_scope_name)
     elif json_obj["type"] == 4:
         return fortran_type(none_file, 0, name, modifiers, enc_scope_name)
     else:
         raise ValueError
 def create_object(json_obj, enc_obj=None):
     enc_scope_name = None
     args = ""
     modifiers = []
     if enc_obj is not None:
         enc_scope_name = enc_obj.FQSN
     if "args" in json_obj:
         args = json_obj["args"]
     if "mods" in json_obj:
         modifiers = parse_keywords(json_obj["mods"])
     if json_obj["type"] == 0:
         mod_tmp = fortran_module(none_file,
                                  0,
                                  json_obj["name"],
                                  enc_scope=enc_scope_name)
         if "use" in json_obj:
             mod_tmp.add_use(json_obj["use"], 0)
         return mod_tmp
     elif json_obj["type"] == 1:
         return fortran_subroutine(none_file,
                                   0,
                                   json_obj["name"],
                                   enc_scope=enc_scope_name,
                                   args=args)
     elif json_obj["type"] == 2:
         return fortran_function(
             none_file,
             0,
             json_obj["name"],
             enc_scope=enc_scope_name,
             args=args,
             return_type=[json_obj["return"], modifiers])
     elif json_obj["type"] == 3:
         return fortran_obj(none_file, 0, json_obj["name"],
                            json_obj["desc"], modifiers, enc_scope_name)
     elif json_obj["type"] == 4:
         return fortran_type(none_file, 0, json_obj["name"], modifiers,
                             enc_scope_name)
     else:
         raise ValueError
Exemplo n.º 3
0
 def create_object(json_obj, enc_obj=None):
     if enc_obj is not None:
         none_ast.enc_scope_name = enc_obj.FQSN
     else:
         none_ast.enc_scope_name = None
     if "mods" in json_obj:
         keywords, keyword_info = map_keywords(json_obj["mods"])
     else:
         keywords = []
         keyword_info = {}
     name = json_obj["name"]
     args = json_obj.get("args", "")
     if lowercase_intrinsics:
         name = name.lower()
         args = args.lower()
     if json_obj["type"] == 0:
         mod_tmp = fortran_module(none_ast, 0, name)
         if "use" in json_obj:
             mod_tmp.add_use(json_obj["use"], 0)
         return mod_tmp
     elif json_obj["type"] == 1:
         return fortran_subroutine(none_ast, 0, name, args=args)
     elif json_obj["type"] == 2:
         return fortran_function(
             none_ast,
             0,
             name,
             args=args,
             return_type=[json_obj["return"], keywords, keyword_info])
     elif json_obj["type"] == 3:
         return fortran_var(none_ast, 0, name, json_obj["desc"], keywords,
                            keyword_info)
     elif json_obj["type"] == 4:
         return fortran_type(none_ast, 0, name, keywords)
     else:
         raise ValueError
def process_file(file_str,
                 close_open_scopes,
                 path=None,
                 fixed_format=False,
                 debug=False,
                 pp_defs=None):
    def preprocess():
        # Look for and mark excluded preprocessor paths in file
        # Initial implementation only looks for "if" and "ifndef" statements.
        # For "if" statements all blocks are excluded except the "else" block if present
        # For "ifndef" statements all blocks excluding the first block are exlucded
        def eval_pp_if(text, defs={}):
            def replace_ops(expr):
                expr = expr.replace("&&", " and ")
                expr = expr.replace("||", " or ")
                expr = expr.replace("!=", " <> ")
                expr = expr.replace("!", " not ")
                expr = expr.replace(" <> ", " != ")
                return expr

            def replace_defined(line):
                DEFINED_REGEX = re.compile(
                    r'defined[ ]*\([ ]*([a-z_][a-z0-9_]*)[ ]*\)', re.I)
                i0 = 0
                out_line = ""
                for match in DEFINED_REGEX.finditer(line):
                    if match.group(1) in defs:
                        out_line += line[i0:match.start(0)] + "($@)"
                    else:
                        out_line += line[i0:match.start(0)] + "($%)"
                    i0 = match.end(0)
                if i0 < len(line):
                    out_line += line[i0:]
                return out_line

            def replace_vars(line):
                WORD_REGEX = re.compile(r'[a-z_][a-z0-9_]*', re.I)
                i0 = 0
                out_line = ""
                for match in WORD_REGEX.finditer(line):
                    if match.group(0) in defs:
                        out_line += line[i0:match.start(0)] + defs[match.group(
                            0)]
                    else:
                        out_line += line[i0:match.start(0)] + "False"
                    i0 = match.end(0)
                if i0 < len(line):
                    out_line += line[i0:]
                out_line = out_line.replace("$@", "True")
                out_line = out_line.replace("$%", "False")
                return out_line

            out_line = replace_defined(text)
            out_line = replace_vars(out_line)
            try:
                line_res = eval(replace_ops(out_line))
            except:
                return False
            else:
                return line_res

        #
        pp_skips = []
        pp_defines = []
        pp_stack = []
        defs_tmp = pp_defs.copy()
        output_file = []
        for (i, line) in enumerate(file_str):
            match = PP_REGEX.match(line)
            if (match is not None):
                output_file.append(line)
                def_name = None
                if_start = False
                if match.group(1) == 'if ':
                    is_path = eval_pp_if(line[match.end(1):], defs_tmp)
                    if_start = True
                elif match.group(1) == 'ifdef':
                    if_start = True
                    def_name = line[match.end(0):].strip()
                    is_path = (def_name in defs_tmp)
                elif match.group(1) == 'ifndef':
                    if_start = True
                    def_name = line[match.end(0):].strip()
                    is_path = not (def_name in defs_tmp)
                if if_start:
                    if is_path:
                        pp_stack.append([-1, -1])
                        if debug:
                            print('{1} !!! Conditional TRUE({0})'.format(
                                i + 1, line.strip()))
                    else:
                        pp_stack.append([i + 1, -1])
                        if debug:
                            print('{1} !!! Conditional FALSE({0})'.format(
                                i + 1, line.strip()))
                    continue
                if len(pp_stack) == 0:
                    continue
                #
                inc_start = False
                exc_start = False
                if (match.group(1) == 'elif'):
                    if (pp_stack[-1][0] < 0):
                        pp_stack[-1][0] = i + 1
                        exc_start = True
                    else:
                        if eval_pp_if(line[match.end(1):], defs_tmp):
                            pp_stack[-1][1] = i - 1
                            pp_stack.append([-1, -1])
                            inc_start = True
                elif match.group(1) == 'else':
                    if pp_stack[-1][0] < 0:
                        pp_stack[-1][0] = i + 1
                        exc_start = True
                    else:
                        pp_stack[-1][1] = i + 1
                        inc_start = True
                elif match.group(1) == 'endif':
                    if pp_stack[-1][0] < 0:
                        pp_stack.pop()
                        continue
                    if pp_stack[-1][1] < 0:
                        pp_stack[-1][1] = i + 1
                        if debug:
                            print('{1} !!! Conditional FALSE/END({0})'.format(
                                i + 1, line.strip()))
                    pp_skips.append(pp_stack.pop())
                if debug:
                    if inc_start:
                        print('{1} !!! Conditional TRUE({0})'.format(
                            i + 1, line.strip()))
                    elif exc_start:
                        print('{1} !!! Conditional FALSE({0})'.format(
                            i + 1, line.strip()))
                continue
            #
            match = PP_DEF_REGEX.match(line)
            if (match is not None) and ((len(pp_stack) == 0) or
                                        (pp_stack[-1][0] < 0)):
                output_file.append(line)
                pp_defines.append(i + 1)
                def_name = match.group(2)
                if (match.group(1) == 'define') and (def_name not in defs_tmp):
                    eq_ind = line[match.end(0):].find(' ')
                    if eq_ind >= 0:
                        defs_tmp[def_name] = line[match.end(0) +
                                                  eq_ind:].strip()
                    else:
                        defs_tmp[def_name] = "True"
                elif (match.group(1) == 'undef') and (def_name in defs_tmp):
                    defs_tmp.pop(def_name, None)
                if debug:
                    print('{1} !!! Define statement({0})'.format(
                        i + 1, line.strip()))
                continue
            #
            for def_tmp, value in defs_tmp.items():
                if line.find(def_tmp) >= 0:
                    if debug:
                        print('{1} !!! Macro sub({0}) "{2}" -> "{3}"'.format(
                            i + 1, line.strip(), def_tmp, value))
                    line = line.replace(def_tmp, value)
            output_file.append(line)
        return pp_skips, pp_defines, output_file

    #
    if fixed_format:
        COMMENT_LINE_MATCH = FIXED_COMMENT_LINE_MATCH
        CONT_REGEX = FIXED_CONT_REGEX
    else:
        COMMENT_LINE_MATCH = FREE_COMMENT_LINE_MATCH
        CONT_REGEX = FREE_CONT_REGEX
    #
    file_obj = fortran_file(path)
    #
    if pp_defs is not None:
        if debug:
            print("=== PreProc Pass ===\n")
        pp_skips, pp_defines, file_str = preprocess()
        for pp_reg in pp_skips:
            file_obj.start_ppif(pp_reg[0])
            file_obj.end_ppif(pp_reg[1])
        if debug:
            print("\n=== Parsing Pass ===\n")
    else:
        pp_skips = []
        pp_defines = []
    #
    line_number = 0
    next_line_num = 1
    int_counter = 0
    block_counter = 0
    do_counter = 0
    if_counter = 0
    select_counter = 0
    block_id_stack = []
    next_line = None
    line_ind = 0
    while ((line_ind < len(file_str)) or (next_line is not None)):
        # Get next line
        if next_line is None:
            line = file_str[line_ind]
            line_ind += 1
        else:
            line = next_line
            next_line = None
        line_number = next_line_num
        next_line_num = line_number + 1
        if line == '':
            continue  # Skip empty lines
        # Skip comment lines
        match = COMMENT_LINE_MATCH.match(line)
        if (match is not None):
            continue
        do_skip = False
        for pp_reg in pp_skips:
            if (line_number >= pp_reg[0]) and (line_number <= pp_reg[1]):
                do_skip = True
                break
        if line_number in pp_defines:
            do_skip = True
        if do_skip:
            continue
        # Get line label
        line, line_label = strip_line_label(line)
        # Merge lines with continuations
        if fixed_format:
            if line_ind < len(file_str):
                next_line = file_str[line_ind]
                line_ind += 1
                cont_match = CONT_REGEX.match(next_line)
                while (cont_match is not None and (line_ind < len(file_str))):
                    line = line.rstrip() + next_line[6:].strip()
                    next_line_num += 1
                    next_line = file_str[line_ind]
                    line_ind += 1
                    cont_match = CONT_REGEX.match(next_line)
        else:
            line_stripped = strip_strings(line, maintain_len=True)
            iAmper = line_stripped.find('&')
            iComm = line_stripped.find('!')
            if iComm < 0:
                iComm = iAmper + 1
            while (iAmper >= 0 and iAmper < iComm):
                line_prefix = line[:iAmper]
                next_line = file_str[line_ind]
                line_ind += 1
                # Skip empty or comment lines
                match = COMMENT_LINE_MATCH.match(next_line)
                if (next_line.rstrip() == '') or (match is not None):
                    next_line_num += 1
                    continue
                next_stripped = strip_strings(next_line, maintain_len=True)
                cont_match = CONT_REGEX.match(next_stripped)
                if cont_match is not None:
                    next_line = next_line[cont_match.end(0):]
                next_line_num += 1
                line = line_prefix.rstrip() + ' ' + next_line.strip()
                line_stripped = strip_strings(line, maintain_len=True)
                iAmper = line_stripped.find('&')
                iComm = line_stripped.find('!')
                if iComm < 0:
                    iComm = iAmper + 1
            next_line = None
        line = line.rstrip()
        line_no_comment = line.split('!')[0]
        # Test for scope end
        if file_obj.END_SCOPE_WORD is not None:
            match = END_WORD_REGEX.match(line_no_comment)
            # Handle end statement
            if match is not None:
                end_scope_word = match.group(1)
                if (end_scope_word is not None) or (match.group(2) == ""):
                    if end_scope_word is not None:
                        end_scope_word = end_scope_word.strip().upper()
                    if ((end_scope_word != file_obj.END_SCOPE_WORD)
                            and (file_obj.current_scope.req_named_end() or
                                 (end_scope_word is not None)) and
                        (file_obj.current_scope is not file_obj.none_scope)):
                        file_obj.end_errors.append(
                            [line_number, file_obj.current_scope.sline])
                    if (file_obj.current_scope.get_type()
                            == 9) and (file_obj.current_scope.type in (3, 4)):
                        file_obj.end_scope(line_number)
                    file_obj.end_scope(line_number)
                    if (debug):
                        print('{1} !!! END "{2}" scope({0})'.format(
                            line_number, line.strip(), end_scope_word))
                    continue
            # Look for old-style end of DO loops with line labels
            if (file_obj.END_SCOPE_WORD == 'DO') and (line_label is not None):
                did_close = False
                while (len(block_id_stack) > 0) and (line_label
                                                     == block_id_stack[-1]):
                    file_obj.end_scope(line_number)
                    block_id_stack.pop()
                    did_close = True
                    if (debug):
                        print('{1} !!! END "DO" scope({0})'.format(
                            line_number, line.strip()))
                if did_close:
                    continue
        # Mark contains statement
        match = CONTAINS_REGEX.match(line_no_comment)
        if match is not None:
            err_message = None
            try:
                if file_obj.current_scope is None:
                    err_message = "Contains statement without enclosing scope"
                else:
                    file_obj.current_scope.mark_contains(line_number)
            except ValueError:
                err_message = "Multiple contains statements in scope"
            if err_message is not None:
                file_obj.parse_errors.append({
                    "line": line_number,
                    "schar": match.start(1),
                    "echar": match.end(1),
                    "mess": err_message,
                    "sev": 1
                })
            if (debug):
                print('{1} !!! CONTAINS statement({0})'.format(
                    line_number, line.strip()))
            continue
        # Loop through tests
        obj_read = None
        for test in def_tests:
            obj_read = test(line)
            if obj_read is not None:
                break
        #
        if obj_read is not None:
            obj_type = obj_read[0]
            obj = obj_read[1]
            if obj_type == 'var':
                if obj[2] is None:
                    continue
                link_name = None
                if obj[0][:3] == 'PRO':
                    if isinstance(file_obj.current_scope, fortran_int):
                        for var_name in obj[2]:
                            file_obj.add_int_member(var_name)
                        if (debug):
                            print(
                                '{1} !!! INTERFACE-PRO statement({0})'.format(
                                    line_number, line.strip()))
                        continue
                    i1 = obj[0].find('(')
                    i2 = obj[0].find(')')
                    if i1 > -1 and i2 > -1:
                        link_name = obj[0][i1 + 1:i2]
                for var_name in obj[2]:
                    link_name = None
                    if var_name.find('=>') > -1:
                        name_split = var_name.split('=>')
                        name_stripped = name_split[0]
                        link_name = name_split[1].split('(')[0].strip()
                        if link_name.lower() == 'null':
                            link_name = None
                    else:
                        name_stripped = var_name.split('=')[0]
                    var_dim_str = None
                    if name_stripped.find('(') > -1:
                        var_dim_str = get_var_dims(name_stripped)
                    name_stripped = name_stripped.split('(')[0].strip()
                    modifiers, dim_str, pass_name = map_keywords(obj[1])
                    if obj[0][:3] == 'PRO':
                        new_var = fortran_meth(file_obj,
                                               line_number,
                                               name_stripped,
                                               obj[0],
                                               modifiers,
                                               file_obj.enc_scope_name,
                                               link_name,
                                               pass_name=pass_name)
                    else:
                        new_var = fortran_obj(file_obj, line_number,
                                              name_stripped, obj[0], modifiers,
                                              dim_str, file_obj.enc_scope_name,
                                              link_name)
                    if var_dim_str is not None:
                        new_var.set_dim(var_dim_str)
                    file_obj.add_variable(new_var)
                if (debug):
                    print('{1} !!! VARIABLE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'mod':
                new_mod = fortran_module(file_obj, line_number, obj,
                                         file_obj.enc_scope_name)
                file_obj.add_scope(new_mod, END_MOD_WORD)
                if (debug):
                    print('{1} !!! MODULE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'smod':
                new_smod = fortran_submodule(file_obj, line_number, obj[0],
                                             file_obj.enc_scope_name, obj[1])
                file_obj.add_scope(new_smod, END_SMOD_WORD)
                if (debug):
                    print('{1} !!! SUBMODULE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'prog':
                new_prog = fortran_program(file_obj, line_number, obj,
                                           file_obj.enc_scope_name)
                file_obj.add_scope(new_prog, END_PROG_WORD)
                if (debug):
                    print('{1} !!! PROGRAM statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'sub':
                new_sub = fortran_subroutine(file_obj, line_number, obj[0],
                                             file_obj.enc_scope_name, obj[1],
                                             obj[2])
                file_obj.add_scope(new_sub, END_SUB_WORD)
                if (debug):
                    print('{1} !!! SUBROUTINE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'fun':
                new_fun = fortran_function(file_obj,
                                           line_number,
                                           obj[0],
                                           file_obj.enc_scope_name,
                                           obj[1],
                                           obj[3],
                                           return_type=obj[2][0],
                                           result_var=obj[2][1])
                file_obj.add_scope(new_fun, END_FUN_WORD)
                if obj[2][0] is not None:
                    new_obj = fortran_obj(file_obj, line_number, obj[0],
                                          obj[2][0][0], obj[2][0][1],
                                          file_obj.enc_scope_name, None)
                    file_obj.add_variable(new_obj)
                if (debug):
                    print('{1} !!! FUNCTION statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'block':
                name = obj[0]
                if name is None:
                    block_counter += 1
                    name = '#BLOCK{0}'.format(block_counter)
                new_block = fortran_block(file_obj, line_number, name,
                                          file_obj.enc_scope_name)
                file_obj.add_scope(new_block,
                                   END_BLOCK_WORD,
                                   req_container=True)
                if (debug):
                    print('{1} !!! BLOCK statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'do':
                do_counter += 1
                name = '#DO{0}'.format(do_counter)
                if obj[0] != '':
                    block_id_stack.append(obj[0])
                new_do = fortran_do(file_obj, line_number, name,
                                    file_obj.enc_scope_name)
                file_obj.add_scope(new_do, END_DO_WORD, req_container=True)
                if (debug):
                    print('{1} !!! DO statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'where':
                # Add block if WHERE is not single line
                if not obj:
                    do_counter += 1
                    name = '#WHERE{0}'.format(do_counter)
                    new_do = fortran_where(file_obj, line_number, name,
                                           file_obj.enc_scope_name)
                    file_obj.add_scope(new_do,
                                       END_WHERE_WORD,
                                       req_container=True)
                if (debug):
                    print('{1} !!! WHERE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'assoc':
                block_counter += 1
                name = '#ASSOC{0}'.format(block_counter)
                new_assoc = fortran_associate(file_obj, line_number, name,
                                              file_obj.enc_scope_name)
                file_obj.add_scope(new_assoc,
                                   END_ASSOCIATE_WORD,
                                   req_container=True)
                if (debug):
                    print('{1} !!! ASSOCIATE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'if':
                if_counter += 1
                name = '#IF{0}'.format(if_counter)
                new_if = fortran_if(file_obj, line_number, name,
                                    file_obj.enc_scope_name)
                file_obj.add_scope(new_if, END_IF_WORD, req_container=True)
                if (debug):
                    print('{1} !!! IF statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'select':
                select_counter += 1
                name = '#SELECT{0}'.format(select_counter)
                binding_name = None
                bound_var = None
                if file_obj.current_scope is not None:
                    if (obj[0]
                            in (3, 4)) and (file_obj.current_scope.get_type()
                                            == 9):
                        if file_obj.current_scope.type in (3, 4):
                            file_obj.end_scope(line_number)
                if file_obj.current_scope is not None:
                    if (obj[0]
                            in (3, 4)) and (file_obj.current_scope.get_type()
                                            == 9):
                        if file_obj.current_scope.type == 2:
                            binding_name = file_obj.current_scope.binding_name
                            bound_var = file_obj.current_scope.bound_var
                new_select = fortran_select(file_obj, line_number, name, obj,
                                            file_obj.enc_scope_name)
                file_obj.add_scope(new_select,
                                   END_SELECT_WORD,
                                   req_container=True)
                if binding_name is not None:
                    if obj[0] != 4:
                        bound_var = None
                    new_var = fortran_obj(file_obj,
                                          line_number,
                                          binding_name,
                                          '{0}({1})'.format(obj[2], obj[1]),
                                          [],
                                          file_obj.enc_scope_name,
                                          link_obj=bound_var)
                    file_obj.add_variable(new_var)
                elif (binding_name is None) and (bound_var is not None):
                    new_var = fortran_obj(file_obj, line_number, bound_var,
                                          '{0}({1})'.format(obj[2], obj[1]),
                                          [], file_obj.enc_scope_name)
                    file_obj.add_variable(new_var)
                if (debug):
                    print('{1} !!! SELECT statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'typ':
                modifiers, _, _ = map_keywords(obj[2])
                new_type = fortran_type(file_obj, line_number, obj[0],
                                        modifiers, file_obj.enc_scope_name)
                if obj[1] is not None:
                    new_type.set_inherit(obj[1])
                file_obj.add_scope(new_type,
                                   END_TYPED_WORD,
                                   req_container=True)
                if (debug):
                    print('{1} !!! TYPE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'enum':
                block_counter += 1
                name = '#ENUM{0}'.format(block_counter)
                new_enum = fortran_enum(file_obj, line_number, name,
                                        file_obj.enc_scope_name)
                file_obj.add_scope(new_enum,
                                   END_ENUMD_WORD,
                                   req_container=True)
                if (debug):
                    print('{1} !!! ENUM statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'int':
                abstract = obj[1]
                name = obj[0]
                if name is None:
                    int_counter += 1
                    name = '#GEN_INT{0}'.format(int_counter)
                new_int = fortran_int(file_obj, line_number, name,
                                      file_obj.enc_scope_name, abstract)
                file_obj.add_scope(new_int, END_INT_WORD, req_container=True)
                if (debug):
                    print('{1} !!! INTERFACE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'gen':
                name = obj[0]
                new_int = fortran_int(file_obj, line_number, name,
                                      file_obj.enc_scope_name, False)
                file_obj.add_scope(new_int, END_INT_WORD, req_container=True)
                for pro_link in obj[1]:
                    file_obj.add_int_member(pro_link)
                file_obj.end_scope(line_number)
                if (debug):
                    print('{1} !!! GENERIC statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'int_pro':
                if file_obj.current_scope is None:
                    continue
                if not isinstance(file_obj.current_scope, fortran_int):
                    continue
                for name in obj:
                    file_obj.add_int_member(name)
                if (debug):
                    print('{1} !!! INTERFACE-PRO statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'use':
                file_obj.add_use(obj[0], line_number, obj[1])
                if (debug):
                    print('{1} !!! USE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'inc':
                file_obj.add_include(obj[0], line_number)
                if (debug):
                    print('{1} !!! INCLUDE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'vis':
                if (len(obj[1]) == 0) and (obj[0] == 1):
                    file_obj.current_scope.set_default_vis(-1)
                else:
                    if obj[0] == 1:
                        for word in obj[1]:
                            file_obj.add_private(word)
                    else:
                        for word in obj[1]:
                            file_obj.add_public(word)
                if (debug):
                    print('{1} !!! Visiblity statement({0})'.format(
                        line_number, line.strip()))
    file_obj.close_file(line_number)
    return file_obj
Exemplo n.º 5
0
def process_file(file_str, close_open_scopes, fixed_format=False, debug=False):
    #
    if fixed_format:
        COMMENT_LINE_MATCH = FIXED_COMMENT_LINE_MATCH
        CONT_REGEX = FIXED_CONT_REGEX
    else:
        COMMENT_LINE_MATCH = FREE_COMMENT_LINE_MATCH
        CONT_REGEX = FREE_CONT_REGEX
    #
    file_obj = fortran_file()
    line_number = 0
    next_line_num = 1
    int_counter = 0
    # at_eof = False
    next_line = None
    line_ind = 0
    while (line_ind < len(file_str)):
        # Get next line
        if next_line is None:
            line = file_str[line_ind]
            line_ind += 1
        else:
            line = next_line
            next_line = None
        line_number = next_line_num
        next_line_num = line_number + 1
        if line == '':
            continue  # Skip empty lines
        # Skip comment lines
        match = COMMENT_LINE_MATCH.match(line)
        if (match is not None):
            continue
        # Merge lines with continuations
        if fixed_format:
            if line_ind < len(file_str):
                next_line = file_str[line_ind]
                line_ind += 1
                cont_match = CONT_REGEX.match(next_line)
                while (cont_match is not None and (line_ind < len(file_str))):
                    line = line.rstrip() + next_line[6:].strip()
                    next_line_num += 1
                    next_line = file_str[line_ind]
                    line_ind += 1
                    cont_match = CONT_REGEX.match(next_line)
        else:
            iAmper = line.find('&')
            iComm = line.find('!')
            if iComm < 0:
                iComm = iAmper + 1
            while (iAmper >= 0 and iAmper < iComm):
                split_line = line.split('&')
                next_line = file_str[line_ind]
                line_ind += 1
                if next_line == '':
                    break  # Next line is empty
                    # at_eof = True
                    # break # Reached end of file
                # Skip comment lines
                match = COMMENT_LINE_MATCH.match(next_line)
                if (match is not None):
                    continue
                cont_match = CONT_REGEX.match(next_line)
                if cont_match is not None:
                    next_line = next_line[cont_match.end(0):]
                next_line_num += 1
                line = split_line[0].rstrip() + ' ' + next_line.strip()
                iAmper = line.find('&')
                iComm = line.find('!')
                if iComm < 0:
                    iComm = iAmper + 1
            next_line = None
        line = line.rstrip()
        # Test for scope end
        if file_obj.END_REGEX is not None:
            match = file_obj.END_REGEX.match(line)
            if (match is not None):
                file_obj.end_scope(line_number)
                if (debug):
                    print('{1} !!! END scope({0})'.format(
                        line_number, line.strip()))
                continue
            line_no_comment = line.split('!')[0]
            match = END_GEN_REGEX.match(line_no_comment)
            if (match is not None):
                file_obj.end_scope(line_number)
                if (debug):
                    print('{1} !!! END scope({0})'.format(
                        line_number, line.strip()))
                continue
        # Loop through tests
        obj_read = None
        for test in def_tests:
            obj_read = test(line)
            if obj_read is not None:
                break
        #
        if obj_read is not None:
            obj_type = obj_read[0]
            obj = obj_read[1]
            if obj_type == 'var':
                link_name = None
                if obj[0][:3] == 'PRO':
                    if isinstance(file_obj.current_scope, fortran_int):
                        for var_name in obj[2]:
                            file_obj.add_int_member(var_name)
                        if (debug):
                            print(
                                '{1} !!! INTERFACE-PRO statement({0})'.format(
                                    line_number, line.strip()))
                        continue
                    i1 = obj[0].find('(')
                    i2 = obj[0].find(')')
                    if i1 > -1 and i2 > -1:
                        link_name = obj[0][i1 + 1:i2]
                for var_name in obj[2]:
                    if var_name.find('=>') > -1:
                        name_split = var_name.split('=>')
                        name_stripped = name_split[0]
                        link_name = name_split[1].split('(')[0].strip()
                        if link_name.lower() == 'null':
                            link_name = None
                    else:
                        name_stripped = var_name.split('=')[0]
                    var_dim = 0
                    if name_stripped.find('(') > -1:
                        var_dim = get_var_dims(name_stripped)
                    name_stripped = name_stripped.split('(')[0].strip()
                    modifiers = parse_keywords(obj[1])
                    if obj[0][:3] == 'PRO':
                        new_var = fortran_meth(line_number, name_stripped,
                                               obj[0], modifiers,
                                               file_obj.enc_scope_name,
                                               link_name)
                    else:
                        new_var = fortran_obj(line_number, name_stripped,
                                              obj[0], modifiers,
                                              file_obj.enc_scope_name,
                                              link_name)
                    if var_dim > 0:
                        new_var.set_dim(var_dim)
                    file_obj.add_variable(new_var)
                if (debug):
                    print('{1} !!! VARIABLE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'mod':
                new_mod = fortran_module(line_number, obj,
                                         file_obj.enc_scope_name)
                file_obj.add_scope(new_mod, END_MOD_REGEX)
                if (debug):
                    print('{1} !!! MODULE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'prog':
                new_prog = fortran_program(line_number, obj,
                                           file_obj.enc_scope_name)
                file_obj.add_scope(new_prog, END_PROG_REGEX)
                if (debug):
                    print('{1} !!! PROGRAM statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'sub':
                new_sub = fortran_subroutine(line_number, obj[0],
                                             file_obj.enc_scope_name, obj[1])
                file_obj.add_scope(new_sub, END_SUB_REGEX)
                if (debug):
                    print('{1} !!! SUBROUTINE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'fun':
                new_fun = fortran_function(line_number,
                                           obj[0],
                                           file_obj.enc_scope_name,
                                           obj[1],
                                           return_type=obj[2][0],
                                           result_var=obj[2][1])
                file_obj.add_scope(new_fun, END_FUN_REGEX)
                if obj[2][0] is not None:
                    new_obj = fortran_obj(line_number, obj[0], obj[2][0][0],
                                          obj[2][0][1],
                                          file_obj.enc_scope_name, None)
                    file_obj.add_variable(new_obj)
                if (debug):
                    print('{1} !!! FUNCTION statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'typ':
                modifiers = parse_keywords(obj[2])
                new_type = fortran_type(line_number, obj[0], modifiers,
                                        file_obj.enc_scope_name)
                if obj[1] is not None:
                    new_type.set_inherit(obj[1])
                file_obj.add_scope(new_type, END_TYPED_REGEX)
                if (debug):
                    print('{1} !!! TYPE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'int':
                if obj is None:
                    int_counter += 1
                    obj = 'GEN_INT{0}'.format(int_counter)
                new_int = fortran_int(line_number, obj,
                                      file_obj.enc_scope_name)
                file_obj.add_scope(new_int, END_INT_REGEX, True)
                if (debug):
                    print('{1} !!! INTERFACE statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'int_pro':
                if file_obj.current_scope is None:
                    continue
                if not isinstance(file_obj.current_scope, fortran_int):
                    continue
                for name in obj:
                    file_obj.add_int_member(name)
                if (debug):
                    print('{1} !!! INTERFACE-PRO statement({0})'.format(
                        line_number, line.strip()))
            elif obj_type == 'use':
                file_obj.current_scope.add_use(obj[0], line_number, obj[1])
                if (debug):
                    print('{1} !!! USE statement({0})'.format(
                        line_number, line.strip()))
        # Look for visiblity statement
        match = VIS_REGEX.match(line)
        if (match is not None):
            match_lower = match.group(0).lower()
            trailing_line = line[match.end(0):]
            mod_words = WORD_REGEX.findall(trailing_line)
            if len(mod_words) == 0:
                if match_lower == 'private':
                    file_obj.current_scope.set_default_vis(-1)
            else:
                if match_lower == 'private':
                    for word in mod_words:
                        file_obj.add_private(word)
                else:
                    for word in mod_words:
                        file_obj.add_public(word)
            if (debug):
                print('{1} !!! Visiblity statement({0})'.format(
                    line_number, line.strip()))
            continue
    file_obj.close_file()
    return file_obj
def process_file(file_str, close_open_scopes, path=None, fixed_format=False, debug=False):
    #
    if fixed_format:
        COMMENT_LINE_MATCH = FIXED_COMMENT_LINE_MATCH
        CONT_REGEX = FIXED_CONT_REGEX
    else:
        COMMENT_LINE_MATCH = FREE_COMMENT_LINE_MATCH
        CONT_REGEX = FREE_CONT_REGEX
    #
    file_obj = fortran_file(path)
    line_number = 0
    next_line_num = 1
    int_counter = 0
    block_counter = 0
    select_counter = 0
    # at_eof = False
    next_line = None
    line_ind = 0
    while((line_ind < len(file_str)) or (next_line is not None)):
        # Get next line
        if next_line is None:
            line = file_str[line_ind]
            line_ind += 1
        else:
            line = next_line
            next_line = None
        line_number = next_line_num
        next_line_num = line_number + 1
        if line == '':
            continue  # Skip empty lines
        # Skip comment lines
        match = COMMENT_LINE_MATCH.match(line)
        if (match is not None):
            continue
        # Start preproccesor if stmt
        match = PPIF_START_TEST.match(line)
        if (match is not None):
            file_obj.start_ppif(line_number)
            continue
        # End preproccesor if stmt
        match = PPIF_END_TEST.match(line)
        if (match is not None):
            file_obj.end_ppif(line_number)
            continue
        # Merge lines with continuations
        if fixed_format:
            if line_ind < len(file_str):
                next_line = file_str[line_ind]
                line_ind += 1
                cont_match = CONT_REGEX.match(next_line)
                while(cont_match is not None and (line_ind < len(file_str))):
                    line = line.rstrip() + next_line[6:].strip()
                    next_line_num += 1
                    next_line = file_str[line_ind]
                    line_ind += 1
                    cont_match = CONT_REGEX.match(next_line)
        else:
            iAmper = line.find('&')
            iComm = line.find('!')
            if iComm < 0:
                iComm = iAmper + 1
            while (iAmper >= 0 and iAmper < iComm):
                split_line = line.split('&')
                next_line = file_str[line_ind]
                line_ind += 1
                if next_line == '':
                    break  # Next line is empty
                    # at_eof = True
                    # break # Reached end of file
                # Skip comment lines
                match = COMMENT_LINE_MATCH.match(next_line)
                if (match is not None):
                    continue
                cont_match = CONT_REGEX.match(next_line)
                if cont_match is not None:
                    next_line = next_line[cont_match.end(0):]
                next_line_num += 1
                line = split_line[0].rstrip() + ' ' + next_line.strip()
                iAmper = line.find('&')
                iComm = line.find('!')
                if iComm < 0:
                    iComm = iAmper + 1
            next_line = None
        line = line.rstrip()
        # Test for scope end
        if file_obj.END_REGEX is not None:
            match = file_obj.END_REGEX.match(line)
            if (match is not None):
                if (file_obj.current_scope.get_type() == 9) and (file_obj.current_scope.type in (3, 4)):
                    file_obj.end_scope(line_number)
                file_obj.end_scope(line_number)
                if(debug):
                    print('{1} !!! END scope({0})'.format(line_number, line.strip()))
                continue
            line_no_comment = line.split('!')[0]
            match = END_GEN_REGEX.match(line_no_comment)
            if (match is not None):
                file_obj.end_scope(line_number)
                if(debug):
                    print('{1} !!! END scope({0})'.format(line_number, line.strip()))
                continue
        # Loop through tests
        obj_read = None
        for test in def_tests:
            obj_read = test(line)
            if obj_read is not None:
                break
        #
        if obj_read is not None:
            obj_type = obj_read[0]
            obj = obj_read[1]
            if obj_type == 'var':
                if obj[2] is None:
                    continue
                link_name = None
                if obj[0][:3] == 'PRO':
                    if isinstance(file_obj.current_scope, fortran_int):
                        for var_name in obj[2]:
                            file_obj.add_int_member(var_name)
                        if(debug):
                            print('{1} !!! INTERFACE-PRO statement({0})'.format(line_number, line.strip()))
                        continue
                    i1 = obj[0].find('(')
                    i2 = obj[0].find(')')
                    if i1 > -1 and i2 > -1:
                        link_name = obj[0][i1+1:i2]
                for var_name in obj[2]:
                    link_name = None
                    if var_name.find('=>') > -1:
                        name_split = var_name.split('=>')
                        name_stripped = name_split[0]
                        link_name = name_split[1].split('(')[0].strip()
                        if link_name.lower() == 'null':
                            link_name = None
                    else:
                        name_stripped = var_name.split('=')[0]
                    var_dim_str = None
                    if name_stripped.find('(') > -1:
                        var_dim_str = get_var_dims(name_stripped)
                    name_stripped = name_stripped.split('(')[0].strip()
                    modifiers, dim_str, pass_name = map_keywords(obj[1])
                    if obj[0][:3] == 'PRO':
                        new_var = fortran_meth(file_obj, line_number, name_stripped, obj[0],
                                               modifiers, file_obj.enc_scope_name, link_name,
                                               pass_name=pass_name)
                    else:
                        new_var = fortran_obj(file_obj, line_number, name_stripped, obj[0],
                                              modifiers, dim_str, file_obj.enc_scope_name, link_name)
                    if var_dim_str is not None:
                        new_var.set_dim(var_dim_str)
                    file_obj.add_variable(new_var)
                if(debug):
                    print('{1} !!! VARIABLE statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'mod':
                new_mod = fortran_module(file_obj, line_number, obj, file_obj.enc_scope_name)
                file_obj.add_scope(new_mod, END_MOD_REGEX)
                if(debug):
                    print('{1} !!! MODULE statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'smod':
                new_smod = fortran_submodule(file_obj, line_number, obj[0], file_obj.enc_scope_name, obj[1])
                file_obj.add_scope(new_smod, END_SMOD_REGEX)
                if(debug):
                    print('{1} !!! SUBMODULE statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'prog':
                new_prog = fortran_program(file_obj, line_number, obj, file_obj.enc_scope_name)
                file_obj.add_scope(new_prog, END_PROG_REGEX)
                if(debug):
                    print('{1} !!! PROGRAM statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'sub':
                new_sub = fortran_subroutine(file_obj, line_number, obj[0], file_obj.enc_scope_name, obj[1], obj[2])
                file_obj.add_scope(new_sub, END_SUB_REGEX)
                if(debug):
                    print('{1} !!! SUBROUTINE statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'fun':
                new_fun = fortran_function(file_obj, line_number, obj[0], file_obj.enc_scope_name,
                                           obj[1], obj[3], return_type=obj[2][0], result_var=obj[2][1])
                file_obj.add_scope(new_fun, END_FUN_REGEX)
                if obj[2][0] is not None:
                    new_obj = fortran_obj(file_obj, line_number, obj[0], obj[2][0][0], obj[2][0][1],
                                          file_obj.enc_scope_name, None)
                    file_obj.add_variable(new_obj)
                if(debug):
                    print('{1} !!! FUNCTION statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'block':
                name = obj[0]
                if name is None:
                    block_counter += 1
                    name = '#BLOCK{0}'.format(block_counter)
                new_block = fortran_block(file_obj, line_number, name, file_obj.enc_scope_name)
                file_obj.add_scope(new_block, END_BLOCK_REGEX, req_container=True)
                if(debug):
                    print('{1} !!! BLOCK statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'select':
                select_counter += 1
                name = '#SELECT{0}'.format(select_counter)
                binding_name = None
                bound_var = None
                if file_obj.current_scope is not None:
                    if (obj[0] in (3, 4)) and (file_obj.current_scope.get_type() == 9):
                        if file_obj.current_scope.type in (3, 4):
                            file_obj.end_scope(line_number)
                if file_obj.current_scope is not None:
                    if (obj[0] in (3, 4)) and (file_obj.current_scope.get_type() == 9):
                        if file_obj.current_scope.type == 2:
                            binding_name = file_obj.current_scope.binding_name
                            bound_var = file_obj.current_scope.bound_var
                new_select = fortran_select(file_obj, line_number, name, obj, file_obj.enc_scope_name)
                file_obj.add_scope(new_select, END_SELECT_REGEX, req_container=True)
                if binding_name is not None:
                    if obj[0] != 4:
                        bound_var = None
                    new_var = fortran_obj(file_obj, line_number, binding_name,
                                          '{0}({1})'.format(obj[2], obj[1]), [], file_obj.enc_scope_name,
                                          link_obj=bound_var)
                    file_obj.add_variable(new_var)
                elif (binding_name is None) and (bound_var is not None):
                    new_var = fortran_obj(file_obj, line_number, bound_var,
                                          '{0}({1})'.format(obj[2], obj[1]), [], file_obj.enc_scope_name)
                    file_obj.add_variable(new_var)
                if(debug):
                    print('{1} !!! SELECT statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'typ':
                modifiers, _, _ = map_keywords(obj[2])
                new_type = fortran_type(file_obj, line_number, obj[0], modifiers, file_obj.enc_scope_name)
                if obj[1] is not None:
                    new_type.set_inherit(obj[1])
                file_obj.add_scope(new_type, END_TYPED_REGEX, req_container=True)
                if(debug):
                    print('{1} !!! TYPE statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'int':
                abstract = obj[1]
                name = obj[0]
                if name is None:
                    int_counter += 1
                    name = '#GEN_INT{0}'.format(int_counter)
                new_int = fortran_int(file_obj, line_number, name, file_obj.enc_scope_name, abstract)
                file_obj.add_scope(new_int, END_INT_REGEX, req_container=True)
                if(debug):
                    print('{1} !!! INTERFACE statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'int_pro':
                if file_obj.current_scope is None:
                    continue
                if not isinstance(file_obj.current_scope, fortran_int):
                    continue
                for name in obj:
                    file_obj.add_int_member(name)
                if(debug):
                    print('{1} !!! INTERFACE-PRO statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'use':
                file_obj.add_use(obj[0], line_number, obj[1])
                if(debug):
                    print('{1} !!! USE statement({0})'.format(line_number, line.strip()))
            elif obj_type == 'inc':
                file_obj.add_include(obj[0], line_number)
                if(debug):
                    print('{1} !!! INCLUDE statement({0})'.format(line_number, line.strip()))
        # Look for visiblity statement
        match = VIS_REGEX.match(line)
        if (match is not None):
            match_lower = match.group(0).lower()
            trailing_line = line[match.end(0):]
            mod_words = WORD_REGEX.findall(trailing_line)
            if len(mod_words) == 0:
                if match_lower == 'private':
                    file_obj.current_scope.set_default_vis(-1)
            else:
                if match_lower == 'private':
                    for word in mod_words:
                        file_obj.add_private(word)
                else:
                    for word in mod_words:
                        file_obj.add_public(word)
            if(debug):
                print('{1} !!! Visiblity statement({0})'.format(line_number, line.strip()))
            continue
    file_obj.close_file(line_number)
    return file_obj