def test_get_type_by_name(monkeypatch): ''' Tests for HasImplicitStmt.get_type_by_name(). ''' from fparser.common.utils import AnalyzeError from fparser.common.readfortran import FortranStringReader from fparser.common.sourceinfo import FortranFormat from fparser.one.typedecl_statements import Real, Integer from fparser.one.parsefortran import FortranParser # We can't just create a HasImplicitStmt object so we get the parser # to create a module object as that sub-classes HasImplicitStmt (amongst # other things). string = '''\ module some_block end module some_block ''' reader = FortranStringReader(string) reader.set_format(FortranFormat(True, False)) parser = FortranParser(reader) parser.parse() mod = parser.block.content[0] # Now we have a Module object, we can call get_type_by_name()... rtype = mod.get_type_by_name("a_real") assert isinstance(rtype, Real) itype = mod.get_type_by_name("i_int") assert isinstance(itype, Integer) # Check that we raise the correct error if we don't have any implicit # rules set monkeypatch.setattr(mod.a, "implicit_rules", None) with pytest.raises(AnalyzeError) as err: _ = mod.get_type_by_name("i_int") assert "Implicit rules mapping is null" in str(err)
def test_get_type_by_name_implicit(): ''' Tests for HasImplicitStmt.get_type_by_name() when the source code contains IMPLICIT statements. ''' from fparser.common.readfortran import FortranStringReader from fparser.common.sourceinfo import FortranFormat from fparser.one.typedecl_statements import Real, Integer from fparser.one.parsefortran import FortranParser # We can't just create a HasImplicitStmt object so we get the parser # to create a module object as that sub-classes HasImplicitStmt (amongst # other things). string = '''\ module some_block implicit real (a-e) implicit integer (f-z) end module some_block ''' reader = FortranStringReader(string) reader.set_format(FortranFormat(True, False)) parser = FortranParser(reader) parser.parse() # Get the module object mod = parser.block.content[0] # We have to run the analyze method on the Implicit objects # produced by the parser in order to populate the implicit_rules # of the module. mod.content[0].analyze() mod.content[1].analyze() # Now we can call get_type_by_name()... rtype = mod.get_type_by_name("a_real") assert isinstance(rtype, Real) itype = mod.get_type_by_name("f_int") assert isinstance(itype, Integer)
def test_implicit_topyf(monkeypatch): ''' Tests for the topyf() method of HasImplicitStmt. ''' from fparser.common.readfortran import FortranStringReader from fparser.common.sourceinfo import FortranFormat from fparser.one.parsefortran import FortranParser # We can't just create a HasImplicitStmt object so we get the parser # to create a module object as that sub-classes HasImplicitStmt (amongst # other things). string = '''\ module some_block implicit real (a-e) implicit integer (f-z) end module some_block ''' reader = FortranStringReader(string) reader.set_format(FortranFormat(True, False)) parser = FortranParser(reader) parser.parse() # Get the module object mod = parser.block.content[0] code = mod.topyf() assert "! default IMPLICIT rules apply" in code mod.content[0].analyze() mod.content[1].analyze() code = mod.topyf() assert "REAL (a, b, c, d, e)" in code assert "INTEGER (f, g, h" in code monkeypatch.setattr(mod.a, "implicit_rules", None) code = mod.topyf() assert "IMPLICIT NONE" in code
def parse(source, isfree=None, isstrict=None, include_dirs=None, source_only=None, ignore_comments=True, analyze=True, clear_cache=True): """ Parse input and return Statement tree. Raises an AnalyzeError if the parser can not parse the Fortran code. :param str source: Specify a string or filename containing Fortran code. :param bool isfree: Whether the Fortran source is free-format. :param bool isstrict: Whether we are to strictly enforce the `isfree` setting. :param list include_dirs: Specify a list of include directories. The default list (when include_dirs=None) contains the current working directory and the directory of ``filename``. :param list source_only: A list of Fortran file names that are searched when the ``USE`` statement is encountered. :param bool ignore_comments: When True then discard all comment lines in the Fortran code. :param bool analyze: When True then apply analyze() method on the Fortran code tree. :param bool clear_cache: Whether or not to wipe the parser cache prior to parsing. Necessary when a new tree object is required, even if the Fortran to be parsed has been seen before. :returns: Abstract Syntax Tree of Fortran source. :rtype: :py:class:`fparser.api.BeginSource` """ from fparser.one.parsefortran import FortranParser if clear_cache: # Wipe the parser cache if requested FortranParser.cache.clear() reader = get_reader(source, isfree, isstrict, include_dirs, source_only, ignore_comments=ignore_comments) parser = FortranParser(reader, ignore_comments=ignore_comments) try: parser.parse() except AnalyzeError: raise if analyze: parser.analyze() return parser.block
def test_analyze_errors(): ''' Tests that AnalyzeErrors are raised as expected. It also tests for various calling-sequence issues, e.g. parsing or analyzing twice, or calling analyze() without calling parse() first.''' from fparser import api source_str = """none subroutine test() end """ with pytest.raises(AnalyzeError) as error: _ = api.parse(source_str, isfree=True, isstrict=False) assert "no parse pattern found" in str(error.value) source_str = """subroutine test() incorrect :: c end """ with pytest.raises(AnalyzeError) as error: _ = api.parse(source_str, isfree=False, isstrict=False) assert "no parse pattern found" in str(error.value) source_str = """subroutine test() end """ from fparser.one.parsefortran import FortranParser reader = api.get_reader(source_str) parser = FortranParser(reader) # Handle analyze before parsing (does not raise an exception atm) parser.analyze() # Cover case that parsing is called twice parser.parse() parser.parse() # Check if analyse is called twice parser.analyze() parser.analyze()
def test_do(name, label, control_comma, terminal_expression, end_name, end_label): # pylint: disable=redefined-outer-name, too-many-arguments, too-many-locals ''' Checks that the "do" loop parser understands the "for-next" variant of the syntax. This is defined in BS ISO/IEC 1539-1:2010 with R814-R822. TODO: Only the terminal expression is tested. This is a short-cut and relies on expression handling being applied identically across all expressions. This was true at the time of writing the test. ''' name_snippet = name + ': ' if name else None label_snippet = label + ' ' if label else None comma_snippet = ', ' if control_comma else None # TODO: Although the Fortran standard allows for "continue" to be used in # place of "end do" fparser does not support it. end_snippet = 'continue' if end_name == 'continue' \ else get_end_do(end_name) do_code = '''{name}do {label}{comma}variable = 1, {term}, 1 write (6, '(I0)') variable {endlabel} {end} '''.format(name=name_snippet or '', label=label_snippet or '', comma=comma_snippet or '', term=terminal_expression, endlabel=end_label or '', end=end_snippet) do_expected = ''' {name}DO {label}variable = 1, {term}, 1 WRITE (6, '(I0)') variable {endlabel} {endstmt} '''.format(name=name_snippet or '', label=label_snippet or '', term=terminal_expression, endlabel=end_label or ' ', endstmt=get_end_do(end_name)) do_reader = FortranStringReader(do_code) do_reader.set_format(FortranFormat(True, False)) do_parser = FortranParser(do_reader) if (name != end_name) or (label and (label != end_label)): with pytest.raises(AnalyzeError): do_parser.parse() else: do_parser.parse() loop = do_parser.block.content[0] assert str(loop).splitlines() == do_expected.splitlines()
def runner(parser, options, args): from fparser.common.readfortran import FortranFileReader from fparser.one.parsefortran import FortranParser for filename in args: reader = FortranFileReader(filename) if options.mode != 'auto': mode = fparser.common.sourceinfo\ .FortranFormat.from_mode(options.mode) reader.format.set_mode(mode) parser = FortranParser(reader) parser.parse() parser.analyze() if options.task == 'show': print(parser.block.torepr(4)) elif options.task == 'none': pass else: raise NotImplementedError(repr(options.task))
def test_do_while(name, label, control_comma, terminal_expression, end_name, end_label): # pylint: disable=redefined-outer-name, too-many-arguments ''' Checks that the "do" loop parser understands the "do-while" variant of the syntax. This is defined in BS ISO/IEC 1539-1:2010 with R814-R822. ''' name_snippet = name + ': ' if name else None label_snippet = label + ' ' if label else None comma_snippet = ', ' if control_comma else None code = '''{name}do {label}{comma}while ({term}) write (6, '(I0)') variable {endlabel} {endstmt} '''.format(name=name_snippet or '', label=label_snippet or '', comma=comma_snippet or '', term=terminal_expression, endlabel=end_label or '', endstmt=get_end_do(end_name)) expected = ''' {name}DO {label}while ({term}) WRITE (6, '(I0)') variable {endlabel} {endstmt} '''.format(name=name_snippet or '', label=label_snippet or '', term=terminal_expression, endlabel=end_label or ' ', endstmt=get_end_do(end_name)) print(code) reader = FortranStringReader(code) reader.set_format(FortranFormat(True, False)) parser = FortranParser(reader) if (name != end_name) or (label and (label != end_label)): with pytest.raises(AnalyzeError): parser.parse() else: parser.parse() loop = parser.block.content[0] assert str(loop).splitlines() == expected.splitlines()
if not os.path.exists(directory_path+"/instrumented"): os.makedirs(directory_path+"/instrumented") f=open(file_name) f2 = open(directory_path+"/instrumented/"+source_name, "w") line_num=1 for line in f: if (line_num in start_line_nums): f2.write("call DLKHunter_startEventEpoch()\n") f2.write(line) if (line_num in end_line_nums): f2.write("call DLKHunter_stopEventEpoch(__FILE__, __LINE__)\n") if (line_num == import_line): f2.write("use dlkhunter_mod\n") line_num+=1 f.close() f2.close() file_name=sys.argv[1] file_ending=file_name.split(".")[1].strip() free_form = file_ending != "f" reader=FortranFileReader(file_name) reader.set_format(FortranFormat(free_form, False)) parser = FortranParser(reader) parser.parse() parser.analyze() parseForFunctionSubroutineNames(parser.block) parse(parser.block) start_line_nums, end_line_nums=processIdentifiedLoopsForInstrumentation(all_loops, True) createInstrumentedFile(file_name, start_line_nums, end_line_nums)