def get_reader(input, isfree=None, isstrict=None, include_dirs = None, source_only = None, ignore_comments = True): """ Returns Fortran reader instance. Parameters ---------- input : str Specify a string or filename containing Fortran code. isfree, isstrict : {None, bool} Specify input Fortran format. The values are determined from the input. If that fails then isfree=True and isstrict=False is assumed. include_dirs : {None, list} Specify a list of include directories. The default list (when include_dirs=None) contains the current working directory and the directory of ``filename``. source_only : {None, list} Specify a list of Fortran file names that are searched when the ``USE`` statement is encountered. Returns ------- reader : `FortranReader` Notes ----- If ``input`` is a C filename then the functions searches for comment lines starting with ``/*f2py`` and reads following lines as PYF file content until a line ``*/`` is found. See also -------- parse """ import os import re from readfortran import FortranFileReader, FortranStringReader if os.path.isfile(input): name,ext = os.path.splitext(input) if ext.lower() in ['.c']: # get signatures from C file comments starting with `/*f2py` and ending with `*/`. # TODO: improve parser to take line number offset making line numbers in # parser messages correct. f2py_c_comments = re.compile('/[*]\s*f2py\s.*[*]/',re.I | re.M) f = open(filename,'r') c_input = '' for s1 in f2py_c_comments.findall(f.read()): c_input += s1[2:-2].lstrip()[4:] + '\n' f.close() if isfree is None: isfree = True if isstrict is None: isstrict = True return parse(c_input, isfree, isstrict, include_dirs) reader = FortranFileReader(input, include_dirs = include_dirs, source_only = source_only) elif isinstance(input, str): reader = FortranStringReader(input, include_dirs = include_dirs, source_only = source_only) else: raise TypeError,'Expected string or filename input but got %s' % (type(input)) if isfree is None: isfree = reader.isfree if isstrict is None: isstrict = reader.isstrict reader.set_mode(isfree, isstrict) return reader
def test_free90(): string = """ module foo subroutine bar real r if ( pc_get_lun() .ne. 6) & write ( pc_get_lun(), '( & & /, a, /, " p=", i4, " stopping c_flag=", a, & & /, " print unit=", i8)') & trim(title), pcpsx_i_pel(), trim(c_flag), pc_get_lun() if (.true.) then call smth end if aaa : if (.false.) then else if (a) then aaa else aaa end if aaa hey = 1 end subroutine bar abstract interface end interface end module foo """ reader = FortranStringReader(string, True, False) parser = FortranParser(reader) block = parser.parse() print block
def get_reader(input, isfree=None, isstrict=None, include_dirs=None): import os import re from readfortran import FortranFileReader, FortranStringReader from parsefortran import FortranParser if os.path.isfile(input): name, ext = os.path.splitext(input) if ext.lower() in ['.c']: # get signatures from C file comments starting with `/*f2py` and ending with `*/`. # TODO: improve parser to take line number offset making line numbers in # parser messages correct. f2py_c_comments = re.compile('/[*]\s*f2py\s.*[*]/', re.I | re.M) f = open(filename, 'r') c_input = '' for s1 in f2py_c_comments.findall(f.read()): c_input += s1[2:-2].lstrip()[4:] + '\n' f.close() if isfree is None: isfree = True if isstrict is None: isstrict = True return parse(c_input, isfree, isstrict, include_dirs) reader = FortranFileReader(input, include_dirs=include_dirs) if isfree is None: isfree = reader.isfree if isstrict is None: isstrict = reader.isstrict reader.set_mode(isfree, isstrict) elif isinstance(input, str): if isfree is None: isfree = True if isstrict is None: isstrict = False reader = FortranStringReader(input, isfree, isstrict, include_dirs=include_dirs) else: raise TypeError, 'Expected string or filename input but got %s' % ( type(input)) return reader
def parse(cls, line, label="", isfree=True, isstrict=False): if label: line = label + " : " + line reader = FortranStringReader(line, isfree, isstrict) item = reader.next() if not cls.match(item.get_line()): raise ValueError, "%r does not match %s pattern" % (line, cls.__name__) stmt = cls(item, item) if stmt.isvalid: r = str(stmt) if not isstrict: r1 = parse(cls, r, isstrict=True) if r != r1: raise ValueError, "Failed to parse %r with %s pattern in pyf mode, got %r" % (r, cls.__name__, r1) return r raise ValueError, "parsing %r with %s pattern failed" % (line, cls.__name__)
def parse(cls, line, label='', isfree=True, isstrict=False): if label: line = label + ' : ' + line reader = FortranStringReader(line, isfree, isstrict) item = reader.next() if not cls.match(item.get_line()): raise ValueError, '%r does not match %s pattern' % (line, cls.__name__) stmt = cls(item, item) if stmt.isvalid: r = str(stmt) if not isstrict: r1 = parse(cls, r, isstrict=True) if r != r1: raise ValueError, 'Failed to parse %r with %s pattern in pyf mode, got %r' % (r, cls.__name__, r1) return r raise ValueError, 'parsing %r with %s pattern failed' % (line, cls.__name__)
def str2stmt(string, isfree=True, isstrict=False): """ Convert Fortran code to Statement tree. """ from readfortran import Line, FortranStringReader from parsefortran import FortranParser reader = FortranStringReader(string, isfree, isstrict) parser = FortranParser(reader) parser.parse() parser.analyze() block = parser.block while len(block.content) == 1: block = block.content[0] return block
def test_pyf(): string = """ python module foo interface tere subroutine bar real r end subroutine bar end interface tere end python module foo """ reader = FortranStringReader(string, True, True) parser = FortranParser(reader) block = parser.parse() print block
def test_f77(): string = """\ program foo a = 3 end subroutine bar end pure function foo(a) end pure real*4 recursive function bar() end """ reader = FortranStringReader(string, False, True) parser = FortranParser(reader) block = parser.parse() print block