summaryrefslogtreecommitdiff
path: root/numpy/f2py/lib
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/f2py/lib')
-rw-r--r--numpy/f2py/lib/__init__.py14
-rw-r--r--numpy/f2py/lib/api.py14
-rw-r--r--numpy/f2py/lib/main.py534
-rw-r--r--numpy/f2py/lib/nary.py32
-rw-r--r--numpy/f2py/lib/parser/Fortran2003.py5889
-rw-r--r--numpy/f2py/lib/parser/__init__.py14
-rw-r--r--numpy/f2py/lib/parser/api.py73
-rw-r--r--numpy/f2py/lib/parser/base_classes.py819
-rw-r--r--numpy/f2py/lib/parser/block_statements.py1229
-rw-r--r--numpy/f2py/lib/parser/doc.txt365
-rw-r--r--numpy/f2py/lib/parser/parsefortran.py197
-rw-r--r--numpy/f2py/lib/parser/pattern_tools.py401
-rw-r--r--numpy/f2py/lib/parser/readfortran.py857
-rw-r--r--numpy/f2py/lib/parser/sourceinfo.py81
-rw-r--r--numpy/f2py/lib/parser/splitline.py426
-rw-r--r--numpy/f2py/lib/parser/statements.py1856
-rw-r--r--numpy/f2py/lib/parser/test_Fortran2003.py2101
-rw-r--r--numpy/f2py/lib/parser/test_parser.py496
-rw-r--r--numpy/f2py/lib/parser/typedecl_statements.py563
-rw-r--r--numpy/f2py/lib/parser/utils.py177
-rw-r--r--numpy/f2py/lib/py_wrap.py128
-rw-r--r--numpy/f2py/lib/py_wrap_subprogram.py210
-rw-r--r--numpy/f2py/lib/py_wrap_type.py753
-rw-r--r--numpy/f2py/lib/setup.py12
-rw-r--r--numpy/f2py/lib/src/F_FUNC.cpp34
-rw-r--r--numpy/f2py/lib/src/pyobj_to_string_len.c11
-rw-r--r--numpy/f2py/lib/tests/test_derived_scalar.py74
-rw-r--r--numpy/f2py/lib/tests/test_module_module.py61
-rw-r--r--numpy/f2py/lib/tests/test_module_scalar.py58
-rw-r--r--numpy/f2py/lib/tests/test_scalar_function_in.py532
-rw-r--r--numpy/f2py/lib/tests/test_scalar_in_out.py529
-rw-r--r--numpy/f2py/lib/wrapper_base.py178
32 files changed, 18718 insertions, 0 deletions
diff --git a/numpy/f2py/lib/__init__.py b/numpy/f2py/lib/__init__.py
new file mode 100644
index 000000000..c3b40cb76
--- /dev/null
+++ b/numpy/f2py/lib/__init__.py
@@ -0,0 +1,14 @@
+"""
+F2PY G3 --- The third generation of Fortran to Python Interface Generator.
+
+Use api module for importing public symbols.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
diff --git a/numpy/f2py/lib/api.py b/numpy/f2py/lib/api.py
new file mode 100644
index 000000000..0d21da28c
--- /dev/null
+++ b/numpy/f2py/lib/api.py
@@ -0,0 +1,14 @@
+"""
+Public API for F2PY G3.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+from main import main
diff --git a/numpy/f2py/lib/main.py b/numpy/f2py/lib/main.py
new file mode 100644
index 000000000..6c2e1415e
--- /dev/null
+++ b/numpy/f2py/lib/main.py
@@ -0,0 +1,534 @@
+"""
+Tools for building F2PY generated extension modules.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import os
+import re
+import sys
+import tempfile
+
+try:
+ from numpy import __version__ as numpy_version
+except ImportError:
+ numpy_version = 'N/A'
+
+__all__ = ['main', 'compile']
+
+__usage__ = """
+F2PY G3 --- The third generation of Fortran to Python Interface Generator
+=========================================================================
+
+Description
+-----------
+
+f2py program generates a Python C/API file (<modulename>module.c) that
+contains wrappers for given Fortran functions and data so that they
+can be accessed from Python. With the -c option the corresponding
+extension modules are built.
+
+Options
+-------
+
+ --g3-numpy Use numpy.f2py.lib tool, the 3rd generation of F2PY,
+ with NumPy support.
+ --2d-numpy Use numpy.f2py tool with NumPy support. [DEFAULT]
+ --2d-numeric Use f2py2e tool with Numeric support.
+ --2d-numarray Use f2py2e tool with Numarray support.
+
+ -m <modulename> Name of the module; f2py generates a Python/C API
+ file <modulename>module.c or extension module <modulename>.
+ For wrapping Fortran 90 modules, f2py will use Fortran
+ module names.
+ --parse Parse Fortran files and print result to stdout.
+
+
+Options effective only with -h
+------------------------------
+
+ -h <filename> Write signatures of the fortran routines to file <filename>
+ and exit. You can then edit <filename> and use it instead
+ of <fortran files> for generating extension module source.
+ If <filename> is stdout or stderr then the signatures are
+ printed to the corresponding stream.
+
+ --overwrite-signature Overwrite existing signature file.
+
+Options effective only with -c
+------------------------------
+
+ -c Compile fortran sources and build extension module.
+
+ --build-dir <dirname> All f2py generated files are created in <dirname>.
+ Default is tempfile.mktemp() and it will be removed after
+ f2py stops unless <dirname> is specified via --build-dir
+ option.
+
+numpy.distutils options effective only with -c
+----------------------------------------------
+
+ --fcompiler=<name> Specify Fortran compiler type by vendor
+
+
+
+Extra options effective only with -c
+------------------------------------
+
+ -L/path/to/lib/ -l<libname>
+ -D<name[=define]> -U<name>
+ -I/path/to/include/
+ <filename>.o <filename>.(so|dynlib|dll) <filename>.a
+
+ Using the following macros may be required with non-gcc Fortran
+ compilers:
+ -DPREPEND_FORTRAN -DNO_APPEND_FORTRAN -DUPPERCASE_FORTRAN
+ -DUNDERSCORE_G77
+
+ -DF2PY_DEBUG_PYOBJ_TOFROM --- pyobj_(to|from)_<ctype> functions will
+ print debugging messages to stderr.
+
+"""
+
+import re
+import shutil
+import parser.api
+from parser.api import parse, PythonModule, EndStatement, Module, Subroutine, Function,\
+ get_reader
+
+def get_values(sys_argv, prefix='', suffix='', strip_prefix=False, strip_suffix=False):
+ """
+ Return a list of values with pattern
+ <prefix><value><suffix>.
+ The corresponding items will be removed from sys_argv.
+ """
+ match = re.compile(prefix + r'.*' + suffix + '\Z').match
+ ret = [item for item in sys_argv if match(item)]
+ [sys_argv.remove(item) for item in ret]
+ if strip_prefix and prefix:
+ i = len(prefix)
+ ret = [item[i:] for item in ret]
+ if strip_suffix and suffix:
+ i = len(suffix)
+ ret = [item[:-i] for item in ret]
+ return ret
+
+def get_option(sys_argv, option, default_return = None):
+ """
+ Return True if sys_argv has <option>.
+ If <option> is not in sys_argv, return default_return.
+ <option> (when present) will be removed from sys_argv.
+ """
+ try:
+ i = sys_argv.index(option)
+ except ValueError:
+ return default_return
+ del sys_argv[i]
+ return True
+
+def get_option_value(sys_argv, option, default_value = None, default_return = None):
+ """
+ Return <value> from
+ sys_argv = [...,<option>,<value>,...]
+ list.
+ If <option> is the last element, return default_value.
+ If <option> is not in sys_argv, return default_return.
+ Both <option> and <value> (when present) will be removed from sys_argv.
+ """
+ try:
+ i = sys_argv.index(option)
+ except ValueError:
+ return default_return
+ if len(sys_argv)-1==i:
+ del sys_argv[i]
+ return default_value
+ value = sys_argv[i+1]
+ del sys_argv[i+1]
+ del sys_argv[i]
+ return value
+
+def get_signature_output(sys_argv):
+ return get_option_value(sys_argv,'-h','stdout')
+
+
+def parse_files(sys_argv):
+ flag = 'file'
+ file_names = []
+ only_names = []
+ skip_names = []
+ options = []
+ for word in sys_argv:
+ if word=='': pass
+ elif word=='only:': flag = 'only'
+ elif word=='skip:': flag = 'skip'
+ elif word==':': flag = 'file'
+ elif word.startswith('--'): options.append(word)
+ else:
+ {'file': file_names,'only': only_names, 'skip': skip_names}[flag].append(word)
+
+ if options:
+ sys.stderr.write('Unused options: %s\n' % (', '.join(options)))
+ for filename in file_names:
+ if not os.path.isfile(filename):
+ sys.stderr.write('No or not a file %r. Skipping.\n' % (filename))
+ continue
+ sys.stderr.write('Parsing %r..\n' % (filename))
+ reader = parser.api.get_reader(filename)
+ print parser.api.Fortran2003.Program(reader)
+ return
+
+def dump_signature(sys_argv):
+ """ Read Fortran files and dump the signatures to file or stdout.
+ XXX: Not well tested.
+ """
+ signature_output = get_signature_output(sys_argv)
+
+ # initialize output stream
+ if signature_output in ['stdout','stderr']:
+ output_stream = getattr(sys, signature_output)
+ modulename = get_option_value(sys_argv,'-m','untitled','unknown')
+ else:
+ name,ext = os.path.splitext(signature_output)
+ if ext != '.pyf':
+ signature_output += '.pyf'
+ if os.path.isfile(signature_output):
+ overwrite = get_option(sys_argv, '--overwrite-signature', False)
+ if not overwrite:
+ print >> sys.stderr, 'Signature file %r exists. '\
+ 'Use --overwrite-signature to overwrite.' % (signature_output)
+ sys.exit()
+ modulename = get_option_value(sys_argv,'-m',os.path.basename(name),
+ os.path.basename(name))
+ output_stream = open(signature_output,'w')
+
+ flag = 'file'
+ file_names = []
+ only_names = []
+ skip_names = []
+ options = []
+ for word in sys_argv:
+ if word=='': pass
+ elif word=='only:': flag = 'only'
+ elif word=='skip:': flag = 'skip'
+ elif word==':': flag = 'file'
+ elif word.startswith('--'): options.append(word)
+ else:
+ {'file': file_names,'only': only_names,
+ 'skip': skip_names}[flag].append(word)
+
+ if options:
+ sys.stderr.write('Unused options: %s\n' % (', '.join(options)))
+
+ output_stream.write('''! -*- f90 -*-
+! Note: the context of this file is case sensitive.
+''')
+ output_stream.write('PYTHON MODULE %s\n' % (modulename))
+ output_stream.write(' INTERFACE\n\n')
+ for filename in file_names:
+ if not os.path.isfile(filename):
+ sys.stderr.write('No or not a file %r. Skipping.\n' % (filename))
+ continue
+ sys.stderr.write('Parsing %r..\n' % (filename))
+ block = parse(filename)
+ if block is None:
+ sys.exit(1)
+ output_stream.write('! File: %s, source mode = %r\n' % (filename, block.reader.mode))
+ if block.content and isinstance(block.content[0],PythonModule):
+ for subblock in block.content[0].content[0].content:
+ if isinstance(subblock, EndStatement):
+ break
+ output_stream.write(subblock.topyf(' ')+'\n')
+ else:
+ output_stream.write(block.topyf(' ')+'\n')
+ output_stream.write(' END INTERFACE\n')
+ output_stream.write('END PYTHON MODULE %s\n' % (modulename))
+
+ if signature_output not in ['stdout','stderr']:
+ output_stream.close()
+ return
+
+def construct_extension_sources(modulename, parse_files, include_dirs, build_dir):
+ """
+ Construct wrapper sources.
+ """
+ from py_wrap import PythonWrapperModule
+
+ f90_modules = []
+ external_subprograms = []
+ for filename in parse_files:
+ if not os.path.isfile(filename):
+ sys.stderr.write('No or not a file %r. Skipping.\n' % (filename))
+ continue
+ sys.stderr.write('Parsing %r..\n' % (filename))
+ for block in parse(filename, include_dirs=include_dirs).content:
+ if isinstance(block, Module):
+ f90_modules.append(block)
+ elif isinstance(block, (Subroutine, Function)):
+ external_subprograms.append(block)
+ else:
+ sys.stderr.write("Unhandled structure: %r\n" % (block.__class__))
+
+ module_infos = []
+
+ for block in f90_modules:
+ wrapper = PythonWrapperModule(block.name)
+ wrapper.add(block)
+ c_code = wrapper.c_code()
+ f_code = '! -*- f90 -*-\n' + wrapper.fortran_code()
+ c_fn = os.path.join(build_dir,'%smodule.c' % (block.name))
+ f_fn = os.path.join(build_dir,'%s_f_wrappers_f2py.f90' % (block.name))
+ f = open(c_fn,'w')
+ f.write(c_code)
+ f.close()
+ f = open(f_fn,'w')
+ f.write(f_code)
+ f.close()
+ #f_lib = '%s_f_wrappers_f2py' % (block.name)
+ module_info = {'name':block.name, 'c_sources':[c_fn],
+ 'f_sources':[f_fn], 'language':'f90'}
+ module_infos.append(module_info)
+
+ if external_subprograms:
+ wrapper = PythonWrapperModule(modulename)
+ for block in external_subprograms:
+ wrapper.add(block)
+ c_code = wrapper.c_code()
+ f_code = wrapper.fortran_code()
+ c_fn = os.path.join(build_dir,'%smodule.c' % (modulename))
+ ext = '.f'
+ language = 'f77'
+ if wrapper.isf90:
+ f_code = '! -*- f90 -*-\n' + f_code
+ ext = '.f90'
+ language = 'f90'
+ f_fn = os.path.join(build_dir,'%s_f_wrappers_f2py%s' % (modulename, ext))
+ f = open(c_fn,'w')
+ f.write(c_code)
+ f.close()
+ f = open(f_fn,'w')
+ f.write(f_code)
+ f.close()
+ module_info = {'name':modulename, 'c_sources':[c_fn],
+ 'f_sources':[f_fn], 'language':language}
+ module_infos.append(module_info)
+
+ return module_infos
+
+def build_extension(sys_argv, sources_only = False):
+ """
+ Build wrappers to Fortran 90 modules and external subprograms.
+ """
+ modulename = get_option_value(sys_argv,'-m','untitled','unspecified')
+
+ if sources_only:
+ build_dir = get_option_value(sys_argv,'--build-dir','.','')
+ else:
+ build_dir = get_option_value(sys_argv,'--build-dir','.',None)
+ if build_dir is None:
+ build_dir = tempfile.mktemp()
+ clean_build_dir = True
+ else:
+ clean_build_dir = False
+ if build_dir and not os.path.exists(build_dir): os.makedirs(build_dir)
+
+ include_dirs = get_values(sys_argv,'-I',strip_prefix=True)
+ library_dirs = get_values(sys_argv,'-L',strip_prefix=True)
+ libraries = get_values(sys_argv,'-l',strip_prefix=True)
+ _define_macros = get_values(sys_argv,'-D',strip_prefix=True)
+ undef_macros = get_values(sys_argv,'-U',strip_prefix=True)
+ extra_objects = get_values(sys_argv,'','[.](o|a|so|dll|dylib|sl)')
+
+ define_macros = []
+ for item in _define_macros:
+ name_value = item.split('=',1)
+ if len(name_value)==1:
+ name_value.append(None)
+ if len(name_value)==2:
+ define_macros.append(tuple(name_value))
+ else:
+ print 'Invalid use of -D:',name_value
+
+ pyf_files = get_values(sys_argv,'','[.]pyf')
+ fortran_files = get_values(sys_argv,'','[.](f|f90|F90|F)')
+ c_files = get_values(sys_argv,'','[.](c|cpp|C|CPP|c[+][+])')
+
+ fc_flags = get_values(sys_argv,'--fcompiler=')
+
+ options = get_values(sys_argv,'-')
+ if options:
+ sys.stderr.write('Unused options: %s\n' % (', '.join(options)))
+
+ if pyf_files:
+ parse_files = pyf_files
+ else:
+ parse_files = fortran_files + c_files
+
+ module_infos = construct_extension_sources(modulename, parse_files, include_dirs, build_dir)
+
+ if sources_only:
+ return
+
+ def configuration(parent_package='', top_path=None or ''):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('',parent_package,top_path)
+ flibname = modulename + '_fortran_f2py'
+ if fortran_files:
+ config.add_library(flibname,
+ sources = fortran_files)
+ libraries.insert(0,flibname)
+
+ for module_info in module_infos:
+ name = module_info['name']
+ c_sources = module_info['c_sources']
+ f_sources = module_info['f_sources']
+ language = module_info['language']
+ if f_sources:
+ f_lib = '%s_f_wrappers_f2py' % (name)
+ config.add_library(f_lib, sources = f_sources)
+ libs = [f_lib] + libraries
+ else:
+ libs = libraries
+ config.add_extension(name,
+ sources=c_sources + c_files,
+ libraries = libs,
+ define_macros = define_macros,
+ undef_macros = undef_macros,
+ include_dirs = include_dirs,
+ extra_objects = extra_objects,
+ language = language,
+ )
+ return config
+
+ old_sys_argv = sys.argv[:]
+ build_dir_ext_temp = os.path.join(build_dir,'ext_temp')
+ build_dir_clib_temp = os.path.join(build_dir,'clib_temp')
+ build_dir_clib_clib = os.path.join(build_dir,'clib_clib')
+ new_sys_argv = [sys.argv[0]] + ['build_ext',
+ '--build-temp',build_dir_ext_temp,
+ '--build-lib',build_dir,
+ 'build_clib',
+ '--build-temp',build_dir_clib_temp,
+ '--build-clib',build_dir_clib_clib,
+ ]
+ temp_dirs = [build_dir_ext_temp, build_dir_clib_temp, build_dir_clib_clib]
+
+ if fc_flags:
+ new_sys_argv += ['config_fc'] + fc_flags
+ sys.argv[:] = new_sys_argv
+
+ sys.stderr.write('setup arguments: %r\n' % (' '.join(sys.argv)))
+
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
+
+ sys.argv[:] = old_sys_argv
+
+ if 1 or clean_build_dir:
+ for d in temp_dirs:
+ if os.path.exists(d):
+ sys.stderr.write('Removing build directory %s\n'%(d))
+ shutil.rmtree(d)
+ return
+
+def main(sys_argv = None):
+ """ Main function of f2py script.
+ """
+ if sys_argv is None:
+ sys_argv = sys.argv[1:]
+ if '--help-link' in sys_argv:
+ sys_argv.remove('--help-link')
+ from numpy.distutils.system_info import show_all
+ show_all()
+ return
+ if '-c' in sys_argv:
+ sys_argv.remove('-c')
+ build_extension(sys_argv)
+ return
+ if '--parse' in sys_argv:
+ sys_argv.remove('--parse')
+ parse_files(sys_argv)
+ return
+ if '-h' in sys_argv:
+ dump_signature(sys_argv)
+ return
+ if not sys_argv or '--help' in sys_argv:
+ print >> sys.stdout, __usage__
+
+ build_extension(sys_argv, sources_only = True)
+ return
+
+def compile(source,
+ jobname = 'untitled',
+ extra_args = [],
+ source_ext = None,
+ modulenames = None
+ ):
+ """
+ Build extension module from processing source with f2py.
+
+ jobname - the name of compile job. For non-module source
+ this will be also the name of extension module.
+ modulenames - the list of extension module names that
+ the given compilation job should create.
+ extra_args - a list of extra arguments for numpy style
+ setup.py command line.
+ source_ext - extension of the Fortran source file: .f90 or .f
+
+ Extension modules are saved to current working directory.
+ Returns a list of module objects according to modulenames
+ input.
+ """
+ from nary import encode
+ tempdir = tempfile.gettempdir()
+ s = 'f2pyjob_%s_%s' % (jobname, encode(source))
+ tmpdir = os.path.join(tempdir, s)
+ if source_ext is None:
+ reader = get_reader(source)
+ source_ext = {'free90':'.f90','fix90':'.f90','fix77':'.f','pyf':'.pyf'}[reader.mode]
+
+ if modulenames is None:
+ modulenames = jobname,
+ if os.path.isdir(tmpdir):
+ sys.path.insert(0, tmpdir)
+ try:
+ modules = []
+ for modulename in modulenames:
+ exec('import %s as m' % (modulename))
+ modules.append(m)
+ sys.path.pop(0)
+ return modules
+ except ImportError:
+ pass
+ sys.path.pop(0)
+ else:
+ os.mkdir(tmpdir)
+
+ fname = os.path.join(tmpdir,'%s_src%s' % (jobname, source_ext))
+
+ f = open(fname,'w')
+ f.write(source)
+ f.close()
+
+ sys_argv = []
+ sys_argv.extend(['--build-dir',tmpdir])
+ #sys_argv.extend(['-DF2PY_DEBUG_PYOBJ_TOFROM'])
+ sys_argv.extend(['-m',jobname, fname])
+
+ build_extension(sys_argv + extra_args)
+
+ sys.path.insert(0, tmpdir)
+ modules = []
+ for modulename in modulenames:
+ exec('import %s as m' % (modulename))
+ modules.append(m)
+ sys.path.pop(0)
+ return modules
+
+#EOF
diff --git a/numpy/f2py/lib/nary.py b/numpy/f2py/lib/nary.py
new file mode 100644
index 000000000..948672b8c
--- /dev/null
+++ b/numpy/f2py/lib/nary.py
@@ -0,0 +1,32 @@
+"""
+nary - convert integer to a number with an arbitrary base.
+"""
+
+__all__ = ['nary']
+
+_alphabet='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+def _getalpha(r):
+ if r>=len(_alphabet):
+ return '_'+nary(r-len(_alphabet),len(_alphabet))
+ return _alphabet[r]
+
+def nary(number, base=64):
+ """
+ Return string representation of a number with a given base.
+ """
+ if isinstance(number, str):
+ number = eval(number)
+ n = number
+ s = ''
+ while n:
+ n1 = n // base
+ r = n - n1*base
+ n = n1
+ s = _getalpha(r) + s
+ return s
+
+def encode(string):
+ import md5
+ return nary('0x'+md5.new(string).hexdigest())
+
+#print nary(12345124254252525522512324,64)
diff --git a/numpy/f2py/lib/parser/Fortran2003.py b/numpy/f2py/lib/parser/Fortran2003.py
new file mode 100644
index 000000000..bfdb8cbba
--- /dev/null
+++ b/numpy/f2py/lib/parser/Fortran2003.py
@@ -0,0 +1,5889 @@
+#!/usr/bin/env python
+"""
+Fortran 2003 Syntax Rules.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import re
+from splitline import string_replace_map
+import pattern_tools as pattern
+from readfortran import FortranReaderBase
+
+###############################################################################
+############################## BASE CLASSES ###################################
+###############################################################################
+
+class NoMatchError(Exception):
+ pass
+
+class ParseError(Exception):
+ pass
+
+class Base(object):
+ """ Base class for Fortran 2003 syntax rules.
+
+ All Base classes have the following attributes:
+ .string - original argument to construct a class instance, it's type
+ is either str or FortranReaderBase.
+ .item - Line instance (holds label) or None.
+ """
+ subclasses = {}
+
+ def __new__(cls, string, parent_cls = None):
+ """
+ """
+ if parent_cls is None:
+ parent_cls = [cls]
+ elif cls not in parent_cls:
+ parent_cls.append(cls)
+ #print '__new__:',cls.__name__,`string`
+ match = cls.__dict__.get('match', None)
+ if isinstance(string, FortranReaderBase) and not issubclass(cls, BlockBase) \
+ and match is not None:
+ reader = string
+ item = reader.get_item()
+ if item is None: return
+ try:
+ obj = cls(item.line, parent_cls = parent_cls)
+ except NoMatchError:
+ obj = None
+ if obj is None:
+ reader.put_item(item)
+ return
+ obj.item = item
+ return obj
+ errmsg = '%s: %r' % (cls.__name__, string)
+ if match is not None:
+ try:
+ result = cls.match(string)
+ except NoMatchError, msg:
+ if str(msg)==errmsg: # avoid recursion 1.
+ raise
+ result = None
+ else:
+ result = None
+
+ #print '__new__:result:',cls.__name__,`string,result`
+ if isinstance(result, tuple):
+ obj = object.__new__(cls)
+ obj.string = string
+ obj.item = None
+ if hasattr(cls, 'init'): obj.init(*result)
+ return obj
+ elif isinstance(result, Base):
+ return result
+ elif result is None:
+ for subcls in Base.subclasses.get(cls.__name__,[]):
+ if subcls in parent_cls: # avoid recursion 2.
+ continue
+ #print '%s:%s: %r' % (cls.__name__,subcls.__name__,string)
+ try:
+ obj = subcls(string, parent_cls = parent_cls)
+ except NoMatchError, msg:
+ obj = None
+ if obj is not None:
+ return obj
+ else:
+ raise AssertionError,`result`
+ raise NoMatchError,errmsg
+
+## def restore_reader(self):
+## self._item.reader.put_item(self._item)
+## return
+
+ def init(self, *items):
+ self.items = items
+ return
+ def torepr(self):
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,self.items)))
+ def compare(self, other):
+ return cmp(self.items,other.items)
+
+ def __str__(self): return self.tostr()
+
+ def __repr__(self): return self.torepr()
+
+ def __cmp__(self, other):
+ if self is other: return 0
+ if not isinstance(other, self.__class__): return cmp(self.__class__, other.__class__)
+ return self.compare(other)
+
+ def tofortran(self, tab='', isfix=None):
+ return tab + str(self)
+
+
+class BlockBase(Base):
+ """
+ <block-base> = [ <startcls> ]
+ [ <subcls> ]...
+ ...
+ [ <subcls> ]...
+ [ <endcls> ]
+ """
+ def match(startcls, subclasses, endcls, reader):
+ assert isinstance(reader,FortranReaderBase),`reader`
+ content = []
+ if startcls is not None:
+ try:
+ obj = startcls(reader)
+ except NoMatchError:
+ obj = None
+ if obj is None: return
+ content.append(obj)
+ if endcls is not None:
+ classes = subclasses + [endcls]
+ else:
+ classes = subclasses[:]
+ i = 0
+ while 1:
+ cls = classes[i]
+ try:
+ obj = cls(reader)
+ except NoMatchError:
+ obj = None
+ if obj is None:
+ j = i
+ for cls in classes[i+1:]:
+ j += 1
+ try:
+ obj = cls(reader)
+ except NoMatchError:
+ obj = None
+ if obj is not None:
+ break
+ if obj is not None:
+ i = j
+ if obj is not None:
+ content.append(obj)
+ if endcls is not None and isinstance(obj, endcls): break
+ continue
+ if endcls is not None:
+ item = reader.get_item()
+ if item is not None:
+ reader.error('failed to parse with %s, skipping.' % ('|'.join([c.__name__ for c in classes[i:]])), item)
+ continue
+ if hasattr(content[0],'name'):
+ reader.error('unexpected eof file while looking line for <%s> of %s.'\
+ % (classes[-1].__name__.lower().replace('_','-'), content[0].name))
+ else:
+ reader.error('unexpected eof file while looking line for <%s>.'\
+ % (classes[-1].__name__.lower().replace('_','-')))
+ break
+ if not content: return
+ if startcls is not None and endcls is not None:
+ # check names of start and end statements:
+ start_stmt = content[0]
+ end_stmt = content[-1]
+ if isinstance(end_stmt, endcls) and hasattr(end_stmt, 'get_name') and hasattr(start_stmt, 'get_name'):
+ if end_stmt.get_name() is not None:
+ if start_stmt.get_name() != end_stmt.get_name():
+ end_stmt._item.reader.error('expected <%s-name> is %s but got %s. Ignoring.'\
+ % (end_stmt.get_type().lower(), start_stmt.get_name(), end_stmt.get_name()))
+ else:
+ end_stmt.set_name(start_stmt.get_name())
+ return content,
+ match = staticmethod(match)
+
+ def init(self, content):
+ self.content = content
+ return
+ def compare(self, other):
+ return cmp(self.content,other.content)
+
+ def tostr(self):
+ return self.tofortran()
+ def torepr(self):
+ return '%s(%s)' % (self.__class__.__name__,', '.join(map(repr, self.content)))
+
+ def tofortran(self, tab='', isfix=None):
+ l = []
+ start = self.content[0]
+ end = self.content[-1]
+ extra_tab = ''
+ if isinstance(end, EndStmtBase):
+ extra_tab = ' '
+ l.append(start.tofortran(tab=tab,isfix=isfix))
+ for item in self.content[1:-1]:
+ l.append(item.tofortran(tab=tab+extra_tab,isfix=isfix))
+ if len(self.content)>1:
+ l.append(end.tofortran(tab=tab,isfix=isfix))
+ return '\n'.join(l)
+
+## def restore_reader(self):
+## content = self.content[:]
+## content.reverse()
+## for obj in content:
+## obj.restore_reader()
+## return
+
+class SequenceBase(Base):
+ """
+ <sequence-base> = <obj>, <obj> [ , <obj> ]...
+ """
+ def match(separator, subcls, string):
+ line, repmap = string_replace_map(string)
+ if isinstance(separator, str):
+ splitted = line.split(separator)
+ else:
+ splitted = separator[1].split(line)
+ separator = separator[0]
+ if len(splitted)<=1: return
+ lst = []
+ for p in splitted:
+ lst.append(subcls(repmap(p.strip())))
+ return separator, tuple(lst)
+ match = staticmethod(match)
+ def init(self, separator, items):
+ self.separator = separator
+ self.items = items
+ return
+ def tostr(self):
+ s = self.separator
+ if s==',': s = s + ' '
+ elif s==' ': pass
+ else: s = ' ' + s + ' '
+ return s.join(map(str, self.items))
+ def torepr(self): return '%s(%r, %r)' % (self.__class__.__name__, self.separator, self.items)
+ def compare(self, other):
+ return cmp((self.separator,self.items),(other.separator,self.items))
+
+class UnaryOpBase(Base):
+ """
+ <unary-op-base> = <unary-op> <rhs>
+ """
+ def tostr(self):
+ return '%s %s' % tuple(self.items)
+ def match(op_pattern, rhs_cls, string):
+ m = op_pattern.match(string)
+ if not m: return
+ #if not m: return rhs_cls(string)
+ rhs = string[m.end():].lstrip()
+ if not rhs: return
+ op = string[:m.end()].rstrip().upper()
+ return op, rhs_cls(rhs)
+ match = staticmethod(match)
+
+
+class BinaryOpBase(Base):
+ """
+ <binary-op-base> = <lhs> <op> <rhs>
+ <op> is searched from right by default.
+ """
+ def match(lhs_cls, op_pattern, rhs_cls, string, right=True):
+ line, repmap = string_replace_map(string)
+ if isinstance(op_pattern, str):
+ if right:
+ t = line.rsplit(op_pattern,1)
+ else:
+ t = line.split(op_pattern,1)
+ if len(t)!=2: return
+ lhs, rhs = t[0].rstrip(), t[1].lstrip()
+ op = op_pattern
+ else:
+ if right:
+ t = op_pattern.rsplit(line)
+ else:
+ t = op_pattern.lsplit(line)
+ if t is None or len(t)!=3: return
+ lhs, op, rhs = t
+ lhs = lhs.rstrip()
+ rhs = rhs.lstrip()
+ op = op.upper()
+ if not lhs: return
+ if not rhs: return
+ lhs_obj = lhs_cls(repmap(lhs))
+ rhs_obj = rhs_cls(repmap(rhs))
+ return lhs_obj, op, rhs_obj
+ match = staticmethod(match)
+ def tostr(self):
+ return '%s %s %s' % tuple(self.items)
+
+class SeparatorBase(Base):
+ """
+ <separator-base> = [ <lhs> ] : [ <rhs> ]
+ """
+ def match(lhs_cls, rhs_cls, string, require_lhs=False, require_rhs=False):
+ line, repmap = string_replace_map(string)
+ if ':' not in line: return
+ lhs,rhs = line.split(':',1)
+ lhs = lhs.rstrip()
+ rhs = rhs.lstrip()
+ lhs_obj, rhs_obj = None, None
+ if lhs:
+ if lhs_cls is None: return
+ lhs_obj = lhs_cls(repmap(lhs))
+ elif require_lhs:
+ return
+ if rhs:
+ if rhs_cls is None: return
+ rhs_obj = rhs_cls(repmap(rhs))
+ elif require_rhs:
+ return
+ return lhs_obj, rhs_obj
+ match = staticmethod(match)
+ def tostr(self):
+ s = ''
+ if self.items[0] is not None:
+ s += '%s :' % (self.items[0])
+ else:
+ s += ':'
+ if self.items[1] is not None:
+ s += ' %s' % (self.items[1])
+ return s
+
+class KeywordValueBase(Base):
+ """
+ <keyword-value-base> = [ <lhs> = ] <rhs>
+ """
+ def match(lhs_cls, rhs_cls, string, require_lhs = True, upper_lhs = False):
+ if require_lhs and '=' not in string: return
+ if isinstance(lhs_cls, (list, tuple)):
+ for s in lhs_cls:
+ try:
+ obj = KeywordValueBase.match(s, rhs_cls, string, require_lhs=require_lhs, upper_lhs=upper_lhs)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return obj
+ lhs,rhs = string.split('=',1)
+ lhs = lhs.rstrip()
+ rhs = rhs.lstrip()
+ if not rhs: return
+ if not lhs:
+ if require_lhs: return
+ return None, rhs_cls(rhs)
+ if isinstance(lhs_cls, str):
+ if upper_lhs:
+ lhs = lhs.upper()
+ if lhs_cls!=lhs: return
+ return lhs, rhs_cls(rhs)
+ return lhs_cls(lhs),rhs_cls(rhs)
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None: return str(self.items[1])
+ return '%s = %s' % tuple(self.items)
+
+class BracketBase(Base):
+ """
+ <bracket-base> = <left-bracket-base> <something> <right-bracket>
+ """
+ def match(brackets, cls, string, require_cls=True):
+ i = len(brackets)/2
+ left = brackets[:i]
+ right = brackets[-i:]
+ if string.startswith(left) and string.endswith(right):
+ line = string[i:-i].strip()
+ if not line:
+ if require_cls:
+ return
+ return left,None,right
+ return left,cls(line),right
+ return
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None:
+ return '%s%s' % (self.items[0], self.items[2])
+ return '%s%s%s' % tuple(self.items)
+
+class NumberBase(Base):
+ """
+ <number-base> = <number> [ _ <kind-param> ]
+ """
+ def match(number_pattern, string):
+ m = number_pattern.match(string)
+ if m is None: return
+ return m.group('value').upper(),m.group('kind_param')
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return str(self.items[0])
+ return '%s_%s' % tuple(self.items)
+ def compare(self, other):
+ return cmp(self.items[0], other.items[0])
+
+class CallBase(Base):
+ """
+ <call-base> = <lhs> ( [ <rhs> ] )
+ """
+ def match(lhs_cls, rhs_cls, string, upper_lhs = False, require_rhs=False):
+ if not string.endswith(')'): return
+ line, repmap = string_replace_map(string)
+ i = line.find('(')
+ if i==-1: return
+ lhs = line[:i].rstrip()
+ if not lhs: return
+ rhs = line[i+1:-1].strip()
+ lhs = repmap(lhs)
+ if upper_lhs:
+ lhs = lhs.upper()
+ rhs = repmap(rhs)
+ if isinstance(lhs_cls, str):
+ if lhs_cls!=lhs: return
+ else:
+ lhs = lhs_cls(lhs)
+ if rhs:
+ if isinstance(rhs_cls, str):
+ if rhs_cls!=rhs: return
+ else:
+ rhs = rhs_cls(rhs)
+ return lhs, rhs
+ elif require_rhs:
+ return
+ return lhs, None
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return '%s()' % (self.items[0])
+ return '%s(%s)' % (self.items[0], self.items[1])
+
+class CALLBase(CallBase):
+ """
+ <CALL-base> = <LHS> ( [ <rhs> ] )
+ """
+ def match(lhs_cls, rhs_cls, string, require_rhs = False):
+ return CallBase.match(lhs_cls, rhs_cls, string, upper_lhs=True, require_rhs = require_rhs)
+ match = staticmethod(match)
+
+class StringBase(Base):
+ """
+ <string-base> = <xyz>
+ """
+ def match(pattern, string):
+ if isinstance(pattern, (list,tuple)):
+ for p in pattern:
+ obj = StringBase.match(p, string)
+ if obj is not None: return obj
+ return
+ if isinstance(pattern, str):
+ if len(pattern)==len(string) and pattern==string: return string,
+ return
+ if pattern.match(string): return string,
+ return
+ match = staticmethod(match)
+ def init(self, string):
+ self.string = string
+ return
+ def tostr(self): return str(self.string)
+ def torepr(self): return '%s(%r)' % (self.__class__.__name__, self.string)
+ def compare(self, other):
+ return cmp(self.string,other.string)
+
+class STRINGBase(StringBase):
+ """
+ <STRING-base> = <XYZ>
+ """
+ match = staticmethod(StringBase.match)
+ def match(pattern, string):
+ if isinstance(pattern, (list,tuple)):
+ for p in pattern:
+ obj = STRINGBase.match(p, string)
+ if obj is not None: return obj
+ return
+ STRING = string.upper()
+ if isinstance(pattern, str):
+ if len(pattern)==len(string) and pattern==STRING: return STRING,
+ return
+ if pattern.match(STRING): return STRING,
+ return
+ match = staticmethod(match)
+
+class StmtBase(Base):
+ """
+ [ <label> ] <stmt>
+ """
+ def tofortran(self, tab='', isfix=None):
+ label = None
+ if self.item is not None: label = self.item.label
+ if isfix:
+ colon = ''
+ c = ' '
+ else:
+ colon = ':'
+ c = ''
+ if label:
+ t = c + label + colon
+ if isfix:
+ while len(t)<6: t += ' '
+ else:
+ tab = tab[len(t):] or ' '
+ else:
+ t = ''
+ return t + tab + str(self)
+
+class EndStmtBase(StmtBase):
+ """
+ <end-stmt-base> = END [ <stmt> [ <stmt-name>] ]
+ """
+ def match(stmt_type, stmt_name, string, require_stmt_type=False):
+ start = string[:3].upper()
+ if start != 'END': return
+ line = string[3:].lstrip()
+ start = line[:len(stmt_type)].upper()
+ if start:
+ if start.replace(' ','') != stmt_type.replace(' ',''): return
+ line = line[len(stmt_type):].lstrip()
+ else:
+ if require_stmt_type: return
+ line = ''
+ if line:
+ if stmt_name is None: return
+ return stmt_type, stmt_name(line)
+ return stmt_type, None
+ match = staticmethod(match)
+ def init(self, stmt_type, stmt_name):
+ self.items = [stmt_type, stmt_name]
+ self.type, self.name = stmt_type, stmt_name
+ return
+ def get_name(self): return self.items[1]
+ def get_type(self): return self.items[0]
+ def set_name(self, name):
+ self.items[1] = name
+ def tostr(self):
+ if self.items[1] is not None:
+ return 'END %s %s' % tuple(self.items)
+ return 'END %s' % (self.items[0])
+ def torepr(self):
+ return '%s(%r, %r)' % (self.__class__.__name__, self.type, self.name)
+
+def isalnum(c): return c.isalnum() or c=='_'
+
+class WORDClsBase(Base):
+ """
+ <WORD-cls> = <WORD> [ [ :: ] <cls> ]
+ """
+ def match(pattern, cls, string, check_colons=False, require_cls=False):
+ if isinstance(pattern, (tuple,list)):
+ for p in pattern:
+ try:
+ obj = WORDClsBase.match(p, cls, string, check_colons=check_colons, require_cls=require_cls)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return
+ if isinstance(pattern, str):
+ if string[:len(pattern)].upper()!=pattern: return
+ line = string[len(pattern):]
+ if not line: return pattern, None
+ if isalnum(line[0]): return
+ line = line.lstrip()
+ if check_colons and line.startswith('::'):
+ line = line[2:].lstrip()
+ if not line:
+ if require_cls: return
+ return pattern, None
+ if cls is None: return
+ return pattern, cls(line)
+ m = pattern.match(string)
+ if m is None: return
+ line = string[len(m.group()):]
+ if pattern.value is not None:
+ pattern_value = pattern.value
+ else:
+ pattern_value = m.group().upper()
+ if not line: return pattern_value, None
+ if isalnum(line[0]): return
+ line = line.lstrip()
+ if check_colons and line.startswith('::'):
+ line = line[2:].lstrip()
+ if not line:
+ if require_cls: return
+ return pattern_value, None
+ if cls is None: return
+ return pattern_value, cls(line)
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return str(self.items[0])
+ s = str(self.items[1])
+ if s and s[0] in '(*':
+ return '%s%s' % (self.items[0], s)
+ return '%s %s' % (self.items[0], s)
+ def tostr_a(self): # colons version of tostr
+ if self.items[1] is None: return str(self.items[0])
+ return '%s :: %s' % (self.items[0], self.items[1])
+
+###############################################################################
+############################### SECTION 1 ####################################
+###############################################################################
+
+#R101: <xyz-list> = <xyz> [ , <xyz> ]...
+#R102: <xyz-name> = <name>
+#R103: <scalar-xyz> = <xyz>
+
+###############################################################################
+############################### SECTION 2 ####################################
+###############################################################################
+
+class Program(BlockBase): # R201
+ """
+ <program> = <program-unit>
+ [ <program-unit> ] ...
+ """
+ subclass_names = []
+ use_names = ['Program_Unit']
+ def match(reader):
+ return BlockBase.match(Program_Unit, [Program_Unit], None, reader)
+ match = staticmethod(match)
+
+class Program_Unit(Base): # R202
+ """
+ <program-unit> = <main-program>
+ | <external-subprogram>
+ | <module>
+ | <block-data>
+ """
+ subclass_names = ['Main_Program', 'External_Subprogram', 'Module', 'Block_Data']
+
+class External_Subprogram(Base): # R203
+ """
+ <external-subprogram> = <function-subprogram>
+ | <subroutine-subprogram>
+ """
+ subclass_names = ['Function_Subprogram', 'Subroutine_Subprogram']
+
+
+class Specification_Part(BlockBase): # R204
+ """
+ <specification-part> = [ <use-stmt> ]...
+ [ <import-stmt> ]...
+ [ <implicit-part> ]
+ [ <declaration-construct> ]...
+ """
+ subclass_names = []
+ use_names = ['Use_Stmt', 'Import_Stmt', 'Implicit_Part', 'Declaration_Construct']
+ def match(reader):
+ return BlockBase.match(None, [Use_Stmt, Import_Stmt, Implicit_Part, Declaration_Construct], None, reader)
+ match = staticmethod(match)
+
+class Implicit_Part(Base): # R205
+ """
+ <implicit-part> = [ <implicit-part-stmt> ]...
+ <implicit-stmt>
+ """
+ subclass_names = []
+ use_names = ['Implicit_Part_Stmt', 'Implicit_Stmt']
+
+class Implicit_Part_Stmt(Base): # R206
+ """
+ <implicit-part-stmt> = <implicit-stmt>
+ | <parameter-stmt>
+ | <format-stmt>
+ | <entry-stmt>
+ """
+ subclass_names = ['Implicit_Stmt', 'Parameter_Stmt', 'Format_Stmt', 'Entry_Stmt']
+
+class Declaration_Construct(Base): # R207
+ """
+ <declaration-construct> = <derived-type-def>
+ | <entry-stmt>
+ | <enum-def>
+ | <format-stmt>
+ | <interface-block>
+ | <parameter-stmt>
+ | <procedure-declaration-stmt>
+ | <specification-stmt>
+ | <type-declaration-stmt>
+ | <stmt-function-stmt>
+ """
+ subclass_names = ['Derived_Type_Def', 'Entry_Stmt', 'Enum_Def', 'Format_Stmt',
+ 'Interface_Block', 'Parameter_Stmt', 'Procedure_Declaration_Stmt',
+ 'Specification_Stmt', 'Type_Declaration_Stmt', 'Stmt_Function_Stmt']
+
+class Execution_Part(BlockBase): # R208
+ """
+ <execution-part> = <executable-construct>
+ | [ <execution-part-construct> ]...
+
+ <execution-part> shall not contain <end-function-stmt>, <end-program-stmt>, <end-subroutine-stmt>
+ """
+ subclass_names = []
+ use_names = ['Executable_Construct_C201', 'Execution_Part_Construct_C201']
+ def match(string): return BlockBase.match(Executable_Construct_C201, [Execution_Part_Construct_C201], None, string)
+ match = staticmethod(match)
+
+class Execution_Part_Construct(Base): # R209
+ """
+ <execution-part-construct> = <executable-construct>
+ | <format-stmt>
+ | <entry-stmt>
+ | <data-stmt>
+ """
+ subclass_names = ['Executable_Construct', 'Format_Stmt', 'Entry_Stmt', 'Data_Stmt']
+
+class Execution_Part_Construct_C201(Base):
+ subclass_names = ['Executable_Construct_C201', 'Format_Stmt', 'Entry_Stmt', 'Data_Stmt']
+
+class Internal_Subprogram_Part(Base): # R210
+ """
+ <internal-subprogram-part> = <contains-stmt>
+ <internal-subprogram>
+ [ <internal-subprogram> ]...
+ """
+ subclass_names = []
+ use_names = ['Contains_Stmt', 'Internal_Subprogram']
+
+class Internal_Subprogram(Base): # R211
+ """
+ <internal-subprogram> = <function-subprogram>
+ | <subroutine-subprogram>
+ """
+ subclass_names = ['Function_Subprogram', 'Subroutine_Subprogram']
+
+class Specification_Stmt(Base):# R212
+ """
+ <specification-stmt> = <access-stmt>
+ | <allocatable-stmt>
+ | <asynchronous-stmt>
+ | <bind-stmt>
+ | <common-stmt>
+ | <data-stmt>
+ | <dimension-stmt>
+ | <equivalence-stmt>
+ | <external-stmt>
+ | <intent-stmt>
+ | <intrinsic-stmt>
+ | <namelist-stmt>
+ | <optional-stmt>
+ | <pointer-stmt>
+ | <protected-stmt>
+ | <save-stmt>
+ | <target-stmt>
+ | <volatile-stmt>
+ | <value-stmt>
+ """
+ subclass_names = ['Access_Stmt', 'Allocatable_Stmt', 'Asynchronous_Stmt','Bind_Stmt',
+ 'Common_Stmt', 'Data_Stmt', 'Dimension_Stmt', 'Equivalence_Stmt',
+ 'External_Stmt', 'Intent_Stmt', 'Intrinsic_Stmt', 'Namelist_Stmt',
+ 'Optional_Stmt','Pointer_Stmt','Protected_Stmt','Save_Stmt',
+ 'Target_Stmt','Volatile_Stmt', 'Value_Stmt']
+
+class Executable_Construct(Base):# R213
+ """
+ <executable-construct> = <action-stmt>
+ | <associate-stmt>
+ | <case-construct>
+ | <do-construct>
+ | <forall-construct>
+ | <if-construct>
+ | <select-type-construct>
+ | <where-construct>
+ """
+ subclass_names = ['Action_Stmt', 'Associate_Stmt', 'Case_Construct', 'Do_Construct',
+ 'Forall_Construct', 'If_Construct', 'Select_Type_Construct', 'Where_Construct']
+
+class Executable_Construct_C201(Base):
+ subclass_names = Executable_Construct.subclass_names[:]
+ subclass_names[subclass_names.index('Action_Stmt')] = 'Action_Stmt_C201'
+
+
+class Action_Stmt(Base):# R214
+ """
+ <action-stmt> = <allocate-stmt>
+ | <assignment-stmt>
+ | <backspace-stmt>
+ | <call-stmt>
+ | <close-stmt>
+ | <continue-stmt>
+ | <cycle-stmt>
+ | <deallocate-stmt>
+ | <endfile-stmt>
+ | <end-function-stmt>
+ | <end-program-stmt>
+ | <end-subroutine-stmt>
+ | <exit-stmt>
+ | <flush-stmt>
+ | <forall-stmt>
+ | <goto-stmt>
+ | <if-stmt>
+ | <inquire-stmt>
+ | <nullify-stmt>
+ | <open-stmt>
+ | <pointer-assignment-stmt>
+ | <print-stmt>
+ | <read-stmt>
+ | <return-stmt>
+ | <rewind-stmt>
+ | <stop-stmt>
+ | <wait-stmt>
+ | <where-stmt>
+ | <write-stmt>
+ | <arithmetic-if-stmt>
+ | <computed-goto-stmt>
+ """
+ subclass_names = ['Allocate_Stmt', 'Assignment_Stmt', 'Backspace_Stmt', 'Call_Stmt',
+ 'Close_Stmt', 'Continue_Stmt', 'Cycle_Stmt', 'Deallocate_Stmt',
+ 'Endfile_Stmt', 'End_Function_Stmt', 'End_Subroutine_Stmt', 'Exit_Stmt',
+ 'Flush_Stmt', 'Forall_Stmt', 'Goto_Stmt', 'If_Stmt', 'Inquire_Stmt',
+ 'Nullify_Stmt', 'Open_Stmt', 'Pointer_Assignment_Stmt', 'Print_Stmt',
+ 'Read_Stmt', 'Return_Stmt', 'Rewind_Stmt', 'Stop_Stmt', 'Wait_Stmt',
+ 'Where_Stmt', 'Write_Stmt', 'Arithmetic_If_Stmt', 'Computed_Goto_Stmt']
+
+class Action_Stmt_C201(Base):
+ """
+ <action-stmt-c201> = <action-stmt>
+ C201 is applied.
+ """
+ subclass_names = Action_Stmt.subclass_names[:]
+ subclass_names.remove('End_Function_Stmt')
+ subclass_names.remove('End_Subroutine_Stmt')
+ #subclass_names.remove('End_Program_Stmt')
+
+class Action_Stmt_C802(Base):
+ """
+ <action-stmt-c802> = <action-stmt>
+ C802 is applied.
+ """
+ subclass_names = Action_Stmt.subclass_names[:]
+ subclass_names.remove('End_Function_Stmt')
+ subclass_names.remove('End_Subroutine_Stmt')
+ subclass_names.remove('If_Stmt')
+
+class Action_Stmt_C824(Base):
+ """
+ <action-stmt-c824> = <action-stmt>
+ C824 is applied.
+ """
+ subclass_names = Action_Stmt.subclass_names[:]
+ subclass_names.remove('End_Function_Stmt')
+ subclass_names.remove('End_Subroutine_Stmt')
+ subclass_names.remove('Continue_Stmt')
+ subclass_names.remove('Goto_Stmt')
+ subclass_names.remove('Return_Stmt')
+ subclass_names.remove('Stop_Stmt')
+ subclass_names.remove('Exit_Stmt')
+ subclass_names.remove('Cycle_Stmt')
+ subclass_names.remove('Arithmetic_If_Stmt')
+
+class Keyword(Base): # R215
+ """
+ <keyword> = <name>
+ """
+ subclass_names = ['Name']
+
+###############################################################################
+############################### SECTION 3 ####################################
+###############################################################################
+
+#R301: <character> = <alphanumeric-character> | <special-character>
+#R302: <alphanumeric-character> = <letter> | <digit> | <underscore>
+#R303: <underscore> = _
+
+class Name(StringBase): # R304
+ """
+ <name> = <letter> [ <alphanumeric_character> ]...
+ """
+ subclass_names = []
+ def match(string): return StringBase.match(pattern.abs_name, string)
+ match = staticmethod(match)
+
+class Constant(Base): # R305
+ """
+ <constant> = <literal-constant>
+ | <named-constant>
+ """
+ subclass_names = ['Literal_Constant','Named_Constant']
+
+class Literal_Constant(Base): # R306
+ """
+ <literal-constant> = <int-literal-constant>
+ | <real-literal-constant>
+ | <complex-literal-constant>
+ | <logical-literal-constant>
+ | <char-literal-constant>
+ | <boz-literal-constant>
+ """
+ subclass_names = ['Int_Literal_Constant', 'Real_Literal_Constant','Complex_Literal_Constant',
+ 'Logical_Literal_Constant','Char_Literal_Constant','Boz_Literal_Constant']
+
+class Named_Constant(Base): # R307
+ """
+ <named-constant> = <name>
+ """
+ subclass_names = ['Name']
+
+class Int_Constant(Base): # R308
+ """
+ <int-constant> = <constant>
+ """
+ subclass_names = ['Constant']
+
+class Char_Constant(Base): # R309
+ """
+ <char-constant> = <constant>
+ """
+ subclass_names = ['Constant']
+
+#R310: <intrinsic-operator> = <power-op> | <mult-op> | <add-op> | <concat-op> | <rel-op> | <not-op> | <and-op> | <or-op> | <equiv-op>
+#R311: <defined-operator> = <defined-unary-op> | <defined-binary-op> | <extended-intrinsic-op>
+#R312: <extended-intrinsic-op> = <intrinsic-op>
+
+class Label(StringBase): # R313
+ """
+ <label> = <digit> [ <digit> [ <digit> [ <digit> [ <digit> ] ] ] ]
+ """
+ subclass_names = []
+ def match(string): return StringBase.match(pattern.abs_label, string)
+ match = staticmethod(match)
+
+###############################################################################
+############################### SECTION 4 ####################################
+###############################################################################
+
+class Type_Spec(Base): # R401
+ """
+ <type-spec> = <intrinsic-type-spec>
+ | <derived-type-spec>
+ """
+ subclass_names = ['Intrinsic_Type_Spec', 'Derived_Type_Spec']
+
+class Type_Param_Value(StringBase): # R402
+ """
+ <type-param-value> = <scalar-int-expr>
+ | *
+ | :
+ """
+ subclass_names = ['Scalar_Int_Expr']
+ use_names = []
+ def match(string): return StringBase.match(['*',':'], string)
+ match = staticmethod(match)
+
+class Intrinsic_Type_Spec(WORDClsBase): # R403
+ """
+ <intrinsic-type-spec> = INTEGER [ <kind-selector> ]
+ | REAL [ <kind-selector> ]
+ | DOUBLE COMPLEX
+ | COMPLEX [ <kind-selector> ]
+ | CHARACTER [ <char-selector> ]
+ | LOGICAL [ <kind-selector> ]
+ Extensions:
+ | DOUBLE PRECISION
+ | BYTE
+ """
+ subclass_names = []
+ use_names = ['Kind_Selector','Char_Selector']
+
+ def match(string):
+ for w,cls in [('INTEGER',Kind_Selector),
+ ('REAL',Kind_Selector),
+ ('COMPLEX',Kind_Selector),
+ ('LOGICAL',Kind_Selector),
+ ('CHARACTER',Char_Selector),
+ (pattern.abs_double_complex_name, None),
+ (pattern.abs_double_precision_name, None),
+ ('BYTE', None),
+ ]:
+ try:
+ obj = WORDClsBase.match(w,cls,string)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return
+ match = staticmethod(match)
+
+
+class Kind_Selector(Base): # R404
+ """
+ <kind-selector> = ( [ KIND = ] <scalar-int-initialization-expr> )
+ Extensions:
+ | * <char-length>
+ """
+ subclass_names = []
+ use_names = ['Char_Length','Scalar_Int_Initialization_Expr']
+
+ def match(string):
+ if string[0]+string[-1] != '()':
+ if not string.startswith('*'): return
+ return '*',Char_Length(string[1:].lstrip())
+ line = string[1:-1].strip()
+ if line[:4].upper()=='KIND':
+ line = line[4:].lstrip()
+ if not line.startswith('='): return
+ line = line[1:].lstrip()
+ return '(',Scalar_Int_Initialization_Expr(line),')'
+ match = staticmethod(match)
+ def tostr(self):
+ if len(self.items)==2: return '%s%s' % tuple(self.items)
+ return '%sKIND = %s%s' % tuple(self.items)
+
+class Signed_Int_Literal_Constant(NumberBase): # R405
+ """
+ <signed-int-literal-constant> = [ <sign> ] <int-literal-constant>
+ """
+ subclass_names = ['Int_Literal_Constant'] # never used because sign is included in pattern
+ def match(string):
+ return NumberBase.match(pattern.abs_signed_int_literal_constant_named, string)
+ match = staticmethod(match)
+
+class Int_Literal_Constant(NumberBase): # R406
+ """
+ <int-literal-constant> = <digit-string> [ _ <kind-param> ]
+ """
+ subclass_names = []
+ def match(string):
+ return NumberBase.match(pattern.abs_int_literal_constant_named, string)
+ match = staticmethod(match)
+
+#R407: <kind-param> = <digit-string> | <scalar-int-constant-name>
+#R408: <signed-digit-string> = [ <sign> ] <digit-string>
+#R409: <digit-string> = <digit> [ <digit> ]...
+#R410: <sign> = + | -
+
+class Boz_Literal_Constant(Base): # R411
+ """
+ <boz-literal-constant> = <binary-constant>
+ | <octal-constant>
+ | <hex-constant>
+ """
+ subclass_names = ['Binary_Constant','Octal_Constant','Hex_Constant']
+
+class Binary_Constant(STRINGBase): # R412
+ """
+ <binary-constant> = B ' <digit> [ <digit> ]... '
+ | B \" <digit> [ <digit> ]... \"
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(pattern.abs_binary_constant, string)
+ match = staticmethod(match)
+
+class Octal_Constant(STRINGBase): # R413
+ """
+ <octal-constant> = O ' <digit> [ <digit> ]... '
+ | O \" <digit> [ <digit> ]... \"
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(pattern.abs_octal_constant, string)
+ match = staticmethod(match)
+
+class Hex_Constant(STRINGBase): # R414
+ """
+ <hex-constant> = Z ' <digit> [ <digit> ]... '
+ | Z \" <digit> [ <digit> ]... \"
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(pattern.abs_hex_constant, string)
+ match = staticmethod(match)
+
+#R415: <hex-digit> = <digit> | A | B | C | D | E | F
+
+class Signed_Real_Literal_Constant(NumberBase): # R416
+ """
+ <signed-real-literal-constant> = [ <sign> ] <real-literal-constant>
+ """
+ subclass_names = ['Real_Literal_Constant'] # never used
+ def match(string):
+ return NumberBase.match(pattern.abs_signed_real_literal_constant_named, string)
+ match = staticmethod(match)
+
+class Real_Literal_Constant(NumberBase): # R417
+ """
+ """
+ subclass_names = []
+ def match(string):
+ return NumberBase.match(pattern.abs_real_literal_constant_named, string)
+ match = staticmethod(match)
+
+#R418: <significand> = <digit-string> . [ <digit-string> ] | . <digit-string>
+#R419: <exponent-letter> = E | D
+#R420: <exponent> = <signed-digit-string>
+
+class Complex_Literal_Constant(Base): # R421
+ """
+ <complex-literal-constant> = ( <real-part>, <imag-part> )
+ """
+ subclass_names = []
+ use_names = ['Real_Part','Imag_Part']
+ def match(string):
+ if not string or string[0]+string[-1]!='()': return
+ if not pattern.abs_complex_literal_constant.match(string):
+ return
+ r,i = string[1:-1].split(',')
+ return Real_Part(r.strip()), Imag_Part(i.strip())
+ match = staticmethod(match)
+ def tostr(self): return '(%s, %s)' % tuple(self.items)
+
+class Real_Part(Base): # R422
+ """
+ <real-part> = <signed-int-literal-constant>
+ | <signed-real-literal-constant>
+ | <named-constant>
+ """
+ subclass_names = ['Signed_Int_Literal_Constant','Signed_Real_Literal_Constant','Named_Constant']
+
+class Imag_Part(Base): # R423
+ """
+ <imag-part> = <real-part>
+ """
+ subclass_names = ['Signed_Int_Literal_Constant','Signed_Real_Literal_Constant','Named_Constant']
+
+class Char_Selector(Base): # R424
+ """
+ <char-selector> = <length-selector>
+ | ( LEN = <type-param-value> , KIND = <scalar-int-initialization-expr> )
+ | ( <type-param-value> , [ KIND = ] <scalar-int-initialization-expr> )
+ | ( KIND = <scalar-int-initialization-expr> [ , LEN = <type-param-value> ] )
+ """
+ subclass_names = ['Length_Selector']
+ use_names = ['Type_Param_Value','Scalar_Int_Initialization_Expr']
+ def match(string):
+ if string[0]+string[-1] != '()': return
+ line, repmap = string_replace_map(string[1:-1].strip())
+ if line[:3].upper()=='LEN':
+ line = line[3:].lstrip()
+ if not line.startswith('='): return
+ line = line[1:].lstrip()
+ i = line.find(',')
+ if i==-1: return
+ v = line[:i].rstrip()
+ line = line[i+1:].lstrip()
+ if line[:4].upper()!='KIND': return
+ line = line[4:].lstrip()
+ if not line.startswith('='): return
+ line = line[1:].lstrip()
+ v = repmap(v)
+ line = repmap(line)
+ return Type_Param_Value(v), Scalar_Int_Initialization_Expr(line)
+ elif line[:4].upper()=='KIND':
+ line = line[4:].lstrip()
+ if not line.startswith('='): return
+ line = line[1:].lstrip()
+ i = line.find(',')
+ if i==-1: return None,Scalar_Int_Initialization_Expr(line)
+ v = line[i+1:].lstrip()
+ line = line[:i].rstrip()
+ if v[:3].upper()!='LEN': return
+ v = v[3:].lstrip()
+ if not v.startswith('='): return
+ v = v[1:].lstrip()
+ return Type_Param_Value(v), Scalar_Int_Initialization_Expr(line)
+ else:
+ i = line.find(',')
+ if i==-1: return
+ v = line[:i].rstrip()
+ line = line[i+1:].lstrip()
+ if line[:4].upper()=='KIND':
+ line = line[4:].lstrip()
+ if not line.startswith('='): return
+ line = line[1:].lstrip()
+ return Type_Param_Value(v), Scalar_Int_Initialization_Expr(line)
+ return
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None:
+ return '(KIND = %s)' % (self.items[1])
+ return '(LEN = %s, KIND = %s)' % (self.items[0],self.items[1])
+
+class Length_Selector(Base): # R425
+ """
+ <length -selector> = ( [ LEN = ] <type-param-value> )
+ | * <char-length> [ , ]
+ """
+ subclass_names = []
+ use_names = ['Type_Param_Value','Char_Length']
+ def match(string):
+ if string[0]+string[-1] == '()':
+ line = string[1:-1].strip()
+ if line[:3].upper()=='LEN':
+ line = line[3:].lstrip()
+ if not line.startswith('='): return
+ line = line[1:].lstrip()
+ return '(',Type_Param_Value(line),')'
+ if not string.startswith('*'): return
+ line = string[1:].lstrip()
+ if string[-1]==',': line = line[:-1].rstrip()
+ return '*',Char_Length(line)
+ match = staticmethod(match)
+ def tostr(self):
+ if len(self.items)==2: return '%s%s' % tuple(self.items)
+ return '%sLEN = %s%s' % tuple(self.items)
+
+class Char_Length(BracketBase): # R426
+ """
+ <char-length> = ( <type-param-value> )
+ | <scalar-int-literal-constant>
+ """
+ subclass_names = ['Scalar_Int_Literal_Constant']
+ use_names = ['Type_Param_Value']
+ def match(string): return BracketBase.match('()',Type_Param_Value, string)
+ match = staticmethod(match)
+
+class Char_Literal_Constant(Base): # R427
+ """
+ <char-literal-constant> = [ <kind-param> _ ] ' <rep-char> '
+ | [ <kind-param> _ ] \" <rep-char> \"
+ """
+ subclass_names = []
+ rep = pattern.char_literal_constant
+ def match(string):
+ if string[-1] not in '"\'': return
+ if string[-1]=='"':
+ abs_a_n_char_literal_constant_named = pattern.abs_a_n_char_literal_constant_named2
+ else:
+ abs_a_n_char_literal_constant_named = pattern.abs_a_n_char_literal_constant_named1
+ line, repmap = string_replace_map(string)
+ m = abs_a_n_char_literal_constant_named.match(line)
+ if not m: return
+ kind_param = m.group('kind_param')
+ line = m.group('value')
+ line = repmap(line)
+ return line, kind_param
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return str(self.items[0])
+ return '%s_%s' % (self.items[1], self.items[0])
+
+class Logical_Literal_Constant(NumberBase): # R428
+ """
+ <logical-literal-constant> = .TRUE. [ _ <kind-param> ]
+ | .FALSE. [ _ <kind-param> ]
+ """
+ subclass_names = []
+ def match(string):
+ return NumberBase.match(pattern.abs_logical_literal_constant_named, string)
+ match = staticmethod(match)
+
+class Derived_Type_Def(Base): # R429
+ """
+ <derived-type-def> = <derived-type-stmt>
+ [ <type-param-def-stmt> ]...
+ [ <private-or-sequence> ]...
+ [ <component-part> ]
+ [ <type-bound-procedure-part> ]
+ <end-type-stmt>
+ """
+ subclass_names = []
+ use_names = ['Derived_Type_Stmt', 'Type_Param_Def_Stmt', 'Private_Or_Sequence',
+ 'Component_Part', 'Type_Bound_Procedure_Part', 'End_Type_Stmt']
+
+class Derived_Type_Stmt(StmtBase): # R430
+ """
+ <derived-type-stmt> = TYPE [ [ , <type-attr-spec-list> ] :: ] <type-name> [ ( <type-param-name-list> ) ]
+ """
+ subclass_names = []
+ use_names = ['Type_Attr_Spec_List', 'Type_Name', 'Type_Param_Name_List']
+ def match(string):
+ if string[:4].upper()!='TYPE': return
+ line = string[4:].lstrip()
+ i = line.find('::')
+ attr_specs = None
+ if i!=-1:
+ if line.startswith(','):
+ l = line[1:i].strip()
+ if not l: return
+ attr_specs = Type_Attr_Spec_List(l)
+ line = line[i+2:].lstrip()
+ m = pattern.name.match(line)
+ if m is None: return
+ name = Type_Name(m.group())
+ line = line[m.end():].lstrip()
+ if not line: return attr_specs, name, None
+ if line[0]+line[-1]!='()': return
+ return attr_specs, name, Type_Param_Name_List(line[1:-1].strip())
+ match = staticmethod(match)
+ def tostr(self):
+ s = 'TYPE'
+ if self.items[0] is not None:
+ s += ', %s :: %s' % (self.items[0], self.items[1])
+ else:
+ s += ' :: %s' % (self.items[1])
+ if self.items[2] is not None:
+ s += '(%s)' % (self.items[2])
+ return s
+
+class Type_Name(Name): # C424
+ """
+ <type-name> = <name>
+ <type-name> shall not be DOUBLEPRECISION or the name of intrinsic type
+ """
+ subclass_names = []
+ use_names = []
+ def match(string):
+ if pattern.abs_intrinsic_type_name.match(string): return
+ return Name.match(string)
+ match = staticmethod(match)
+
+class Type_EXTENDS_Parent_Type_Name(CALLBase):
+ """
+ <..> = EXTENDS ( <parent-type-name> )
+ """
+ subclass_names = []
+ use_names = ['Parent_Type_Name']
+ def match(string): return CALLBase.match('EXTENDS', Parent_Type_Name, string)
+ match = staticmethod(match)
+
+class Type_Attr_Spec(STRINGBase): # R431
+ """
+ <type-attr-spec> = <access-spec>
+ | EXTENDS ( <parent-type-name> )
+ | ABSTRACT
+ | BIND (C)
+ """
+ subclass_names = ['Access_Spec', 'Type_EXTENDS_Parent_Type_Name', 'Language_Binding_Spec']
+ def match(string): return STRINGBase.match('ABSTRACT', string)
+ match = staticmethod(match)
+
+class Private_Or_Sequence(Base): # R432
+ """
+ <private-or-sequence> = <private-components-stmt>
+ | <sequence-stmt>
+ """
+ subclass_names = ['Private_Components_Stmt', 'Sequence_Stmt']
+
+class End_Type_Stmt(EndStmtBase): # R433
+ """
+ <end-type-stmt> = END TYPE [ <type-name> ]
+ """
+ subclass_names = []
+ use_names = ['Type_Name']
+ def match(string): return EndStmtBase.match('TYPE',Type_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class Sequence_Stmt(STRINGBase): # R434
+ """
+ <sequence-stmt> = SEQUENCE
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match('SEQUENCE', string)
+ match = staticmethod(match)
+
+class Type_Param_Def_Stmt(StmtBase): # R435
+ """
+ <type-param-def-stmt> = INTEGER [ <kind-selector> ] , <type-param-attr-spec> :: <type-param-decl-list>
+ """
+ subclass_names = []
+ use_names = ['Kind_Selector', 'Type_Param_Attr_Spec', 'Type_Param_Decl_List']
+ def match(string):
+ if string[:7].upper()!='INTEGER': return
+ line, repmap = string_replace_map(string[7:].lstrip())
+ if not line: return
+ i = line.find(',')
+ if i==-1: return
+ kind_selector = repmap(line[:i].rstrip()) or None
+ line = repmap(line[i+1:].lstrip())
+ i = line.find('::')
+ if i==-1: return
+ l1 = line[:i].rstrip()
+ l2 = line[i+2:].lstrip()
+ if not l1 or not l2: return
+ if kind_selector: kind_selector = Kind_Selector(kind_selector)
+ return kind_selector, Type_Param_Attr_Spec(l1), Type_Param_Decl_List(l2)
+ match = staticmethod(match)
+ def tostr(self):
+ s = 'INTEGER'
+ if self.items[0] is not None:
+ s += '%s, %s :: %s' % tuple(self.items)
+ else:
+ s += ', %s :: %s' % tuple(self.items[1:])
+ return s
+
+class Type_Param_Decl(BinaryOpBase): # R436
+ """
+ <type-param-decl> = <type-param-name> [ = <scalar-int-initialization-expr> ]
+ """
+ subclass_names = ['Type_Param_Name']
+ use_names = ['Scalar_Int_Initialization_Expr']
+ def match(string):
+ if '=' not in string: return
+ lhs,rhs = string.split('=',1)
+ lhs = lhs.rstrip()
+ rhs = rhs.lstrip()
+ if not lhs or not rhs: return
+ return Type_Param_Name(lhs),'=',Scalar_Int_Initialization_Expr(rhs)
+ match = staticmethod(match)
+
+class Type_Param_Attr_Spec(STRINGBase): # R437
+ """
+ <type-param-attr-spec> = KIND
+ | LEN
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(['KIND', 'LEN'], string)
+ match = staticmethod(match)
+
+
+class Component_Part(BlockBase): # R438
+ """
+ <component-part> = [ <component-def-stmt> ]...
+ """
+ subclass_names = []
+ use_names = ['Component_Def_Stmt']
+ def match(reader):
+ content = []
+ while 1:
+ try:
+ obj = Component_Def_Stmt(reader)
+ except NoMatchError:
+ obj = None
+ if obj is None:
+ break
+ content.append(obj)
+ if content:
+ return content,
+ return
+ match = staticmethod(match)
+
+ def tofortran(self, tab='', isfix=None):
+ l = []
+ for item in self.content:
+ l.append(item.tofortran(tab=tab,isfix=isfix))
+ return '\n'.join(l)
+
+class Component_Def_Stmt(Base): # R439
+ """
+ <component-def-stmt> = <data-component-def-stmt>
+ | <proc-component-def-stmt>
+ """
+ subclass_names = ['Data_Component_Def_Stmt', 'Proc_Component_Def_Stmt']
+
+class Data_Component_Def_Stmt(StmtBase): # R440
+ """
+ <data-component-def-stmt> = <declaration-type-spec> [ [ , <component-attr-spec-list> ] :: ] <component-decl-list>
+ """
+ subclass_names = []
+ use_names = ['Declaration_Type_Spec', 'Component_Attr_Spec_List', 'Component_Decl_List']
+
+class Dimension_Component_Attr_Spec(CALLBase):
+ """
+ <dimension-component-attr-spec> = DIMENSION ( <component-array-spec> )
+ """
+ subclass_names = []
+ use_names = ['Component_Array_Spec']
+ def match(string): return CALLBase.match('DIMENSION', Component_Array_Spec, string)
+ match = staticmethod(match)
+
+class Component_Attr_Spec(STRINGBase): # R441
+ """
+ <component-attr-spec> = POINTER
+ | DIMENSION ( <component-array-spec> )
+ | ALLOCATABLE
+ | <access-spec>
+ """
+ subclass_names = ['Access_Spec', 'Dimension_Component_Attr_Spec']
+ use_names = []
+ def match(string): return STRINGBase.match(['POINTER', 'ALLOCATABLE'], string)
+ match = staticmethod(match)
+
+class Component_Decl(Base): # R442
+ """
+ <component-decl> = <component-name> [ ( <component-array-spec> ) ] [ * <char-length> ] [ <component-initialization> ]
+ """
+ subclass_names = []
+ use_names = ['Component_Name', 'Component_Array_Spec', 'Char_Length', 'Component_Initialization']
+ def match(string):
+ m = pattern.name.match(string)
+ if m is None: return
+ name = Component_Name(m.group())
+ newline = string[m.end():].lstrip()
+ if not newline: return name, None, None, None
+ array_spec = None
+ char_length = None
+ init = None
+ if newline.startswith('('):
+ line, repmap = string_replace_map(newline)
+ i = line.find(')')
+ if i==-1: return
+ array_spec = Component_Array_Spec(repmap(line[1:i].strip()))
+ newline = repmap(line[i+1:].lstrip())
+ if newline.startswith('*'):
+ line, repmap = string_replace_map(newline)
+ i = line.find('=')
+ if i!=-1:
+ char_length = repmap(line[1:i].strip())
+ newline = repmap(newline[i:].lstrip())
+ else:
+ char_length = repmap(newline[1:].strip())
+ newline = ''
+ char_length = Char_Length(char_length)
+ if newline.startswith('='):
+ init = Component_Initialization(newline)
+ else:
+ assert newline=='',`newline`
+ return name, array_spec, char_length, init
+ match = staticmethod(match)
+ def tostr(self):
+ s = str(self.items[0])
+ if self.items[1] is not None:
+ s += '(' + str(self.items[1]) + ')'
+ if self.items[2] is not None:
+ s += '*' + str(self.items[2])
+ if self.items[3] is not None:
+ s += ' ' + str(self.items[3])
+ return s
+
+class Component_Array_Spec(Base): # R443
+ """
+ <component-array-spec> = <explicit-shape-spec-list>
+ | <deferred-shape-spec-list>
+ """
+ subclass_names = ['Explicit_Shape_Spec_List', 'Deferred_Shape_Spec_List']
+
+class Component_Initialization(Base): # R444
+ """
+ <component-initialization> = = <initialization-expr>
+ | => <null-init>
+ """
+ subclass_names = []
+ use_names = ['Initialization_Expr', 'Null_Init']
+ def match(string):
+ if string.startswith('=>'):
+ return '=>', Null_Init(string[2:].lstrip())
+ if string.startswith('='):
+ return '=', Initialization_Expr(string[2:].lstrip())
+ return
+ match = staticmethod(match)
+ def tostr(self): return '%s %s' % tuple(self.items)
+
+
+class Proc_Component_Def_Stmt(StmtBase): # R445
+ """
+ <proc-component-def-stmt> = PROCEDURE ( [ <proc-interface> ] ) , <proc-component-attr-spec-list> :: <proc-decl-list>
+ """
+ subclass_names = []
+ use_names = ['Proc_Interface', 'Proc_Component_Attr_Spec_List', 'Proc_Decl_List']
+
+class Proc_Component_PASS_Arg_Name(CALLBase):
+ """
+ <proc-component-PASS-arg-name> = PASS ( <arg-name> )
+ """
+ subclass_names = []
+ use_names = ['Arg_Name']
+ def match(string): return CALLBase.match('PASS', Arg_Name, string)
+ match = staticmethod(match)
+
+class Proc_Component_Attr_Spec(STRINGBase): # R446
+ """
+ <proc-component-attr-spec> = POINTER
+ | PASS [ ( <arg-name> ) ]
+ | NOPASS
+ | <access-spec>
+ """
+ subclass_names = ['Access_Spec', 'Proc_Component_PASS_Arg_Name']
+ def match(string): return STRINGBase.match(['POINTER','PASS','NOPASS'], string)
+ match = staticmethod(match)
+
+class Private_Components_Stmt(StmtBase): # R447
+ """
+ <private-components-stmt> = PRIVATE
+ """
+ subclass_names = []
+ def match(string): return StringBase.match('PRIVATE', string)
+ match = staticmethod(match)
+
+class Type_Bound_Procedure_Part(Base): # R448
+ """
+ <type-bound-procedure-part> = <contains-stmt>
+ [ <binding-private-stmt> ]
+ <proc-binding-stmt>
+ [ <proc-binding-stmt> ]...
+ """
+ subclass_names = []
+ use_names = ['Contains_Stmt', 'Binding_Private_Stmt', 'Proc_Binding_Stmt']
+
+class Binding_Private_Stmt(StmtBase, STRINGBase): # R449
+ """
+ <binding-private-stmt> = PRIVATE
+ """
+ subclass_names = []
+ def match(string): return StringBase.match('PRIVATE', string)
+ match = staticmethod(match)
+
+class Proc_Binding_Stmt(Base): # R450
+ """
+ <proc-binding-stmt> = <specific-binding>
+ | <generic-binding>
+ | <final-binding>
+ """
+ subclass_names = ['Specific_Binding', 'Generic_Binding', 'Final_Binding']
+
+class Specific_Binding(StmtBase): # R451
+ """
+ <specific-binding> = PROCEDURE [ ( <interface-name> ) ] [ [ , <binding-attr-list> ] :: ] <binding-name> [ => <procedure-name> ]
+ """
+ subclass_names = []
+ use_names = ['Interface_Name', 'Binding_Attr_List', 'Binding_Name', 'Procedure_Name']
+
+class Generic_Binding(StmtBase): # R452
+ """
+ <generic-binding> = GENERIC [ , <access-spec> ] :: <generic-spec> => <binding-name-list>
+ """
+ subclass_names = []
+ use_names = ['Access_Spec', 'Generic_Spec', 'Binding_Name_List']
+
+class Binding_PASS_Arg_Name(CALLBase):
+ """
+ <binding-PASS-arg-name> = PASS ( <arg-name> )
+ """
+ subclass_names = []
+ use_names = ['Arg_Name']
+ def match(string): return CALLBase.match('PASS', Arg_Name, string)
+ match = staticmethod(match)
+
+class Binding_Attr(STRINGBase): # R453
+ """
+ <binding-attr> = PASS [ ( <arg-name> ) ]
+ | NOPASS
+ | NON_OVERRIDABLE
+ | <access-spec>
+ """
+ subclass_names = ['Access_Spec', 'Binding_PASS_Arg_Name']
+ def match(string): return STRINGBase.match(['PASS', 'NOPASS', 'NON_OVERRIDABLE'], string)
+ match = staticmethod(match)
+
+class Final_Binding(StmtBase, WORDClsBase): # R454
+ """
+ <final-binding> = FINAL [ :: ] <final-subroutine-name-list>
+ """
+ subclass_names = []
+ use_names = ['Final_Subroutine_Name_List']
+ def match(string): return WORDClsBase.match('FINAL',Final_Subroutine_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Derived_Type_Spec(CallBase): # R455
+ """
+ <derived-type-spec> = <type-name> [ ( <type-param-spec-list> ) ]
+ """
+ subclass_names = ['Type_Name']
+ use_names = ['Type_Param_Spec_List']
+ def match(string): return CallBase.match(Type_Name, Type_Param_Spec_List, string)
+ match = staticmethod(match)
+
+class Type_Param_Spec(KeywordValueBase): # R456
+ """
+ <type-param-spec> = [ <keyword> = ] <type-param-value>
+ """
+ subclass_names = ['Type_Param_Value']
+ use_names = ['Keyword']
+ def match(string): return KeywordValueBase.match(Keyword, Type_Param_Value, string)
+ match = staticmethod(match)
+
+class Structure_Constructor_2(KeywordValueBase): # R457.b
+ """
+ <structure-constructor-2> = [ <keyword> = ] <component-data-source>
+ """
+ subclass_names = ['Component_Data_Source']
+ use_names = ['Keyword']
+ def match(string): return KeywordValueBase.match(Keyword, Component_Data_Source, string)
+ match = staticmethod(match)
+
+class Structure_Constructor(CallBase): # R457
+ """
+ <structure-constructor> = <derived-type-spec> ( [ <component-spec-list> ] )
+ | <structure-constructor-2>
+ """
+ subclass_names = ['Structure_Constructor_2']
+ use_names = ['Derived_Type_Spec', 'Component_Spec_List']
+ def match(string): return CallBase.match(Derived_Type_Spec, Component_Spec_List, string)
+ match = staticmethod(match)
+
+class Component_Spec(KeywordValueBase): # R458
+ """
+ <component-spec> = [ <keyword> = ] <component-data-source>
+ """
+ subclass_names = ['Component_Data_Source']
+ use_names = ['Keyword']
+ def match(string): return KeywordValueBase.match(Keyword, Component_Data_Source, string)
+ match = staticmethod(match)
+
+class Component_Data_Source(Base): # R459
+ """
+ <component-data-source> = <expr>
+ | <data-target>
+ | <proc-target>
+ """
+ subclass_names = ['Proc_Target', 'Data_Target', 'Expr']
+
+class Enum_Def(Base): # R460
+ """
+ <enum-def> = <enum-def-stmt>
+ <enumerator-def-stmt>
+ [ <enumerator-def-stmt> ]...
+ <end-enum-stmt>
+ """
+ subclass_names = []
+ use_names = ['Enum_Def_Stmt', 'Enumerator_Def_Stmt', 'End_Enum_Stmt']
+
+class Enum_Def_Stmt(STRINGBase): # R461
+ """
+ <enum-def-stmt> = ENUM, BIND(C)
+ """
+ subclass_names = []
+ def match(string):
+ if string[:4].upper()!='ENUM': return
+ line = string[4:].lstrip()
+ if not line.startswith(','): return
+ line = line[1:].lstrip()
+ if line[:4].upper()!='BIND': return
+ line = line[4:].lstrip()
+ if not line or line[0]+line[-1]!='()': return
+ line = line[1:-1].strip()
+ if line!='C' or line!='c': return
+ return 'ENUM, BIND(C)',
+ match = staticmethod(match)
+
+class Enumerator_Def_Stmt(StmtBase, WORDClsBase): # R462
+ """
+ <enumerator-def-stmt> = ENUMERATOR [ :: ] <enumerator-list>
+ """
+ subclass_names = []
+ use_names = ['Enumerator_List']
+ def match(string): return WORDClsBase.match('ENUMERATOR',Enumerator_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Enumerator(BinaryOpBase): # R463
+ """
+ <enumerator> = <named-constant> [ = <scalar-int-initialization-expr> ]
+ """
+ subclass_names = ['Named_Constant']
+ use_names = ['Scalar_Int_Initialization_Expr']
+ def match(string):
+ if '=' not in string: return
+ lhs,rhs = string.split('=',1)
+ return Named_Constant(lhs.rstrip()),'=',Scalar_Int_Initialization_Expr(rhs.lstrip())
+ match = staticmethod(match)
+
+class End_Enum_Stmt(EndStmtBase): # R464
+ """
+ <end-enum-stmt> = END ENUM
+ """
+ subclass_names = []
+ def match(string): return EndStmtBase.match('ENUM',None, string, requite_stmt_type=True)
+ match = staticmethod(match)
+
+class Array_Constructor(BracketBase): # R465
+ """
+ <array-constructor> = (/ <ac-spec> /)
+ | <left-square-bracket> <ac-spec> <right-square-bracket>
+
+ """
+ subclass_names = []
+ use_names = ['Ac_Spec']
+ def match(string):
+ try:
+ obj = BracketBase.match('(//)', Ac_Spec, string)
+ except NoMatchError:
+ obj = None
+ if obj is None:
+ obj = BracketBase.match('[]', Ac_Spec, string)
+ return obj
+ match = staticmethod(match)
+
+class Ac_Spec(Base): # R466
+ """
+ <ac-spec> = <type-spec> ::
+ | [ <type-spec> :: ] <ac-value-list>
+ """
+ subclass_names = ['Ac_Value_List']
+ use_names = ['Type_Spec']
+ def match(string):
+ if string.endswith('::'):
+ return Type_Spec(string[:-2].rstrip()),None
+ line, repmap = string_replace_map(string)
+ i = line.find('::')
+ if i==-1: return
+ ts = line[:i].rstrip()
+ line = line[i+2:].lstrip()
+ ts = repmap(ts)
+ line = repmap(line)
+ return Type_Spec(ts),Ac_Value_List(line)
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None:
+ return str(self.items[1])
+ if self.items[1] is None:
+ return str(self.items[0]) + ' ::'
+ return '%s :: %s' % self.items
+
+# R467: <left-square-bracket> = [
+# R468: <right-square-bracket> = ]
+
+class Ac_Value(Base): # R469
+ """
+ <ac-value> = <expr>
+ | <ac-implied-do>
+ """
+ subclass_names = ['Ac_Implied_Do','Expr']
+
+class Ac_Implied_Do(Base): # R470
+ """
+ <ac-implied-do> = ( <ac-value-list> , <ac-implied-do-control> )
+ """
+ subclass_names = []
+ use_names = ['Ac_Value_List','Ac_Implied_Do_Control']
+ def match(string):
+ if string[0]+string[-1] != '()': return
+ line, repmap = string_replace_map(string[1:-1].strip())
+ i = line.rfind('=')
+ if i==-1: return
+ j = line[:i].rfind(',')
+ assert j!=-1
+ s1 = repmap(line[:j].rstrip())
+ s2 = repmap(line[j+1:].lstrip())
+ return Ac_Value_List(s1),Ac_Implied_Do_Control(s2)
+ match = staticmethod(match)
+ def tostr(self): return '(%s, %s)' % tuple(self.items)
+
+class Ac_Implied_Do_Control(Base): # R471
+ """
+ <ac-implied-do-control> = <ac-do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ]
+ """
+ subclass_names = []
+ use_names = ['Ac_Do_Variable','Scalar_Int_Expr']
+ def match(string):
+ i = string.find('=')
+ if i==-1: return
+ s1 = string[:i].rstrip()
+ line, repmap = string_replace_map(string[i+1:].lstrip())
+ t = line.split(',')
+ if not (2<=len(t)<=3): return
+ t = [Scalar_Int_Expr(s.strip()) for s in t]
+ return Ac_Do_Variable(s1), t
+ match = staticmethod(match)
+ def tostr(self): return '%s = %s' % (self.items[0], ', '.join(map(str,self.items[1])))
+
+class Ac_Do_Variable(Base): # R472
+ """
+ <ac-do-variable> = <scalar-int-variable>
+ <ac-do-variable> shall be a named variable
+ """
+ subclass_names = ['Scalar_Int_Variable']
+
+###############################################################################
+############################### SECTION 5 ####################################
+###############################################################################
+
+class Type_Declaration_Stmt(Base): # R501
+ """
+ <type-declaration-stmt> = <declaration-type-spec> [ [ , <attr-spec> ]... :: ] <entity-decl-list>
+ """
+ subclass_names = []
+ use_names = ['Declaration_Type_Spec', 'Attr_Spec_List', 'Entity_Decl_List']
+
+ def match(string):
+ line, repmap = string_replace_map(string)
+ i = line.find('::')
+ if i!=-1:
+ j = line[:i].find(',')
+ if j!=-1:
+ i = j
+ else:
+ if line[:6].upper()=='DOUBLE':
+ m = re.search(r'\s[a-z_]',line[6:].lstrip(),re.I)
+ if m is None: return
+ i = m.start() + len(line)-len(line[6:].lstrip())
+ else:
+ m = re.search(r'\s[a-z_]',line,re.I)
+ if m is None: return
+ i = m.start()
+ type_spec = Declaration_Type_Spec(repmap(line[:i].rstrip()))
+ if type_spec is None: return
+ line = line[i:].lstrip()
+ if line.startswith(','):
+ i = line.find('::')
+ if i==-1: return
+ attr_specs = Attr_Spec_List(repmap(line[1:i].strip()))
+ if attr_specs is None: return
+ line = line[i:]
+ else:
+ attr_specs = None
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ entity_decls = Entity_Decl_List(repmap(line))
+ if entity_decls is None: return
+ return type_spec, attr_specs, entity_decls
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None:
+ return '%s :: %s' % (self.items[0], self.items[2])
+ else:
+ return '%s, %s :: %s' % self.items
+
+class Declaration_Type_Spec(Base): # R502
+ """
+ <declaration-type-spec> = <intrinsic-type-spec>
+ | TYPE ( <derived-type-spec> )
+ | CLASS ( <derived-type-spec> )
+ | CLASS ( * )
+ """
+ subclass_names = ['Intrinsic_Type_Spec']
+ use_names = ['Derived_Type_Spec']
+
+ def match(string):
+ if string[-1] != ')': return
+ start = string[:4].upper()
+ if start == 'TYPE':
+ line = string[4:].lstrip()
+ if not line.startswith('('): return
+ return 'TYPE',Derived_Type_Spec(line[1:-1].strip())
+ start = string[:5].upper()
+ if start == 'CLASS':
+ line = string[5:].lstrip()
+ if not line.startswith('('): return
+ line = line[1:-1].strip()
+ if line=='*': return 'CLASS','*'
+ return 'CLASS', Derived_Type_Spec(line)
+ return
+ match = staticmethod(match)
+ def tostr(self): return '%s(%s)' % self.items
+
+class Dimension_Attr_Spec(CALLBase): # R503.d
+ """
+ <dimension-attr-spec> = DIMENSION ( <array-spec> )
+ """
+ subclass_names = []
+ use_names = ['Array_Spec']
+ def match(string): return CALLBase.match('DIMENSION', Array_Spec, string)
+ match = staticmethod(match)
+
+class Intent_Attr_Spec(CALLBase): # R503.f
+ """
+ <intent-attr-spec> = INTENT ( <intent-spec> )
+ """
+ subclass_names = []
+ use_names = ['Intent_Spec']
+ def match(string): return CALLBase.match('INTENT', Intent_Spec, string)
+ match = staticmethod(match)
+
+class Attr_Spec(STRINGBase): # R503
+ """
+ <attr-spec> = <access-spec>
+ | ALLOCATABLE
+ | ASYNCHRONOUS
+ | DIMENSION ( <array-spec> )
+ | EXTERNAL
+ | INTENT ( <intent-spec> )
+ | INTRINSIC
+ | <language-binding-spec>
+ | OPTIONAL
+ | PARAMETER
+ | POINTER
+ | PROTECTED
+ | SAVE
+ | TARGET
+ | VALUE
+ | VOLATILE
+ """
+ subclass_names = ['Access_Spec', 'Language_Binding_Spec',
+ 'Dimension_Attr_Spec', 'Intent_Attr_Spec']
+ use_names = []
+ def match(string): return STRINGBase.match(pattern.abs_attr_spec, string)
+ match = staticmethod(match)
+
+class Entity_Decl(Base): # R504
+ """
+ <entity-decl> = <object-name> [ ( <array-spec> ) ] [ * <char-length> ] [ <initialization> ]
+ | <function-name> [ * <char-length> ]
+ """
+ subclass_names = []
+ use_names = ['Object_Name', 'Array_Spec', 'Char_Length', 'Initialization', 'Function_Name']
+ def match(string):
+ m = pattern.name.match(string)
+ if m is None: return
+ name = Name(m.group())
+ newline = string[m.end():].lstrip()
+ if not newline: return name, None, None, None
+ array_spec = None
+ char_length = None
+ init = None
+ if newline.startswith('('):
+ line, repmap = string_replace_map(newline)
+ i = line.find(')')
+ if i==-1: return
+ array_spec = Array_Spec(repmap(line[1:i].strip()))
+ newline = repmap(line[i+1:].lstrip())
+ if newline.startswith('*'):
+ line, repmap = string_replace_map(newline)
+ i = line.find('=')
+ if i!=-1:
+ char_length = repmap(line[1:i].strip())
+ newline = repmap(newline[i:].lstrip())
+ else:
+ char_length = repmap(newline[1:].strip())
+ newline = ''
+ char_length = Char_Length(char_length)
+ if newline.startswith('='):
+ init = Initialization(newline)
+ else:
+ assert newline=='',`newline`
+ return name, array_spec, char_length, init
+ match = staticmethod(match)
+ def tostr(self):
+ s = str(self.items[0])
+ if self.items[1] is not None:
+ s += '(' + str(self.items[1]) + ')'
+ if self.items[2] is not None:
+ s += '*' + str(self.items[2])
+ if self.items[3] is not None:
+ s += ' ' + str(self.items[3])
+ return s
+
+class Object_Name(Base): # R505
+ """
+ <object-name> = <name>
+ """
+ subclass_names = ['Name']
+
+class Initialization(Base): # R506
+ """
+ <initialization> = = <initialization-expr>
+ | => <null-init>
+ """
+ subclass_names = []
+ use_names = ['Initialization_Expr', 'Null_Init']
+ def match(string):
+ if string.startswith('=>'):
+ return '=>', Null_Init(string[2:].lstrip())
+ if string.startswith('='):
+ return '=', Initialization_Expr(string[2:].lstrip())
+ return
+ match = staticmethod(match)
+ def tostr(self): return '%s %s' % self.items
+
+class Null_Init(STRINGBase): # R507
+ """
+ <null-init> = <function-reference>
+
+ <function-reference> shall be a reference to the NULL intrinsic function with no arguments.
+ """
+ subclass_names = ['Function_Reference']
+ def match(string): return STRINGBase.match('NULL', string)
+ match = staticmethod(match)
+
+class Access_Spec(STRINGBase): # R508
+ """
+ <access-spec> = PUBLIC
+ | PRIVATE
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(['PUBLIC','PRIVATE'], string)
+ match = staticmethod(match)
+
+class Language_Binding_Spec(Base): # R509
+ """
+ <language-binding-spec> = BIND ( C [ , NAME = <scalar-char-initialization-expr> ] )
+ """
+ subclass_names = []
+ use_names = ['Scalar_Char_Initialization_Expr']
+ def match(string):
+ start = string[:4].upper()
+ if start != 'BIND': return
+ line = string[4:].lstrip()
+ if not line or line[0]+line[-1]!='()': return
+ line = line[1:-1].strip()
+ if not line: return
+ start = line[0].upper()
+ if start!='C': return
+ line = line[1:].lstrip()
+ if not line: return None,
+ if not line.startswith(','): return
+ line = line[1:].lstrip()
+ start = line[:4].upper()
+ if start!='NAME': return
+ line=line[4:].lstrip()
+ if not line.startswith('='): return
+ return Scalar_Char_Initialization_Expr(line[1:].lstrip()),
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None: return 'BIND(C)'
+ return 'BIND(C, NAME = %s)' % (self.items[0])
+
+class Array_Spec(Base): # R510
+ """
+ <array-spec> = <explicit-shape-spec-list>
+ | <assumed-shape-spec-list>
+ | <deferred-shape-spec-list>
+ | <assumed-size-spec>
+ """
+ subclass_names = ['Assumed_Size_Spec', 'Explicit_Shape_Spec_List', 'Assumed_Shape_Spec_List',
+ 'Deferred_Shape_Spec_List']
+
+class Explicit_Shape_Spec(SeparatorBase): # R511
+ """
+ <explicit-shape-spec> = [ <lower-bound> : ] <upper-bound>
+ """
+ subclass_names = []
+ use_names = ['Lower_Bound', 'Upper_Bound']
+ def match(string):
+ line, repmap = string_replace_map(string)
+ if ':' not in line:
+ return None, Upper_Bound(string)
+ lower,upper = line.split(':',1)
+ lower = lower.rstrip()
+ upper = upper.lstrip()
+ if not upper: return
+ if not lower: return
+ return Lower_Bound(repmap(lower)), Upper_Bound(repmap(upper))
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None: return str(self.items[1])
+ return SeparatorBase.tostr(self)
+
+class Lower_Bound(Base): # R512
+ """
+ <lower-bound> = <specification-expr>
+ """
+ subclass_names = ['Specification_Expr']
+
+class Upper_Bound(Base): # R513
+ """
+ <upper-bound> = <specification-expr>
+ """
+ subclass_names = ['Specification_Expr']
+
+class Assumed_Shape_Spec(SeparatorBase): # R514
+ """
+ <assumed-shape-spec> = [ <lower-bound> ] :
+ """
+ subclass_names = []
+ use_names = ['Lower_Bound']
+ def match(string): return SeparatorBase.match(Lower_Bound, None, string)
+ match = staticmethod(match)
+
+class Deferred_Shape_Spec(SeparatorBase): # R515
+ """
+ <deferred_shape_spec> = :
+ """
+ subclass_names = []
+ def match(string):
+ if string==':': return None,None
+ return
+ match = staticmethod(match)
+
+class Assumed_Size_Spec(Base): # R516
+ """
+ <assumed-size-spec> = [ <explicit-shape-spec-list> , ] [ <lower-bound> : ] *
+ """
+ subclass_names = []
+ use_names = ['Explicit_Shape_Spec_List', 'Lower_Bound']
+ def match(string):
+ if not string.endswith('*'): return
+ line = string[:-1].rstrip()
+ if not line: return None,None
+ if line.endswith(':'):
+ line, repmap = string_replace_map(line[:-1].rstrip())
+ i = line.rfind(',')
+ if i==-1:
+ return None, Lower_Bound(repmap(line))
+ return Explicit_Shape_Spec_List(repmap(line[:i].rstrip())), Lower_Bound(repmap(line[i+1:].lstrip()))
+ if not line.endswith(','): return
+ line = line[:-1].rstrip()
+ return Explicit_Shape_Spec_List(line), None
+ match = staticmethod(match)
+ def tostr(self):
+ s = ''
+ if self.items[0] is not None:
+ s += str(self.items[0]) + ', '
+ if self.items[1] is not None:
+ s += str(self.items[1]) + ' : '
+ s += '*'
+ return s
+
+class Intent_Spec(STRINGBase): # R517
+ """
+ <intent-spec> = IN
+ | OUT
+ | INOUT
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(pattern.abs_intent_spec, string)
+ match = staticmethod(match)
+
+class Access_Stmt(StmtBase, WORDClsBase): # R518
+ """
+ <access-stmt> = <access-spec> [ [ :: ] <access-id-list> ]
+ """
+ subclass_names = []
+ use_names = ['Access_Spec', 'Access_Id_List']
+ def match(string): return WORDClsBase.match(['PUBLIC', 'PRIVATE'],Access_Id_List,string,check_colons=True, require_cls=False)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Access_Id(Base): # R519
+ """
+ <access-id> = <use-name>
+ | <generic-spec>
+ """
+ subclass_names = ['Use_Name', 'Generic_Spec']
+
+class Object_Name_Deferred_Shape_Spec_List_Item(CallBase):
+ """
+ <..> = <object-name> [ ( <deferred-shape-spec-list> ) ]
+ """
+ subclass_names = ['Object_Name']
+ use_names = ['Deferred_Shape_Spec_List']
+ def match(string): return CallBase.match(Object_Name, Deferred_Shape_Spec_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Allocatable_Stmt(StmtBase, WORDClsBase): # R520
+ """
+ <allocateble-stmt> = ALLOCATABLE [ :: ] <object-name> [ ( <deferred-shape-spec-list> ) ] [ , <object-name> [ ( <deferred-shape-spec-list> ) ] ]...
+ """
+ subclass_names = []
+ use_names = ['Object_Name_Deferred_Shape_Spec_List_Item_List']
+ def match(string):
+ return WORDClsBase.match('ALLOCATABLE', Object_Name_Deferred_Shape_Spec_List_Item_List, string,
+ check_colons=True, require_cls=True)
+ match = staticmethod(match)
+
+class Asynchronous_Stmt(StmtBase, WORDClsBase): # R521
+ """
+ <asynchronous-stmt> = ASYNCHRONOUS [ :: ] <object-name-list>
+ """
+ subclass_names = []
+ use_names = ['Object_Name_List']
+ def match(string): return WORDClsBase.match('ASYNCHRONOUS',Object_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+
+
+class Bind_Stmt(StmtBase): # R522
+ """
+ <bind-stmt> = <language-binding-spec> [ :: ] <bind-entity-list>
+ """
+ subclass_names = []
+ use_names = ['Language_Binding_Spec', 'Bind_Entity_List']
+ def match(string):
+ i = string.find('::')
+ if i==-1:
+ i = string.find(')')
+ if i==-1: return
+ lhs. rhs = string[:i], string[i+1:]
+ else:
+ lhs, rhs = string.split('::',1)
+ lhs = lhs.rstrip()
+ rhs = rhs.lstrip()
+ if not lhs or not rhs: return
+ return Language_Binding_Spec(lhs), Bind_Entity_List(rhs)
+ match = staticmethod(match)
+ def tostr(self):
+ return '%s :: %s' % self.items
+
+
+class Bind_Entity(BracketBase): # R523
+ """
+ <bind-entity> = <entity-name>
+ | / <common-block-name> /
+ """
+ subclass_names = ['Entity_Name']
+ use_names = ['Common_Block_Name']
+ def match(string): return BracketBase.match('//',Common_Block_Name, string)
+ match = staticmethod(match)
+
+class Data_Stmt(StmtBase): # R524
+ """
+ <data-stmt> = DATA <data-stmt-set> [ [ , ] <data-stmt-set> ]...
+ """
+ subclass_names = []
+ use_names = ['Data_Stmt_Set']
+
+class Data_Stmt_Set(Base): # R525
+ """
+ <data-stmt-set> = <data-stmt-object-list> / <data-stmt-value-list> /
+ """
+ subclass_names = []
+ use_names = ['Data_Stmt_Object_List', 'Data_Stmt_Value_List']
+
+class Data_Stmt_Object(Base): # R526
+ """
+ <data-stmt-object> = <variable>
+ | <data-implied-do>
+ """
+ subclass_names = ['Variable', 'Data_Implied_Do']
+
+class Data_Implied_Do(Base): # R527
+ """
+ <data-implied-do> = ( <data-i-do-object-list> , <data-i-do-variable> = <scalar-int-expr > , <scalar-int-expr> [ , <scalar-int-expr> ] )
+ """
+ subclass_names = []
+ use_names = ['Data_I_Do_Object_List', 'Data_I_Do_Variable', 'Scalar_Int_Expr']
+
+class Data_I_Do_Object(Base): # R528
+ """
+ <data-i-do-object> = <array-element>
+ | <scalar-structure-component>
+ | <data-implied-do>
+ """
+ subclass_names = ['Array_Element', 'Scalar_Structure_Component', 'Data_Implied_Do']
+
+class Data_I_Do_Variable(Base): # R529
+ """
+ <data-i-do-variable> = <scalar-int-variable>
+ """
+ subclass_names = ['Scalar_Int_Variable']
+
+class Data_Stmt_Value(Base): # R530
+ """
+ <data-stmt-value> = [ <data-stmt-repeat> * ] <data-stmt-constant>
+ """
+ subclass_names = ['Data_Stmt_Constant']
+ use_names = ['Data_Stmt_Repeat']
+ def match(string):
+ line, repmap = string_replace_map(string)
+ s = line.split('*')
+ if len(s)!=2: return
+ lhs = repmap(s[0].rstrip())
+ rhs = repmap(s[1].lstrip())
+ if not lhs or not rhs: return
+ return Data_Stmt_Repeat(lhs), Data_Stmt_Constant(rhs)
+ match = staticmethod(match)
+ def tostr(self):
+ return '%s * %s' % self.items
+
+class Data_Stmt_Repeat(Base): # R531
+ """
+ <data-stmt-repeat> = <scalar-int-constant>
+ | <scalar-int-constant-subobject>
+ """
+ subclass_names = ['Scalar_Int_Constant', 'Scalar_Int_Constant_Subobject']
+
+class Data_Stmt_Constant(Base): # R532
+ """
+ <data-stmt-constant> = <scalar-constant>
+ | <scalar-constant-subobject>
+ | <signed-int-literal-constant>
+ | <signed-real-literal-constant>
+ | <null-init>
+ | <structure-constructor>
+ """
+ subclass_names = ['Scalar_Constant', 'Scalar_Constant_Subobject',
+ 'Signed_Int_Literal_Constant', 'Signed_Real_Literal_Constant',
+ 'Null_Init', 'Structure_Constructor']
+
+class Int_Constant_Subobject(Base): # R533
+ """
+ <int-constant-subobject> = <constant-subobject>
+ """
+ subclass_names = ['Constant_Subobject']
+
+class Constant_Subobject(Base): # R534
+ """
+ <constant-subobject> = <designator>
+ """
+ subclass_names = ['Designator']
+
+class Dimension_Stmt(StmtBase): # R535
+ """
+ <dimension-stmt> = DIMENSION [ :: ] <array-name> ( <array-spec> ) [ , <array-name> ( <array-spec> ) ]...
+ """
+ subclass_names = []
+ use_names = ['Array_Name', 'Array_Spec']
+ def match(string):
+ if string[:9].upper()!='DIMENSION': return
+ line, repmap = string_replace_map(string[9:].lstrip())
+ if line.startswith('::'): line = line[2:].lstrip()
+ decls = []
+ for s in line.split(','):
+ s = s.strip()
+ if not s.endswith(')'): return
+ i = s.find('(')
+ if i==-1: return
+ decls.append((Array_Name(repmap(s[:i].rstrip())), Array_Spec(repmap(s[i+1:-1].strip()))))
+ if not decls: return
+ return decls,
+ match = staticmethod(match)
+ def tostr(self):
+ return 'DIMENSION :: ' + ', '.join(['%s(%s)' % ns for ns in self.items[0]])
+
+class Intent_Stmt(StmtBase): # R536
+ """
+ <intent-stmt> = INTENT ( <intent-spec> ) [ :: ] <dummy-arg-name-list>
+ """
+ subclass_names = []
+ use_names = ['Intent_Spec', 'Dummy_Arg_Name_List']
+ def match(string):
+ if string[:6].upper()!='INTENT': return
+ line = string[6:].lstrip()
+ if not line or not line.startswith('('): return
+ i = line.rfind(')')
+ if i==-1: return
+ spec = line[1:i].strip()
+ if not spec: return
+ line = line[i+1:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ if not line: return
+ return Intent_Spec(spec), Dummy_Arg_Name_List(line)
+ match = staticmethod(match)
+ def tostr(self):
+ return 'INTENT(%s) :: %s' % self.items
+
+class Optional_Stmt(StmtBase, WORDClsBase): # R537
+ """
+ <optional-stmt> = OPTIONAL [ :: ] <dummy-arg-name-list>
+ """
+ subclass_names = []
+ use_names = ['Dummy_Arg_Name_List']
+ def match(string): return WORDClsBase.match('OPTIONAL',Dummy_Arg_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Parameter_Stmt(StmtBase, CALLBase): # R538
+ """
+ <parameter-stmt> = PARAMETER ( <named-constant-def-list> )
+ """
+ subclass_names = []
+ use_names = ['Named_Constant_Def_List']
+ def match(string): return CALLBase.match('PARAMETER', Named_Constant_Def_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Named_Constant_Def(KeywordValueBase): # R539
+ """
+ <named-constant-def> = <named-constant> = <initialization-expr>
+ """
+ subclass_names = []
+ use_names = ['Named_Constant', 'Initialization_Expr']
+ def match(string): return KeywordValueBase.match(Named_Constant, Initialization_Expr, string)
+ match = staticmethod(match)
+
+class Pointer_Stmt(StmtBase, WORDClsBase): # R540
+ """
+ <pointer-stmt> = POINTER [ :: ] <pointer-decl-list>
+ """
+ subclass_names = []
+ use_names = ['Pointer_Decl_List']
+ def match(string): return WORDClsBase.match('POINTER',Pointer_Decl_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Pointer_Decl(CallBase): # R541
+ """
+ <pointer-decl> = <object-name> [ ( <deferred-shape-spec-list> ) ]
+ | <proc-entity-name>
+ """
+ subclass_names = ['Proc_Entity_Name', 'Object_Name']
+ use_names = ['Deferred_Shape_Spec_List']
+ def match(string): return CallBase.match(Object_Name, Deferred_Shape_Spec_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Protected_Stmt(StmtBase, WORDClsBase): # R542
+ """
+ <protected-stmt> = PROTECTED [ :: ] <entity-name-list>
+ """
+ subclass_names = []
+ use_names = ['Entity_Name_List']
+ def match(string): return WORDClsBase.match('PROTECTED',Entity_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Save_Stmt(StmtBase, WORDClsBase): # R543
+ """
+ <save-stmt> = SAVE [ [ :: ] <saved-entity-list> ]
+ """
+ subclass_names = []
+ use_names = ['Saved_Entity_List']
+ def match(string): return WORDClsBase.match('SAVE',Saved_Entity_List,string,check_colons=True, require_cls=False)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Saved_Entity(BracketBase): # R544
+ """
+ <saved-entity> = <object-name>
+ | <proc-pointer-name>
+ | / <common-block-name> /
+ """
+ subclass_names = ['Object_Name', 'Proc_Pointer_Name']
+ use_names = ['Common_Block_Name']
+ def match(string): return BracketBase.match('//',CommonBlockName, string)
+ match = staticmethod(match)
+
+class Proc_Pointer_Name(Base): # R545
+ """
+ <proc-pointer-name> = <name>
+ """
+ subclass_names = ['Name']
+
+class Target_Stmt(StmtBase): # R546
+ """
+ <target-stmt> = TARGET [ :: ] <object-name> [ ( <array-spec> ) ] [ , <object-name> [ ( <array-spec> ) ] ]...
+ """
+ subclass_names = []
+ use_names = ['Object_Name', 'Array_Spec']
+
+class Value_Stmt(StmtBase, WORDClsBase): # R547
+ """
+ <value-stmt> = VALUE [ :: ] <dummy-arg-name-list>
+ """
+ subclass_names = []
+ use_names = ['Dummy_Arg_Name_List']
+ def match(string): return WORDClsBase.match('VALUE',Dummy_Arg_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Volatile_Stmt(StmtBase, WORDClsBase): # R548
+ """
+ <volatile-stmt> = VOLATILE [ :: ] <object-name-list>
+ """
+ subclass_names = []
+ use_names = ['Object_Name_List']
+ def match(string): return WORDClsBase.match('VOLATILE',Object_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Implicit_Stmt(StmtBase, WORDClsBase): # R549
+ """
+ <implicit-stmt> = IMPLICIT <implicit-spec-list>
+ | IMPLICIT NONE
+ """
+ subclass_names = []
+ use_names = ['Implicit_Spec_List']
+ def match(string):
+ for w,cls in [(pattern.abs_implicit_none, None),
+ ('IMPLICIT', Implicit_Spec_List)]:
+ try:
+ obj = WORDClsBase.match(w, cls, string)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return
+ match = staticmethod(match)
+
+class Implicit_Spec(CallBase): # R550
+ """
+ <implicit-spec> = <declaration-type-spec> ( <letter-spec-list> )
+ """
+ subclass_names = []
+ use_names = ['Declaration_Type_Spec', 'Letter_Spec_List']
+ def match(string):
+ if not string.endswith(')'): return
+ i = string.rfind('(')
+ if i==-1: return
+ s1 = string[:i].rstrip()
+ s2 = string[i+1:-1].strip()
+ if not s1 or not s2: return
+ return Declaration_Type_Spec(s1), Letter_Spec_List(s2)
+ match = staticmethod(match)
+
+class Letter_Spec(Base): # R551
+ """
+ <letter-spec> = <letter> [ - <letter> ]
+ """
+ subclass_names = []
+ def match(string):
+ if len(string)==1:
+ lhs = string.upper()
+ if 'A'<=lhs<='Z': return lhs, None
+ return
+ if '-' not in string: return
+ lhs,rhs = string.split('-',1)
+ lhs = lhs.strip().upper()
+ rhs = rhs.strip().upper()
+ if not len(lhs)==len(rhs)==1: return
+ if not ('A'<=lhs<=rhs<='Z'): return
+ return lhs,rhs
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return str(self.items[0])
+ return '%s - %s' % tuple(self.items)
+
+class Namelist_Stmt(StmtBase): # R552
+ """
+ <namelist-stmt> = NAMELIST / <namelist-group-name> / <namelist-group-object-list> [ [ , ] / <namelist-group-name> / <namelist-group-object-list> ]
+ """
+ subclass_names = []
+ use_names = ['Namelist_Group_Name', 'Namelist_Group_Object_List']
+
+class Namelist_Group_Object(Base): # R553
+ """
+ <namelist-group-object> = <variable-name>
+ """
+ subclass_names = ['Variable_Name']
+
+class Equivalence_Stmt(StmtBase, WORDClsBase): # R554
+ """
+ <equivalence-stmt> = EQUIVALENCE <equivalence-set-list>
+ """
+ subclass_names = []
+ use_names = ['Equivalence_Set_List']
+ def match(string): return WORDClsBase.match('EQUIVALENCE', Equivalence_Set_List, string)
+ match = staticmethod(match)
+
+class Equivalence_Set(Base): # R555
+ """
+ <equivalence-set> = ( <equivalence-object> , <equivalence-object-list> )
+ """
+ subclass_names = []
+ use_names = ['Equivalence_Object', 'Equivalence_Object_List']
+ def match(string):
+ if not string or string[0]+string[-1]!='()': return
+ line = string[1:-1].strip()
+ if not line: return
+ l = Equivalence_Object_List(line)
+ obj = l.items[0]
+ l.items = l.items[1:]
+ if not l.items: return
+ return obj, l
+ match = staticmethod(match)
+ def tostr(self): return '(%s, %s)' % tuple(self.items)
+
+class Equivalence_Object(Base): # R556
+ """
+ <equivalence-object> = <variable-name>
+ | <array-element>
+ | <substring>
+ """
+ subclass_names = ['Variable_Name', 'Array_Element', 'Substring']
+
+class Common_Stmt(StmtBase): # R557
+ """
+ <common-stmt> = COMMON [ / [ <common-block-name> ] / ] <common-block-object-list> [ [ , ] / [ <common-block-name> ] / <common-block-object-list> ]...
+ """
+ subclass_names = []
+ use_names = ['Common_Block_Name', 'Common_Block_Object_List']
+ def match(string):
+ if string[:6].upper()!='COMMON': return
+ line = string[6:]
+ if not line or 'A'<=line[0].upper()<='Z' or line[0]=='_': return
+ line, repmap = string_replace_map(line.lstrip())
+ items = []
+ if line.startswith('/'):
+ i = line.find('/',1)
+ if i==-1: return
+ name = line[1:i].strip() or None
+ if name is not None: name = Common_Block_Name(name)
+ line = line[i+1:].lstrip()
+ i = line.find('/')
+ if i==-1:
+ lst = Common_Block_Object_List(repmap(line))
+ line = ''
+ else:
+ l = line[:i].rstrip()
+ if l.endswith(','): l = l[:-1].rstrip()
+ if not l: return
+ lst = Common_Block_Object_List(repmap(l))
+ line = line[i:].lstrip()
+ else:
+ name = None
+ i = line.find('/')
+ if i==-1:
+ lst = Common_Block_Object_List(repmap(line))
+ line = ''
+ else:
+ l = line[:i].rstrip()
+ if l.endswith(','): l = l[:-1].rstrip()
+ if not l: return
+ lst = Common_Block_Object_List(repmap(l))
+ line = line[i:].lstrip()
+ items.append((name, lst))
+ while line:
+ if line.startswith(','): line = line[1:].lstrip()
+ if not line.startswith('/'): return
+ i = line.find('/',1)
+ name = line[1:i].strip() or None
+ if name is not None: name = Common_Block_Name(name)
+ line = line[i+1:].lstrip()
+ i = line.find('/')
+ if i==-1:
+ lst = Common_Block_Object_List(repmap(line))
+ line = ''
+ else:
+ l = line[:i].rstrip()
+ if l.endswith(','): l = l[:-1].rstrip()
+ if not l: return
+ lst = Common_Block_Object_List(repmap(l))
+ line = line[i:].lstrip()
+ items.append((name, lst))
+ return items,
+ match = staticmethod(match)
+ def tostr(self):
+ s = 'COMMON'
+ for (name, lst) in self.items[0]:
+ if name is not None:
+ s += ' /%s/ %s' % (name, lst)
+ else:
+ s += ' // %s' % (lst)
+ return s
+
+class Common_Block_Object(CallBase): # R558
+ """
+ <common-block-object> = <variable-name> [ ( <explicit-shape-spec-list> ) ]
+ | <proc-pointer-name>
+ """
+ subclass_names = ['Proc_Pointer_Name','Variable_Name']
+ use_names = ['Variable_Name', 'Explicit_Shape_Spec_List']
+ def match(string): return CallBase.match(Variable_Name, Explicit_Shape_Spec_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+###############################################################################
+############################### SECTION 6 ####################################
+###############################################################################
+
+class Variable(Base): # R601
+ """
+ <variable> = <designator>
+ """
+ subclass_names = ['Designator']
+
+class Variable_Name(Base): # R602
+ """
+ <variable-name> = <name>
+ """
+ subclass_names = ['Name']
+
+class Designator(Base): # R603
+ """
+ <designator> = <object-name>
+ | <array-element>
+ | <array-section>
+ | <structure-component>
+ | <substring>
+ <substring-range> = [ <scalar-int-expr> ] : [ <scalar-int-expr> ]
+ <structure-component> = <data-ref>
+ """
+ subclass_names = ['Object_Name','Array_Section','Array_Element','Structure_Component',
+ 'Substring'
+ ]
+
+class Logical_Variable(Base): # R604
+ """
+ <logical-variable> = <variable>
+ """
+ subclass_names = ['Variable']
+
+class Default_Logical_Variable(Base): # R605
+ """
+ <default-logical-variable> = <variable>
+ """
+ subclass_names = ['Variable']
+
+class Char_Variable(Base): # R606
+ """
+ <char-variable> = <variable>
+ """
+ subclass_names = ['Variable']
+
+class Default_Char_Variable(Base): # R607
+ """
+ <default-char-variable> = <variable>
+ """
+ subclass_names = ['Variable']
+
+
+class Int_Variable(Base): # R608
+ """
+ <int-variable> = <variable>
+ """
+ subclass_names = ['Variable']
+
+
+class Substring(CallBase): # R609
+ """
+ <substring> = <parent-string> ( <substring-range> )
+ """
+ subclass_names = []
+ use_names = ['Parent_String','Substring_Range']
+ def match(string): return CallBase.match(Parent_String, Substring_Range, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Parent_String(Base): # R610
+ """
+ <parent-string> = <scalar-variable-name>
+ | <array-element>
+ | <scalar-structure-component>
+ | <scalar-constant>
+ """
+ subclass_names = ['Scalar_Variable_Name', 'Array_Element', 'Scalar_Structure_Component', 'Scalar_Constant']
+
+class Substring_Range(SeparatorBase): # R611
+ """
+ <substring-range> = [ <scalar-int-expr> ] : [ <scalar-int-expr> ]
+ """
+ subclass_names = []
+ use_names = ['Scalar_Int_Expr']
+ def match(string):
+ return SeparatorBase.match(Scalar_Int_Expr, Scalar_Int_Expr, string)
+ match = staticmethod(match)
+
+class Data_Ref(SequenceBase): # R612
+ """
+ <data-ref> = <part-ref> [ % <part-ref> ]...
+ """
+ subclass_names = ['Part_Ref']
+ use_names = []
+ def match(string): return SequenceBase.match(r'%', Part_Ref, string)
+ match = staticmethod(match)
+
+class Part_Ref(CallBase): # R613
+ """
+ <part-ref> = <part-name> [ ( <section-subscript-list> ) ]
+ """
+ subclass_names = ['Part_Name']
+ use_names = ['Section_Subscript_List']
+ def match(string):
+ return CallBase.match(Part_Name, Section_Subscript_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Structure_Component(Base): # R614
+ """
+ <structure-component> = <data-ref>
+ """
+ subclass_names = ['Data_Ref']
+
+class Type_Param_Inquiry(BinaryOpBase): # R615
+ """
+ <type-param-inquiry> = <designator> % <type-param-name>
+ """
+ subclass_names = []
+ use_names = ['Designator','Type_Param_Name']
+ def match(string):
+ return BinaryOpBase.match(\
+ Designator, pattern.percent_op.named(), Type_Param_Name, string)
+ match = staticmethod(match)
+
+class Array_Element(Base): # R616
+ """
+ <array-element> = <data-ref>
+ """
+ subclass_names = ['Data_Ref']
+
+class Array_Section(CallBase): # R617
+ """
+ <array-section> = <data-ref> [ ( <substring-range> ) ]
+ """
+ subclass_names = ['Data_Ref']
+ use_names = ['Substring_Range']
+ def match(string): return CallBase.match(Data_Ref, Substring_Range, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Subscript(Base): # R618
+ """
+ <subscript> = <scalar-int-expr>
+ """
+ subclass_names = ['Scalar_Int_Expr']
+
+class Section_Subscript(Base): # R619
+ """
+ <section-subscript> = <subscript>
+ | <subscript-triplet>
+ | <vector-subscript>
+ """
+ subclass_names = ['Subscript_Triplet', 'Vector_Subscript', 'Subscript']
+
+class Subscript_Triplet(Base): # R620
+ """
+ <subscript-triplet> = [ <subscript> ] : [ <subscript> ] [ : <stride> ]
+ """
+ subclass_names = []
+ use_names = ['Subscript','Stride']
+ def match(string):
+ line, repmap = string_replace_map(string)
+ t = line.split(':')
+ if len(t)<=1 or len(t)>3: return
+ lhs_obj,rhs_obj, stride_obj = None, None, None
+ if len(t)==2:
+ lhs,rhs = t[0].rstrip(),t[1].lstrip()
+ else:
+ lhs,rhs,stride = t[0].rstrip(),t[1].strip(),t[2].lstrip()
+ if stride:
+ stride_obj = Stride(repmap(stride))
+ if lhs:
+ lhs_obj = Subscript(repmap(lhs))
+ if rhs:
+ rhs_obj = Subscript(repmap(rhs))
+ return lhs_obj, rhs_obj, stride_obj
+ match = staticmethod(match)
+ def tostr(self):
+ s = ''
+ if self.items[0] is not None:
+ s += str(self.items[0]) + ' :'
+ else:
+ s += ':'
+ if self.items[1] is not None:
+ s += ' ' + str(self.items[1])
+ if self.items[2] is not None:
+ s += ' : ' + str(self.items[2])
+ return s
+
+class Stride(Base): # R621
+ """
+ <stride> = <scalar-int-expr>
+ """
+ subclass_names = ['Scalar_Int_Expr']
+
+class Vector_Subscript(Base): # R622
+ """
+ <vector-subscript> = <int-expr>
+ """
+ subclass_names = ['Int_Expr']
+
+class Allocate_Stmt(StmtBase): # R623
+ """
+ <allocate-stmt> = ALLOCATE ( [ <type-spec> :: ] <allocation-list> [ , <alloc-opt-list> ] )
+ """
+ subclass_names = []
+ use_names = ['Type_Spec', 'Allocation_List', 'Alloc_Opt_List']
+
+class Alloc_Opt(KeywordValueBase):# R624
+ """
+ <alloc-opt> = STAT = <stat-variable>
+ | ERRMSG = <errmsg-variable>
+ | SOURCE = <source-expr>
+ """
+ subclass_names = []
+ use_names = ['Stat_Variable', 'Errmsg_Variable', 'Source_Expr']
+ def match(string):
+ for (k,v) in [('STAT', Stat_Variable),
+ ('ERRMSG', Errmsg_Variable),
+ ('SOURCE', Source_Expr)
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return
+ match = staticmethod(match)
+
+
+class Stat_Variable(Base):# R625
+ """
+ <stat-variable> = <scalar-int-variable>
+ """
+ subclass_names = ['Scalar_Int_Variable']
+
+class Errmsg_Variable(Base):# R626
+ """
+ <errmsg-variable> = <scalar-default-char-variable>
+ """
+ subclass_names = ['Scalar_Default_Char_Variable']
+
+class Source_Expr(Base):# R627
+ """
+ <source-expr> = <expr>
+ """
+ subclass_names = ['Expr']
+
+class Allocation(CallBase):# R628
+ """
+ <allocation> = <allocate-object> [ ( <allocate-shape-spec-list> ) ]
+ | <variable-name>
+ """
+ subclass_names = ['Variable_Name', 'Allocate_Object']
+ use_names = ['Allocate_Shape_Spec_List']
+ def match(string):
+ return CallBase.match(Allocate_Object, Allocate_Shape_Spec_List, string, require_rhs = True)
+ match = staticmethod(match)
+
+class Allocate_Object(Base): # R629
+ """
+ <allocate-object> = <variable-name>
+ | <structure-component>
+ """
+ subclass_names = ['Variable_Name', 'Structure_Component']
+
+class Allocate_Shape_Spec(SeparatorBase): # R630
+ """
+ <allocate-shape-spec> = [ <lower-bound-expr> : ] <upper-bound-expr>
+ """
+ subclass_names = []
+ use_names = ['Lower_Bound_Expr', 'Upper_Bound_Expr']
+ def match(string):
+ line, repmap = string_replace_map(string)
+ if ':' not in line: return None, Upper_Bound_Expr(string)
+ lower,upper = line.split(':',1)
+ lower = lower.rstrip()
+ upper = upper.lstrip()
+ if not upper: return
+ if not lower: return
+ return Lower_Bound_Expr(repmap(lower)), Upper_Bound_Expr(repmap(upper))
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None: return str(self.items[1])
+ return SeparatorBase.tostr(self)
+
+
+class Lower_Bound_Expr(Base): # R631
+ """
+ <lower-bound-expr> = <scalar-int-expr>
+ """
+ subclass_names = ['Scalar_Int_Expr']
+
+class Upper_Bound_Expr(Base): # R632
+ """
+ <upper-bound-expr> = <scalar-int-expr>
+ """
+ subclass_names = ['Scalar_Int_Expr']
+
+class Nullify_Stmt(StmtBase, CALLBase): # R633
+ """
+ <nullify-stmt> = NULLIFY ( <pointer-object-list> )
+ """
+ subclass_names = []
+ use_names = ['Pointer_Object_List']
+ def match(string): return CALLBase.match('NULLIFY', Pointer_Object_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Pointer_Object(Base): # R634
+ """
+ <pointer-object> = <variable-name>
+ | <structure-component>
+ | <proc-pointer-name>
+ """
+ subclass_names = ['Variable_Name', 'Structure_Component', 'Proc_Pointer_Name']
+
+class Deallocate_Stmt(StmtBase): # R635
+ """
+ <deallocate-stmt> = DEALLOCATE ( <allocate-object-list> [ , <dealloc-opt-list> ] )
+ """
+ subclass_names = []
+ use_names = ['Allocate_Object_List', 'Dealloc_Opt_List']
+
+class Dealloc_Opt(KeywordValueBase): # R636
+ """
+ <dealloc-opt> = STAT = <stat-variable>
+ | ERRMSG = <errmsg-variable>
+ """
+ subclass_names = []
+ use_names = ['Stat_Variable', 'Errmsg_Variable']
+ def match(string):
+ for (k,v) in [('STAT', Stat_Variable),
+ ('ERRMSG', Errmsg_Variable),
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return
+ match = staticmethod(match)
+
+class Scalar_Char_Initialization_Expr(Base):
+ subclass_names = ['Char_Initialization_Expr']
+
+###############################################################################
+############################### SECTION 7 ####################################
+###############################################################################
+
+class Primary(Base): # R701
+ """
+ <primary> = <constant>
+ | <designator>
+ | <array-constructor>
+ | <structure-constructor>
+ | <function-reference>
+ | <type-param-inquiry>
+ | <type-param-name>
+ | ( <expr> )
+ """
+ subclass_names = ['Constant', 'Parenthesis', 'Designator','Array_Constructor',
+ 'Structure_Constructor',
+ 'Function_Reference', 'Type_Param_Inquiry', 'Type_Param_Name',
+ ]
+
+class Parenthesis(BracketBase): # R701.h
+ """
+ <parenthesis> = ( <expr> )
+ """
+ subclass_names = []
+ use_names = ['Expr']
+ def match(string): return BracketBase.match('()', Expr, string)
+ match = staticmethod(match)
+
+class Level_1_Expr(UnaryOpBase): # R702
+ """
+ <level-1-expr> = [ <defined-unary-op> ] <primary>
+ <defined-unary-op> = . <letter> [ <letter> ]... .
+ """
+ subclass_names = ['Primary']
+ use_names = []
+ def match(string):
+ if pattern.non_defined_binary_op.match(string):
+ raise NoMatchError,'%s: %r' % (Level_1_Expr.__name__, string)
+ return UnaryOpBase.match(\
+ pattern.defined_unary_op.named(),Primary,string)
+ match = staticmethod(match)
+
+class Defined_Unary_Op(STRINGBase): # R703
+ """
+ <defined-unary-op> = . <letter> [ <letter> ]... .
+ """
+ subclass_names = ['Defined_Op']
+
+
+class Defined_Op(STRINGBase): # R703, 723
+ """
+ <defined-op> = . <letter> [ <letter> ]... .
+ """
+ subclass_names = []
+ def match(string):
+ if pattern.non_defined_binary_op.match(string):
+ raise NoMatchError,'%s: %r' % (Defined_Unary_Op.__name__, string)
+ return STRINGBase.match(pattern.abs_defined_op, string)
+ match = staticmethod(match)
+
+class Mult_Operand(BinaryOpBase): # R704
+ """
+ <mult-operand> = <level-1-expr> [ <power-op> <mult-operand> ]
+ <power-op> = **
+ """
+ subclass_names = ['Level_1_Expr']
+ use_names = ['Mult_Operand']
+ def match(string):
+ return BinaryOpBase.match(\
+ Level_1_Expr,pattern.power_op.named(),Mult_Operand,string,right=False)
+ match = staticmethod(match)
+
+class Add_Operand(BinaryOpBase): # R705
+ """
+ <add-operand> = [ <add-operand> <mult-op> ] <mult-operand>
+ <mult-op> = *
+ | /
+ """
+ subclass_names = ['Mult_Operand']
+ use_names = ['Add_Operand','Mult_Operand']
+ def match(string):
+ return BinaryOpBase.match(Add_Operand,pattern.mult_op.named(),Mult_Operand,string)
+ match = staticmethod(match)
+
+class Level_2_Expr(BinaryOpBase): # R706
+ """
+ <level-2-expr> = [ [ <level-2-expr> ] <add-op> ] <add-operand>
+ <level-2-expr> = [ <level-2-expr> <add-op> ] <add-operand>
+ | <level-2-unary-expr>
+ <add-op> = +
+ | -
+ """
+ subclass_names = ['Level_2_Unary_Expr']
+ use_names = ['Level_2_Expr']
+ def match(string):
+ return BinaryOpBase.match(\
+ Level_2_Expr,pattern.add_op.named(),Add_Operand,string)
+ match = staticmethod(match)
+
+class Level_2_Unary_Expr(UnaryOpBase): # R706.c
+ """
+ <level-2-unary-expr> = [ <add-op> ] <add-operand>
+ """
+ subclass_names = ['Add_Operand']
+ use_names = []
+ def match(string): return UnaryOpBase.match(pattern.add_op.named(),Add_Operand,string)
+ match = staticmethod(match)
+
+#R707: <power-op> = **
+#R708: <mult-op> = * | /
+#R709: <add-op> = + | -
+
+class Level_3_Expr(BinaryOpBase): # R710
+ """
+ <level-3-expr> = [ <level-3-expr> <concat-op> ] <level-2-expr>
+ <concat-op> = //
+ """
+ subclass_names = ['Level_2_Expr']
+ use_names =['Level_3_Expr']
+ def match(string):
+ return BinaryOpBase.match(\
+ Level_3_Expr,pattern.concat_op.named(),Level_2_Expr,string)
+ match = staticmethod(match)
+
+#R711: <concat-op> = //
+
+class Level_4_Expr(BinaryOpBase): # R712
+ """
+ <level-4-expr> = [ <level-3-expr> <rel-op> ] <level-3-expr>
+ <rel-op> = .EQ. | .NE. | .LT. | .LE. | .GT. | .GE. | == | /= | < | <= | > | >=
+ """
+ subclass_names = ['Level_3_Expr']
+ use_names = []
+ def match(string):
+ return BinaryOpBase.match(\
+ Level_3_Expr,pattern.rel_op.named(),Level_3_Expr,string)
+ match = staticmethod(match)
+
+#R713: <rel-op> = .EQ. | .NE. | .LT. | .LE. | .GT. | .GE. | == | /= | < | <= | > | >=
+
+class And_Operand(UnaryOpBase): # R714
+ """
+ <and-operand> = [ <not-op> ] <level-4-expr>
+ <not-op> = .NOT.
+ """
+ subclass_names = ['Level_4_Expr']
+ use_names = []
+ def match(string):
+ return UnaryOpBase.match(\
+ pattern.not_op.named(),Level_4_Expr,string)
+ match = staticmethod(match)
+
+class Or_Operand(BinaryOpBase): # R715
+ """
+ <or-operand> = [ <or-operand> <and-op> ] <and-operand>
+ <and-op> = .AND.
+ """
+ subclass_names = ['And_Operand']
+ use_names = ['Or_Operand','And_Operand']
+ def match(string):
+ return BinaryOpBase.match(\
+ Or_Operand,pattern.and_op.named(),And_Operand,string)
+ match = staticmethod(match)
+
+class Equiv_Operand(BinaryOpBase): # R716
+ """
+ <equiv-operand> = [ <equiv-operand> <or-op> ] <or-operand>
+ <or-op> = .OR.
+ """
+ subclass_names = ['Or_Operand']
+ use_names = ['Equiv_Operand']
+ def match(string):
+ return BinaryOpBase.match(\
+ Equiv_Operand,pattern.or_op.named(),Or_Operand,string)
+ match = staticmethod(match)
+
+
+class Level_5_Expr(BinaryOpBase): # R717
+ """
+ <level-5-expr> = [ <level-5-expr> <equiv-op> ] <equiv-operand>
+ <equiv-op> = .EQV.
+ | .NEQV.
+ """
+ subclass_names = ['Equiv_Operand']
+ use_names = ['Level_5_Expr']
+ def match(string):
+ return BinaryOpBase.match(\
+ Level_5_Expr,pattern.equiv_op.named(),Equiv_Operand,string)
+ match = staticmethod(match)
+
+#R718: <not-op> = .NOT.
+#R719: <and-op> = .AND.
+#R720: <or-op> = .OR.
+#R721: <equiv-op> = .EQV. | .NEQV.
+
+class Expr(BinaryOpBase): # R722
+ """
+ <expr> = [ <expr> <defined-binary-op> ] <level-5-expr>
+ <defined-binary-op> = . <letter> [ <letter> ]... .
+ TODO: defined_binary_op must not be intrinsic_binary_op!!
+ """
+ subclass_names = ['Level_5_Expr']
+ use_names = ['Expr']
+ def match(string):
+ return BinaryOpBase.match(Expr, pattern.defined_binary_op.named(), Level_5_Expr,
+ string)
+ match = staticmethod(match)
+
+class Defined_Unary_Op(STRINGBase): # R723
+ """
+ <defined-unary-op> = . <letter> [ <letter> ]... .
+ """
+ subclass_names = ['Defined_Op']
+
+class Logical_Expr(Base): # R724
+ """
+ <logical-expr> = <expr>
+ """
+ subclass_names = ['Expr']
+
+class Char_Expr(Base): # R725
+ """
+ <char-expr> = <expr>
+ """
+ subclass_names = ['Expr']
+
+class Default_Char_Expr(Base): # R726
+ """
+ <default-char-expr> = <expr>
+ """
+ subclass_names = ['Expr']
+
+class Int_Expr(Base): # R727
+ """
+ <int-expr> = <expr>
+ """
+ subclass_names = ['Expr']
+
+class Numeric_Expr(Base): # R728
+ """
+ <numeric-expr> = <expr>
+ """
+ subclass_names = ['Expr']
+
+class Specification_Expr(Base): # R729
+ """
+ <specification-expr> = <scalar-int-expr>
+ """
+ subclass_names = ['Scalar_Int_Expr']
+
+class Initialization_Expr(Base): # R730
+ """
+ <initialization-expr> = <expr>
+ """
+ subclass_names = ['Expr']
+
+class Char_Initialization_Expr(Base): # R731
+ """
+ <char-initialization-expr> = <char-expr>
+ """
+ subclass_names = ['Char_Expr']
+
+class Int_Initialization_Expr(Base): # R732
+ """
+ <int-initialization-expr> = <int-expr>
+ """
+ subclass_names = ['Int_Expr']
+
+class Logical_Initialization_Expr(Base): # R733
+ """
+ <logical-initialization-expr> = <logical-expr>
+ """
+ subclass_names = ['Logical_Expr']
+
+class Assignment_Stmt(StmtBase, BinaryOpBase): # R734
+ """
+ <assignment-stmt> = <variable> = <expr>
+ """
+ subclass_names = []
+ use_names = ['Variable', 'Expr']
+ def match(string):
+ return BinaryOpBase.match(Variable, '=', Expr, string, right=False)
+ match = staticmethod(match)
+
+class Pointer_Assignment_Stmt(StmtBase): # R735
+ """
+ <pointer-assignment-stmt> = <data-pointer-object> [ ( <bounds-spec-list> ) ] => <data-target>
+ | <data-pointer-object> ( <bounds-remapping-list> ) => <data-target>
+ | <proc-pointer-object> => <proc-target>
+ """
+ subclass_names = []
+ use_names = ['Data_Pointer_Object', 'Bounds_Spec_List', 'Data_Target', 'Bounds_Remapping_List',
+ 'Proc_Pointer_Object', 'Proc_Target']
+
+class Data_Pointer_Object(BinaryOpBase): # R736
+ """
+ <data-pointer-object> = <variable-name>
+ | <variable> % <data-pointer-component-name>
+ """
+ subclass_names = ['Variable_Name']
+ use_names = ['Variable', 'Data_Pointer_Component_Name']
+ def match(string):
+ return BinaryOpBase.match(Variable, r'%', Data_Pointer_Component_Name, string)
+ match = staticmethod(match)
+
+class Bounds_Spec(SeparatorBase): # R737
+ """
+ <bounds-spec> = <lower-bound-expr> :
+ """
+ subclass_names = []
+ use_names = ['Lower_Bound_Expr']
+ def match(string): return SeparatorBase.match(Lower_Bound_Expr, None, string, require_lhs=True)
+ match = staticmethod(match)
+
+class Bounds_Remapping(SeparatorBase): # R738
+ """
+ <bounds-remapping> = <lower-bound-expr> : <upper-bound-expr>
+ """
+ subclass_names = []
+ use_classes = ['Lower_Bound_Expr', 'Upper_Bound_Expr']
+ def match(string): return SeparatorBase.match(Lower_Bound_Expr, Upper_Bound_Expr, string, require_lhs=True, require_rhs=True)
+ match = staticmethod(match)
+
+class Data_Target(Base): # R739
+ """
+ <data-target> = <variable>
+ | <expr>
+ """
+ subclass_names = ['Variable','Expr']
+
+class Proc_Pointer_Object(Base): # R740
+ """
+ <proc-pointer-object> = <proc-pointer-name>
+ | <proc-component-ref>
+ """
+ subclass_names = ['Proc_Pointer_Name', 'Proc_Component_Ref']
+
+class Proc_Component_Ref(BinaryOpBase): # R741
+ """
+ <proc-component-ref> = <variable> % <procedure-component-name>
+ """
+ subclass_names = []
+ use_names = ['Variable','Procedure_Component_Name']
+ def match(string):
+ return BinaryOpBase.match(Variable, r'%', Procedure_Component_Name, string)
+ match = staticmethod(match)
+
+class Proc_Target(Base): # R742
+ """
+ <proc-target> = <expr>
+ | <procedure-name>
+ | <proc-component-ref>
+ """
+ subclass_names = ['Proc_Component_Ref', 'Procedure_Name', 'Expr']
+
+
+class Where_Stmt(StmtBase): # R743
+ """
+ <where-stmt> = WHERE ( <mask-expr> ) <where-assignment-stmt>
+ """
+ subclass_names = []
+ use_names = ['Mask_Expr', 'Where_Assignment_Stmt']
+ def match(string):
+ if string[:5].upper()!='WHERE': return
+ line, repmap = string_replace_map(string[5:].lstrip())
+ if not line.startswith('('): return
+ i = line.find(')')
+ if i==-1: return
+ stmt = repmap(line[i+1:].lstrip())
+ if not stmt: return
+ expr = repmap(line[1:i].strip())
+ if not expr: return
+ return Mask_Expr(expr), Where_Assignment_Stmt(stmt)
+ match = staticmethod(match)
+ def tostr(self): return 'WHERE (%s) %s' % tuple(self.items)
+
+
+class Where_Construct(Base): # R744
+ """
+ <where-construct> = <where-construct-stmt>
+ [ <where-body-construct> ]...
+ [ <masked-elsewhere-stmt>
+ [ <where-body-construct> ]...
+ ]...
+ [ <elsewhere-stmt>
+ [ <where-body-construct> ]... ]
+ <end-where-stmt>
+ """
+ subclass_names = []
+ use_names = ['Where_Construct_Stmt', 'Where_Body_Construct',
+ 'Elsewhere_Stmt', 'End_Where_Stmt'
+ ]
+
+class Where_Construct_Stmt(StmtBase): # R745
+ """
+ <where-construct-stmt> = [ <where-construct-name> : ] WHERE ( <mask-expr> )
+ """
+ subclass_names = []
+ use_names = ['Where_Construct_Name', 'Mask_Expr']
+
+ def match(string):
+ if string[:5].upper()!='WHERE': return
+ line = string[5:].lstrip()
+ if not line: return
+ if line[0]+line[-1] != '()': return
+ line = line[1:-1].strip()
+ if not line: return
+ return Mask_Expr(line),
+ match = staticmethod(match)
+ def tostr(self): return 'WHERE (%s)' % tuple(self.items)
+
+class Where_Body_Construct(Base): # R746
+ """
+ <where-body-construct> = <where-assignment-stmt>
+ | <where-stmt>
+ | <where-construct>
+ """
+ subclass_names = ['Where_Assignment_Stmt', 'Where_Stmt', 'Where_Construct']
+
+class Where_Assignment_Stmt(Base): # R747
+ """
+ <where-assignment-stmt> = <assignment-stmt>
+ """
+ subclass_names = ['Assignment_Stmt']
+
+class Mask_Expr(Base): # R748
+ """
+ <mask-expr> = <logical-expr>
+ """
+ subclass_names = ['Logical_Expr']
+
+class Masked_Elsewhere_Stmt(StmtBase): # R749
+ """
+ <masked-elsewhere-stmt> = ELSEWHERE ( <mask-expr> ) [ <where-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Mask_Expr', 'Where_Construct_Name']
+ def match(string):
+ if string[:9].upper()!='ELSEWHERE': return
+ line = string[9:].lstrip()
+ if not line.startswith('('): return
+ i = line.rfind(')')
+ if i==-1: return
+ expr = line[1:i].strip()
+ if not expr: return
+ line = line[i+1:].rstrip()
+ if line:
+ return Mask_Expr(expr), Where_Construct_Name(line)
+ return Mask_Expr(expr), None
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return 'ELSEWHERE(%s)' % (self.items[0])
+ return 'ELSEWHERE(%s) %s' % self.items
+
+class Elsewhere_Stmt(StmtBase, WORDClsBase): # R750
+ """
+ <elsewhere-stmt> = ELSEWHERE [ <where-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Where_Construct_Name']
+ def match(string): return WORDClsBase.match('ELSEWHERE', Where_Construct_Name, string)
+ match = staticmethod(match)
+
+class End_Where_Stmt(EndStmtBase): # R751
+ """
+ <end-where-stmt> = END WHERE [ <where-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Where_Construct_Name']
+ def match(string): return EndStmtBase.match('WHERE',Where_Construct_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+
+class Forall_Construct(Base): # R752
+ """
+ <forall-construct> = <forall-construct-stmt>
+ [ <forall-body-construct> ]...
+ <end-forall-stmt>
+ """
+ subclass_names = []
+ use_names = ['Forall_Construct_Stmt', 'Forall_Body_Construct', 'End_Forall_Stmt']
+
+class Forall_Construct_Stmt(StmtBase, WORDClsBase): # R753
+ """
+ <forall-construct-stmt> = [ <forall-construct-name> : ] FORALL <forall-header>
+ """
+ subclass_names = []
+ use_names = ['Forall_Construct_Name', 'Forall_Header']
+ def match(string): return WORDClsBase.match('FORALL', Forall_Header, string, require_cls = True)
+ match = staticmethod(match)
+
+class Forall_Header(Base): # R754
+ """
+ <forall-header> = ( <forall-triplet-spec-list> [ , <scalar-mask-expr> ] )
+ """
+ subclass_names = []
+ use_names = ['Forall_Triplet_Spec_List', 'Scalar_Mask_Expr']
+
+class Forall_Triplet_Spec(Base): # R755
+ """
+ <forall-triplet-spec> = <index-name> = <subscript> : <subscript> [ : <stride> ]
+ """
+ subclass_names = []
+ use_names = ['Index_Name', 'Subscript', 'Stride']
+
+class Forall_Body_Construct(Base): # R756
+ """
+ <forall-body-construct> = <forall-assignment-stmt>
+ | <where-stmt>
+ | <where-construct>
+ | <forall-construct>
+ | <forall-stmt>
+ """
+ subclass_names = ['Forall_Assignment_Stmt', 'Where_Stmt', 'Where_Construct',
+ 'Forall_Construct', 'Forall_Stmt']
+
+class Forall_Assignment_Stmt(Base): # R757
+ """
+ <forall-assignment-stmt> = <assignment-stmt>
+ | <pointer-assignment-stmt>
+ """
+ subclass_names = ['Assignment_Stmt', 'Pointer_Assignment_Stmt']
+
+class End_Forall_Stmt(EndStmtBase): # R758
+ """
+ <end-forall-stmt> = END FORALL [ <forall-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Forall_Construct_Name']
+ def match(string): return EndStmtBase.match('FORALL',Forall_Construct_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class Forall_Stmt(StmtBase): # R759
+ """
+ <forall-stmt> = FORALL <forall-header> <forall-assignment-stmt>
+ """
+ subclass_names = []
+ use_names = ['Forall_Header', 'Forall_Assignment_Stmt']
+ def match(string):
+ if string[:6].upper()!='FORALL': return
+ line, repmap = string_replace_map(string[6:].lstrip())
+ if not line.startswith(')'): return
+ i = line.find(')')
+ if i==-1: return
+ header = repmap(line[1:i].strip())
+ if not header: return
+ line = repmap(line[i+1:].lstrip())
+ if not line: return
+ return Forall_Header(header), Forall_Assignment_Stmt(line)
+ match = staticmethod(match)
+ def tostr(self): return 'FORALL %s %s' % self.items
+
+###############################################################################
+############################### SECTION 8 ####################################
+###############################################################################
+
+class Block(BlockBase): # R801
+ """
+ block = [ <execution-part-construct> ]...
+ """
+ subclass_names = []
+ use_names = ['Execution_Part_Construct']
+ def match(string): return BlockBase.match(None, [Execution_Part_Construct], None, string)
+ match = staticmethod(match)
+
+class If_Construct(BlockBase): # R802
+ """
+ <if-construct> = <if-then-stmt>
+ <block>
+ [ <else-if-stmt>
+ <block>
+ ]...
+ [ <else-stmt>
+ <block>
+ ]
+ <end-if-stmt>
+ """
+ subclass_names = []
+ use_names = ['If_Then_Stmt', 'Block', 'Else_If_Stmt', 'Else_Stmt', 'End_If_Stmt']
+
+ def match(reader):
+ content = []
+ try:
+ obj = If_Then_Stmt(reader)
+ except NoMatchError:
+ obj = None
+ if obj is None: return
+ content.append(obj)
+ obj = Block(reader)
+ if obj is None: return # todo: restore reader
+ content.append(obj)
+ while 1:
+ try:
+ obj = Else_If_Stmt(reader)
+ except NoMatchError:
+ obj = None
+ if obj is not None:
+ content.append(obj)
+ obj = Block(reader)
+ if obj is None: return # todo: restore reader
+ content.append(obj)
+ continue
+ try:
+ obj = Else_Stmt(reader)
+ except NoMatchError:
+ obj = None
+ if obj is not None:
+ content.append(obj)
+ obj = Block(reader)
+ if obj is None: return # todo: restore reader
+ content.append(obj)
+ break
+ try:
+ obj = End_If_Stmt(reader)
+ except NoMatchError:
+ obj = None
+ if obj is None: return # todo: restore reader
+ content.append(obj)
+ return content,
+ match = staticmethod(match)
+
+ def tofortran(self, tab='', isfix=None):
+ l = []
+ start = self.content[0]
+ end = self.content[-1]
+ l.append(start.tofortran(tab=tab,isfix=isfix))
+ for item in self.content[1:-1]:
+ if isinstance(item, (Else_If_Stmt, Else_Stmt)):
+ l.append(item.tofortran(tab=tab,isfix=isfix))
+ else:
+ l.append(item.tofortran(tab=tab+' ',isfix=isfix))
+ l.append(end.tofortran(tab=tab,isfix=isfix))
+ return '\n'.join(l)
+
+
+class If_Then_Stmt(StmtBase): # R803
+ """
+ <if-then-stmt> = [ <if-construct-name> : ] IF ( <scalar-logical-expr> ) THEN
+ """
+ subclass_names = []
+ use_names = ['If_Construct_Name', 'Scalar_Logical_Expr']
+ def match(string):
+ if string[:2].upper()!='IF': return
+ if string[-4:].upper()!='THEN': return
+ line = string[2:-4].strip()
+ if not line: return
+ if line[0]+line[-1]!='()': return
+ return Scalar_Logical_Expr(line[1:-1].strip()),
+ match = staticmethod(match)
+ def tostr(self): return 'IF (%s) THEN' % self.items
+
+class Else_If_Stmt(StmtBase): # R804
+ """
+ <else-if-stmt> = ELSE IF ( <scalar-logical-expr> ) THEN [ <if-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Scalar_Logical_Expr', 'If_Construct_Name']
+
+ def match(string):
+ if string[:4].upper()!='ELSE': return
+ line = string[4:].lstrip()
+ if line[:2].upper()!='IF': return
+ line = line[2:].lstrip()
+ if not line.startswith('('): return
+ i = line.rfind(')')
+ if i==-1: return
+ expr = line[1:i].strip()
+ line = line[i+1:].lstrip()
+ if line[:4].upper()!='THEN': return
+ line = line[4:].lstrip()
+ if line: return Scalar_Logical_Expr(expr), If_Construct_Name(line)
+ return Scalar_Logical_Expr(expr), None
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None:
+ return 'ELSE IF (%s) THEN' % (self.items[0])
+ return 'ELSE IF (%s) THEN %s' % self.items
+
+class Else_Stmt(StmtBase): # R805
+ """
+ <else-stmt> = ELSE [ <if-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['If_Construct_Name']
+ def match(string):
+ if string[:4].upper()!='ELSE': return
+ line = string[4:].lstrip()
+ if line: return If_Construct_Name(line),
+ return None,
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None:
+ return 'ELSE'
+ return 'ELSE %s' % self.items
+
+class End_If_Stmt(EndStmtBase): # R806
+ """
+ <end-if-stmt> = END IF [ <if-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['If_Construct_Name']
+ def match(string): return EndStmtBase.match('IF',If_Construct_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class If_Stmt(StmtBase): # R807
+ """
+ <if-stmt> = IF ( <scalar-logical-expr> ) <action-stmt>
+ """
+ subclass_names = []
+ use_names = ['Scalar_Logical_Expr', 'Action_Stmt_C802']
+ def match(string):
+ if string[:2].upper() != 'IF': return
+ line, repmap = string_replace_map(string)
+ line = line[2:].lstrip()
+ if not line.startswith('('): return
+ i = line.find(')')
+ if i==-1: return
+ expr = repmap(line[1:i].strip())
+ stmt = repmap(line[i+1:].lstrip())
+ return Scalar_Logical_Expr(expr), Action_Stmt_C802(stmt)
+ match = staticmethod(match)
+ def tostr(self): return 'IF (%s) %s' % self.items
+
+class Case_Construct(Base): # R808
+ """
+ <case-construct> = <select-case-stmt>
+ [ <case-stmt>
+ <block>
+ ]..
+ <end-select-stmt>
+ """
+ subclass_names = []
+ use_names = ['Select_Case_Stmt', 'Case_Stmt', 'End_Select_Stmt']
+
+class Select_Case_Stmt(StmtBase, CALLBase): # R809
+ """
+ <select-case-stmt> = [ <case-construct-name> : ] SELECT CASE ( <case-expr> )
+ """
+ subclass_names = []
+ use_names = ['Case_Construct_Name', 'Case_Expr']
+ def match(string): return CALLBase.match(pattter.abs_select_case, Case_Expr, string)
+ match = staticmethod(match)
+
+class Case_Stmt(StmtBase): # R810
+ """
+ <case-stmt> = CASE <case-selector> [ <case-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Case_Selector', 'Case_Construct_Name']
+
+class End_Select_Stmt(EndStmtBase): # R811
+ """
+ <end-select-stmt> = END SELECT [ <case-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Case_Construct_Name']
+ def match(string): return EndStmtBase.match('SELECT',Case_Construct_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class Case_Expr(Base): # R812
+ """
+ <case-expr> = <scalar-int-expr>
+ | <scalar-char-expr>
+ | <scalar-logical-expr>
+ """
+ subclass_names = []
+ subclass_names = ['Scalar_Int_Expr', 'Scalar_Char_Expr', 'Scalar_Logical_Expr']
+
+class Case_Selector(Base): # R813
+ """
+ <case-selector> = ( <case-value-range-list> )
+ | DEFAULT
+ """
+ subclass_names = []
+ use_names = ['Case_Value_Range_List']
+
+class Case_Value_Range(SeparatorBase): # R814
+ """
+ <case-value-range> = <case-value>
+ | <case-value> :
+ | : <case-value>
+ | <case-value> : <case-value>
+ """
+ subclass_names = ['Case_Value']
+ def match(string): return SeparatorBase.match(Case_Value, Case_Value, string)
+ match = staticmethod(match)
+
+class Case_Value(Base): # R815
+ """
+ <case-value> = <scalar-int-initialization-expr>
+ | <scalar-char-initialization-expr>
+ | <scalar-logical-initialization-expr>
+ """
+ subclass_names = ['Scalar_Int_Initialization_Expr', 'Scalar_Char_Initialization_Expr', 'Scalar_Logical_Initialization_Expr']
+
+
+class Associate_Construct(Base): # R816
+ """
+ <associate-construct> = <associate-stmt>
+ <block>
+ <end-associate-stmt>
+ """
+ subclass_names = []
+ use_names = ['Associate_Stmt', 'Block', 'End_Associate_Stmt']
+
+class Associate_Stmt(StmtBase, CALLBase): # R817
+ """
+ <associate-stmt> = [ <associate-construct-name> : ] ASSOCIATE ( <association-list> )
+ """
+ subclass_names = []
+ use_names = ['Associate_Construct_Name', 'Association_List']
+ def match(string): return CALLBase.match('ASSOCIATE', Association_List, string)
+ match = staticmethod(match)
+
+class Association(BinaryOpBase): # R818
+ """
+ <association> = <associate-name> => <selector>
+ """
+ subclass_names = []
+ use_names = ['Associate_Name', 'Selector']
+ def match(string): return BinaryOpBase.match(Assiciate_Name, '=>', Selector, string)
+ match = staticmethod(match)
+
+class Selector(Base): # R819
+ """
+ <selector> = <expr>
+ | <variable>
+ """
+ subclass_names = ['Expr', 'Variable']
+
+class End_Associate_Stmt(EndStmtBase): # R820
+ """
+ <end-associate-stmt> = END ASSOCIATE [ <associate-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Associate_Construct_Name']
+ def match(string): return EndStmtBase.match('ASSOCIATE',Associate_Construct_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class Select_Type_Construct(Base): # R821
+ """
+ <select-type-construct> = <select-type-stmt>
+ [ <type-guard-stmt>
+ <block>
+ ]...
+ <end-select-type-stmt>
+ """
+ subclass_names = []
+ use_names = ['Select_Type_Stmt', 'Type_Guard_Stmt', 'Block', 'End_Select_Type_Stmt']
+
+class Select_Type_Stmt(StmtBase): # R822
+ """
+ <select-type-stmt> = [ <select-construct-name> : ] SELECT TYPE ( [ <associate-name> => ] <selector> )
+ """
+ subclass_names = []
+ use_names = ['Select_Construct_Name', 'Associate_Name', 'Selector']
+
+class Type_Guard_Stmt(StmtBase): # R823
+ """
+ <type-guard-stmt> = TYPE IS ( <type-spec> ) [ <select-construct-name> ]
+ | CLASS IS ( <type-spec> ) [ <select-construct-name> ]
+ | CLASS DEFAULT [ <select-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Type_Spec', 'Select_Construct_Name']
+ def match(string):
+ if string[:4].upper()=='TYPE':
+ line = string[4:].lstrip()
+ if not line[:2].upper()=='IS': return
+ line = line[2:].lstrip()
+ kind = 'TYPE IS'
+ elif string[:5].upper()=='CLASS':
+ line = string[5:].lstrip()
+ if line[:2].upper()=='IS':
+ line = line[2:].lstrip()
+ kind = 'CLASS IS'
+ elif line[:7].upper()=='DEFAULT':
+ line = line[7:].lstrip()
+ if line:
+ if isalnum(line[0]): return
+ return 'CLASS DEFAULT', None, Select_Construct_Name(line)
+ return 'CLASS DEFAULT', None, None
+ else:
+ return
+ else:
+ return
+ if not line.startswith('('): return
+ i = line.rfind(')')
+ if i==-1: return
+ l = line[1:i].strip()
+ if not l: return
+ line = line[i+1:].lstrip()
+ if line:
+ return kind, Type_Spec(l), Select_Construct_Name(line)
+ return kind, Type_Spec(l), None
+ match = staticmethod(match)
+ def tostr(self):
+ s = str(self.items[0])
+ if self.items[1] is not None:
+ s += ' (%s)' % (self.items[0])
+ if self.items[2] is not None:
+ s += ' %s' % (self.items[2])
+ return s
+
+class End_Select_Type_Stmt(EndStmtBase): # R824
+ """
+ <end-select-type-stmt> = END SELECT [ <select-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Select_Construct_Name']
+ def match(string): return EndStmtBase.match('SELECT',Select_Construct_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class Do_Construct(Base): # R825
+ """
+ <do-construct> = <block-do-construct>
+ | <nonblock-do-construct>
+ """
+ subclass_names = ['Block_Do_Construct', 'Nonblock_Do_Construct']
+
+class Block_Do_Construct(BlockBase): # R826
+ """
+ <block-do-construct> = <do-stmt>
+ <do-block>
+ <end-do>
+ """
+ subclass_names = []
+ use_names = ['Do_Stmt', 'Do_Block', 'End_Do']
+ def match(reader):
+ assert isinstance(reader,FortranReaderBase),`reader`
+ content = []
+ try:
+ obj = Do_Stmt(reader)
+ except NoMatchError:
+ obj = None
+ if obj is None: return
+ content.append(obj)
+ if isinstance(obj, Label_Do_Stmt):
+ label = str(obj.dolabel)
+ while 1:
+ try:
+ obj = Execution_Part_Construct(reader)
+ except NoMatchError:
+ obj = None
+ if obj is None: break
+ content.append(obj)
+ if isinstance(obj, Continue_Stmt) and obj.item.label==label:
+ return content,
+ return
+ raise RuntimeError,'Expected continue stmt with specified label'
+ else:
+ obj = End_Do(reader)
+ content.append(obj)
+ raise NotImplementedError
+ return content,
+ match = staticmethod(match)
+
+ def tofortran(self, tab='', isfix=None):
+ if not isinstance(self.content[0], Label_Do_Stmt):
+ return BlockBase.tofortran(tab, isfix)
+ l = []
+ start = self.content[0]
+ end = self.content[-1]
+ extra_tab = ' '
+ l.append(start.tofortran(tab=tab,isfix=isfix))
+ for item in self.content[1:-1]:
+ l.append(item.tofortran(tab=tab+extra_tab,isfix=isfix))
+ if len(self.content)>1:
+ l.append(end.tofortran(tab=tab,isfix=isfix))
+ return '\n'.join(l)
+
+class Do_Stmt(Base): # R827
+ """
+ <do-stmt> = <label-do-stmt>
+ | <nonlabel-do-stmt>
+ """
+ subclass_names = ['Label_Do_Stmt', 'Nonlabel_Do_Stmt']
+
+class Label_Do_Stmt(StmtBase): # R828
+ """
+ <label-do-stmt> = [ <do-construct-name> : ] DO <label> [ <loop-control> ]
+ """
+ subclass_names = []
+ use_names = ['Do_Construct_Name', 'Label', 'Loop_Control']
+ def match(string):
+ if string[:2].upper()!='DO': return
+ line = string[2:].lstrip()
+ m = pattern.label.match(line)
+ if m is None: return
+ label = m.group()
+ line = line[m.end():].lstrip()
+ if line: return Label(label), Loop_Control(line)
+ return Label(label), None
+ match = staticmethod(match)
+ def tostr(self):
+ if self.itens[1] is None: return 'DO %s' % (self.items[0])
+ return 'DO %s %s' % self.items
+
+class Nonlabel_Do_Stmt(StmtBase, WORDClsBase): # R829
+ """
+ <nonlabel-do-stmt> = [ <do-construct-name> : ] DO [ <loop-control> ]
+ """
+ subclass_names = []
+ use_names = ['Do_Construct_Name', 'Loop_Control']
+ def match(string): return WORDClsBase.match('DO', Loop_Control, string)
+ match = staticmethod(match)
+
+class Loop_Control(Base): # R830
+ """
+ <loop-control> = [ , ] <do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ]
+ | [ , ] WHILE ( <scalar-logical-expr> )
+ """
+ subclass_names = []
+ use_names = ['Do_Variable', 'Scalar_Int_Expr', 'Scalar_Logical_Expr']
+ def match(string):
+ if string.startswith(','):
+ line, repmap = string_replace_map(string[1:].lstrip())
+ else:
+ line, repmap = string_replace_map(string)
+ if line[:5].upper()=='WHILE' and line[5:].lstrip().startswith('('):
+ l = line[5:].lstrip()
+ i = l.find(')')
+ if i!=-1 and i==len(l)-1:
+ return Scalar_Logical_Expr(repmap(l[1:i].strip())),
+ if line.count('=')!=1: return
+ var,rhs = line.split('=')
+ rhs = [s.strip() for s in rhs.lstrip().split(',')]
+ if not 2<=len(rhs)<=3: return
+ return Variable(repmap(var.rstrip())),map(Scalar_Int_Expr, map(repmap,rhs))
+ match = staticmethod(match)
+ def tostr(self):
+ if len(self.items)==1: return ', WHILE (%s)' % (self.items[0])
+ return ', %s = %s' % (self.items[0], ', '.join(map(str,self.items[1])))
+
+class Do_Variable(Base): # R831
+ """
+ <do-variable> = <scalar-int-variable>
+ """
+ subclass_names = ['Scalar_Int_Variable']
+
+class Do_Block(Base): # R832
+ """
+ <do-block> = <block>
+ """
+ subclass_names = ['Block']
+
+class End_Do(Base): # R833
+ """
+ <end-do> = <end-do-stmt>
+ | <continue-stmt>
+ """
+ subclass_names = ['End_Do_Stmt', 'Continue_Stmt']
+
+class End_Do_Stmt(EndStmtBase): # R834
+ """
+ <end-do-stmt> = END DO [ <do-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Do_Construct_Name']
+ def match(string): return EndStmtBase.match('DO',Do_Construct_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class Nonblock_Do_Construct(Base): # R835
+ """
+ <nonblock-do-stmt> = <action-term-do-construct>
+ | <outer-shared-do-construct>
+ """
+ subclass_names = ['Action_Term_Do_Construct', 'Outer_Shared_Do_Construct']
+
+class Action_Term_Do_Construct(BlockBase): # R836
+ """
+ <action-term-do-construct> = <label-do-stmt>
+ <do-body>
+ <do-term-action-stmt>
+ """
+ subclass_names = []
+ use_names = ['Label_Do_Stmt', 'Do_Body', 'Do_Term_Action_Stmt']
+ def match(reader):
+ content = []
+ for cls in [Label_Do_Stmt, Do_Body, Do_Term_Action_Stmt]:
+ obj = cls(reader)
+ if obj is None: # todo: restore reader
+ return
+ content.append(obj)
+ return content,
+ match = staticmethod(match)
+
+class Do_Body(BlockBase): # R837
+ """
+ <do-body> = [ <execution-part-construct> ]...
+ """
+ subclass_names = []
+ use_names = ['Execution_Part_Construct']
+ def match(string): return BlockBase.match(None, [Execution_Part_Construct], None, string)
+ match = staticmethod(match)
+
+class Do_Term_Action_Stmt(StmtBase): # R838
+ """
+ <do-term-action-stmt> = <action-stmt>
+ C824: <do-term-action-stmt> shall not be <continue-stmt>, <goto-stmt>, <return-stmt>, <stop-stmt>,
+ <exit-stmt>, <cycle-stmt>, <end-function-stmt>, <end-subroutine-stmt>,
+ <end-program-stmt>, <arithmetic-if-stmt>
+ """
+ subclass_names = ['Action_Stmt_C824']
+
+class Outer_Shared_Do_Construct(BlockBase): # R839
+ """
+ <outer-shared-do-construct> = <label-do-stmt>
+ <do-body>
+ <shared-term-do-construct>
+ """
+ subclass_names = []
+ use_names = ['Label_Do_Stmt', 'Do_Body', 'Shared_Term_Do_Construct']
+ def match(reader):
+ content = []
+ for cls in [Label_Do_Stmt, Do_Body, Shared_Term_Do_Construct]:
+ obj = cls(reader)
+ if obj is None: # todo: restore reader
+ return
+ content.append(obj)
+ return content,
+ match = staticmethod(match)
+
+class Shared_Term_Do_Construct(Base): # R840
+ """
+ <shared-term-do-construct> = <outer-shared-do-construct>
+ | <inner-shared-do-construct>
+ """
+ subclass_names = ['Outer_Shared_Do_Construct', 'Inner_Shared_Do_Construct']
+
+class Inner_Shared_Do_Construct(BlockBase): # R841
+ """
+ <inner-shared-do-construct> = <label-do-stmt>
+ <do-body>
+ <do-term-shared-stmt>
+ """
+ subclass_names = []
+ use_names = ['Label_Do_Stmt', 'Do_Body', 'Do_Term_Shared_Stmt']
+
+ def match(reader):
+ content = []
+ for cls in [Label_Do_Stmt, Do_Body, Do_Term_Shared_Stmt]:
+ obj = cls(reader)
+ if obj is None: # todo: restore reader
+ return
+ content.append(obj)
+ return content,
+ match = staticmethod(match)
+
+class Do_Term_Shared_Stmt(StmtBase): # R842
+ """
+ <do-term-shared-stmt> = <action-stmt>
+ C826: see C824 above.
+ """
+ subclass_names = ['Action_Stmt']
+
+class Cycle_Stmt(StmtBase, WORDClsBase): # R843
+ """
+ <cycle-stmt> = CYCLE [ <do-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Do_Construct_Name']
+ def match(string): return WORDClsBase.match('CYCLE', Do_Construct_Name, string)
+ match = staticmethod(match)
+
+class Exit_Stmt(StmtBase, WORDClsBase): # R844
+ """
+ <exit-stmt> = EXIT [ <do-construct-name> ]
+ """
+ subclass_names = []
+ use_names = ['Do_Construct_Name']
+ def match(string): return WORDClsBase.match('EXIT', Do_Construct_Name, string)
+ match = staticmethod(match)
+
+class Goto_Stmt(StmtBase): # R845
+ """
+ <goto-stmt> = GO TO <label>
+ """
+ subclass_names = []
+ use_names = ['Label']
+ def match(string):
+ if string[:2].upper() != 'GO': return
+ line = string[2:].lstrip()
+ if line[:2].upper() != 'TO': return
+ return Label(line[2:].lstrip()),
+ match = staticmethod(match)
+ def tostr(self): return 'GO TO %s' % (self.items[0])
+
+class Computed_Goto_Stmt(StmtBase): # R846
+ """
+ <computed-goto-stmt> = GO TO ( <label-list> ) [ , ] <scalar-int-expr>
+ """
+ subclass_names = []
+ use_names = ['Label_List', 'Scalar_Int_Expr']
+ def match(string):
+ if string[:2].upper()!='GO': return
+ line = string[2:].lstrip()
+ if line[:2].upper()!='TO': return
+ line = line[2:].lstrip()
+ if not line.startswith('('): return
+ i = line.find(')')
+ if i==-1: return
+ lst = line[1:i].strip()
+ if not lst: return
+ line = line[i+1:].lstrip()
+ if line.startswith(','):
+ line = line[1:].lstrip()
+ if not line: return
+ return Label_List(lst), Scalar_Int_Expr(line)
+ match = staticmethod(match)
+ def tostr(self): return 'GO TO (%s), %s' % self.items
+
+class Arithmetic_If_Stmt(StmtBase): # R847
+ """
+ <arithmetic-if-stmt> = IF ( <scalar-numeric-expr> ) <label> , <label> , <label>
+ """
+ subclass_names = []
+ use_names = ['Scalar_Numeric_Expr', 'Label']
+ def match(string):
+ if string[:2].upper() != 'IF': return
+ line = string[2:].lstrip()
+ if not line.startswith('('): return
+ i = line.rfind(')')
+ if i==-1: return
+ labels = line[i+1:].lstrip().split(',')
+ if len(labels) != 3: return
+ labels = [Label(l.strip()) for l in labels]
+ return (Scalar_Numeric_Expr(line[1:i].strip()),) + tuple(labels)
+ match = staticmethod(match)
+ def tostr(self): return 'IF (%s) %s, %s, %s' % self.items
+
+class Continue_Stmt(StmtBase, STRINGBase): # R848
+ """
+ <continue-stmt> = CONTINUE
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match('CONTINUE', string)
+ match = staticmethod(match)
+
+
+class Stop_Stmt(StmtBase, WORDClsBase): # R849
+ """
+ <stop-stmt> = STOP [ <stop-code> ]
+ """
+ subclass_names = []
+ use_names = ['Stop_Code']
+ def match(string): return WORDClsBase.match('STOP', Stop_Code, string)
+ match = staticmethod(match)
+
+class Stop_Code(StringBase): # R850
+ """
+ <stop-code> = <scalar-char-constant>
+ | <digit> [ <digit> [ <digit> [ <digit> [ <digit> ] ] ] ]
+ """
+ subclass_names = ['Scalar_Char_Constant']
+ def match(string): return StringBase.match(pattern.abs_label, string)
+ match = staticmethod(match)
+
+
+###############################################################################
+############################### SECTION 9 ####################################
+###############################################################################
+
+class Io_Unit(StringBase): # R901
+ """
+ <io-unit> = <file-unit-number>
+ | *
+ | <internal-file-variable>
+ """
+ subclass_names = ['File_Unit_Number', 'Internal_File_Variable']
+ def match(string): return StringBase.match('*', string)
+ match = staticmethod(match)
+
+class File_Unit_Number(Base): # R902
+ """
+ <file-unit-number> = <scalar-int-expr>
+ """
+ subclass_names = ['Scalar_Int_Expr']
+
+class Internal_File_Variable(Base): # R903
+ """
+ <internal-file-variable> = <char-variable>
+ C901: <char-variable> shall not be an array section with a vector subscript.
+ """
+ subclass_names = ['Char_Variable']
+
+class Open_Stmt(StmtBase, CALLBase): # R904
+ """
+ <open-stmt> = OPEN ( <connect-spec-list> )
+ """
+ subclass_names = []
+ use_names = ['Connect_Spec_List']
+ def match(string): CALLBase.match('OPEN', Connect_Spec_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Connect_Spec(KeywordValueBase): # R905
+ """
+ <connect-spec> = [ UNIT = ] <file-unit-number>
+ | ACCESS = <scalar-default-char-expr>
+ | ACTION = <scalar-default-char-expr>
+ | ASYNCHRONOUS = <scalar-default-char-expr>
+ | BLANK = <scalar-default-char-expr>
+ | DECIMAL = <scalar-default-char-expr>
+ | DELIM = <scalar-default-char-expr>
+ | ENCODING = <scalar-default-char-expr>
+ | ERR = <label>
+ | FILE = <file-name-expr>
+ | FORM = <scalar-default-char-expr>
+ | IOMSG = <iomsg-variable>
+ | IOSTAT = <scalar-int-variable>
+ | PAD = <scalar-default-char-expr>
+ | POSITION = <scalar-default-char-expr>
+ | RECL = <scalar-int-expr>
+ | ROUND = <scalar-default-char-expr>
+ | SIGN = <scalar-default-char-expr>
+ | STATUS = <scalar-default-char-expr>
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Scalar_Default_Char_Expr', 'Label', 'File_Name_Expr', 'Iomsg_Variable',
+ 'Scalar_Int_Expr', 'Scalar_Int_Variable']
+ def match(string):
+ for (k,v) in [\
+ (['ACCESS','ACTION','ASYNCHRONOUS','BLANK','DECIMAL','DELIM','ENCODING',
+ 'FORM','PAD','POSITION','ROUND','SIGN','STATUS'], Scalar_Default_Char_Expr),
+ ('ERR', Label),
+ ('FILE',File_Name_Expr),
+ ('IOSTAT', Scalar_Int_Variable),
+ ('IOMSG', Iomsg_Variable),
+ ('RECL', Scalar_Int_Expr),
+ ('UNIT', File_Unit_Number),
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return 'UNIT', File_Unit_Number
+ match = staticmethod(match)
+
+
+class File_Name_Expr(Base): # R906
+ """
+ <file-name-expr> = <scalar-default-char-expr>
+ """
+ subclass_names = ['Scalar_Default_Char_Expr']
+
+class Iomsg_Variable(Base): # R907
+ """
+ <iomsg-variable> = <scalar-default-char-variable>
+ """
+ subclass_names = ['Scalar_Default_Char_Variable']
+
+class Close_Stmt(StmtBase, CALLBase): # R908
+ """
+ <close-stmt> = CLOSE ( <close-spec-list> )
+ """
+ subclass_names = []
+ use_names = ['Close_Spec_List']
+ def match(string): CALLBase.match('CLOSE', Close_Spec_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Close_Spec(KeywordValueBase): # R909
+ """
+ <close-spec> = [ UNIT = ] <file-unit-number>
+ | IOSTAT = <scalar-int-variable>
+ | IOMSG = <iomsg-variable>
+ | ERR = <label>
+ | STATUS = <scalar-default-char-expr>
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Scalar_Default_Char_Expr', 'Label', 'Iomsg_Variable',
+ 'Scalar_Int_Variable']
+ def match(string):
+ for (k,v) in [\
+ ('ERR', Label),
+ ('IOSTAT', Scalar_Int_Variable),
+ ('IOMSG', Iomsg_Variable),
+ ('STATUS', Scalar_Default_Char_Expr),
+ ('UNIT', File_Unit_Number),
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return 'UNIT', File_Unit_Number(string)
+ match = staticmethod(match)
+
+class Read_Stmt(StmtBase): # R910
+ """
+ <read-stmt> = READ ( <io-control-spec-list> ) [ <input-item-list> ]
+ | READ <format> [ , <input-item-list> ]
+ """
+ subclass_names = []
+ use_names = ['Io_Control_Spec_List', 'Input_Item_List', 'Format']
+
+class Write_Stmt(StmtBase): # R911
+ """
+ <write-stmt> = WRITE ( <io-control-spec-list> ) [ <output-item-list> ]
+ """
+ subclass_names = []
+ use_names = ['Io_Control_Spec_List', 'Output_Item_List']
+ def match(string):
+ if string[:5].upper()!='WRITE': return
+ line = string[5:].lstrip()
+ if not line.startswith('('): return
+ line, repmap = string_replace_map(line)
+ i = line.find(')')
+ if i==-1: return
+ l = line[1:i].strip()
+ if not l: return
+ l = repmap(l)
+ if i==len(line)-1:
+ return Io_Control_Spec_List(l),None
+ return Io_Control_Spec_List(l), Output_Item_List(repmap(line[i+1:].lstrip()))
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return 'WRITE(%s)' % (self.items[0])
+ return 'WRITE(%s) %s' % tuple(self.items)
+
+class Print_Stmt(StmtBase): # R912
+ """
+ <print-stmt> = PRINT <format> [ , <output-item-list> ]
+ """
+ subclass_names = []
+ use_names = ['Format', 'Output_Item_List']
+ def match(string):
+ if string[:5].upper()!='PRINT': return
+ line = string[5:]
+ if not line: return
+ c = line[0].upper()
+ if 'A'<=c<='Z' or c=='_' or '0'<=c<='9': return
+ line, repmap = string_replace_map(line.lstrip())
+ i = line.find(',')
+ if i==-1: return Format(repmap(line)), None
+ l = repmap(line[i+1:].lstrip())
+ if not l: return
+ return Format(repmap(line[:i].rstrip())), Output_Item_List(l)
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return 'PRINT %s' % (self.items[0])
+ return 'PRINT %s, %s' % tuple(self.items)
+
+class Io_Control_Spec_List(SequenceBase): # R913-list
+ """
+ <io-control-spec-list> is a list taking into account C910, C917, C918
+ """
+ subclass_names = []
+ use_names = ['Io_Control_Spec']
+ def match(string):
+ line, repmap = string_replace_map(string)
+ splitted = line.split(',')
+ if not splitted: return
+ lst = []
+ for i in range(len(splitted)):
+ p = splitted[i].strip()
+ if i==0:
+ if '=' not in p: p = 'UNIT=%s' % (repmap(p))
+ else: p = repmap(p)
+ elif i==1:
+ if '=' not in p:
+ p = repmap(p)
+ try:
+ f = Format(p)
+ # todo: make sure that f is char-expr, if not, raise NoMatchError
+ p = 'FMT=%s' % (Format(p))
+ except NoMatchError:
+ p = 'NML=%s' % (Namelist_Group_Name(p))
+ else:
+ p = repmap(p)
+ else:
+ p = repmap(p)
+ lst.append(Io_Control_Spec(p))
+ return ',', tuple(lst)
+ match = staticmethod(match)
+
+class Io_Control_Spec(KeywordValueBase): # R913
+ """
+ <io-control-spec> = [ UNIT = ] <io-unit>
+ | [ FMT = ] <format>
+ | [ NML = ] <namelist-group-name>
+ | ADVANCE = <scalar-default-char-expr>
+ | ASYNCHRONOUS = <scalar-char-initialization-expr>
+ | BLANK = <scalar-default-char-expr>
+ | DECIMAL = <scalar-default-char-expr>
+ | DELIM = <scalar-default-char-expr>
+ | END = <label>
+ | EOR = <label>
+ | ERR = <label>
+ | ID = <scalar-int-variable>
+ | IOMSG = <iomsg-variable>
+ | IOSTAT = <scalar-int-variable>
+ | PAD = <scalar-default-char-expr>
+ | POS = <scalar-int-expr>
+ | REC = <scalar-int-expr>
+ | ROUND = <scalar-default-char-expr>
+ | SIGN = <scalar-default-char-expr>
+ | SIZE = <scalar-int-variable>
+ """
+ subclass_names = []
+ use_names = ['Io_Unit', 'Format', 'Namelist_Group_Name', 'Scalar_Default_Char_Expr',
+ 'Scalar_Char_Initialization_Expr', 'Label', 'Scalar_Int_Variable',
+ 'Iomsg_Variable', 'Scalar_Int_Expr']
+ def match(string):
+ for (k,v) in [\
+ (['ADVANCE', 'BLANK', 'DECIMAL', 'DELIM', 'PAD', 'ROUND', 'SIGN'], Scalar_Default_Char_Expr),
+ ('ASYNCHRONOUS', Scalar_Char_Initialization_Expr),
+ (['END','EOR','ERR'], Label),
+ (['ID','IOSTAT','SIZE'], Scalar_Int_Variable),
+ ('IOMSG', Iomsg_Variable),
+ (['POS', 'REC'], Scalar_Int_Expr),
+ ('UNIT', Io_Unit),
+ ('FMT', Format),
+ ('NML', Namelist_Group_Name)
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return
+ match = staticmethod(match)
+
+class Format(StringBase): # R914
+ """
+ <format> = <default-char-expr>
+ | <label>
+ | *
+ """
+ subclass_names = ['Label', 'Default_Char_Expr']
+ def match(string): return StringBase.match('*', string)
+ match = staticmethod(match)
+
+class Input_Item(Base): # R915
+ """
+ <input-item> = <variable>
+ | <io-implied-do>
+ """
+ subclass_names = ['Variable', 'Io_Implied_Do']
+
+class Output_Item(Base): # R916
+ """
+ <output-item> = <expr>
+ | <io-implied-do>
+ """
+ subclass_names = ['Expr', 'Io_Implied_Do']
+
+class Io_Implied_Do(Base): # R917
+ """
+ <io-implied-do> = ( <io-implied-do-object-list> , <io-implied-do-control> )
+ """
+ subclass_names = []
+ use_names = ['Io_Implied_Do_Object_List', 'Io_Implied_Do_Control']
+
+class Io_Implied_Do_Object(Base): # R918
+ """
+ <io-implied-do-object> = <input-item>
+ | <output-item>
+ """
+ subclass_names = ['Input_Item', 'Output_Item']
+
+class Io_Implied_Do_Control(Base): # R919
+ """
+ <io-implied-do-control> = <do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ]
+ """
+ subclass_names = []
+ use_names = ['Do_Variable', 'Scalar_Int_Expr']
+
+class Dtv_Type_Spec(CALLBase): # R920
+ """
+ <dtv-type-spec> = TYPE ( <derived-type-spec> )
+ | CLASS ( <derived-type-spec> )
+ """
+ subclass_names = []
+ use_names = ['Derived_Type_Spec']
+ def match(string): CALLStmt.match(['TYPE', 'CLASS'], Derived_Type_Spec, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Wait_Stmt(StmtBase, CALLBase): # R921
+ """
+ <wait-stmt> = WAIT ( <wait-spec-list> )
+ """
+ subclass_names = []
+ use_names = ['Wait_Spec_List']
+ def match(string): return CALLBase.match('WAIT', Wait_Spec_List, string, require_rhs=True)
+ match = staticmethod(match)
+
+class Wait_Spec(KeywordValueBase): # R922
+ """
+ <wait-spec> = [ UNIT = ] <file-unit-number>
+ | END = <label>
+ | EOR = <label>
+ | ERR = <label>
+ | ID = <scalar-int-expr>
+ | IOMSG = <iomsg-variable>
+ | IOSTAT = <scalar-int-variable>
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Label', 'Scalar_Int_Expr', 'Iomsg_Variable', 'Scalar_Int_Variable']
+ def match(string):
+ for (k,v) in [\
+ (['END','EOR','ERR'], Label),
+ ('IOSTAT', Scalar_Int_Variable),
+ ('IOMSG', Iomsg_Variable),
+ ('ID', Scalar_Int_Expr),
+ ('UNIT', File_Unit_Number),
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return 'UNIT', File_Unit_Number(string)
+
+ match = staticmethod(match)
+
+class Backspace_Stmt(StmtBase): # R923
+ """
+ <backspace-stmt> = BACKSPACE <file-unit-number>
+ | BACKSPACE ( <position-spec-list> )
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Position_Spec_List']
+
+class Endfile_Stmt(StmtBase): # R924
+ """
+ <endfile-stmt> = ENDFILE <file-unit-number>
+ | ENDFILE ( <position-spec-list> )
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Position_Spec_List']
+
+class Rewind_Stmt(StmtBase): # R925
+ """
+ <rewind-stmt> = REWIND <file-unit-number>
+ | REWIND ( <position-spec-list> )
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Position_Spec_List']
+
+class Position_Spec(KeywordValueBase): # R926
+ """
+ <position-spec> = [ UNIT = ] <file-unit-number>
+ | IOMSG = <iomsg-variable>
+ | IOSTAT = <scalar-int-variable>
+ | ERR = <label>
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Iomsg_Variable', 'Scalar_Int_Variable', 'Label']
+ def match(string):
+ for (k,v) in [\
+ ('ERR', Label),
+ ('IOSTAT', Scalar_Int_Variable),
+ ('IOMSG', Iomsg_Variable),
+ ('UNIT', File_Unit_Number),
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return 'UNIT', File_Unit_Number(string)
+ match = staticmethod(match)
+
+
+class Flush_Stmt(StmtBase): # R927
+ """
+ <flush-stmt> = FLUSH <file-unit-number>
+ | FLUSH ( <position-spec-list> )
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Position_Spec_List']
+
+class Flush_Spec(KeywordValueBase): # R928
+ """
+ <flush-spec> = [ UNIT = ] <file-unit-number>
+ | IOMSG = <iomsg-variable>
+ | IOSTAT = <scalar-int-variable>
+ | ERR = <label>
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'Iomsg_Variable', 'Scalar_Int_Variable', 'Label']
+ def match(string):
+ for (k,v) in [\
+ ('ERR', Label),
+ ('IOSTAT', Scalar_Int_Variable),
+ ('IOMSG', Iomsg_Variable),
+ ('UNIT', File_Unit_Number),
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return 'UNIT', File_Unit_Number(string)
+ match = staticmethod(match)
+
+class Inquire_Stmt(StmtBase): # R929
+ """
+ <inquire-stmt> = INQUIRE ( <inquire-spec-list> )
+ | INQUIRE ( IOLENGTH = <scalar-int-variable> ) <output-item-list>
+ """
+ subclass_names = []
+ use_names = ['Inquire_Spec_List', 'Scalar_Int_Variable', 'Output_Item_List']
+
+class Inquire_Spec(KeywordValueBase): # R930
+ """
+ <inquire-spec> = [ UNIT = ] <file-unit-number>
+ | FILE = <file-name-expr>
+ | ACCESS = <scalar-default-char-variable>
+ | ACTION = <scalar-default-char-variable>
+ | ASYNCHRONOUS = <scalar-default-char-variable>
+ | BLANK = <scalar-default-char-variable>
+ | DECIMAL = <scalar-default-char-variable>
+ | DELIM = <scalar-default-char-variable>
+ | DIRECT = <scalar-default-char-variable>
+ | ENCODING = <scalar-default-char-variable>
+ | ERR = <label>
+ | EXIST = <scalar-default-logical-variable>
+ | FORM = <scalar-default-char-variable>
+ | FORMATTED = <scalar-default-char-variable>
+ | ID = <scalar-int-expr>
+ | IOMSG = <iomsg-variable>
+ | IOSTAT = <scalar-int-variable>
+ | NAME = <scalar-default-char-variable>
+ | NAMED = <scalar-default-logical-variable>
+ | NEXTREC = <scalar-int-variable>
+ | NUMBER = <scalar-int-variable>
+ | OPENED = <scalar-default-logical-variable>
+ | PAD = <scalar-default-char-variable>
+ | PENDING = <scalar-default-logical-variable>
+ | POS = <scalar-int-variable>
+ | POSITION = <scalar-default-char-variable>
+ | READ = <scalar-default-char-variable>
+ | READWRITE = <scalar-default-char-variable>
+ | RECL = <scalar-int-variable>
+ | ROUND = <scalar-default-char-variable>
+ | SEQUENTIAL = <scalar-default-char-variable>
+ | SIGN = <scalar-default-char-variable>
+ | SIZE = <scalar-int-variable>
+ | STREAM = <scalar-default-char-variable>
+ | UNFORMATTED = <scalar-default-char-variable>
+ | WRITE = <scalar-default-char-variable>
+ """
+ subclass_names = []
+ use_names = ['File_Unit_Number', 'File_Name_Expr', 'Scalar_Default_Char_Variable',
+ 'Scalar_Default_Logical_Variable', 'Scalar_Int_Variable', 'Scalar_Int_Expr',
+ 'Label', 'Iomsg_Variable']
+ def match(string):
+ for (k,v) in [\
+ (['ACCESS','ACTION','ASYNCHRONOUS', 'BLANK', 'DECIMAL', 'DELIM',
+ 'DIRECT','ENCODING','FORM','NAME','PAD', 'POSITION','READ','READWRITE',
+ 'ROUND', 'SEQUENTIAL', 'SIGN','STREAM','UNFORMATTED','WRITE'],
+ Scalar_Default_Char_Variable),
+ ('ERR', Label),
+ (['EXIST','NAMED','PENDING'], Scalar_Default_Logical_Variable),
+ ('ID', Scalar_Int_Expr),
+ (['IOSTAT','NEXTREC','NUMBER','POS','RECL','SIZE'], Scalar_Int_Variable),
+ ('IOMSG', Iomsg_Variable),
+ ('FILE', File_Name_Expr),
+ ('UNIT', File_Unit_Number),
+ ]:
+ try:
+ obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+ except NoMatchError:
+ obj = None
+ if obj is not None: return obj
+ return 'UNIT', File_Unit_Number(string)
+ return
+ match = staticmethod(match)
+
+###############################################################################
+############################### SECTION 10 ####################################
+###############################################################################
+
+class Format_Stmt(StmtBase, WORDClsBase): # R1001
+ """
+ <format-stmt> = FORMAT <format-specification>
+ """
+ subclass_names = []
+ use_names = ['Format_Specification']
+ def match(string): WORDClsBase.match('FORMAT', Format_Specification, string, require_cls=True)
+ match = staticmethod(match)
+
+class Format_Specification(BracketBase): # R1002
+ """
+ <format-specification> = ( [ <format-item-list> ] )
+ """
+ subclass_names = []
+ use_names = ['Format_Item_List']
+ def match(string): return BracketBase.match('()', Format_Item_List, string, require_cls=False)
+ match = staticmethod(match)
+
+class Format_Item(Base): # R1003
+ """
+ <format-item> = [ <r> ] <data-edit-desc>
+ | <control-edit-desc>
+ | <char-string-edit-desc>
+ | [ <r> ] ( <format-item-list> )
+ """
+ subclass_names = ['Control_Edit_Desc', 'Char_String_Edit_Desc']
+ use_names = ['R', 'Format_Item_List']
+
+class R(Base): # R1004
+ """
+ <r> = <int-literal-constant>
+ <r> shall be positive and without kind parameter specified.
+ """
+ subclass_names = ['Int_Literal_Constant']
+
+class Data_Edit_Desc(Base): # R1005
+ """
+ <data-edit-desc> = I <w> [ . <m> ]
+ | B <w> [ . <m> ]
+ | O <w> [ . <m> ]
+ | Z <w> [ . <m> ]
+ | F <w> . <d>
+ | E <w> . <d> [ E <e> ]
+ | EN <w> . <d> [ E <e> ]
+ | ES <w> . <d> [ E <e>]
+ | G <w> . <d> [ E <e> ]
+ | L <w>
+ | A [ <w> ]
+ | D <w> . <d>
+ | DT [ <char-literal-constant> ] [ ( <v-list> ) ]
+ """
+ subclass_names = []
+ use_names = ['W', 'M', 'D', 'E', 'Char_Literal_Constant', 'V_List']
+ def match(string):
+ c = string[0].upper()
+ if c in ['I','B','O','Z','D']:
+ line = string[1:].lstrip()
+ if '.' in line:
+ i1,i2 = line.split('.',1)
+ i1 = i1.rstrip()
+ i2 = i2.lstrip()
+ return c, W(i1), M(i2), None
+ return c,W(line), None, None
+ if c in ['E','G']:
+ line = string[1:].lstrip()
+ if line.count('.')==1:
+ i1,i2 = line.split('.',1)
+ i1 = i1.rstrip()
+ i2 = i2.lstrip()
+ return c, W(i1), D(i2), None
+ elif line.count('.')==2:
+ i1,i2,i3 = line.split('.',2)
+ i1 = i1.rstrip()
+ i2 = i2.lstrip()
+ i3 = i3.lstrip()
+ return c, W(i1), D(i2), E(i3)
+ else:
+ return
+ if c=='L':
+ line = string[1:].lstrip()
+ if not line: return
+ return c, W(line), None, None
+ if c=='A':
+ line = string[1:].lstrip()
+ if not line:
+ return c, None, None, None
+ return c, W(line), None, None
+ c = string[:2].upper()
+ if len(c)!=2: return
+ if c in ['EN','ES']:
+ line = string[2:].lstrip()
+ if line.count('.')==1:
+ i1,i2 = line.split('.',1)
+ i1 = i1.rstrip()
+ i2 = i2.lstrip()
+ return c, W(i1), D(i2), None
+ elif line.count('.')==2:
+ i1,i2,i3 = line.split('.',2)
+ i1 = i1.rstrip()
+ i2 = i2.lstrip()
+ i3 = i3.lstrip()
+ return c, W(i1), D(i2), E(i3)
+ else:
+ return
+ if c=='DT':
+ line = string[2:].lstrip()
+ if not line:
+ return c, None, None, None
+ lst = None
+ if line.endswith(')'):
+ i = line.rfind('(')
+ if i==-1: return
+ l = line[i+1:-1].strip()
+ if not l: return
+ lst = V_List(l)
+ line = line[:i].rstrip()
+ if not line:
+ return c, None, lst, None
+ return c, Char_Literal_Constant(line), lst, None
+ return
+ match = staticmethod(match)
+ def tostr(self):
+ c = selt.items[0]
+ if c in ['I', 'B', 'O', 'Z', 'F', 'D', 'A', 'L']:
+ if self.items[2] is None:
+ return '%s%s' % (c, self.items[1])
+ return '%s%s.%s' % (c, self.items[1], self.items[2])
+ if c in ['E', 'EN', 'ES', 'G']:
+ if self.items[3] is None:
+ return '%s%s.%s' % (c, self.items[1], self.items[2])
+ return '%s%s.%sE%s' % (c, self.items[1], self.items[2], self.items[3])
+ if c=='DT':
+ if self.items[1] is None:
+ if self.items[2] is None:
+ return c
+ else:
+ return '%s(%s)' % (c, self.items[2])
+ else:
+ if self.items[2] is None:
+ return '%s%s' % (c, self.items[1])
+ else:
+ return '%s%s(%s)' % (c, self.items[1], self.items[2])
+ raise NotImpletenetedError,`c`
+
+class W(Base): # R1006
+ """
+ <w> = <int-literal-constant>
+ """
+ subclass_names = ['Int_Literal_Constant']
+
+class M(Base): # R1007
+ """
+ <m> = <int-literal-constant>
+ """
+ subclass_names = ['Int_Literal_Constant']
+
+class D(Base): # R1008
+ """
+ <d> = <int-literal-constant>
+ """
+ subclass_names = ['Int_Literal_Constant']
+
+class E(Base): # R1009
+ """
+ <e> = <int-literal-constant>
+ """
+ subclass_names = ['Int_Literal_Constant']
+
+class V(Base): # R1010
+ """
+ <v> = <signed-int-literal-constant>
+ """
+ subclass_names = ['Signed_Int_Literal_Constant']
+
+class Control_Edit_Desc(Base): # R1011
+ """
+ <control-edit-desc> = <position-edit-desc>
+ | [ <r> ] /
+ | :
+ | <sign-edit-desc>
+ | <k> P
+ | <blank-interp-edit-desc>
+ | <round-edit-desc>
+ | <decimal-edit-desc>
+ """
+ subclass_names = ['Position_Edit_Desc', 'Sign_Edit_Desc', 'Blank_Interp_Edit_Desc', 'Round_Edit_Desc',
+ 'Decimal_Edit_Desc']
+ use_names = ['R', 'K']
+
+class K(Base): # R1012
+ """
+ <k> = <signed-int-literal-constant>
+ """
+ subclass_names = ['Signed_Int_Literal_Constant']
+
+class Position_Edit_Desc(Base): # R1013
+ """
+ <position-edit-desc> = T <n>
+ | TL <n>
+ | TR <n>
+ | <n> X
+ """
+ subclass_names = []
+ use_names = ['N']
+
+class N(Base): # R1014
+ """
+ <n> = <int-literal-constant>
+ """
+ subclass_names = ['Int_Literal_Constant']
+
+class Sign_Edit_Desc(STRINGBase): # R1015
+ """
+ <sign-edit-desc> = SS
+ | SP
+ | S
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(['SS','SP','S'], string)
+ match = staticmethod(match)
+
+class Blank_Interp_Edit_Desc(STRINGBase): # R1016
+ """
+ <blank-interp-edit-desc> = BN
+ | BZ
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(['BN','BZ',], string)
+ match = staticmethod(match)
+
+class Round_Edit_Desc(STRINGBase): # R1017
+ """
+ <round-edit-desc> = RU
+ | RD
+ | RZ
+ | RN
+ | RC
+ | RP
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(['RU','RD','RZ','RN','RC','RP'], string)
+ match = staticmethod(match)
+
+class Decimal_Edit_Desc(STRINGBase): # R1018
+ """
+ <decimal-edit-desc> = DC
+ | DP
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(['DC','DP'], string)
+ match = staticmethod(match)
+
+class Char_String_Edit_Desc(Base): # R1019
+ """
+ <char-string-edit-desc> = <char-literal-constant>
+ """
+ subclass_names = ['Char_Literal_Constant']
+
+###############################################################################
+############################### SECTION 11 ####################################
+###############################################################################
+
+class Main_Program(Base): # R1101
+ """
+ <main-program> = [ <program-stmt> ]
+ [ <specification-part> ]
+ [ <execution-part> ]
+ [ <internal-subprogram-part> ]
+ <end-program-stmt>
+ """
+ subclass_names = []
+ use_names = ['Program_Stmt', 'Specification_Part', 'Execution_Part', 'Internal_Subprogram_Part',
+ 'End_Program_Stmt']
+
+class Program_Stmt(StmtBase, WORDClsBase): # R1102
+ """
+ <program-stmt> = PROGRAM <program-name>
+ """
+ subclass_names = []
+ use_names = ['Program_Name']
+ def match(string): return WORDClsBase.match('PROGRAM',Program_Name, string, require_cls = True)
+ match = staticmethod(match)
+
+class End_Program_Stmt(EndStmtBase): # R1103
+ """
+ <end-program-stmt> = END [ PROGRAM [ <program-name> ] ]
+ """
+ subclass_names = []
+ use_names = ['Program_Name']
+ def match(string): return EndStmtBase.match('PROGRAM',Program_Name, string)
+ match = staticmethod(match)
+
+class Module(Base): # R1104
+ """
+ <module> = <module-stmt>
+ [ <specification-part> ]
+ [ <module-subprogram-part> ]
+ <end-module-stmt>
+ """
+ subclass_names = []
+ use_names = ['Module_Stmt', 'Specification_Part', 'Module_Subprogram_Part', 'End_Module_Stmt']
+
+class Module_Stmt(StmtBase, WORDClsBase): # R1105
+ """
+ <module-stmt> = MODULE <module-name>
+ """
+ subclass_names = []
+ use_names = ['Module_Name']
+ def match(string): return WORDClsBase.match('MODULE',Module_Name, string, require_cls = True)
+ match = staticmethod(match)
+
+class End_Module_Stmt(EndStmtBase): # R1106
+ """
+ <end-module-stmt> = END [ MODULE [ <module-name> ] ]
+ """
+ subclass_names = []
+ use_names = ['Module_Name']
+ def match(string): return EndStmtBase.match('MODULE',Module_Name, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class Module_Subprogram_Part(Base): # R1107
+ """
+ <module-subprogram-part> = <contains-stmt>
+ <module-subprogram>
+ [ <module-subprogram> ]...
+ """
+ subclass_names = []
+ use_names = ['Contains_Stmt', 'Module_Subprogram']
+
+class Module_Subprogram(Base): # R1108
+ """
+ <module-subprogram> = <function-subprogram>
+ | <subroutine-subprogram>
+ """
+ subclass_names = ['Function_Subprogram', 'Subroutine_Subprogram']
+
+class Use_Stmt(StmtBase): # R1109
+ """
+ <use-stmt> = USE [ [ , <module-nature> ] :: ] <module-name> [ , <rename-list> ]
+ | USE [ [ , <module-nature> ] :: ] <module-name> , ONLY: [ <only-list> ]
+ """
+ subclass_names = []
+ use_names = ['Module_Nature', 'Module_Name', 'Rename_List', 'Only_List']
+
+ def match(string):
+ if string[:3].upper() != 'USE': return
+ line = string[3:]
+ if not line: return
+ if isalnum(line[0]): return
+ line = line.lstrip()
+ i = line.find('::')
+ nature = None
+ if i!=-1:
+ if line.startswith(','):
+ l = line[1:i].strip()
+ if not l: return
+ nature = Module_Nature(l)
+ line = line[i+2:].lstrip()
+ if not line: return
+ i = line.find(',')
+ if i==-1: return nature, Module_Name(line), '', None
+ name = line[:i].rstrip()
+ if not name: return
+ name = Module_Name(name)
+ line = line[i+1:].lstrip()
+ if not line: return
+ if line[:5].upper()=='ONLY:':
+ line = line[5:].lstrip()
+ if not line:
+ return nature, name, ', ONLY:', None
+ return nature, name, ', ONLY:', Only_List(line)
+ return nature, name, ',', Rename_List(line)
+ match = staticmethod(match)
+ def tostr(self):
+ s = 'USE'
+ if self.items[0] is not None:
+ s += ', %s' % (self.items[0])
+ s += ' :: %s%s' % (self.items[1], self.items[2])
+ if self.items[3] is not None:
+ s += ' %s' % (self.items[3])
+ return s
+
+class Module_Nature(STRINGBase): # R1110
+ """
+ <module-nature> = INTRINSIC
+ | NON_INTRINSIC
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match(['INTRINSIC','NON_INTRINSIC'], string)
+ match = staticmethod(match)
+
+class Rename(Base): # R1111
+ """
+ <rename> = <local-name> => <use-name>
+ | OPERATOR(<local-defined-operator>) => OPERATOR(<use-defined-operator>)
+ """
+ subclass_names = []
+ use_names = ['Local_Name', 'Use_Name', 'Local_Defined_Operator', 'Use_Defined_Operator']
+ def match(string):
+ s = string.split('=>', 1)
+ if len(s) != 2: return
+ lhs, rhs = s[0].rstrip(), s[1].lstrip()
+ if not lhs or not rhs: return
+ if lhs[:8].upper()=='OPERATOR' and rhs[:8].upper()=='OPERATOR':
+ l = lhs[8:].lstrip()
+ r = rhs[8:].lstrip()
+ if l and r and l[0]+l[-1]=='()':
+ if r[0]+r[-1] != '()': return
+ l = l[1:-1].strip()
+ r = r[1:-1].strip()
+ if not l or not r: return
+ return 'OPERATOR', Local_Defined_Operator(l), Use_Defined_Operator(r)
+ return None, Local_Name(lhs), Use_Name(rhs)
+ match = staticmethod(match)
+ def tostr(self):
+ if not self.items[0]:
+ return '%s => %s' % self.items[1:]
+ return '%s(%s) => %s(%s)' % (self.items[0], self.items[1],self.items[0], self.items[2])
+
+class Only(Base): # R1112
+ """
+ <only> = <generic-spec>
+ | <only-use-name>
+ | <rename>
+ """
+ subclass_names = ['Generic_Spec', 'Only_Use_Name', 'Rename']
+
+class Only_Use_Name(Base): # R1113
+ """
+ <only-use-name> = <name>
+ """
+ subclass_names = ['Name']
+
+class Local_Defined_Operator(Base): # R1114
+ """
+ <local-defined-operator> = <defined-unary-op>
+ | <defined-binary-op>
+ """
+ subclass_names = ['Defined_Unary_Op', 'Defined_Binary_Op']
+
+class Use_Defined_Operator(Base): # R1115
+ """
+ <use-defined-operator> = <defined-unary-op>
+ | <defined-binary-op>
+ """
+ subclass_names = ['Defined_Unary_Op', 'Defined_Binary_Op']
+
+class Block_Data(Base): # R1116
+ """
+ <block-data> = <block-data-stmt>
+ [ <specification-part> ]
+ <end-block-data-stmt>
+ """
+ subclass_names = []
+ use_names = ['Block_Data_Stmt', 'Specification_Part', 'End_Block_Data_Stmt']
+
+class Block_Data_Stmt(StmtBase): # R1117
+ """
+ <block-data-stmt> = BLOCK DATA [ <block-data-name> ]
+ """
+ subclass_names = []
+ use_names = ['Block_Data_Name']
+ def match(string):
+ if string[:5].upper()!='BLOCK': return
+ line = string[5:].lstrip()
+ if line[:4].upper()!='DATA': return
+ line = line[4:].lstrip()
+ if not line: return None,
+ return Block_Data_Name(line),
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None: return 'BLOCK DATA'
+ return 'BLOCK DATA %s' % self.items
+
+class End_Block_Data_Stmt(EndStmtBase): # R1118
+ """
+ <end-block-data-stmt> = END [ BLOCK DATA [ <block-data-name> ] ]
+ """
+ subclass_names = []
+ use_names = ['Block_Data_Name']
+ def match(string): return EndStmtBase.match('BLOCK DATA',Block_Data_Name, string)
+ match = staticmethod(match)
+
+###############################################################################
+############################### SECTION 12 ####################################
+###############################################################################
+
+
+class Interface_Block(Base): # R1201
+ """
+ <interface-block> = <interface-stmt>
+ [ <interface-specification> ]...
+ <end-interface-stmt>
+ """
+ subclass_names = []
+ use_names = ['Interface_Stmt', 'Interface_Specification', 'End_Interface_Stmt']
+
+class Interface_Specification(Base): # R1202
+ """
+ <interface-specification> = <interface-body>
+ | <procedure-stmt>
+ """
+ subclass_names = ['Interface_Body', 'Procedure_Stmt']
+
+class Interface_Stmt(StmtBase): # R1203
+ """
+ <interface-stmt> = INTERFACE [ <generic-spec> ]
+ | ABSTRACT INTERFACE
+ """
+ subclass_names = []
+ use_names = ['Generic_Spec']
+
+class End_Interface_Stmt(EndStmtBase): # R1204
+ """
+ <end-interface-stmt> = END INTERFACE [ <generic-spec> ]
+ """
+ subclass_names = []
+ use_names = ['Generic_Spec']
+ def match(string): return EndStmtBase.match('INTERFACE',Generic_Spec, string, require_stmt_type=True)
+ match = staticmethod(match)
+
+class Interface_Body(Base): # R1205
+ """
+ <interface-body> = <function-stmt>
+ [ <specification-part> ]
+ <end-function-stmt>
+ | <subroutine-stmt>
+ [ <specification-part> ]
+ <end-subroutine-stmt>
+ """
+ subclass_names = []
+ use_names = ['Function_Stmt', 'Specification_Part', 'Subroutine_Stmt', 'End_Function_Stmt', 'End_Subroutine_Stmt']
+
+class Procedure_Stmt(StmtBase): # R1206
+ """
+ <procedure-stmt> = [ MODULE ] PROCEDURE <procedure-name-list>
+ """
+ subclass_names = []
+ use_names = ['Procedure_Name_List']
+
+class Generic_Spec(Base): # R1207
+ """
+ <generic-spec> = <generic-name>
+ | OPERATOR ( <defined-operator> )
+ | ASSIGNMENT ( = )
+ | <dtio-generic-spec>
+ """
+ subclass_names = ['Generic_Name', 'Dtio_Generic_Spec']
+ use_names = ['Defined_Operator']
+
+class Dtio_Generic_Spec(Base): # R1208
+ """
+ <dtio-generic-spec> = READ ( FORMATTED )
+ | READ ( UNFORMATTED )
+ | WRITE ( FORMATTED )
+ | WRITE ( UNFORMATTED )
+ """
+ subclass_names = []
+
+class Import_Stmt(StmtBase, WORDClsBase): # R1209
+ """
+ <import-stmt> = IMPORT [ :: ] <import-name-list>
+ """
+ subclass_names = []
+ use_names = ['Import_Name_List']
+ def match(string): return WORDClsBase.match('IMPORT',Import_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class External_Stmt(StmtBase, WORDClsBase): # R1210
+ """
+ <external-stmt> = EXTERNAL [ :: ] <external-name-list>
+ """
+ subclass_names = []
+ use_names = ['External_Name_List']
+ def match(string): return WORDClsBase.match('EXTERNAL',External_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Procedure_Declaration_Stmt(StmtBase): # R1211
+ """
+ <procedure-declaration-stmt> = PROCEDURE ( [ <proc-interface> ] ) [ [ , <proc-attr-spec> ]... :: ] <proc-decl-list>
+ """
+ subclass_names = []
+ use_names = ['Proc_Interface', 'Proc_Attr_Spec', 'Proc_Decl_List']
+
+class Proc_Interface(Base): # R1212
+ """
+ <proc-interface> = <interface-name>
+ | <declaration-type-spec>
+ """
+ subclass_names = ['Interface_Name', 'Declaration_Type_Spec']
+
+class Proc_Attr_Spec(Base): # R1213
+ """
+ <proc-attr-spec> = <access-spec>
+ | <proc-language-binding-spec>
+ | INTENT ( <intent-spec> )
+ | OPTIONAL
+ | SAVE
+ """
+ subclass_names = ['Access_Spec', 'Proc_Language_Binding_Spec']
+ use_names = ['Intent_Spec']
+
+class Proc_Decl(BinaryOpBase): # R1214
+ """
+ <proc-decl> = <procedure-entity-name> [ => <null-init> ]
+ """
+ subclass_names = ['Procedure_Entity_Name']
+ use_names = ['Null_Init']
+ def match(string): return BinaryOpBase.match(Procedure_Entity_Name,'=>', Null_Init, string)
+ match = staticmethod(match)
+
+class Interface_Name(Base): # R1215
+ """
+ <interface-name> = <name>
+ """
+ subclass_names = ['Name']
+
+class Intrinsic_Stmt(StmtBase, WORDClsBase): # R1216
+ """
+ <intrinsic-stmt> = INTRINSIC [ :: ] <intrinsic-procedure-name-list>
+ """
+ subclass_names = []
+ use_names = ['Intrinsic_Procedure_Name_List']
+ def match(string): return WORDClsBase.match('INTRINSIC',Intrinsic_Procedure_Name_List,string,check_colons=True, require_cls=True)
+ match = staticmethod(match)
+ tostr = WORDClsBase.tostr_a
+
+class Function_Reference(CallBase): # R1217
+ """
+ <function-reference> = <procedure-designator> ( [ <actual-arg-spec-list> ] )
+ """
+ subclass_names = []
+ use_names = ['Procedure_Designator','Actual_Arg_Spec_List']
+ def match(string):
+ return CallBase.match(Procedure_Designator, Actual_Arg_Spec_List, string)
+ match = staticmethod(match)
+
+class Call_Stmt(StmtBase): # R1218
+ """
+ <call-stmt> = CALL <procedure-designator> [ ( [ <actual-arg-spec-list> ] ) ]
+ """
+ subclass_names = []
+ use_names = ['Procedure_Designator', 'Actual_Arg_Spec_List']
+ def match(string):
+ if string[:4].upper()!='CALL': return
+ line, repmap = string_replace_map(string[4:].lstrip())
+ if line.endswith(')'):
+ i = line.rfind('(')
+ if i==-1: return
+ args = repmap(line[i+1:-1].strip())
+ if args:
+ return Procedure_Designator(repmap(line[:i].rstrip())),Actual_Arg_Spec_List(args)
+ return Procedure_Designator(repmap(line[:i].rstrip())),None
+ return Procedure_Designator(string[4:].lstrip()),None
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None: return 'CALL %s' % (self.items[0])
+ return 'CALL %s(%s)' % self.items
+
+class Procedure_Designator(BinaryOpBase): # R1219
+ """
+ <procedure-designator> = <procedure-name>
+ | <proc-component-ref>
+ | <data-ref> % <binding-name>
+ """
+ subclass_names = ['Procedure_Name','Proc_Component_Ref']
+ use_names = ['Data_Ref','Binding_Name']
+ def match(string):
+ return BinaryOpBase.match(\
+ Data_Ref, pattern.percent_op.named(), Binding_Name, string)
+ match = staticmethod(match)
+
+class Actual_Arg_Spec(KeywordValueBase): # R1220
+ """
+ <actual-arg-spec> = [ <keyword> = ] <actual-arg>
+ """
+ subclass_names = ['Actual_Arg']
+ use_names = ['Keyword']
+ def match(string): return KeywordValueBase.match(Keyword, Actual_Arg, string)
+ match = staticmethod(match)
+
+class Actual_Arg(Base): # R1221
+ """
+ <actual-arg> = <expr>
+ | <variable>
+ | <procedure-name>
+ | <proc-component-ref>
+ | <alt-return-spec>
+ """
+ subclass_names = ['Procedure_Name','Proc_Component_Ref','Alt_Return_Spec', 'Variable', 'Expr']
+
+class Alt_Return_Spec(Base): # R1222
+ """
+ <alt-return-spec> = * <label>
+ """
+ subclass_names = []
+ use_names = ['Label']
+ def match(string):
+ if not string.startswith('*'): return
+ line = string[1:].lstrip()
+ if not line: return
+ return Label(line),
+ match = staticmethod(match)
+ def tostr(self): return '*%s' % (self.items[0])
+
+class Function_Subprogram(BlockBase): # R1223
+ """
+ <function-subprogram> = <function-stmt>
+ [ <specification-part> ]
+ [ <execution-part> ]
+ [ <internal-subprogram-part> ]
+ <end-function-stmt>
+ """
+ subclass_names = []
+ use_names = ['Function_Stmt', 'Specification_Part', 'Execution_Part',
+ 'Internal_Subprogram_Part', 'End_Function_Stmt']
+ def match(reader):
+ return BlockBase.match(Function_Stmt, [Specification_Part, Execution_Part, Internal_Subprogram_Part], End_Function_Stmt, reader)
+ match = staticmethod(match)
+
+class Function_Stmt(StmtBase): # R1224
+ """
+ <function-stmt> = [ <prefix> ] FUNCTION <function-name> ( [ <dummy-arg-name-list> ] ) [ <suffix> ]
+ """
+ subclass_names = []
+ use_names = ['Prefix','Function_Name','Dummy_Arg_Name_List', 'Suffix']
+
+class Proc_Language_Binding_Spec(Base): #1225
+ """
+ <proc-language-binding-spec> = <language-binding-spec>
+ """
+ subclass_names = ['Language_Binding_Spec']
+
+class Dummy_Arg_Name(Base): # R1226
+ """
+ <dummy-arg-name> = <name>
+ """
+ subclass_names = ['Name']
+
+class Prefix(SequenceBase): # R1227
+ """
+ <prefix> = <prefix-spec> [ <prefix-spec> ]..
+ """
+ subclass_names = ['Prefix_Spec']
+ _separator = (' ',re.compile(r'\s+(?=[a-z_])',re.I))
+ def match(string): return SequenceBase.match(Prefix._separator, Prefix_Spec, string)
+ match = staticmethod(match)
+
+class Prefix_Spec(STRINGBase): # R1228
+ """
+ <prefix-spec> = <declaration-type-spec>
+ | RECURSIVE
+ | PURE
+ | ELEMENTAL
+ """
+ subclass_names = ['Declaration_Type_Spec']
+ def match(string):
+ return STRINGBase.match(['RECURSIVE', 'PURE', 'ELEMENTAL'], string)
+ match = staticmethod(match)
+
+class Suffix(Base): # R1229
+ """
+ <suffix> = <proc-language-binding-spec> [ RESULT ( <result-name> ) ]
+ | RESULT ( <result-name> ) [ <proc-language-binding-spec> ]
+ """
+ subclass_names = ['Proc_Language_Binding_Spec']
+ use_names = ['Result_Name']
+
+ def match(string):
+ if string[:6].upper()=='RESULT':
+ line = string[6:].lstrip()
+ if not line.startswith('('): return
+ i = line.find(')')
+ if i==-1: return
+ name = line[1:i].strip()
+ if not name: return
+ line = line[i+1:].lstrip()
+ if line: return Result_Name(name), Proc_Language_Binding_Spec(line)
+ return Result_Name(name), None
+ if not string.endswith(')'): return
+ i = string.rfind('(')
+ if i==-1: return
+ name = string[i+1:-1].strip()
+ if not name: return
+ line = string[:i].rstrip()
+ if line[-6:].upper()!='RESULT': return
+ line = line[:-6].rstrip()
+ if not line: return
+ return Result_Name(name), Proc_Language_Binding_Spec(line)
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None:
+ return 'RESULT(%s)' % (self.items[0])
+ return 'RESULT(%s) %s' % self.items
+
+class End_Function_Stmt(EndStmtBase): # R1230
+ """
+ <end-function-stmt> = END [ FUNCTION [ <function-name> ] ]
+ """
+ subclass_names = []
+ use_names = ['Function_Name']
+ def match(string): return EndStmtBase.match('FUNCTION',Function_Name, string)
+ match = staticmethod(match)
+
+class Subroutine_Subprogram(BlockBase): # R1231
+ """
+ <subroutine-subprogram> = <subroutine-stmt>
+ [ <specification-part> ]
+ [ <execution-part> ]
+ [ <internal-subprogram-part> ]
+ <end-subroutine-stmt>
+ """
+ subclass_names = []
+ use_names = ['Subroutine_Stmt', 'Specification_Part', 'Execution_Part',
+ 'Internal_Subprogram_Part', 'End_Subroutine_Stmt']
+ def match(reader):
+ return BlockBase.match(Subroutine_Stmt, [Specification_Part, Execution_Part, Internal_Subprogram_Part], End_Subroutine_Stmt, reader)
+ match = staticmethod(match)
+
+class Subroutine_Stmt(StmtBase): # R1232
+ """
+ <subroutine-stmt> = [ <prefix> ] SUBROUTINE <subroutine-name> [ ( [ <dummy-arg-list> ] ) [ <proc-language-binding-spec> ] ]
+ """
+ subclass_names = []
+ use_names = ['Prefix', 'Subroutine_Name', 'Dummy_Arg_List', 'Proc_Language_Binding_Spec']
+ def match(string):
+ line, repmap = string_replace_map(string)
+ m = pattern.subroutine.search(line)
+ if m is None: return
+ prefix = line[:m.start()].rstrip() or None
+ if prefix is not None:
+ prefix = Prefix(repmap(prefix))
+ line = line[m.end():].lstrip()
+ m = pattern.name.match(line)
+ if m is None: return
+ name = Subroutine_Name(m.group())
+ line = line[m.end():].lstrip()
+ dummy_args = None
+ if line.startswith('('):
+ i = line.find(')')
+ if i==-1: return
+ dummy_args = line[1:i].strip() or None
+ if dummy_args is not None:
+ dummy_args = Dummy_Arg_List(repmap(dummy_args))
+ line = line[i+1:].lstrip()
+ binding_spec = None
+ if line:
+ binding_spec = Proc_Language_Binding_Spec(repmap(line))
+ return prefix, name, dummy_args, binding_spec
+ match = staticmethod(match)
+ def get_name(self): return self.items[1]
+ def tostr(self):
+ if self.items[0] is not None:
+ s = '%s SUBROUTINE %s' % (self.items[0], self.items[1])
+ else:
+ s = 'SUBROUTINE %s' % (self.items[1])
+ if self.items[2] is not None:
+ s += '(%s)' % (self.items[2])
+ if self.items[3] is not None:
+ s += ' %s' % (self.items[3])
+ return s
+
+class Dummy_Arg(StringBase): # R1233
+ """
+ <dummy-arg> = <dummy-arg-name>
+ | *
+ """
+ subclass_names = ['Dummy_Arg_Name']
+ def match(string): return StringBase.match('*', string)
+ match = staticmethod(match)
+
+class End_Subroutine_Stmt(EndStmtBase): # R1234
+ """
+ <end-subroutine-stmt> = END [ SUBROUTINE [ <subroutine-name> ] ]
+ """
+ subclass_names = []
+ use_names = ['Subroutine_Name']
+ def match(string): return EndStmtBase.match('SUBROUTINE', Subroutine_Name, string)
+ match = staticmethod(match)
+
+class Entry_Stmt(StmtBase): # R1235
+ """
+ <entry-stmt> = ENTRY <entry-name> [ ( [ <dummy-arg-list> ] ) [ <suffix> ] ]
+ """
+ subclass_names = []
+ use_names = ['Entry_Name', 'Dummy_Arg_List', 'Suffix']
+
+class Return_Stmt(StmtBase): # R1236
+ """
+ <return-stmt> = RETURN [ <scalar-int-expr> ]
+ """
+ subclass_names = []
+ use_names = ['Scalar_Int_Expr']
+ def match(string):
+ start = string[:6].upper()
+ if start!='RETURN': return
+ if len(string)==6: return None,
+ return Scalar_Int_Expr(string[6:].lstrip()),
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[0] is None: return 'RETURN'
+ return 'RETURN %s' % self.items
+
+class Contains_Stmt(StmtBase, STRINGBase): # R1237
+ """
+ <contains-stmt> = CONTAINS
+ """
+ subclass_names = []
+ def match(string): return STRINGBase.match('CONTAINS',string)
+ match = staticmethod(match)
+
+class Stmt_Function_Stmt(StmtBase): # R1238
+ """
+ <stmt-function-stmt> = <function-name> ( [ <dummy-arg-name-list> ] ) = Scalar_Expr
+ """
+ subclass_names = []
+ use_names = ['Function_Name', 'Dummy_Arg_Name_List', 'Scalar_Expr']
+
+ def match(string):
+ i = string.find('=')
+ if i==-1: return
+ expr = string[i+1:].lstrip()
+ if not expr: return
+ line = string[:i].rstrip()
+ if not line or not line.endswith(')'): return
+ i = line.find('(')
+ if i==-1: return
+ name = line[:i].rstrip()
+ if not name: return
+ args = line[i+1:-1].strip()
+ if args:
+ return Function_Name(name), Dummy_Arg_Name_List(args), Scalar_Expr(expr)
+ return Function_Name(name), None, Scalar_Expr(expr)
+ match = staticmethod(match)
+ def tostr(self):
+ if self.items[1] is None:
+ return '%s () = %s' % (self.items[0], self.items[2])
+ return '%s (%s) = %s' % self.items
+
+###############################################################################
+################ GENERATE Scalar_, _List, _Name CLASSES #######################
+###############################################################################
+
+ClassType = type(Base)
+_names = dir()
+for clsname in _names:
+ cls = eval(clsname)
+ if not (isinstance(cls, ClassType) and issubclass(cls, Base) and not cls.__name__.endswith('Base')): continue
+ names = getattr(cls, 'subclass_names', []) + getattr(cls, 'use_names', [])
+ for n in names:
+ if n in _names: continue
+ if n.endswith('_List'):
+ _names.append(n)
+ n = n[:-5]
+ #print 'Generating %s_List' % (n)
+ exec '''\
+class %s_List(SequenceBase):
+ subclass_names = [\'%s\']
+ use_names = []
+ def match(string): return SequenceBase.match(r\',\', %s, string)
+ match = staticmethod(match)
+''' % (n, n, n)
+ elif n.endswith('_Name'):
+ _names.append(n)
+ n = n[:-5]
+ #print 'Generating %s_Name' % (n)
+ exec '''\
+class %s_Name(Base):
+ subclass_names = [\'Name\']
+''' % (n)
+ elif n.startswith('Scalar_'):
+ _names.append(n)
+ n = n[7:]
+ #print 'Generating Scalar_%s' % (n)
+ exec '''\
+class Scalar_%s(Base):
+ subclass_names = [\'%s\']
+''' % (n,n)
+
+
+Base_classes = {}
+for clsname in dir():
+ cls = eval(clsname)
+ if isinstance(cls, ClassType) and issubclass(cls, Base) and not cls.__name__.endswith('Base'):
+ Base_classes[cls.__name__] = cls
+
+
+###############################################################################
+##################### OPTIMIZE subclass_names tree ############################
+###############################################################################
+
+if 1: # Optimize subclass tree:
+
+ def _rpl_list(clsname):
+ if not Base_classes.has_key(clsname):
+ print 'Not implemented:',clsname
+ return [] # remove this code when all classes are implemented
+ cls = Base_classes[clsname]
+ if cls.__dict__.has_key('match'): return [clsname]
+ l = []
+ for n in getattr(cls,'subclass_names',[]):
+ l1 = _rpl_list(n)
+ for n1 in l1:
+ if n1 not in l:
+ l.append(n1)
+ return l
+
+ for cls in Base_classes.values():
+ if not hasattr(cls, 'subclass_names'): continue
+ opt_subclass_names = []
+ for n in cls.subclass_names:
+ for n1 in _rpl_list(n):
+ if n1 not in opt_subclass_names: opt_subclass_names.append(n1)
+ if not opt_subclass_names==cls.subclass_names:
+ #print cls.__name__,':',', '.join(cls.subclass_names),'->',', '.join(opt_subclass_names)
+ cls.subclass_names[:] = opt_subclass_names
+ #else:
+ # print cls.__name__,':',opt_subclass_names
+
+
+# Initialize Base.subclasses dictionary:
+for clsname, cls in Base_classes.items():
+ subclass_names = getattr(cls, 'subclass_names', None)
+ if subclass_names is None:
+ print '%s class is missing subclass_names list' % (clsname)
+ continue
+ try:
+ l = Base.subclasses[clsname]
+ except KeyError:
+ Base.subclasses[clsname] = l = []
+ for n in subclass_names:
+ if Base_classes.has_key(n):
+ l.append(Base_classes[n])
+ else:
+ print '%s not implemented needed by %s' % (n,clsname)
+
+if 1:
+ for cls in Base_classes.values():
+ subclasses = Base.subclasses.get(cls.__name__,[])
+ subclasses_names = [c.__name__ for c in subclasses]
+ subclass_names = getattr(cls,'subclass_names', [])
+ use_names = getattr(cls,'use_names',[])
+ for n in subclasses_names:
+ break
+ if n not in subclass_names:
+ print '%s needs to be added to %s subclasses_name list' % (n,cls.__name__)
+ for n in subclass_names:
+ break
+ if n not in subclasses_names:
+ print '%s needs to be added to %s subclass_name list' % (n,cls.__name__)
+ for n in use_names + subclass_names:
+ if not Base_classes.has_key(n):
+ print '%s not defined used by %s' % (n, cls.__name__)
+
+
+#EOF
diff --git a/numpy/f2py/lib/parser/__init__.py b/numpy/f2py/lib/parser/__init__.py
new file mode 100644
index 000000000..9d707c01f
--- /dev/null
+++ b/numpy/f2py/lib/parser/__init__.py
@@ -0,0 +1,14 @@
+"""
+Tools for parsing Fortran 60/77/90/2003 codes into Statement tree.
+
+Use api module for importing public symbols.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
diff --git a/numpy/f2py/lib/parser/api.py b/numpy/f2py/lib/parser/api.py
new file mode 100644
index 000000000..476c142e5
--- /dev/null
+++ b/numpy/f2py/lib/parser/api.py
@@ -0,0 +1,73 @@
+"""
+Public API for Fortran parser.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import Fortran2003
+# import all Statement classes:
+from base_classes import EndStatement
+from block_statements import *
+
+# CHAR_BIT is used to convert object bit sizes to byte sizes
+from utils import CHAR_BIT
+
+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(input, isfree=None, isstrict=None, include_dirs = None):
+ """ Parse input and return Statement tree.
+
+ input --- string or filename.
+ isfree, isstrict --- specify input Fortran format.
+ Defaults are True, False, respectively, or
+ determined from input.
+ include_dirs --- list of include directories.
+ Default contains current working directory
+ and the directory of file name.
+ """
+ from parsefortran import FortranParser
+ reader = get_reader(input, isfree, isstrict, include_dirs)
+ parser = FortranParser(reader)
+ parser.parse()
+ parser.analyze()
+ return parser.block
diff --git a/numpy/f2py/lib/parser/base_classes.py b/numpy/f2py/lib/parser/base_classes.py
new file mode 100644
index 000000000..68ea9c24a
--- /dev/null
+++ b/numpy/f2py/lib/parser/base_classes.py
@@ -0,0 +1,819 @@
+"""
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['Statement','BeginStatement','EndStatement', 'Variable',
+ 'AttributeHolder','ProgramBlock']
+
+import re
+import sys
+import copy
+from readfortran import Line
+from numpy.distutils.misc_util import yellow_text, red_text
+from utils import split_comma, specs_split_comma, is_int_literal_constant
+
+class AttributeHolder:
+ # copied from symbolic.base module
+ """
+ Defines a object with predefined attributes. Only those attributes
+ are allowed that are specified as keyword arguments of a constructor.
+ When an argument is callable then the corresponding attribute will
+ be read-only and set by the value the callable object returns.
+ """
+ def __init__(self, **kws):
+ self._attributes = {}
+ self._readonly = []
+ for k,v in kws.items():
+ self._attributes[k] = v
+ if callable(v):
+ self._readonly.append(k)
+ return
+
+ def __getattr__(self, name):
+ if name not in self._attributes:
+ raise AttributeError,'%s instance has no attribute %r, '\
+ 'expected attributes: %s' \
+ % (self.__class__.__name__,name,
+ ','.join(self._attributes.keys()))
+ value = self._attributes[name]
+ if callable(value):
+ value = value()
+ self._attributes[name] = value
+ return value
+
+ def __setattr__(self, name, value):
+ if name in ['_attributes','_readonly']:
+ self.__dict__[name] = value
+ return
+ if name in self._readonly:
+ raise AttributeError,'%s instance attribute %r is readonly' \
+ % (self.__class__.__name__, name)
+ if name not in self._attributes:
+ raise AttributeError,'%s instance has no attribute %r, '\
+ 'expected attributes: %s' \
+ % (self.__class__.__name__,name,','.join(self._attributes.keys()))
+ self._attributes[name] = value
+
+ def isempty(self):
+ for k in self._attributes.keys():
+ v = getattr(self,k)
+ if v: return False
+ return True
+
+ def __repr__(self): return self.torepr()
+
+ def torepr(self, depth=-1, tab = ''):
+ if depth==0: return tab + self.__class__.__name__
+ l = [self.__class__.__name__+':']
+ ttab = tab + ' '
+ for k in self._attributes.keys():
+ v = getattr(self,k)
+ if v:
+ if isinstance(v,list):
+ l.append(ttab + '%s=<%s-list>' % (k,len(v)))
+ elif isinstance(v,dict):
+ l.append(ttab + '%s=<dict with keys %s>' % (k,v.keys()))
+ else:
+ l.append(ttab + '%s=<%s>' % (k,type(v)))
+ return '\n'.join(l)
+
+ def todict(self):
+ d = {}
+ for k in self._attributes.keys():
+ v = getattr(self, k)
+ d[k] = v
+ return d
+
+def get_base_classes(cls):
+ bases = ()
+ for c in cls.__bases__:
+ bases += get_base_classes(c)
+ return bases + cls.__bases__ + (cls,)
+
+class Variable:
+ """
+ Variable instance has attributes:
+ name
+ typedecl
+ dimension
+ attributes
+ intent
+ parent - Statement instances defining the variable
+ """
+ def __init__(self, parent, name):
+ self.parent = parent
+ self.parents = [parent]
+ self.name = name
+ self.typedecl = None
+ self.dimension = None
+ self.bounds = None
+ self.length = None
+ self.attributes = []
+ self.intent = None
+ self.bind = []
+ self.check = []
+ self.init = None
+
+ # after calling analyze the following additional attributes are set:
+ # .is_array:
+ # rank
+ # shape
+ return
+
+ def __repr__(self):
+ l = []
+ for a in ['name','typedecl','dimension','bounds','length','attributes','intent','bind','check','init']:
+ v = getattr(self,a)
+ if v:
+ l.append('%s=%r' % (a,v))
+ return 'Variable: ' + ', '.join(l)
+
+ def get_bit_size(self):
+ typesize = self.typedecl.get_bit_size()
+ if self.is_pointer():
+ # The size of pointer descriptor is compiler version dependent. Read:
+ # http://www.nersc.gov/vendor_docs/intel/f_ug1/pgwarray.htm
+ # https://www.cca-forum.org/pipermail/cca-fortran/2003-February/000123.html
+ # https://www.cca-forum.org/pipermail/cca-fortran/2003-February/000122.html
+ # On sgi descriptor size may be 128+ bits!
+ if self.is_array():
+ wordsize = 4 # XXX: on a 64-bit system it is 8.
+ rank = len(self.bounds or self.dimension)
+ return 6 * wordsize + 12 * rank
+ return typesize
+ if self.is_array():
+ size = reduce(lambda x,y:x*y,self.bounds or self.dimension,1)
+ if self.length:
+ size *= self.length
+ return size * typesize
+ if self.length:
+ return self.length * typesize
+ return typesize
+
+ def get_typedecl(self):
+ if self.typedecl is None:
+ self.set_type(self.parent.get_type(self.name))
+ return self.typedecl
+
+ def add_parent(self, parent):
+ if id(parent) not in map(id, self.parents):
+ self.parents.append(parent)
+ self.parent = parent
+ return
+
+ def set_type(self, typedecl):
+ if self.typedecl is not None:
+ if not self.typedecl==typedecl:
+ self.parent.warning(\
+ 'variable %r already has type %s,'\
+ ' resetting to %s' \
+ % (self.name, self.typedecl.tostr(),typedecl.tostr()))
+ assert typedecl is not None
+ self.typedecl = typedecl
+ return
+
+ def set_init(self, expr):
+ if self.init is not None:
+ if not self.init==expr:
+ self.parent.warning(\
+ 'variable %r already has initialization %r, '\
+ ' resetting to %r' % (self.name, self.expr, expr))
+ self.init = expr
+ return
+
+ def set_dimension(self, dims):
+ if self.dimension is not None:
+ if not self.dimension==dims:
+ self.parent.warning(\
+ 'variable %r already has dimension %r, '\
+ ' resetting to %r' % (self.name, self.dimension, dims))
+ self.dimension = dims
+ return
+
+ def set_bounds(self, bounds):
+ if self.bounds is not None:
+ if not self.bounds==bounds:
+ self.parent.warning(\
+ 'variable %r already has bounds %r, '\
+ ' resetting to %r' % (self.name, self.bounds, bounds))
+ self.bounds = bounds
+ return
+
+ def set_length(self, length):
+ if self.length is not None:
+ if not self.length==length:
+ self.parent.warning(\
+ 'variable %r already has length %r, '\
+ ' resetting to %r' % (self.name, self.length, length))
+ self.length = length
+ return
+
+ known_intent_specs = ['IN','OUT','INOUT','CACHE','HIDE', 'COPY',
+ 'OVERWRITE', 'CALLBACK', 'AUX', 'C', 'INPLACE',
+ 'OUT=']
+
+ def set_intent(self, intent):
+ if self.intent is None:
+ self.intent = []
+ for i in intent:
+ if i not in self.intent:
+ if i not in self.known_intent_specs:
+ self.parent.warning('unknown intent-spec %r for %r'\
+ % (i, self.name))
+ self.intent.append(i)
+ return
+
+ known_attributes = ['PUBLIC', 'PRIVATE', 'ALLOCATABLE', 'ASYNCHRONOUS',
+ 'EXTERNAL', 'INTRINSIC', 'OPTIONAL', 'PARAMETER',
+ 'POINTER', 'PROTECTED', 'SAVE', 'TARGET', 'VALUE',
+ 'VOLATILE', 'REQUIRED']
+
+ def is_intent_in(self):
+ if not self.intent: return True
+ if 'HIDE' in self.intent: return False
+ if 'INPLACE' in self.intent: return False
+ if 'IN' in self.intent: return True
+ if 'OUT' in self.intent: return False
+ if 'INOUT' in self.intent: return False
+ if 'OUTIN' in self.intent: return False
+ return True
+
+ def is_intent_inout(self):
+ if not self.intent: return False
+ if 'INOUT' in self.intent:
+ if 'IN' in self.intent or 'HIDE' in self.intent or 'INPLACE' in self.intent:
+ self.warning('INOUT ignored in INPUT(%s)' % (', '.join(self.intent)))
+ return False
+ return True
+ return False
+
+ def is_intent_hide(self):
+ if not self.intent: return False
+ if 'HIDE' in self.intent: return True
+ if 'OUT' in self.intent:
+ return 'IN' not in self.intent and 'INPLACE' not in self.intent and 'INOUT' not in self.intent
+ return False
+
+ def is_intent_inplace(self): return self.intent and 'INPLACE' in self.intent
+ def is_intent_out(self): return self.intent and 'OUT' in self.intent
+ def is_intent_c(self): return self.intent and 'C' in self.intent
+ def is_intent_cache(self): return self.intent and 'CACHE' in self.intent
+ def is_intent_copy(self): return self.intent and 'COPY' in self.intent
+ def is_intent_overwrite(self): return self.intent and 'OVERWRITE' in self.intent
+ def is_intent_callback(self): return self.intent and 'CALLBACK' in self.intent
+ def is_intent_aux(self): return self.intent and 'AUX' in self.intent
+
+ def is_private(self):
+ if 'PUBLIC' in self.attributes: return False
+ if 'PRIVATE' in self.attributes: return True
+ parent_attrs = self.parent.parent.a.attributes
+ if 'PUBLIC' in parent_attrs: return False
+ if 'PRIVATE' in parent_attrs: return True
+ return
+ def is_public(self): return not self.is_private()
+
+ def is_allocatable(self): return 'ALLOCATABLE' in self.attributes
+ def is_external(self): return 'EXTERNAL' in self.attributes
+ def is_intrinsic(self): return 'INTRINSIC' in self.attributes
+ def is_parameter(self): return 'PARAMETER' in self.attributes
+ def is_optional(self): return 'OPTIONAL' in self.attributes and 'REQUIRED' not in self.attributes and not self.is_intent_hide()
+ def is_required(self): return self.is_optional() and not self.is_intent_hide()
+ def is_pointer(self): return 'POINTER' in self.attributes
+
+ def is_array(self): return not not (self.bounds or self.dimension)
+ def is_scalar(self): return not self.is_array()
+
+ def update(self, *attrs):
+ attributes = self.attributes
+ if len(attrs)==1 and isinstance(attrs[0],(tuple,list)):
+ attrs = attrs[0]
+ for attr in attrs:
+ lattr = attr.lower()
+ uattr = attr.upper()
+ if lattr.startswith('dimension'):
+ assert self.dimension is None, `self.dimension,attr`
+ l = attr[9:].lstrip()
+ assert l[0]+l[-1]=='()',`l`
+ self.set_dimension(split_comma(l[1:-1].strip(), self.parent.item))
+ continue
+ if lattr.startswith('intent'):
+ l = attr[6:].lstrip()
+ assert l[0]+l[-1]=='()',`l`
+ self.set_intent(specs_split_comma(l[1:-1].strip(),
+ self.parent.item, upper=True))
+ continue
+ if lattr.startswith('bind'):
+ l = attr[4:].lstrip()
+ assert l[0]+l[-1]=='()',`l`
+ self.bind = specs_split_comma(l[1:-1].strip(), self.parent.item,
+ upper = True)
+ continue
+ if lattr.startswith('check'):
+ l = attr[5:].lstrip()
+ assert l[0]+l[-1]=='()',`l`
+ self.check.extend(split_comma(l[1:-1].strip()), self.parent.item)
+ continue
+ if uattr not in attributes:
+ if uattr not in self.known_attributes:
+ self.parent.warning('unknown attribute %r' % (attr))
+ attributes.append(uattr)
+ return
+
+ def __str__(self):
+ s = ''
+ typedecl = self.get_typedecl()
+ if typedecl is not None:
+ s += typedecl.tostr() + ' '
+ a = self.attributes[:]
+ if self.dimension is not None:
+ a.append('DIMENSION(%s)' % (', '.join(self.dimension)))
+ if self.intent is not None:
+ a.append('INTENT(%s)' % (', '.join(self.intent)))
+ if self.bind:
+ a.append('BIND(%s)' % (', '.join(self.bind)))
+ if self.check:
+ a.append('CHECK(%s)' % (', '.join(self.check)))
+ if a:
+ s += ', ' + ', '.join(a) + ' :: '
+ s += self.name
+ if self.bounds:
+ s += '(%s)' % (', '.join([':'.join(spec) for spec in self.bounds]))
+ if self.length:
+ if is_int_literal_constant(self.length):
+ s += '*%s' % (self.length)
+ else:
+ s += '*(%s)' % (self.length)
+ if self.init:
+ s += ' = ' + self.init
+ return s
+
+ def get_array_spec(self):
+ assert self.is_array(),'array_spec is available only for arrays'
+ if self.bounds:
+ if self.dimension:
+ self.parent.warning('both bounds=%r and dimension=%r are defined, ignoring dimension.' % (self.bounds, self.dimension))
+ array_spec = self.bounds
+ else:
+ array_spec = self.dimension
+ return array_spec
+
+ def is_deferred_shape_array(self):
+ if not self.is_array(): return False
+ return self.is_allocatable() or self.is_pointer()
+
+ def is_assumed_size_array(self):
+ if not self.is_array(): return False
+ return self.get_array_spec()[-1][-1]=='*'
+
+ def is_assumed_shape_array(self):
+ if not self.is_array(): return False
+ if self.is_deferred_shape_array(): return False
+ for spec in self.get_array_spec():
+ if not spec[-1]: return True
+ return False
+
+ def is_explicit_shape_array(self):
+ if not self.is_array(): return False
+ if self.is_deferred_shape_array(): return False
+ for spec in self.get_array_spec():
+ if not spec[-1] or spec[-1] == '*': return False
+ return True
+
+ def is_allocatable_array(self):
+ return self.is_array() and self.is_allocatable()
+
+ def is_array_pointer(self):
+ return self.is_array() and self.is_pointer()
+
+ def analyze(self):
+ typedecl = self.get_typedecl()
+ if self.is_array():
+ array_spec = self.get_array_spec()
+ self.rank = len(array_spec)
+ if self.is_deferred_shape_array(): # a(:,:)
+ pass
+ elif self.is_explicit_shape_array():
+ shape = []
+ for spec in array_spec:
+ if len(spec)==1:
+ shape.append(spec[0])
+ else:
+ shape.append(spec[1]-spec[0])
+ self.shape = shape
+ return
+
+class ProgramBlock:
+ pass
+
+class Statement:
+ """
+ Statement instance has attributes:
+ parent - Parent BeginStatement or FortranParser instance
+ item - Line instance containing the statement line
+ isvalid - boolean, when False, the Statement instance will be ignored
+ """
+ modes = ['free90','fix90','fix77','pyf']
+ _repr_attr_names = []
+
+ def __init__(self, parent, item):
+ self.parent = parent
+ if item is not None:
+ self.reader = item.reader
+ else:
+ self.reader = parent.reader
+ self.top = getattr(parent,'top',None) # the top of statement tree
+ self.item = item
+
+ if isinstance(parent, ProgramBlock):
+ self.programblock = parent
+ elif isinstance(self, ProgramBlock):
+ self.programblock = self
+ elif hasattr(parent,'programblock'):
+ self.programblock = parent.programblock
+ else:
+ #self.warning('%s.programblock attribute not set.' % (self.__class__.__name__))
+ pass
+
+ # when a statement instance is constructed by error, set isvalid to False
+ self.isvalid = True
+ # when a statement should be ignored, set ignore to True
+ self.ignore = False
+
+ # attribute a will hold analyze information.
+ a_dict = {}
+ for cls in get_base_classes(self.__class__):
+ if hasattr(cls,'a'):
+ a_dict.update(copy.deepcopy(cls.a.todict()))
+ self.a = AttributeHolder(**a_dict)
+ if hasattr(self.__class__,'a'):
+ assert self.a is not self.__class__.a
+
+ self.process_item()
+
+ return
+
+ def __repr__(self):
+ return self.torepr()
+
+ def torepr(self, depth=-1,incrtab=''):
+ tab = incrtab + self.get_indent_tab()
+ clsname = self.__class__.__name__
+ l = [tab + yellow_text(clsname)]
+ if depth==0:
+ return '\n'.join(l)
+ ttab = tab + ' '
+ for n in self._repr_attr_names:
+ attr = getattr(self, n, None)
+ if not attr: continue
+ if hasattr(attr, 'torepr'):
+ r = attr.torepr(depth-1,incrtab)
+ else:
+ r = repr(attr)
+ l.append(ttab + '%s=%s' % (n, r))
+ if self.item is not None: l.append(ttab + 'item=%r' % (self.item))
+ if not self.isvalid: l.append(ttab + 'isvalid=%r' % (self.isvalid))
+ if self.ignore: l.append(ttab + 'ignore=%r' % (self.ignore))
+ if not self.a.isempty():
+ l.append(ttab + 'a=' + self.a.torepr(depth-1,incrtab+' ').lstrip())
+ return '\n'.join(l)
+
+ def get_indent_tab(self,colon=None,deindent=False,isfix=None):
+ if isfix is None: isfix = self.reader.isfix
+ if isfix:
+ tab = ' '*6
+ else:
+ tab = ''
+ p = self.parent
+ while isinstance(p, Statement):
+ tab += ' '
+ p = p.parent
+ if deindent:
+ tab = tab[:-2]
+ if self.item is None:
+ return tab
+ s = self.item.label
+ if colon is None:
+ if isfix:
+ colon = ''
+ else:
+ colon = ':'
+ if s:
+ c = ''
+ if isfix:
+ c = ' '
+ tab = tab[len(c+s)+len(colon):]
+ if not tab: tab = ' '
+ tab = c + s + colon + tab
+ return tab
+
+ def __str__(self):
+ return self.tofortran()
+
+ def asfix(self):
+ lines = []
+ for line in self.tofortran(isfix=True).split('\n'):
+ if len(line)>72 and line[0]==' ':
+ lines.append(line[:72]+'&\n &')
+ line = line[72:]
+ while len(line)>66:
+ lines.append(line[:66]+'&\n &')
+ line = line[66:]
+ lines.append(line+'\n')
+ else: lines.append(line+'\n')
+ return ''.join(lines).replace('\n &\n','\n')
+
+ def format_message(self, kind, message):
+ if self.item is not None:
+ message = self.reader.format_message(kind, message,
+ self.item.span[0], self.item.span[1])
+ else:
+ return message
+ return message
+
+ def show_message(self, message, stream=sys.stderr):
+ print >> stream, message
+ stream.flush()
+ return
+
+ def error(self, message):
+ message = self.format_message('ERROR', red_text(message))
+ self.show_message(message)
+ return
+
+ def warning(self, message):
+ message = self.format_message('WARNING', yellow_text(message))
+ self.show_message(message)
+ return
+
+ def info(self, message):
+ message = self.format_message('INFO', message)
+ self.show_message(message)
+ return
+
+ def analyze(self):
+ self.warning('nothing analyzed')
+ return
+
+ def get_variable(self, name):
+ """ Return Variable instance of variable name.
+ """
+ mth = getattr(self,'get_variable_by_name', self.parent.get_variable)
+ return mth(name)
+
+ def get_type(self, name):
+ """ Return type declaration using implicit rules
+ for name.
+ """
+ mth = getattr(self,'get_type_by_name', self.parent.get_type)
+ return mth(name)
+
+ def get_type_decl(self, kind):
+ mth = getattr(self,'get_type_decl_by_kind', self.parent.get_type_decl)
+ return mth(kind)
+
+ def get_provides(self):
+ """ Returns dictonary containing statements that block provides or None when N/A.
+ """
+ return
+
+class BeginStatement(Statement):
+ """ <blocktype> <name>
+
+ BeginStatement instances have additional attributes:
+ name
+ blocktype
+
+ Block instance has attributes:
+ content - list of Line or Statement instances
+ name - name of the block, unnamed blocks are named
+ with the line label
+ parent - Block or FortranParser instance
+ item - Line instance containing the block start statement
+ get_item, put_item - methods to retrive/submit Line instances
+ from/to Fortran reader.
+ isvalid - boolean, when False, the Block instance will be ignored.
+
+ stmt_cls, end_stmt_cls
+
+ """
+ _repr_attr_names = ['blocktype','name'] + Statement._repr_attr_names
+ def __init__(self, parent, item=None):
+
+ self.content = []
+ self.get_item = parent.get_item # get line function
+ self.put_item = parent.put_item # put line function
+ if not hasattr(self, 'blocktype'):
+ self.blocktype = self.__class__.__name__.lower()
+ if not hasattr(self, 'name'):
+ # process_item may change this
+ self.name = '__'+self.blocktype.upper()+'__'
+ Statement.__init__(self, parent, item)
+ return
+
+ def tostr(self):
+ return self.blocktype.upper() + ' '+ self.name
+
+ def tofortran(self, isfix=None):
+ l=[self.get_indent_tab(colon=':', isfix=isfix) + self.tostr()]
+ for c in self.content:
+ l.append(c.tofortran(isfix=isfix))
+ return '\n'.join(l)
+
+ def torepr(self, depth=-1, incrtab=''):
+ tab = incrtab + self.get_indent_tab()
+ ttab = tab + ' '
+ l=[Statement.torepr(self, depth=depth,incrtab=incrtab)]
+ if depth==0 or not self.content:
+ return '\n'.join(l)
+ l.append(ttab+'content:')
+ for c in self.content:
+ if isinstance(c,EndStatement):
+ l.append(c.torepr(depth-1,incrtab))
+ else:
+ l.append(c.torepr(depth-1,incrtab + ' '))
+ return '\n'.join(l)
+
+ def process_item(self):
+ """ Process the line
+ """
+ item = self.item
+ if item is None: return
+ self.fill()
+ return
+
+ def fill(self, end_flag = False):
+ """
+ Fills blocks content until the end of block statement.
+ """
+
+ mode = self.reader.mode
+ classes = self.get_classes()
+ self.classes = [cls for cls in classes if mode in cls.modes]
+ self.pyf_classes = [cls for cls in classes if 'pyf' in cls.modes]
+
+ item = self.get_item()
+ while item is not None:
+ if isinstance(item, Line):
+ if self.process_subitem(item):
+ end_flag = True
+ break
+ item = self.get_item()
+
+ if not end_flag:
+ self.warning('failed to find the end of block')
+ return
+
+ def process_subitem(self, item):
+ """
+ Check is item is blocks start statement, if it is, read the block.
+
+ Return True to stop adding items to given block.
+ """
+ line = item.get_line()
+
+ # First check for the end of block
+ cls = self.end_stmt_cls
+ if cls.match(line):
+ stmt = cls(self, item)
+ if stmt.isvalid:
+ self.content.append(stmt)
+ return True
+
+ if item.is_f2py_directive:
+ classes = self.pyf_classes
+ else:
+ classes = self.classes
+
+ # Look for statement match
+ for cls in classes:
+ if cls.match(line):
+ stmt = cls(self, item)
+ if stmt.isvalid:
+ if not stmt.ignore:
+ self.content.append(stmt)
+ return False
+ # item may be cloned that changes the items line:
+ line = item.get_line()
+
+ # Check if f77 code contains inline comments or other f90
+ # constructs that got undetected by get_source_info.
+ if item.reader.isfix77:
+ i = line.find('!')
+ if i != -1:
+ message = item.reader.format_message(\
+ 'WARNING',
+ 'no parse pattern found for "%s" in %r block'\
+ ' maybe due to inline comment.'\
+ ' Trying to remove the comment.'\
+ % (item.get_line(),self.__class__.__name__),
+ item.span[0], item.span[1])
+ # .. but at the expense of loosing the comment.
+ self.show_message(message)
+ newitem = item.copy(line[:i].rstrip())
+ return self.process_subitem(newitem)
+
+ # try fix90 statement classes
+ f77_classes = self.classes
+ classes = []
+ for cls in self.get_classes():
+ if 'fix90' in cls.modes and cls not in f77_classes:
+ classes.append(cls)
+ if classes:
+ message = item.reader.format_message(\
+ 'WARNING',
+ 'no parse pattern found for "%s" in %r block'\
+ ' maybe due to strict f77 mode.'\
+ ' Trying f90 fix mode patterns..'\
+ % (item.get_line(),self.__class__.__name__),
+ item.span[0], item.span[1])
+ self.show_message(message)
+
+ item.reader.set_mode(False, False)
+ self.classes = classes
+
+ r = BeginStatement.process_subitem(self, item)
+ if r is None:
+ # restore f77 fix mode
+ self.classes = f77_classes
+ item.reader.set_mode(False, True)
+ else:
+ message = item.reader.format_message(\
+ 'INFORMATION',
+ 'The f90 fix mode resolved the parse pattern issue.'\
+ ' Setting reader to f90 fix mode.',
+ item.span[0], item.span[1])
+ self.show_message(message)
+ # set f90 fix mode
+ self.classes = f77_classes + classes
+ self.reader.set_mode(False, False)
+ return r
+
+ self.handle_unknown_item(item)
+ return
+
+ def handle_unknown_item(self, item):
+ message = item.reader.format_message(\
+ 'WARNING',
+ 'no parse pattern found for "%s" in %r block.'\
+ % (item.get_line(),self.__class__.__name__),
+ item.span[0], item.span[1])
+ self.show_message(message)
+ self.content.append(item)
+ #sys.exit()
+ return
+
+ def analyze(self):
+ for stmt in self.content:
+ stmt.analyze()
+ return
+
+class EndStatement(Statement):
+ """
+ END [<blocktype> [<name>]]
+
+ EndStatement instances have additional attributes:
+ name
+ blocktype
+ """
+ _repr_attr_names = ['blocktype','name'] + Statement._repr_attr_names
+
+ def __init__(self, parent, item):
+ if not hasattr(self, 'blocktype'):
+ self.blocktype = self.__class__.__name__.lower()[3:]
+ Statement.__init__(self, parent, item)
+
+ def process_item(self):
+ item = self.item
+ line = item.get_line().replace(' ','')[3:]
+ blocktype = self.blocktype
+ if line.lower().startswith(blocktype):
+ line = line[len(blocktype):].strip()
+ else:
+ if line:
+ # not the end of expected block
+ line = ''
+ self.isvalid = False
+ if line:
+ if not line==self.parent.name:
+ self.warning(\
+ 'expected the end of %r block but got the end of %r, skipping.'\
+ % (self.parent.name, line))
+ self.isvalid = False
+ self.name = self.parent.name
+
+ def analyze(self):
+ return
+
+ def get_indent_tab(self,colon=None,deindent=False,isfix=None):
+ return Statement.get_indent_tab(self, colon=colon, deindent=True,isfix=isfix)
+
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'END %s %s'\
+ % (self.blocktype.upper(),self.name or '')
diff --git a/numpy/f2py/lib/parser/block_statements.py b/numpy/f2py/lib/parser/block_statements.py
new file mode 100644
index 000000000..b3d29c911
--- /dev/null
+++ b/numpy/f2py/lib/parser/block_statements.py
@@ -0,0 +1,1229 @@
+"""
+Fortran block statements.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['BeginSource','Module','PythonModule','Program','BlockData','Interface',
+ 'Subroutine','Function','Select','WhereConstruct','ForallConstruct',
+ 'IfThen','If','Do','Associate','TypeDecl','Enum',
+ 'EndSource','EndModule','EndPythonModule','EndProgram','EndBlockData','EndInterface',
+ 'EndSubroutine','EndFunction','EndSelect','EndWhere','EndForall',
+ 'EndIfThen','EndDo','EndAssociate','EndType','EndEnum',
+ ]
+
+import re
+import sys
+
+from base_classes import BeginStatement, EndStatement, Statement,\
+ AttributeHolder, ProgramBlock, Variable
+from readfortran import Line
+from utils import filter_stmts, parse_bind, parse_result, AnalyzeError, is_name
+
+class HasImplicitStmt:
+
+ a = AttributeHolder(implicit_rules = {})
+
+ def get_type_by_name(self, name):
+ implicit_rules = self.a.implicit_rules
+ if implicit_rules is None:
+ raise AnalyzeError,'Implicit rules mapping is null while getting %r type' % (name)
+ l = name[0].lower()
+ if implicit_rules.has_key(l):
+ return implicit_rules[l]
+ # default rules:
+ if l in 'ijklmn':
+ l = 'default_integer'
+ else:
+ l = 'default_real'
+ t = implicit_rules.get(l, None)
+ if t is None:
+ if l[8:]=='real':
+ implicit_rules[l] = t = Real(self, self.item.copy('real'))
+ else:
+ implicit_rules[l] = t = Integer(self, self.item.copy('integer'))
+ return t
+
+ def topyf(self, tab=' '):
+ implicit_rules = self.a.implicit_rules
+ if implicit_rules is None:
+ return tab + 'IMPLICIT NONE\n'
+ items = {}
+ for c,t in implicit_rules.items():
+ if c.startswith('default'):
+ continue
+ st = t.tostr()
+ if items.has_key(st):
+ items[st].append(c)
+ else:
+ items[st] = [c]
+ if not items:
+ return tab + '! default IMPLICIT rules apply\n'
+ s = 'IMPLICIT'
+ ls = []
+ for st,l in items.items():
+ l.sort()
+ ls.append(st + ' (%s)' % (', '.join(l)))
+ s += ' ' + ', '.join(ls)
+ return tab + s + '\n'
+
+class HasUseStmt:
+
+ a = AttributeHolder(use = {},
+ use_provides = {})
+
+ def get_entity(self, name):
+ for modname, modblock in self.top.a.module.items():
+ for stmt in modblock.content:
+ if getattr(stmt,'name','') == name:
+ return stmt
+ return
+
+ def topyf(self, tab=' '):
+ sys.stderr.write('HasUseStmt.topyf not implemented\n')
+ return ''
+
+class AccessSpecs:
+
+ a = AttributeHolder(private_id_list = [], public_id_list = [])
+
+ def topyf(self, tab=' '):
+ private_list = self.a.private_id_list
+ public_list = self.a.public_id_list
+ l = []
+ if '' in private_list: l.append(tab + 'PRIVATE\n')
+ if '' in public_list: l.append(tab + 'PUBLIC\n')
+ for a in private_list:
+ if not a: continue
+ l.append(tab + 'PRIVATE :: %s\n' % (a))
+ for a in public_list:
+ if not a: continue
+ l.append(tab + 'PUBLIC :: %s\n' % (a))
+ return ''.join(l)
+
+class HasVariables:
+
+ a = AttributeHolder(variables = {},
+ variable_names = [] # defines the order of declarations
+ )
+
+ def get_variable_by_name(self, name):
+ variables = self.a.variables
+ if variables.has_key(name):
+ var = variables[name]
+ else:
+ var = variables[name] = Variable(self, name)
+ self.a.variable_names.append(name)
+ return var
+
+ def topyf(self,tab='', only_variables = None):
+ s = ''
+ if only_variables is None:
+ only_variables = self.a.variables.keys()
+ for name in only_variables:
+ var = self.a.variables[name]
+ s += tab + str(var) + '\n'
+ return s
+
+class HasTypeDecls:
+
+ a = AttributeHolder(type_decls = {})
+
+ def topyf(self, tab=''):
+ s = ''
+ for name, stmt in self.a.type_decls.items():
+ s += stmt.topyf(tab=' '+tab)
+ return s
+
+ def get_type_decl_by_kind(self, kind):
+ type_decls = self.a.type_decls
+ type_decl = type_decls.get(kind, None)
+ if type_decl is None:
+ return self.get_entity(kind)
+ return type_decl
+
+class HasAttributes:
+
+ known_attributes = []
+ a = AttributeHolder(attributes = [])
+
+ def topyf(self, tab=''):
+ s = ''
+ for attr in self.a.attributes:
+ s += tab + attr + '\n'
+ return s
+
+ def update_attributes(self,*attrs):
+ attributes = self.a.attributes
+ known_attributes = self.known_attributes
+ if len(attrs)==1 and isinstance(attrs[0],(tuple,list)):
+ attrs = attrs[0]
+ for attr in attrs:
+ uattr = attr.upper()
+ if uattr not in attributes:
+ if isinstance(known_attributes,(list, tuple)):
+ if uattr not in known_attributes:
+ self.warning('unknown attribute %r' % (attr))
+ elif not known_attributes(uattr):
+ self.warning('unknown attribute %r' % (attr))
+ attributes.append(uattr)
+ return
+
+class HasModuleProcedures:
+
+ a = AttributeHolder(module_procedures = [])
+
+# File block
+
+class EndSource(EndStatement):
+ """
+ Dummy End statement for BeginSource.
+ """
+ match = staticmethod(lambda s: False)
+
+class BeginSource(BeginStatement):
+ """
+ Fortran source content.
+ """
+ match = staticmethod(lambda s: True)
+ end_stmt_cls = EndSource
+ a = AttributeHolder(module = {},
+ external_subprogram = {},
+ blockdata = {},
+ )
+
+ def tostr(self):
+ return '!' + self.blocktype.upper() + ' '+ self.name
+
+ def process_item(self):
+ self.name = self.reader.name
+ self.top = self
+ self.fill(end_flag = True)
+ return
+
+ def analyze(self):
+ for stmt in self.content:
+ if isinstance(stmt, Module):
+ stmt.analyze()
+ self.a.module[stmt.name] = stmt
+ elif isinstance(stmt, SubProgramStatement):
+ stmt.analyze()
+ self.a.external_subprogram[stmt.name] = stmt
+ elif isinstance(stmt, BlockData):
+ stmt.analyze()
+ self.a.blockdata[stmt.name] = stmt
+ else:
+ stmt.analyze()
+ return
+
+ def get_classes(self):
+ if self.reader.ispyf:
+ return [PythonModule] + program_unit
+ return program_unit
+
+ def process_subitem(self, item):
+ # MAIN block does not define start/end line conditions,
+ # so it should never end until all lines are read.
+ # However, sometimes F77 programs lack the PROGRAM statement,
+ # and here we fix that:
+ if self.reader.isfix77:
+ line = item.get_line()
+ if line=='end':
+ message = item.reader.format_message(\
+ 'WARNING',
+ 'assuming the end of undefined PROGRAM statement',
+ item.span[0],item.span[1])
+ print >> sys.stderr, message
+ p = Program(self)
+ p.content.extend(self.content)
+ p.content.append(EndProgram(p,item))
+ self.content[:] = [p]
+ return
+ return BeginStatement.process_subitem(self, item)
+
+ def topyf(self, tab=''): # XXXX
+ s = ''
+ for name, stmt in self.a.module.items():
+ s += stmt.topyf(tab=tab)
+ for name, stmt in self.a.external_subprogram.items():
+ s += stmt.topyf(tab=tab)
+ for name, stmt in self.a.blockdata.items():
+ s += stmt.topyf(tab=tab)
+ return s
+# Module
+
+class EndModule(EndStatement):
+ match = re.compile(r'end(\s*module\s*\w*|)\Z', re.I).match
+
+class Module(BeginStatement, HasAttributes,
+ HasImplicitStmt, HasUseStmt, HasVariables,
+ HasTypeDecls, AccessSpecs):
+ """
+ MODULE <name>
+ ..
+ END [MODULE [name]]
+ """
+ match = re.compile(r'module\s*\w+\Z', re.I).match
+ end_stmt_cls = EndModule
+
+ a = AttributeHolder(module_subprogram = {},
+ module_provides = {}, # all symbols that are public and so
+ # can be imported via USE statement
+ # by other blocks
+ module_interface = {}
+ )
+
+ known_attributes = ['PUBLIC', 'PRIVATE']
+
+ def get_classes(self):
+ return access_spec + specification_part + module_subprogram_part
+
+ def process_item(self):
+ name = self.item.get_line().replace(' ','')[len(self.blocktype):].strip()
+ self.name = name
+ return BeginStatement.process_item(self)
+
+ def get_provides(self):
+ return self.a.module_provides
+
+ def get_interface(self):
+ return self.a.module_interface
+
+ def analyze(self):
+ content = self.content[:]
+
+ while content:
+ stmt = content.pop(0)
+ if isinstance(stmt, Contains):
+ for stmt in filter_stmts(content, SubProgramStatement):
+ stmt.analyze()
+ self.a.module_subprogram[stmt.name] = stmt
+ stmt = content.pop(0)
+ assert isinstance(stmt, EndModule),`stmt`
+ continue
+ stmt.analyze()
+
+ if content:
+ self.show_message('Not analyzed content: %s' % content)
+
+ #module_provides = self.a.module_provides
+ #for name, var in self.a.variables.items():
+ # if var.is_public():
+ # if module_provides.has_key(name):
+ # self.warning('module data object name conflict with %s, overriding.' % (name))
+ # module_provides[name] = var
+
+ return
+
+ def topyf(self, tab=''):
+ s = tab + 'MODULE '+self.name + '\n'
+ s += HasImplicitStmt.topyf(self, tab=tab+' ')
+ s += AccessSpecs.topyf(self, tab=tab+' ')
+ s += HasAttributes.topyf(self, tab=tab+' ')
+ s += HasTypeDecls.topyf(self, tab=tab+' ')
+ s += HasVariables.topyf(self, tab=tab+' ')
+ for name, stmt in self.a.module_interface.items():
+ s += stmt.topyf(tab=tab+' ')
+ s += tab + ' CONTAINS\n'
+ for name, stmt in self.a.module_subprogram.items():
+ s += stmt.topyf(tab=tab+' ')
+ s += tab + 'END MODULE ' + self.name + '\n'
+ return s
+
+# Python Module
+
+class EndPythonModule(EndStatement):
+ match = re.compile(r'end(\s*python\s*module\s*\w*|)\Z', re.I).match
+
+class PythonModule(BeginStatement, HasImplicitStmt, HasUseStmt):
+ """
+ PYTHON MODULE <name>
+ ..
+ END [PYTHON MODULE [name]]
+ """
+ modes = ['pyf']
+ match = re.compile(r'python\s*module\s*\w+\Z', re.I).match
+ end_stmt_cls = EndPythonModule
+
+ def get_classes(self):
+ return [Interface, Function, Subroutine, Module]
+
+ def process_item(self):
+ self.name = self.item.get_line().replace(' ','')\
+ [len(self.blocktype):].strip()
+ return BeginStatement.process_item(self)
+
+# Program
+
+class EndProgram(EndStatement):
+ """
+ END [PROGRAM [name]]
+ """
+ match = re.compile(r'end(\s*program\s*\w*|)\Z', re.I).match
+
+class Program(BeginStatement, ProgramBlock,
+ #HasAttributes, # XXX: why Program needs .attributes?
+ HasImplicitStmt, HasUseStmt, AccessSpecs):
+ """ PROGRAM [name]
+ """
+ match = re.compile(r'program\s*\w*\Z', re.I).match
+ end_stmt_cls = EndProgram
+
+ def get_classes(self):
+ return specification_part + execution_part + internal_subprogram_part
+
+ def process_item(self):
+ if self.item is not None:
+ name = self.item.get_line().replace(' ','')\
+ [len(self.blocktype):].strip()
+ if name:
+ self.name = name
+ return BeginStatement.process_item(self)
+
+# BlockData
+
+class EndBlockData(EndStatement):
+ """
+ END [ BLOCK DATA [ <block-data-name> ] ]
+ """
+ match = re.compile(r'end(\s*block\s*data\s*\w*|)\Z', re.I).match
+ blocktype = 'blockdata'
+
+class BlockData(BeginStatement, HasImplicitStmt, HasUseStmt,
+ HasVariables, AccessSpecs):
+ """
+ BLOCK DATA [ <block-data-name> ]
+ """
+ end_stmt_cls = EndBlockData
+ match = re.compile(r'block\s*data\s*\w*\Z', re.I).match
+
+ def process_item(self):
+ self.name = self.item.get_line()[5:].lstrip()[4:].lstrip()
+ return BeginStatement.process_item(self)
+
+ def get_classes(self):
+ return specification_part
+
+# Interface
+
+class EndInterface(EndStatement):
+ match = re.compile(r'end\s*interface\s*\w*\Z', re.I).match
+ blocktype = 'interface'
+
+class Interface(BeginStatement, HasImplicitStmt, HasUseStmt,
+ HasModuleProcedures, AccessSpecs
+ ):
+ """
+ INTERFACE [<generic-spec>] | ABSTRACT INTERFACE
+ END INTERFACE [<generic-spec>]
+
+ <generic-spec> = <generic-name>
+ | OPERATOR ( <defined-operator> )
+ | ASSIGNMENT ( = )
+ | <dtio-generic-spec>
+ <dtio-generic-spec> = READ ( FORMATTED )
+ | READ ( UNFORMATTED )
+ | WRITE ( FORMATTED )
+ | WRITE ( UNFORMATTED )
+
+ """
+ modes = ['free90', 'fix90', 'pyf']
+ match = re.compile(r'(interface\s*(\w+\s*\(.*\)|\w*)|abstract\s*interface)\Z',re.I).match
+ end_stmt_cls = EndInterface
+ blocktype = 'interface'
+
+ a = AttributeHolder(interface_provides = {})
+
+ def get_classes(self):
+ l = intrinsic_type_spec + interface_specification
+ if self.reader.mode=='pyf':
+ return [Subroutine, Function] + l
+ return l
+
+ def process_item(self):
+ line = self.item.get_line()
+ self.isabstract = line.startswith('abstract')
+ if self.isabstract:
+ self.generic_spec = ''
+ else:
+ self.generic_spec = line[len(self.blocktype):].strip()
+ self.name = self.generic_spec # XXX
+ return BeginStatement.process_item(self)
+
+ def tostr(self):
+ if self.isabstract:
+ return 'ABSTRACT INTERFACE'
+ return 'INTERFACE '+ str(self.generic_spec)
+
+ #def get_provides(self):
+ # return self.a.interface_provides
+
+ def analyze(self):
+ content = self.content[:]
+
+ while content:
+ stmt = content.pop(0)
+ if isinstance(stmt, self.end_stmt_cls):
+ break
+ stmt.analyze()
+ #assert isinstance(stmt, SubProgramStatement),`stmt.__class__.__name__`
+ if content:
+ self.show_message('Not analyzed content: %s' % content)
+
+ if self.parent.a.variables.has_key(self.name):
+ var = self.parent.a.variables.pop(self.name)
+ self.update_attributes(var.attributes)
+
+ parent_interface = self.parent.get_interface()
+ if parent_interface.has_key(self.name):
+ p = parent_interface[self.name]
+ last = p.content.pop()
+ assert isinstance(last,EndInterface),`last.__class__`
+ p.content += self.content
+ p.update_attributes(self.a.attributes)
+ else:
+ parent_interface[self.name] = self
+ return
+
+ def topyf(self, tab=''):
+ s = tab + self.tostr() + '\n'
+ s += HasImplicitStmt.topyf(self, tab=tab+' ')
+ s += HasAttributes.topyf(self, tab=tab+' ')
+ s += HasUseStmt.topyf(self, tab=tab+' ')
+ s += tab + 'END' + self.tostr() + '\n'
+ return s
+
+# Subroutine
+
+class SubProgramStatement(BeginStatement, ProgramBlock,
+ HasImplicitStmt, HasAttributes,
+ HasUseStmt,
+ HasVariables, HasTypeDecls, AccessSpecs
+ ):
+ """
+ [ <prefix> ] <FUNCTION|SUBROUTINE> <name> [ ( <args> ) ] [ <suffix> ]
+ """
+
+ a = AttributeHolder(internal_subprogram = {})
+
+ def process_item(self):
+ clsname = self.__class__.__name__.lower()
+ item = self.item
+ line = item.get_line()
+ m = self.match(line)
+ i = line.lower().find(clsname)
+ assert i!=-1,`clsname, line`
+ self.prefix = line[:i].rstrip()
+ self.name = line[i:m.end()].lstrip()[len(clsname):].strip()
+ line = line[m.end():].lstrip()
+ args = []
+ if line.startswith('('):
+ i = line.find(')')
+ assert i!=-1,`line`
+ line2 = item.apply_map(line[:i+1])
+ for a in line2[1:-1].split(','):
+ a=a.strip()
+ if not a: continue
+ args.append(a)
+ line = line[i+1:].lstrip()
+ suffix = item.apply_map(line)
+ self.bind, suffix = parse_bind(suffix, item)
+ self.result = None
+ if isinstance(self, Function):
+ self.result, suffix = parse_result(suffix, item)
+ if suffix:
+ assert self.bind is None,`self.bind`
+ self.bind, suffix = parse_result(suffix, item)
+ if self.result is None:
+ self.result = self.name
+ assert not suffix,`suffix`
+ self.args = args
+ self.typedecl = None
+ return BeginStatement.process_item(self)
+
+ def tostr(self):
+ clsname = self.__class__.__name__.upper()
+ s = ''
+ if self.prefix:
+ s += self.prefix + ' '
+ if self.typedecl is not None:
+ assert isinstance(self, Function),`self.__class__.__name__`
+ s += self.typedecl.tostr() + ' '
+ s += clsname
+ suf = ''
+ if self.result and self.result!=self.name:
+ suf += ' RESULT ( %s )' % (self.result)
+ if self.bind:
+ suf += ' BIND ( %s )' % (', '.join(self.bind))
+ return '%s %s(%s)%s' % (s, self.name,', '.join(self.args),suf)
+
+ def get_classes(self):
+ return f2py_stmt + specification_part + execution_part \
+ + internal_subprogram_part
+
+ def analyze(self):
+ content = self.content[:]
+
+ if self.prefix:
+ self.update_attributes(prefix.upper().split())
+
+ variables = self.a.variables
+ for a in self.args:
+ assert not variables.has_key(a)
+ assert is_name(a)
+ variables[a] = Variable(self, a)
+
+ if isinstance(self, Function):
+ var = variables[self.result] = Variable(self, self.result)
+ if self.typedecl is not None:
+ var.set_type(self.typedecl)
+
+ while content:
+ stmt = content.pop(0)
+ if isinstance(stmt, Contains):
+ for stmt in filter_stmts(content, SubProgramStatement):
+ stmt.analyze()
+ self.a.internal_subprogram[stmt.name] = stmt
+ stmt = content.pop(0)
+ assert isinstance(stmt, self.end_stmt_cls),`stmt`
+ elif isinstance(stmt, self.end_stmt_cls):
+ continue
+ else:
+ stmt.analyze()
+
+ if content:
+ self.show_message('Not analyzed content: %s' % content)
+
+ #parent_provides = self.parent.get_provides()
+ #if parent_provides is not None:
+ # if self.is_public():
+ # if parent_provides.has_key(self.name):
+ # self.warning('module subprogram name conflict with %s, overriding.' % (self.name))
+ # parent_provides[self.name] = self
+
+ return
+
+ def topyf(self, tab=''):
+ s = tab + self.__class__.__name__.upper()
+ s += ' ' + self.name + ' (%s)' % (', '.join(self.args))
+ if isinstance(self, Function) and self.result != self.name:
+ s += ' RESULT (%s)' % (self.result)
+ s += '\n'
+ s += HasImplicitStmt.topyf(self, tab=tab+' ')
+ s += AccessSpecs.topyf(self, tab=tab+' ')
+ s += HasTypeDecls.topyf(self, tab=tab+' ')
+ s += HasVariables.topyf(self, tab=tab+' ', only_variables = self.args)
+ s += tab + 'END ' + self.__class__.__name__.upper() + ' ' + self.name + '\n'
+ return s
+
+class EndSubroutine(EndStatement):
+ """
+ END [SUBROUTINE [name]]
+ """
+ match = re.compile(r'end(\s*subroutine\s*\w*|)\Z', re.I).match
+
+
+class Subroutine(SubProgramStatement):
+ """
+ [ <prefix> ] SUBROUTINE <name> [ ( [ <dummy-arg-list> ] ) [ <proc-language-binding-spec> ]]
+ """
+ end_stmt_cls = EndSubroutine
+ match = re.compile(r'(recursive|pure|elemental|\s)*subroutine\s*\w+', re.I).match
+ _repr_attr_names = ['prefix','bind','suffix','args'] + Statement._repr_attr_names
+
+# Function
+
+class EndFunction(EndStatement):
+ """
+ END [FUNCTION [name]]
+ """
+ match = re.compile(r'end(\s*function\s*\w*|)\Z', re.I).match
+
+class Function(SubProgramStatement):
+ """
+ [ <prefix> ] FUNCTION <name> ( [<dummy-arg-list>] ) [<suffix>]
+ <prefix> = <prefix-spec> [ <prefix-spec> ]...
+ <prefix-spec> = <declaration-type-spec>
+ | RECURSIVE | PURE | ELEMENTAL
+ <suffix> = <proc-language-binding-spec> [ RESULT ( <result-name> ) ]
+ | RESULT ( <result-name> ) [ <proc-language-binding-spec> ]
+ """
+ end_stmt_cls = EndFunction
+ match = re.compile(r'(recursive|pure|elemental|\s)*function\s*\w+', re.I).match
+ _repr_attr_names = ['prefix','bind','suffix','args','typedecl'] + Statement._repr_attr_names
+
+ def subroutine_wrapper_code(self):
+ name = 'f2pywrap_' + self.name
+ args = ['f2pyvalue_'+self.result] + self.args
+ var = self.a.variables[self.result]
+ typedecl = var.get_typedecl().astypedecl()
+ lines = []
+ tab = ' '*6
+ lines.append('%sSUBROUTINE %s(%s)' % (tab, name, ', '.join(args)))
+ if isinstance(self.parent,Module):
+ lines.append('%s USE %s' % (tab, self.parent.name))
+ else:
+ if isinstance(typedecl, TypeStmt):
+ type_decl = typedecl.get_type_decl(typedecl.name)
+ if type_decl.parent is self:
+ for line in str(type_decl).split('\n'):
+ lines.append('%s %s' % (tab, line.lstrip()))
+ lines.append('%s EXTERNAL %s' % (tab, self.name))
+ lines.append('%s %s %s' % (tab, str(typedecl).lstrip(), self.name))
+ lines.append('%s %s %s' % (tab, str(typedecl).lstrip(), args[0]))
+ lines.append('!f2py intent(out) %s' % (args[0]))
+ for a in self.args:
+ v = self.a.variables[a]
+ lines.append('%s %s' % (tab, str(v).lstrip()))
+ lines.append('%s %s = %s(%s)' % (tab, args[0], self.name, ', '.join(self.args)))
+ #lines.append('%s print*,"%s=",%s' % (tab, args[0], args[0])) # debug line
+ lines.append('%sEND SUBROUTINE %s' % (tab, name))
+ return '\n'.join(lines)
+
+ def subroutine_wrapper(self):
+ code = self.subroutine_wrapper_code()
+ from api import parse
+ block = parse(code) # XXX: set include_dirs
+ while len(block.content)==1:
+ block = block.content[0]
+ return block
+
+# Handle subprogram prefixes
+
+class SubprogramPrefix(Statement):
+ """
+ <prefix> <declaration-type-spec> <function|subroutine> ...
+ """
+ match = re.compile(r'(pure|elemental|recursive|\s)+\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()
+ m = self.match(line)
+ prefix = line[:m.end()].rstrip()
+ rest = self.item.get_line()[m.end():].lstrip()
+ if rest:
+ self.parent.put_item(self.item.copy(prefix))
+ self.item.clone(rest)
+ self.isvalid = False
+ return
+ if self.parent.__class__ not in [Function, Subroutine]:
+ self.isvalid = False
+ return
+ prefix = prefix + ' ' + self.parent.prefix
+ self.parent.prefix = prefix.strip()
+ self.ignore = True
+ return
+
+# SelectCase
+
+class EndSelect(EndStatement):
+ match = re.compile(r'end\s*select\s*\w*\Z', re.I).match
+ blocktype = 'select'
+
+class Select(BeginStatement):
+ """
+ [ <case-construct-name> : ] SELECT CASE ( <case-expr> )
+
+ """
+ match = re.compile(r'select\s*case\s*\(.*\)\Z',re.I).match
+ end_stmt_cls = EndSelect
+ name = ''
+ def tostr(self):
+ return 'SELECT CASE ( %s )' % (self.expr)
+ def process_item(self):
+ self.expr = self.item.get_line()[6:].lstrip()[4:].lstrip()[1:-1].strip()
+ self.name = self.item.label
+ return BeginStatement.process_item(self)
+
+ def get_classes(self):
+ return [Case] + execution_part_construct
+
+# Where
+
+class EndWhere(EndStatement):
+ """
+ END WHERE [ <where-construct-name> ]
+ """
+ match = re.compile(r'end\s*\where\s*\w*\Z',re.I).match
+
+
+class Where(BeginStatement):
+ """
+ [ <where-construct-name> : ] WHERE ( <mask-expr> )
+ <mask-expr> = <logical-expr>
+ """
+ match = re.compile(r'where\s*\([^)]*\)\Z',re.I).match
+ end_stmt_cls = EndWhere
+ name = ''
+ def tostr(self):
+ return 'WHERE ( %s )' % (self.expr)
+ def process_item(self):
+ self.expr = self.item.get_line()[5:].lstrip()[1:-1].strip()
+ self.name = self.item.label
+ return BeginStatement.process_item(self)
+
+ def get_classes(self):
+ return [Assignment, WhereStmt,
+ WhereConstruct, ElseWhere
+ ]
+
+WhereConstruct = Where
+
+# Forall
+
+class EndForall(EndStatement):
+ """
+ END FORALL [ <forall-construct-name> ]
+ """
+ match = re.compile(r'end\s*forall\s*\w*\Z',re.I).match
+
+class Forall(BeginStatement):
+ """
+ [ <forall-construct-name> : ] FORALL <forall-header>
+ [ <forall-body-construct> ]...
+ <forall-body-construct> = <forall-assignment-stmt>
+ | <where-stmt>
+ | <where-construct>
+ | <forall-construct>
+ | <forall-stmt>
+ <forall-header> = ( <forall-triplet-spec-list> [ , <scalar-mask-expr> ] )
+ <forall-triplet-spec> = <index-name> = <subscript> : <subscript> [ : <stride> ]
+ <subscript|stride> = <scalar-int-expr>
+ <forall-assignment-stmt> = <assignment-stmt> | <pointer-assignment-stmt>
+ """
+ end_stmt_cls = EndForall
+ match = re.compile(r'forarr\s*\(.*\)\Z',re.I).match
+ name = ''
+ def process_item(self):
+ self.specs = self.item.get_line()[6:].lstrip()[1:-1].strip()
+ return BeginStatement.process_item(self)
+ def tostr(self):
+ return 'FORALL (%s)' % (self.specs)
+ def get_classes(self):
+ return [GeneralAssignment, WhereStmt, WhereConstruct,
+ ForallConstruct, ForallStmt]
+
+ForallConstruct = Forall
+
+# IfThen
+
+class EndIfThen(EndStatement):
+ """
+ END IF [ <if-construct-name> ]
+ """
+ match = re.compile(r'end\s*if\s*\w*\Z', re.I).match
+ blocktype = 'if'
+
+class IfThen(BeginStatement):
+ """
+ [<if-construct-name> :] IF ( <scalar-logical-expr> ) THEN
+
+ IfThen instance has the following attributes:
+ expr
+ """
+
+ match = re.compile(r'if\s*\(.*\)\s*then\Z',re.I).match
+ end_stmt_cls = EndIfThen
+ name = ''
+
+ def tostr(self):
+ return 'IF (%s) THEN' % (self.expr)
+
+ def process_item(self):
+ item = self.item
+ line = item.get_line()[2:-4].strip()
+ assert line[0]=='(' and line[-1]==')',`line`
+ self.expr = line[1:-1].strip()
+ self.name = item.label
+ return BeginStatement.process_item(self)
+
+ def get_classes(self):
+ return [Else, ElseIf] + execution_part_construct
+
+class If(BeginStatement):
+ """
+ IF ( <scalar-logical-expr> ) action-stmt
+ """
+
+ match = re.compile(r'if\s*\(',re.I).match
+
+ def process_item(self):
+ item = self.item
+ mode = self.reader.mode
+ classes = self.get_classes()
+ classes = [cls for cls in classes if mode in cls.modes]
+
+ line = item.get_line()[2:].lstrip()
+ i = line.find(')')
+ expr = line[1:i].strip()
+ line = line[i+1:].strip()
+ if line.lower()=='then':
+ self.isvalid = False
+ return
+ self.expr = item.apply_map(expr)
+
+ if not line:
+ newitem = self.get_item()
+ else:
+ newitem = item.copy(line)
+ newline = newitem.get_line()
+ for cls in classes:
+ if cls.match(newline):
+ stmt = cls(self, newitem)
+ if stmt.isvalid:
+ self.content.append(stmt)
+ return
+ if not line:
+ self.put_item(newitem)
+ self.isvalid = False
+ return
+
+ def tostr(self):
+ assert len(self.content)==1,`self.content`
+ return 'IF (%s) %s' % (self.expr, str(self.content[0]).lstrip())
+
+ def tofortran(self,isfix=None):
+ return self.get_indent_tab(colon=':',isfix=isfix) + self.tostr()
+
+ def get_classes(self):
+ return action_stmt
+
+# Do
+
+class EndDo(EndStatement):
+ """
+ END DO [ <do-construct-name> ]
+ """
+ match = re.compile(r'end\s*do\s*\w*\Z', re.I).match
+ blocktype = 'do'
+
+class Do(BeginStatement):
+ """
+ [ <do-construct-name> : ] DO label [loopcontrol]
+ [ <do-construct-name> : ] DO [loopcontrol]
+
+ """
+
+ match = re.compile(r'do\b\s*\d*',re.I).match
+ item_re = re.compile(r'do\b\s*(?P<label>\d*)\s*,?\s*(?P<loopcontrol>.*)\Z',re.I).match
+ end_stmt_cls = EndDo
+ name = ''
+
+ def tostr(self):
+ return 'DO %s %s' % (self.endlabel, self.loopcontrol)
+
+ def process_item(self):
+ item = self.item
+ line = item.get_line()
+ m = self.item_re(line)
+ self.endlabel = m.group('label').strip()
+ self.name = item.label
+ self.loopcontrol = m.group('loopcontrol').strip()
+ return BeginStatement.process_item(self)
+
+ def process_subitem(self, item):
+ r = False
+ if self.endlabel:
+ label = item.label
+ if label == self.endlabel:
+ r = True
+ if isinstance(self.parent, Do) and label==self.parent.endlabel:
+ # the same item label may be used for different block ends
+ self.put_item(item)
+ return BeginStatement.process_subitem(self, item) or r
+
+ def get_classes(self):
+ return execution_part_construct
+
+# Associate
+
+class EndAssociate(EndStatement):
+ """
+ END ASSOCIATE [ <associate-construct-name> ]
+ """
+ match = re.compile(r'end\s*associate\s*\w*\Z',re.I).match
+
+class Associate(BeginStatement):
+ """
+ [ <associate-construct-name> : ] ASSOCIATE ( <association-list> )
+ <block>
+
+ <association> = <associate-name> => <selector>
+ <selector> = <expr> | <variable>
+ """
+ match = re.compile(r'associate\s*\(.*\)\Z',re.I).match
+ end_stmt_cls = EndAssociate
+
+ def process_item(self):
+ line = self.item.get_line()[9:].lstrip()
+ self.associations = line[1:-1].strip()
+ return BeginStatement.process_item(self)
+ def tostr(self):
+ return 'ASSOCIATE (%s)' % (self.associations)
+ def get_classes(self):
+ return execution_part_construct
+
+# Type
+
+class EndType(EndStatement):
+ """
+ END TYPE [<type-name>]
+ """
+ match = re.compile(r'end\s*type\s*\w*\Z', re.I).match
+ blocktype = 'type'
+
+class Type(BeginStatement, HasVariables, HasAttributes, AccessSpecs):
+ """
+ TYPE [ [ , <type-attr-spec-list>] :: ] <type-name> [ ( <type-param-name-list> ) ]
+ <type-attr-spec> = <access-spec> | EXTENDS ( <parent-type-name> )
+ | ABSTRACT | BIND(C)
+ """
+ match = re.compile(r'type\b\s*').match
+ end_stmt_cls = EndType
+
+ a = AttributeHolder(extends = None,
+ parameters = {},
+ component_names = [], # specifies component order for sequence types
+ components = {}
+ )
+ known_attributes = re.compile(r'\A(PUBLIC|PRIVATE|SEQUENCE|ABSTRACT|BIND\s*\(.*\))\Z',re.I).match
+
+ def process_item(self):
+ line = self.item.get_line()[4:].lstrip()
+ if line.startswith('('):
+ self.isvalid = False
+ return
+ specs = []
+ i = line.find('::')
+ if i!=-1:
+ for s in line[:i].split(','):
+ s = s.strip()
+ if s: specs.append(s)
+ line = line[i+2:].lstrip()
+ self.specs = specs
+ i = line.find('(')
+ if i!=-1:
+ self.name = line[:i].rstrip()
+ assert line[-1]==')',`line`
+ self.params = split_comma(line[i+1:-1].lstrip())
+ else:
+ self.name = line
+ self.params = []
+ if not is_name(self.name):
+ self.isvalid = False
+ return
+ return BeginStatement.process_item(self)
+
+ def tostr(self):
+ s = 'TYPE'
+ if self.specs:
+ s += ', '.join(['']+self.specs) + ' ::'
+ s += ' ' + self.name
+ if self.params:
+ s += ' ('+', '.join(self.params)+')'
+ return s
+
+ def get_classes(self):
+ return [Integer] + private_or_sequence + component_part +\
+ type_bound_procedure_part
+
+ def analyze(self):
+ BeginStatement.analyze(self)
+ for spec in self.specs:
+ i = spec.find('(')
+ if i!=-1:
+ assert spec.endswith(')'),`spec`
+ s = spec[:i].rstrip().upper()
+ n = spec[i+1:-1].strip()
+ if s=='EXTENDS':
+ self.a.extends = n
+ continue
+ elif s=='BIND':
+ args,rest = parse_bind(spec)
+ assert not rest,`rest`
+ spec = 'BIND(%s)' % (', '.join(args))
+ else:
+ spec = '%s(%s)' % (s,n)
+ else:
+ spec = spec.upper()
+ self.update_attributes(spec)
+
+ component_names = self.a.component_names
+ content = self.content[:]
+ while content:
+ stmt = content.pop(0)
+ if isinstance(stmt, self.end_stmt_cls):
+ break
+ stmt.analyze()
+
+ if content:
+ self.show_message('Not analyzed content: %s' % content)
+
+ parameters = self.a.parameters
+ components = self.a.components
+ component_names = self.a.component_names
+ for name in self.a.variable_names:
+ var = self.a.variables[name]
+ if name in self.params:
+ parameters[name] = var
+ else:
+ component_names.append(name)
+ components[name] = var
+
+ self.parent.a.type_decls[self.name] = self
+
+ #parent_provides = self.parent.get_provides()
+ #if parent_provides is not None:
+ # if self.is_public():
+ # if parent_provides.has_key(self.name):
+ # self.warning('type declaration name conflict with %s, overriding.' % (self.name))
+ # parent_provides[self.name] = self
+
+ return
+
+ def topyf(self, tab=''):
+ s = tab + 'TYPE'
+ if self.a.extends is not None:
+ s += ', EXTENDS(%s) ::' % (self.a.extends)
+ s += ' ' + self.name
+ if self.a.parameters:
+ s += ' (%s)' % (', '.join(self.a.parameters))
+ s += '\n'
+ s += AccessSpecs.topyf(self, tab=tab+' ')
+ s += HasAttributes.topyf(self, tab=tab+' ')
+ s += HasVariables.topyf(self, tab=tab+' ')
+ s += tab + 'END TYPE ' + self.name + '\n'
+ return s
+
+ # Wrapper methods:
+
+ def get_bit_size(self, _cache={}):
+ try:
+ return _cache[id(self)]
+ except KeyError:
+ s = 0
+ for name,var in self.a.components.items():
+ s += var.get_bit_size()
+ _cache[id(self)] = s
+ return s
+
+TypeDecl = Type
+
+# Enum
+
+class EndEnum(EndStatement):
+ """
+ END ENUM
+ """
+ match = re.compile(r'end\s*enum\Z',re.I).match
+ blocktype = 'enum'
+
+class Enum(BeginStatement):
+ """
+ ENUM , BIND(C)
+ <enumerator-def-stmt>
+ [ <enumerator-def-stmt> ]...
+ """
+ blocktype = 'enum'
+ end_stmt_cls = EndEnum
+ match = re.compile(r'enum\s*,\s*bind\s*\(\s*c\s*\)\Z',re.I).match
+ def process_item(self):
+ return BeginStatement.process_item(self)
+ def get_classes(self):
+ return [Enumerator]
+
+###################################################
+
+import statements
+import typedecl_statements
+__all__.extend(statements.__all__)
+__all__.extend(typedecl_statements.__all__)
+
+from statements import *
+from typedecl_statements import *
+
+f2py_stmt = [Threadsafe, FortranName, Depend, Check, CallStatement,
+ CallProtoArgument]
+
+access_spec = [Public, Private]
+
+interface_specification = [Function, Subroutine,
+ ModuleProcedure
+ ]
+
+module_subprogram_part = [ Contains, Function, Subroutine ]
+
+specification_stmt = access_spec + [ Allocatable, Asynchronous, Bind,
+ Common, Data, Dimension, Equivalence, External, Intent, Intrinsic,
+ Namelist, Optional, Pointer, Protected, Save, Target, Volatile,
+ Value ]
+
+intrinsic_type_spec = [ SubprogramPrefix, Integer , Real,
+ DoublePrecision, Complex, DoubleComplex, Character, Logical, Byte
+ ]
+
+derived_type_spec = [ ]
+type_spec = intrinsic_type_spec + derived_type_spec
+declaration_type_spec = intrinsic_type_spec + [ TypeStmt, Class ]
+
+type_declaration_stmt = declaration_type_spec
+
+private_or_sequence = [ Private, Sequence ]
+
+component_part = declaration_type_spec + [ ModuleProcedure ]
+
+proc_binding_stmt = [SpecificBinding, GenericBinding, FinalBinding]
+
+type_bound_procedure_part = [Contains, Private] + proc_binding_stmt
+
+#R214
+action_stmt = [ Allocate, GeneralAssignment, Assign, Backspace, Call, Close,
+ Continue, Cycle, Deallocate, Endfile, Exit, Flush, ForallStmt,
+ Goto, If, Inquire, Nullify, Open, Print, Read, Return, Rewind,
+ Stop, Wait, WhereStmt, Write, ArithmeticIf, ComputedGoto,
+ AssignedGoto, Pause ]
+# GeneralAssignment = Assignment + PointerAssignment
+# EndFunction, EndProgram, EndSubroutine - part of the corresponding blocks
+
+executable_construct = [ Associate, Do, ForallConstruct, IfThen,
+ Select, WhereConstruct ] + action_stmt
+#Case, see Select
+
+execution_part_construct = executable_construct + [ Format, Entry,
+ Data ]
+
+execution_part = execution_part_construct[:]
+
+#C201, R208
+for cls in [EndFunction, EndProgram, EndSubroutine]:
+ try: execution_part.remove(cls)
+ except ValueError: pass
+
+internal_subprogram = [Function, Subroutine]
+
+internal_subprogram_part = [ Contains, ] + internal_subprogram
+
+declaration_construct = [ TypeDecl, Entry, Enum, Format, Interface,
+ Parameter, ModuleProcedure, ] + specification_stmt + \
+ type_declaration_stmt
+# stmt-function-stmt
+
+implicit_part = [ Implicit, Parameter, Format, Entry ]
+
+specification_part = [ Use, Import ] + implicit_part + \
+ declaration_construct
+
+
+external_subprogram = [Function, Subroutine]
+
+main_program = [Program] + specification_part + execution_part + \
+ internal_subprogram_part
+
+program_unit = main_program + external_subprogram + [Module,
+ BlockData ]
diff --git a/numpy/f2py/lib/parser/doc.txt b/numpy/f2py/lib/parser/doc.txt
new file mode 100644
index 000000000..0d20bf73f
--- /dev/null
+++ b/numpy/f2py/lib/parser/doc.txt
@@ -0,0 +1,365 @@
+.. -*- rest -*-
+
+Created: September 2006
+Author: Pearu Peterson <pearu.peterson@gmail.com>
+
+Fortran parser package structure
+================================
+
+numpy.f2py.lib.parser package contains the following files:
+
+api.py
+------
+
+Public API for Fortran parser.
+
+It exposes Statement classes, CHAR_BIT constant, and parse function.
+
+Function parse(<input>, ..) parses, analyzes and returns Statement
+tree of Fortran input. For example,
+
+::
+
+ >>> from api import parse
+ >>> code = """
+ ... c comment
+ ... subroutine foo(a)
+ ... integer a
+ ... print*,"a=",a
+ ... end
+ ... """
+ >>> tree = parse(code,isfree=False)
+ >>> print tree
+ !BEGINSOURCE <cStringIO.StringI object at 0xb75ac410> mode=fix90
+ SUBROUTINE foo(a)
+ INTEGER a
+ PRINT *, "a=", a
+ END SUBROUTINE foo
+ >>>
+ >>> tree
+ BeginSource
+ blocktype='beginsource'
+ name='<cStringIO.StringI object at 0xb75ac410> mode=fix90'
+ a=AttributeHolder:
+ external_subprogram=<dict with keys ['foo']>
+ content:
+ Subroutine
+ args=['a']
+ item=Line('subroutine foo(a)',(3, 3),'')
+ a=AttributeHolder:
+ variables=<dict with keys ['a']>
+ content:
+ Integer
+ selector=('', '')
+ entity_decls=['a']
+ item=Line('integer a',(4, 4),'')
+ Print
+ item=Line('print*,"a=",a',(5, 5),'')
+ EndSubroutine
+ blocktype='subroutine'
+ name='foo'
+ item=Line('end',(6, 6),'')
+
+readfortran.py
+--------------
+
+Tools for reading Fortran codes from file and string objects.
+
+To read Fortran code from a file, use FortranFileReader class.
+
+FortranFileReader class is iterator over Fortran code lines
+as is derived from FortranReaderBase class.
+It automatically handles line continuations and comments as
+well as detects if Fortran file is in free or fixed format.
+
+For example,
+
+::
+
+ >>> from readfortran import *
+ >>> import os
+ >>> reader = FortranFileReader(os.path.expanduser('~/src/blas/daxpy.f'))
+ >>> reader.next()
+ Line('subroutine daxpy(n,da,dx,incx,dy,incy)',(1, 1),'')
+ >>> reader.next()
+ Comment('c constant times a vector plus a vector.\nc uses unrolled loops for increments equal to one.\nc jack dongarra, linpack, 3/11/78.\nc modified 12/3/93, array(1) declarations changed to array(*)',(3, 6))
+ >>> reader.next()
+ Line('double precision dx(*),dy(*),da',(8, 8),'')
+ >>> reader.next()
+ Line('integer i,incx,incy,ix,iy,m,mp1,n',(9, 9),'')
+
+FortranReaderBase.next() method may return Line, SyntaxErrorLine, Comment, MultiLine,
+SyntaxErrorMultiLine instances.
+
+Line instance has the following attributes:
+
+ * .line - contains Fortran code line
+ * .span - a 2-tuple containing the span of line numbers containing
+ Fortran code in the original Fortran file
+ * .label - the label of Fortran code line
+ * .reader - the FortranReaderBase class instance
+ * .strline - if not None then contains Fortran code line with parenthesis
+ content and string literal constants saved in .strlinemap dictionary.
+ * .is_f2py_directive - True if line started with f2py directive comment.
+
+and the following methods:
+
+ * .get_line() - returns .strline (also evalutes it if None). Also
+ handles Hollerith contstants in fixed F77 mode.
+ * .isempty() - returns True if Fortran line contains no code.
+ * .copy(line=None, apply_map=False) - returns a Line instance
+ with given .span, .label, .reader information but line content
+ replaced with line (when not None) and applying .strlinemap
+ mapping (when apply_map is True).
+ * .apply_map(line) - apply .strlinemap mapping to line.
+ * .has_map() - returns True if .strlinemap mapping exists.
+
+For example,
+
+::
+
+ >>> item = reader.next()
+ >>> item
+ Line('if(n.le.0)return',(11, 11),'')
+ >>> item.line
+ 'if(n.le.0)return'
+ >>> item.strline
+ 'if(F2PY_EXPR_TUPLE_4)return'
+ >>> item.strlinemap
+ {'F2PY_EXPR_TUPLE_4': 'n.le.0'}
+ >>> item.label
+ ''
+ >>> item.span
+ (11, 11)
+ >>> item.get_line()
+ 'if(F2PY_EXPR_TUPLE_4)return'
+ >>> item.copy('if(F2PY_EXPR_TUPLE_4)pause',True)
+ Line('if(n.le.0)pause',(11, 11),'')
+
+Comment instance has the following attributes:
+
+ * .comment - comment string
+ * .span - a 2-tuple containing the span of line numbers containing
+ Fortran comment in the original Fortran file
+ * .reader - the FortranReaderBase class instance
+
+and .isempty() method.
+
+MultiLine class represents multiline syntax in .pyf files::
+
+ <prefix>'''<lines>'''<suffix>
+
+MultiLine instance has the following attributes:
+
+ * .prefix - the content of <prefix>
+ * .block - a list of lines
+ * .suffix - the content of <suffix>
+ * .span - a 2-tuple containing the span of line numbers containing
+ multiline syntax in the original Fortran file
+ * .reader - the FortranReaderBase class instance
+
+and .isempty() method.
+
+SyntaxErrorLine and SyntaxErrorMultiLine are like Line and MultiLine
+classes, respectively, with a functionality of issuing an error
+message to sys.stdout when constructing an instance of the corresponding
+class.
+
+To read a Fortran code from a string, use FortranStringReader class::
+
+ reader = FortranStringReader(<string>, <isfree>, <isstrict>)
+
+where the second and third arguments are used to specify the format
+of the given <string> content. When <isfree> and <isstrict> are both
+True, the content of a .pyf file is assumed. For example,
+
+::
+
+ >>> code = """
+ ... c comment
+ ... subroutine foo(a)
+ ... print*, "a=",a
+ ... end
+ ... """
+ >>> reader = FortranStringReader(code, False, True)
+ >>> reader.next()
+ Comment('c comment',(2, 2))
+ >>> reader.next()
+ Line('subroutine foo(a)',(3, 3),'')
+ >>> reader.next()
+ Line('print*, "a=",a',(4, 4),'')
+ >>> reader.next()
+ Line('end',(5, 5),'')
+
+FortranReaderBase has the following attributes:
+
+ * .source - a file-like object with .next() method to retrive
+ a source code line
+ * .source_lines - a list of read source lines
+ * .reader - a FortranReaderBase instance for reading files
+ from INCLUDE statements.
+ * .include_dirs - a list of directories where INCLUDE files
+ are searched. Default is ['.'].
+
+and the following methods:
+
+ * .set_mode(isfree, isstrict) - set Fortran code format information
+ * .close_source() - called when .next() raises StopIteration exception.
+
+parsefortran.py
+---------------
+
+Parse Fortran code from FortranReaderBase iterator.
+
+FortranParser class holds the parser information while
+iterating over items returned by FortranReaderBase iterator.
+The parsing information, collected when calling .parse() method,
+is saved in .block attribute as an instance
+of BeginSource class defined in block_statements.py file.
+
+For example,
+
+::
+
+ >>> reader = FortranStringReader(code, False, True)
+ >>> parser = FortranParser(reader)
+ >>> parser.parse()
+ >>> print parser.block
+ !BEGINSOURCE <cStringIO.StringI object at 0xb751d500> mode=fix77
+ SUBROUTINE foo(a)
+ PRINT *, "a=", a
+ END SUBROUTINE foo
+
+block_statements.py, base_classes.py, typedecl_statements.py, statements.py
+---------------------------------------------------------------------------
+
+The model for representing Fortran code statements consists of a tree of Statement
+classes defined in base_classes.py. There are two types of statements: one line
+statements and block statements. Block statements consists of start and end
+statements, and content statements in between that can be of both types again.
+
+Statement instance has the following attributes:
+
+ * .parent - it is either parent block-type statement or FortranParser instance.
+ * .item - Line instance containing Fortran statement line information, see above.
+ * .isvalid - when False then processing this Statement instance will be skipped,
+ for example, when the content of .item does not match with
+ the Statement class.
+ * .ignore - when True then the Statement instance will be ignored.
+ * .modes - a list of Fortran format modes where the Statement instance is valid.
+
+and the following methods:
+
+ * .info(message), .warning(message), .error(message) - to spit messages to
+ sys.stderr stream.
+ * .get_variable(name) - get Variable instance by name that is defined in
+ current namespace. If name is not defined, then the corresponding
+ Variable instance is created.
+ * .analyze() - calculate various information about the Statement, this information
+ is saved in .a attribute that is AttributeHolder instance.
+
+All statement classes are derived from Statement class. Block statements are
+derived from BeginStatement class and is assumed to end with EndStatement
+instance in .content attribute list. BeginStatement and EndStatement instances
+have the following attributes:
+
+ * .name - name of the block, blocks without names use line label
+ as the name.
+ * .blocktype - type of the block (derived from class name)
+ * .content - a list of Statement (or Line) instances.
+
+and the following methods:
+
+ * .__str__() - returns string representation of Fortran code.
+
+A number of statements may declare a variable that is used in other
+statement expressions. Variables are represented via Variable class
+and its instances have the following attributes:
+
+ * .name - name of the variable
+ * .typedecl - type declaration
+ * .dimension - list of dimensions
+ * .bounds - list of bounds
+ * .length - length specs
+ * .attributes - list of attributes
+ * .bind - list of bind information
+ * .intent - list of intent information
+ * .check - list of check expressions
+ * .init - initial value of the variable
+ * .parent - statement instance declaring the variable
+ * .parents - list of statements that specify variable information
+
+and the following methods:
+
+ * .is_private()
+ * .is_public()
+ * .is_allocatable()
+ * .is_external()
+ * .is_intrinsic()
+ * .is_parameter()
+ * .is_optional()
+ * .is_required()
+
+The following type declaration statements are defined in typedecl_statements.py:
+
+ Integer, Real, DoublePrecision, Complex, DoubleComplex, Logical,
+ Character, Byte, Type, Class
+
+and they have the following attributes:
+
+ * .selector - contains lenght and kind specs
+ * .entity_decls, .attrspec
+
+and methods:
+
+ * .tostr() - return string representation of Fortran type declaration
+ * .astypedecl() - pure type declaration instance, it has no .entity_decls
+ and .attrspec.
+ * .analyze() - processes .entity_decls and .attsspec attributes and adds
+ Variable instance to .parent.a.variables dictionary.
+
+The following block statements are defined in block_statements.py:
+
+ BeginSource, Module, PythonModule, Program, BlockData, Interface,
+ Subroutine, Function, Select, Where, Forall, IfThen, If, Do,
+ Associate, TypeDecl (Type), Enum
+
+Block statement classes may have different properties which are declared via
+deriving them from the following classes:
+
+ HasImplicitStmt, HasUseStmt, HasVariables, HasTypeDecls,
+ HasAttributes, HasModuleProcedures, ProgramBlock
+
+In summary, .a attribute may hold different information sets as follows:
+
+ * BeginSource - .module, .external_subprogram, .blockdata
+ * Module - .attributes, .implicit_rules, .use, .use_provides, .variables,
+ .type_decls, .module_subprogram, .module_data
+ * PythonModule - .implicit_rules, .use, .use_provides
+ * Program - .attributes, .implicit_rules, .use, .use_provides
+ * BlockData - .implicit_rules, .use, .use_provides, .variables
+ * Interface - .implicit_rules, .use, .use_provides, .module_procedures
+ * Function, Subroutine - .implicit_rules, .attributes, .use, .use_statements,
+ .variables, .type_decls, .internal_subprogram
+ * TypeDecl - .variables, .attributes
+
+Block statements have the following methods:
+
+ * .get_classes() - returns a list of Statement classes that are valid
+ as a content of given block statement.
+
+The following one line statements are defined:
+
+ Implicit, TypeDeclarationStatement derivatives (see above),
+ Assignment, PointerAssignment, Assign, Call, Goto, ComputedGoto,
+ AssignedGoto, Continue, Return, Stop, Print, Read, Write, Flush,
+ Wait, Contains, Allocate, Deallocate, ModuleProcedure, Access,
+ Public, Private, Close, Cycle, Backspace, Endfile, Reeinf, Open,
+ Format, Save, Data, Nullify, Use, Exit, Parameter, Equivalence,
+ Dimension, Target, Pointer, Protected, Volatile, Value,
+ ArithmeticIf, Intrinsic, Inquire, Sequence, External, Namelist,
+ Common, Optional, Intent, Entry, Import, Forall,
+ SpecificBinding, GenericBinding, FinalBinding, Allocatable,
+ Asynchronous, Bind, Else, ElseIf, Case, Where, ElseWhere,
+ Enumerator, FortranName, Threadsafe, Depend, Check,
+ CallStatement, CallProtoArgument, Pause
diff --git a/numpy/f2py/lib/parser/parsefortran.py b/numpy/f2py/lib/parser/parsefortran.py
new file mode 100644
index 000000000..08716e7c8
--- /dev/null
+++ b/numpy/f2py/lib/parser/parsefortran.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+"""
+Defines FortranParser.
+
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+"""
+
+__all__ = ['FortranParser']
+
+import re
+import sys
+import traceback
+from numpy.distutils.misc_util import yellow_text, red_text
+
+from readfortran import FortranFileReader, FortranStringReader
+from block_statements import BeginSource
+from utils import AnalyzeError
+
+class FortranParser:
+
+ cache = {}
+
+ def __init__(self, reader):
+ """
+ Parser of FortranReader structure.
+ Use .parse() method for parsing, parsing result is saved in .block attribute.
+ """
+ self.reader = reader
+ if self.cache.has_key(reader.id):
+ parser = self.cache[reader.id]
+ self.block = parser.block
+ self.is_analyzed = parser.is_analyzed
+ self.block.show_message('using cached %s' % (reader.id))
+ else:
+ self.cache[reader.id] = self
+ self.block = None
+ self.is_analyzed = False
+ return
+
+ def get_item(self):
+ try:
+ return self.reader.next(ignore_comments = True)
+ except StopIteration:
+ pass
+ return
+
+ def put_item(self, item):
+ self.reader.fifo_item.insert(0, item)
+ return
+
+ def parse(self):
+ if self.block is not None:
+ return
+ try:
+ block = self.block = BeginSource(self)
+ except KeyboardInterrupt:
+ raise
+ except:
+ reader = self.reader
+ while reader is not None:
+ message = reader.format_message('FATAL ERROR',
+ 'while processing line',
+ reader.linecount, reader.linecount)
+ reader.show_message(message, sys.stderr)
+ reader = reader.reader
+ traceback.print_exc(file=sys.stderr)
+ self.reader.show_message(red_text('STOPPED PARSING'), sys.stderr)
+ return
+ return
+
+ def analyze(self):
+ if self.is_analyzed:
+ return
+ if self.block is None:
+ self.reader.show_message('Nothing to analyze.')
+ return
+
+ try:
+ self.block.analyze()
+ except AnalyzeError:
+ pass
+ except Exception, msg:
+ if str(msg) != '123454321':
+ traceback.print_exc(file=sys.stderr)
+ self.reader.show_message(red_text('FATAL ERROR: STOPPED ANALYSING %r CONTENT' % (self.reader.source) ), sys.stderr)
+ sys.exit(123454321)
+ return
+ self.is_analyzed = True
+ return
+
+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_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 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
+
+def simple_main():
+ import sys
+ if not sys.argv[1:]:
+ return parse_all_f()
+ for filename in sys.argv[1:]:
+ reader = FortranFileReader(filename)
+ print yellow_text('Processing '+filename+' (mode=%r)' % (reader.mode))
+ parser = FortranParser(reader)
+ parser.parse()
+ parser.analyze()
+ print parser.block.torepr(4)
+ #print parser.block
+
+def profile_main():
+ import hotshot, hotshot.stats
+ prof = hotshot.Profile("_parsefortran.prof")
+ prof.runcall(simple_main)
+ prof.close()
+ stats = hotshot.stats.load("_parsefortran.prof")
+ stats.strip_dirs()
+ stats.sort_stats('time', 'calls')
+ stats.print_stats(30)
+
+def parse_all_f():
+ for filename in open('opt_all_f.txt'):
+ filename = filename.strip()
+ reader = FortranFileReader(filename)
+ print yellow_text('Processing '+filename+' (mode=%r)' % (reader.mode))
+ parser = FortranParser(reader)
+ block = parser.parse()
+ print block
+
+if __name__ == "__main__":
+ #test_f77()
+ #test_free90()
+ #test_pyf()
+ simple_main()
+ #profile_main()
+ #parse_all_f()
diff --git a/numpy/f2py/lib/parser/pattern_tools.py b/numpy/f2py/lib/parser/pattern_tools.py
new file mode 100644
index 000000000..3c009a6a8
--- /dev/null
+++ b/numpy/f2py/lib/parser/pattern_tools.py
@@ -0,0 +1,401 @@
+"""
+Tools for constructing patterns.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import re
+
+class Pattern:
+ """
+ p1 | p2 -> <p1> | <p2>
+ p1 + p2 -> <p1> <p2>
+ p1 & p2 -> <p1><p2>
+ ~p1 -> [ <p1> ]
+ ~~p1 -> [ <p1> ]...
+ ~~~p1 -> <p1> [ <p1> ]...
+ ~~~~p1 -> ~~~p1
+ abs(p1) -> whole string match of <p1>
+ p1.named(name) -> match of <p1> has name
+ p1.match(string) -> return string match with <p1>
+ p1.flags(<re.I,..>)
+ p1.rsplit(..) -> split a string from the rightmost p1 occurrence
+ p1.lsplit(..) -> split a string from the leftmost p1 occurrence
+ """
+ _special_symbol_map = {'.': '[.]',
+ '*': '[*]',
+ '+': '[+]',
+ '|': '[|]',
+ '(': r'\(',
+ ')': r'\)',
+ '[': r'\[',
+ ']': r'\]',
+ '^': '[^]',
+ '$': '[$]',
+ '?': '[?]',
+ '{': '\{',
+ '}': '\}',
+ '>': '[>]',
+ '<': '[<]',
+ '=': '[=]'
+ }
+
+ def __init__(self, label, pattern, optional=0, flags=0, value=None):
+ self.label = label
+ self.pattern = pattern
+ self.optional = optional
+ self._flags = flags
+ self.value = value
+ return
+
+ def flags(self, *flags):
+ f = self._flags
+ for f1 in flags:
+ f = f | f1
+ return Pattern(self.label, self.pattern, optional=self.optional, flags=f, value=self.value)
+
+ def get_compiled(self):
+ try:
+ return self._compiled_pattern
+ except AttributeError:
+ self._compiled_pattern = compiled = re.compile(self.pattern, self._flags)
+ return compiled
+
+ def match(self, string):
+ return self.get_compiled().match(string)
+
+ def search(self, string):
+ return self.get_compiled().search(string)
+
+ def rsplit(self, string):
+ """
+ Return (<lhs>, <pattern_match>, <rhs>) where
+ string = lhs + pattern_match + rhs
+ and rhs does not contain pattern_match.
+ If no pattern_match is found in string, return None.
+ """
+ compiled = self.get_compiled()
+ t = compiled.split(string)
+ if len(t) < 3: return
+ if '' in t[1:-1]: return
+ rhs = t[-1].strip()
+ pattern_match = t[-2].strip()
+ assert abs(self).match(pattern_match),`self,string,t,pattern_match`
+ lhs = (''.join(t[:-2])).strip()
+ return lhs, pattern_match, rhs
+
+ def lsplit(self, string):
+ """
+ Return (<lhs>, <pattern_match>, <rhs>) where
+ string = lhs + pattern_match + rhs
+ and rhs does not contain pattern_match.
+ If no pattern_match is found in string, return None.
+ """
+ compiled = self.get_compiled()
+ t = compiled.split(string) # can be optimized
+ if len(t) < 3: return
+ lhs = t[0].strip()
+ pattern_match = t[1].strip()
+ rhs = (''.join(t[2:])).strip()
+ assert abs(self).match(pattern_match),`pattern_match`
+ return lhs, pattern_match, rhs
+
+ def __abs__(self):
+ return Pattern(self.label, r'\A' + self.pattern+ r'\Z',flags=self._flags, value=self.value)
+
+ def __repr__(self):
+ return '%s(%r, %r)' % (self.__class__.__name__, self.label, self.pattern)
+
+ def __or__(self, other):
+ label = '( %s OR %s )' % (self.label, other.label)
+ if self.pattern==other.pattern:
+ pattern = self.pattern
+ flags = self._flags
+ else:
+ pattern = '(%s|%s)' % (self.pattern, other.pattern)
+ flags = self._flags | other._flags
+ return Pattern(label, pattern, flags=flags)
+
+ def __and__(self, other):
+ if isinstance(other, Pattern):
+ label = '%s%s' % (self.label, other.label)
+ pattern = self.pattern + other.pattern
+ flags = self._flags | other._flags
+ else:
+ assert isinstance(other,str),`other`
+ label = '%s%s' % (self.label, other)
+ pattern = self.pattern + other
+ flags = self._flags
+ return Pattern(label, pattern, flags=flags)
+
+ def __rand__(self, other):
+ assert isinstance(other,str),`other`
+ label = '%s%s' % (other, self.label)
+ pattern = other + self.pattern
+ return Pattern(label, pattern, flags=self._flags)
+
+ def __invert__(self):
+ if self.optional:
+ if self.optional==1:
+ return Pattern(self.label + '...', self.pattern[:-1] + '*', optional=2,flags=self._flags)
+ if self.optional==2:
+ return Pattern('%s %s' % (self.label[1:-4].strip(), self.label), self.pattern[:-1] + '+',
+ optional=3, flags=self._flags)
+ return self
+ label = '[ %s ]' % (self.label)
+ pattern = '(%s)?' % (self.pattern)
+ return Pattern(label, pattern, optional=1, flags=self._flags)
+
+ def __add__(self, other):
+ if isinstance(other, Pattern):
+ label = '%s %s' % (self.label, other.label)
+ pattern = self.pattern + r'\s*' + other.pattern
+ flags = self._flags | other._flags
+ else:
+ assert isinstance(other,str),`other`
+ label = '%s %s' % (self.label, other)
+ other = self._special_symbol_map.get(other, other)
+ pattern = self.pattern + r'\s*' + other
+ flags = self._flags
+ return Pattern(label, pattern, flags = flags)
+
+ def __radd__(self, other):
+ assert isinstance(other,str),`other`
+ label = '%s %s' % (other, self.label)
+ other = self._special_symbol_map.get(other, other)
+ pattern = other + r'\s*' + self.pattern
+ return Pattern(label, pattern, flags=self._flags)
+
+ def named(self, name = None):
+ if name is None:
+ label = self.label
+ assert label[0]+label[-1]=='<>' and ' ' not in label,`label`
+ else:
+ label = '<%s>' % (name)
+ pattern = '(?P%s%s)' % (label.replace('-','_'), self.pattern)
+ return Pattern(label, pattern, flags=self._flags, value= self.value)
+
+ def rename(self, label):
+ if label[0]+label[-1]!='<>':
+ label = '<%s>' % (label)
+ return Pattern(label, self.pattern, optional=self.optional, flags=self._flags, value=self.value)
+
+ def __call__(self, string):
+ m = self.match(string)
+ if m is None: return
+ if self.value is not None: return self.value
+ return m.group()
+
+# Predefined patterns
+
+letter = Pattern('<letter>','[A-Z]',flags=re.I)
+name = Pattern('<name>', r'[A-Z]\w*',flags=re.I)
+digit = Pattern('<digit>',r'\d')
+underscore = Pattern('<underscore>', '_')
+binary_digit = Pattern('<binary-digit>',r'[01]')
+octal_digit = Pattern('<octal-digit>',r'[0-7]')
+hex_digit = Pattern('<hex-digit>',r'[\dA-F]',flags=re.I)
+
+digit_string = Pattern('<digit-string>',r'\d+')
+binary_digit_string = Pattern('<binary-digit-string>',r'[01]+')
+octal_digit_string = Pattern('<octal-digit-string>',r'[0-7]+')
+hex_digit_string = Pattern('<hex-digit-string>',r'[\dA-F]+',flags=re.I)
+
+sign = Pattern('<sign>',r'[+-]')
+exponent_letter = Pattern('<exponent-letter>',r'[ED]',flags=re.I)
+
+alphanumeric_character = Pattern('<alphanumeric-character>',r'\w') # [A-Z0-9_]
+special_character = Pattern('<special-character>',r'[ =+-*/\()[\]{},.:;!"%&~<>?,\'`^|$#@]')
+character = alphanumeric_character | special_character
+
+kind_param = digit_string | name
+kind_param_named = kind_param.named('kind-param')
+signed_digit_string = ~sign + digit_string
+int_literal_constant = digit_string + ~('_' + kind_param)
+signed_int_literal_constant = ~sign + int_literal_constant
+int_literal_constant_named = digit_string.named('value') + ~ ('_' + kind_param_named)
+signed_int_literal_constant_named = (~sign + digit_string).named('value') + ~ ('_' + kind_param_named)
+
+binary_constant = ('B' + ("'" & binary_digit_string & "'" | '"' & binary_digit_string & '"')).flags(re.I)
+octal_constant = ('O' + ("'" & octal_digit_string & "'" | '"' & octal_digit_string & '"')).flags(re.I)
+hex_constant = ('Z' + ("'" & hex_digit_string & "'" | '"' & hex_digit_string & '"')).flags(re.I)
+boz_literal_constant = binary_constant | octal_constant | hex_constant
+
+exponent = signed_digit_string
+significand = digit_string + '.' + ~digit_string | '.' + digit_string
+real_literal_constant = significand + ~(exponent_letter + exponent) + ~ ('_' + kind_param) | \
+ digit_string + exponent_letter + exponent + ~ ('_' + kind_param)
+real_literal_constant_named = (significand + ~(exponent_letter + exponent) |\
+ digit_string + exponent_letter + exponent).named('value') + ~ ('_' + kind_param_named)
+signed_real_literal_constant_named = (~sign + (significand + ~(exponent_letter + exponent) |\
+ digit_string + exponent_letter + exponent)).named('value') + ~ ('_' + kind_param_named)
+signed_real_literal_constant = ~sign + real_literal_constant
+
+named_constant = name
+real_part = signed_int_literal_constant | signed_real_literal_constant | named_constant
+imag_part = real_part
+complex_literal_constant = '(' + real_part + ',' + imag_part + ')'
+
+a_n_rep_char = Pattern('<alpha-numeric-rep-char>',r'\w')
+rep_char = Pattern('<rep-char>',r'.')
+char_literal_constant = ~( kind_param + '_') + ("'" + ~~rep_char + "'" | '"' + ~~rep_char + '"' )
+a_n_char_literal_constant_named1 = ~( kind_param_named + '_') + (~~~("'" + ~~a_n_rep_char + "'" )).named('value')
+a_n_char_literal_constant_named2 = ~( kind_param_named + '_') + (~~~('"' + ~~a_n_rep_char + '"' )).named('value')
+
+logical_literal_constant = ('[.](TRUE|FALSE)[.]' + ~ ('_' + kind_param)).flags(re.I)
+logical_literal_constant_named = Pattern('<value>',r'[.](TRUE|FALSE)[.]',flags=re.I).named() + ~ ('_' + kind_param_named)
+literal_constant = int_literal_constant | real_literal_constant | complex_literal_constant | logical_literal_constant | char_literal_constant | boz_literal_constant
+constant = literal_constant | named_constant
+int_constant = int_literal_constant | boz_literal_constant | named_constant
+char_constant = char_literal_constant | named_constant
+
+# assume that replace_string_map is applied:
+part_ref = name + ~((r'[(]' + name + r'[)]'))
+data_ref = part_ref + ~~~(r'[%]' + part_ref)
+primary = constant | name | data_ref | (r'[(]' + name + r'[)]')
+
+power_op = Pattern('<power-op>',r'(?<![*])[*]{2}(?![*])')
+mult_op = Pattern('<mult-op>',r'(?<![*])[*](?![*])|(?<![/])[/](?![/])')
+add_op = Pattern('<add-op>',r'[+-]')
+concat_op = Pattern('<concat-op>',r'(?<![/])[/]{2}(?![/])')
+rel_op = Pattern('<rel-op>','[.]EQ[.]|[.]NE[.]|[.]LT[.]|[.]LE[.]|[.]GT[.]|[.]GE[.]|[=]{2}|/[=]|[<][=]|[<]|[>][=]|[>]',flags=re.I)
+not_op = Pattern('<not-op>','[.]NOT[.]',flags=re.I)
+and_op = Pattern('<and-op>','[.]AND[.]',flags=re.I)
+or_op = Pattern('<or-op>','[.]OR[.]',flags=re.I)
+equiv_op = Pattern('<equiv-op>','[.]EQV[.]|[.]NEQV[.]',flags=re.I)
+percent_op = Pattern('<percent-op>',r'%',flags=re.I)
+intrinsic_operator = power_op | mult_op | add_op | concat_op | rel_op | not_op | and_op | or_op | equiv_op
+extended_intrinsic_operator = intrinsic_operator
+
+defined_unary_op = Pattern('<defined-unary-op>','[.][A-Z]+[.]',flags=re.I)
+defined_binary_op = Pattern('<defined-binary-op>','[.][A-Z]+[.]',flags=re.I)
+defined_operator = defined_unary_op | defined_binary_op | extended_intrinsic_operator
+abs_defined_operator = abs(defined_operator)
+defined_op = Pattern('<defined-op>','[.][A-Z]+[.]',flags=re.I)
+abs_defined_op = abs(defined_op)
+
+non_defined_binary_op = intrinsic_operator | logical_literal_constant
+
+label = Pattern('<label>','\d{1,5}')
+abs_label = abs(label)
+
+keyword = name
+keyword_equal = keyword + '='
+
+
+
+
+abs_constant = abs(constant)
+abs_literal_constant = abs(literal_constant)
+abs_int_literal_constant = abs(int_literal_constant)
+abs_signed_int_literal_constant = abs(signed_int_literal_constant)
+abs_signed_int_literal_constant_named = abs(signed_int_literal_constant_named)
+abs_int_literal_constant_named = abs(int_literal_constant_named)
+abs_real_literal_constant = abs(real_literal_constant)
+abs_signed_real_literal_constant = abs(signed_real_literal_constant)
+abs_signed_real_literal_constant_named = abs(signed_real_literal_constant_named)
+abs_real_literal_constant_named = abs(real_literal_constant_named)
+abs_complex_literal_constant = abs(complex_literal_constant)
+abs_logical_literal_constant = abs(logical_literal_constant)
+abs_char_literal_constant = abs(char_literal_constant)
+abs_boz_literal_constant = abs(boz_literal_constant)
+abs_name = abs(name)
+abs_a_n_char_literal_constant_named1 = abs(a_n_char_literal_constant_named1)
+abs_a_n_char_literal_constant_named2 = abs(a_n_char_literal_constant_named2)
+abs_logical_literal_constant_named = abs(logical_literal_constant_named)
+abs_binary_constant = abs(binary_constant)
+abs_octal_constant = abs(octal_constant)
+abs_hex_constant = abs(hex_constant)
+
+intrinsic_type_name = Pattern('<intrinsic-type-name>',r'(INTEGER|REAL|COMPLEX|LOGICAL|CHARACTER|DOUBLE\s*COMPLEX|DOUBLE\s*PRECISION|BYTE)',flags=re.I)
+abs_intrinsic_type_name = abs(intrinsic_type_name)
+double_complex_name = Pattern('<double-complex-name>','DOUBLE\s*COMPLEX', flags=re.I, value='DOUBLE COMPLEX')
+double_precision_name = Pattern('<double-precision-name>','DOUBLE\s*PRECISION', flags=re.I, value='DOUBLE PRECISION')
+abs_double_complex_name = abs(double_complex_name)
+abs_double_precision_name = abs(double_precision_name)
+
+access_spec = Pattern('<access-spec>',r'PUBLIC|PRIVATE',flags=re.I)
+abs_access_spec = abs(access_spec)
+
+implicit_none = Pattern('<implicit-none>',r'IMPLICIT\s*NONE',flags=re.I, value='IMPLICIT NONE')
+abs_implicit_none = abs(implicit_none)
+
+attr_spec = Pattern('<attr-spec>',r'ALLOCATABLE|ASYNCHRONOUS|EXTERNAL|INTENT|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|SAVE|TARGET|VALUE|VOLATILE',flags=re.I)
+abs_attr_spec = abs(attr_spec)
+
+dimension = Pattern('<dimension>',r'DIMENSION', flags=re.I)
+abs_dimension = abs(dimension)
+
+intent = Pattern('<intent>', r'INTENT', flags=re.I)
+abs_intent = abs(intent)
+
+intent_spec = Pattern('<intent-spec>', r'INOUT|IN|OUT', flags=re.I)
+abs_intent_spec = abs(intent_spec)
+
+subroutine = Pattern('<subroutine>', r'SUBROUTINE', flags=re.I)
+
+select_case = Pattern('<select-case>', r'SELECT\s*CASE', flags=re.I, value='SELECT CASE')
+abs_select_case = abs(select_case)
+
+def _test():
+ assert name.match('a1_a')
+ assert abs(name).match('a1_a')
+ assert not abs(name).match('a1_a[]')
+
+ m = abs(kind_param)
+ assert m.match('23')
+ assert m.match('SHORT')
+
+ m = abs(signed_digit_string)
+ assert m.match('23')
+ assert m.match('+ 23')
+ assert m.match('- 23')
+ assert m.match('-23')
+ assert not m.match('+n')
+
+ m = ~sign.named() + digit_string.named('number')
+ r = m.match('23')
+ assert r.groupdict()=={'number': '23', 'sign': None}
+ r = m.match('- 23')
+ assert r.groupdict()=={'number': '23', 'sign': '-'}
+
+ m = abs(char_literal_constant)
+ assert m.match('"adadfa"')
+ assert m.match('"adadfa""adad"')
+ assert m.match('HEY_"adadfa"')
+ assert m.match('HEY _ "ad\tadfa"')
+ assert not m.match('adadfa')
+
+ def assert_equal(result, expect):
+ try:
+ assert result==expect
+ except AssertionError, msg:
+ raise AssertionError,"Expected %r but got %r: %s" \
+ % (expect, result, msg)
+
+ m = mult_op.named()
+ assert m.rsplit('a * b')
+ assert_equal(m.lsplit('a * c* b'),('a','*','c* b'))
+ assert_equal(m.rsplit('a * c* b'),('a * c','*','b'))
+ assert_equal(m.lsplit('a * b ** c'),('a','*','b ** c'))
+ assert_equal(m.rsplit('a * b ** c'),('a','*','b ** c'))
+ assert_equal(m.lsplit('a * b ** c * d'),('a','*','b ** c * d'))
+ assert_equal(m.rsplit('a * b ** c * d'),('a * b ** c','*','d'))
+
+ m = power_op.named()
+ assert m.rsplit('a ** b')
+ assert_equal(m.lsplit('a * b ** c'),('a * b','**','c'))
+ assert_equal(m.rsplit('a * b ** c'),('a * b','**','c'))
+ assert_equal(m.lsplit('a ** b ** c'),('a','**','b ** c'))
+ assert_equal(m.rsplit('a ** b ** c'),('a ** b','**','c'))
+ print 'ok'
+
+if __name__ == '__main__':
+ _test()
diff --git a/numpy/f2py/lib/parser/readfortran.py b/numpy/f2py/lib/parser/readfortran.py
new file mode 100644
index 000000000..e3acffa36
--- /dev/null
+++ b/numpy/f2py/lib/parser/readfortran.py
@@ -0,0 +1,857 @@
+#!/usr/bin/env python
+"""
+Defines FortranReader classes for reading Fortran codes from
+files and strings. FortranReader handles comments and line continuations
+of both fix and free format Fortran codes.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['FortranFileReader',
+ 'FortranStringReader',
+ 'FortranReaderError',
+ 'Line', 'SyntaxErrorLine',
+ 'Comment',
+ 'MultiLine','SyntaxErrorMultiLine',
+ ]
+
+import re
+import os
+import sys
+import tempfile
+import traceback
+from cStringIO import StringIO
+from numpy.distutils.misc_util import yellow_text, red_text, blue_text
+
+from sourceinfo import get_source_info
+from splitline import String, string_replace_map, splitquote
+
+_spacedigits=' 0123456789'
+_cf2py_re = re.compile(r'(?P<indent>\s*)!f2py(?P<rest>.*)',re.I)
+_is_fix_cont = lambda line: line and len(line)>5 and line[5]!=' ' and line[:5]==5*' '
+_is_f90_cont = lambda line: line and '&' in line and line.rstrip()[-1]=='&'
+_f90label_re = re.compile(r'\s*(?P<label>(\w+\s*:|\d+))\s*(\b|(?=&)|\Z)',re.I)
+_is_include_line = re.compile(r'\s*include\s*("[^"]+"|\'[^\']+\')\s*\Z',re.I).match
+_is_fix_comment = lambda line: line and line[0] in '*cC!'
+_hollerith_start_search = re.compile(r'(?P<pre>\A|,\s*)(?P<num>\d+)h',re.I).search
+_is_call_stmt = re.compile(r'call\b', re.I).match
+
+class FortranReaderError: # TODO: may be derive it from Exception
+ def __init__(self, message):
+ self.message = message
+ print >> sys.stderr,message
+ sys.stderr.flush()
+
+class Line:
+ """ Holds a Fortran source line.
+ """
+
+ f2py_strmap_findall = re.compile(r'(_F2PY_STRING_CONSTANT_\d+_|F2PY_EXPR_TUPLE_\d+)').findall
+
+ def __init__(self, line, linenospan, label, reader):
+ self.line = line.strip()
+ self.span = linenospan
+ self.label = label
+ self.reader = reader
+ self.strline = None
+ self.is_f2py_directive = linenospan[0] in reader.f2py_comment_lines
+
+ def has_map(self):
+ return not not (hasattr(self,'strlinemap') and self.strlinemap)
+
+ def apply_map(self, line):
+ if not hasattr(self,'strlinemap') or not self.strlinemap:
+ return line
+ findall = self.f2py_strmap_findall
+ str_map = self.strlinemap
+ keys = findall(line)
+ for k in keys:
+ line = line.replace(k, str_map[k])
+ return line
+
+ def copy(self, line = None, apply_map = False):
+ if line is None:
+ line = self.line
+ if apply_map:
+ line = self.apply_map(line)
+ return Line(line, self.span, self.label, self.reader)
+
+ def clone(self, line):
+ self.line = self.apply_map(line)
+ self.strline = None
+ return
+
+ def __repr__(self):
+ return self.__class__.__name__+'(%r,%s,%r)' \
+ % (self.line, self.span, self.label)
+
+ def isempty(self, ignore_comments=False):
+ return not (self.line.strip() or self.label)
+
+ def get_line(self):
+ if self.strline is not None:
+ return self.strline
+ line = self.line
+ if self.reader.isfix77:
+ # Handle Hollerith constants by replacing them
+ # with char-literal-constants.
+ # H constants may appear only in DATA statements and
+ # in the argument list of CALL statement.
+ # Holleriht constants were removed from the Fortran 77 standard.
+ # The following handling is not perfect but works for simple
+ # usage cases.
+ # todo: Handle hollerith constants in DATA statement
+ if _is_call_stmt(line):
+ l2 = self.line[4:].lstrip()
+ i = l2.find('(')
+ if i != -1 and l2[-1]==')':
+ substrings = ['call '+l2[:i+1]]
+ start_search = _hollerith_start_search
+ l2 = l2[i+1:-1].strip()
+ m = start_search(l2)
+ while m:
+ substrings.append(l2[:m.start()])
+ substrings.append(m.group('pre'))
+ num = int(m.group('num'))
+ substrings.append("'"+l2[m.end():m.end()+num]+"'")
+ l2 = l2[m.end()+num:]
+ m = start_search(l2)
+ substrings.append(l2)
+ substrings.append(')')
+ line = ''.join(substrings)
+
+ line, str_map = string_replace_map(line, lower=not self.reader.ispyf)
+ self.strline = line
+ self.strlinemap = str_map
+ return line
+
+class SyntaxErrorLine(Line, FortranReaderError):
+ def __init__(self, line, linenospan, label, reader, message):
+ Line.__init__(self, line, linenospan, label, reader)
+ FortranReaderError.__init__(self, message)
+
+class Comment:
+ """ Holds Fortran comment.
+ """
+ def __init__(self, comment, linenospan, reader):
+ self.comment = comment
+ self.span = linenospan
+ self.reader = reader
+ def __repr__(self):
+ return self.__class__.__name__+'(%r,%s)' \
+ % (self.comment, self.span)
+ def isempty(self, ignore_comments=False):
+ return ignore_comments or len(self.comment)<2
+
+class MultiLine:
+ """ Holds (prefix, line list, suffix) representing multiline
+ syntax in .pyf files:
+ prefix+'''+lines+'''+suffix.
+ """
+ def __init__(self, prefix, block, suffix, linenospan, reader):
+ self.prefix = prefix
+ self.block = block
+ self.suffix = suffix
+ self.span = linenospan
+ self.reader = reader
+ def __repr__(self):
+ return self.__class__.__name__+'(%r,%r,%r,%s)' \
+ % (self.prefix,self.block,self.suffix,
+ self.span)
+ def isempty(self, ignore_comments=False):
+ return not (self.prefix or self.block or self.suffix)
+
+class SyntaxErrorMultiLine(MultiLine, FortranReaderError):
+ def __init__(self, prefix, block, suffix, linenospan, reader, message):
+ MultiLine.__init__(self, prefix, block, suffix, linenospan, reader)
+ FortranReaderError.__init__(self, message)
+
+
+class FortranReaderBase:
+
+ def __init__(self, source, isfree, isstrict):
+ """
+ source - file-like object with .next() method
+ used to retrive a line.
+ source may contain
+ - Fortran 77 code
+ - fixed format Fortran 90 code
+ - free format Fortran 90 code
+ - .pyf signatures - extended free format Fortran 90 syntax
+ """
+
+ self.linecount = 0
+ self.source = source
+ self.isclosed = False
+
+ self.filo_line = []
+ self.fifo_item = []
+ self.source_lines = []
+
+ self.f2py_comment_lines = [] # line numbers that contain f2py directives
+
+ self.reader = None
+ self.include_dirs = ['.']
+
+ self.set_mode(isfree, isstrict)
+ return
+
+ def set_mode(self, isfree, isstrict):
+ self.isfree90 = isfree and not isstrict
+ self.isfix90 = not isfree and not isstrict
+ self.isfix77 = not isfree and isstrict
+ self.ispyf = isfree and isstrict
+ self.isfree = isfree
+ self.isfix = not isfree
+ self.isstrict = isstrict
+
+ if self.isfree90: mode = 'free90'
+ elif self.isfix90: mode = 'fix90'
+ elif self.isfix77: mode = 'fix77'
+ else: mode = 'pyf'
+ self.mode = mode
+ self.name = '%s mode=%s' % (self.source, mode)
+ return
+
+ def close_source(self):
+ # called when self.source.next() raises StopIteration.
+ pass
+
+ # For handling raw source lines:
+
+ def put_single_line(self, line):
+ self.filo_line.append(line)
+ self.linecount -= 1
+ return
+
+ def get_single_line(self):
+ try:
+ line = self.filo_line.pop()
+ self.linecount += 1
+ return line
+ except IndexError:
+ pass
+ if self.isclosed:
+ return None
+ try:
+ line = self.source.next()
+ except StopIteration:
+ self.isclosed = True
+ self.close_source()
+ return None
+ self.linecount += 1
+ # expand tabs, replace special symbols, get rid of nl characters
+ line = line.expandtabs().replace('\xa0',' ').rstrip()
+ self.source_lines.append(line)
+ if not line:
+ return self.get_single_line()
+ return line
+
+ def get_next_line(self):
+ line = self.get_single_line()
+ if line is None: return
+ self.put_single_line(line)
+ return line
+
+ # Parser methods:
+ def get_item(self):
+ try:
+ return self.next(ignore_comments = True)
+ except StopIteration:
+ pass
+ return
+
+ def put_item(self, item):
+ self.fifo_item.insert(0, item)
+ return
+ # Iterator methods:
+
+ def __iter__(self):
+ return self
+
+ def next(self, ignore_comments = False):
+
+ try:
+ if self.reader is not None:
+ try:
+ return self.reader.next()
+ except StopIteration:
+ self.reader = None
+ item = self._next(ignore_comments)
+ if isinstance(item, Line) and _is_include_line(item.line):
+ reader = item.reader
+ filename = item.line.strip()[7:].lstrip()[1:-1]
+ include_dirs = self.include_dirs[:]
+ path = filename
+ for incl_dir in include_dirs:
+ path = os.path.join(incl_dir, filename)
+ if os.path.exists(path):
+ break
+ if not os.path.isfile(path):
+ dirs = os.pathsep.join(include_dirs)
+ message = reader.format_message(\
+ 'WARNING',
+ 'include file %r not found in %r,'\
+ ' ignoring.' % (filename, dirs),
+ item.span[0], item.span[1])
+ reader.show_message(message, sys.stdout)
+ return self.next(ignore_comments = ignore_comments)
+ message = reader.format_message('INFORMATION',
+ 'found file %r' % (path),
+ item.span[0], item.span[1])
+ reader.show_message(message, sys.stdout)
+ self.reader = FortranFileReader(path, include_dirs = include_dirs)
+ return self.reader.next(ignore_comments = ignore_comments)
+ return item
+ except StopIteration:
+ raise
+ except:
+ message = self.format_message('FATAL ERROR',
+ 'while processing line',
+ self.linecount, self.linecount)
+ self.show_message(message, sys.stdout)
+ traceback.print_exc(file=sys.stdout)
+ self.show_message(red_text('STOPPED READING'), sys.stdout)
+ raise StopIteration
+
+ def _next(self, ignore_comments = False):
+ fifo_item_pop = self.fifo_item.pop
+ while 1:
+ try:
+ item = fifo_item_pop(0)
+ except IndexError:
+ item = self.get_source_item()
+ if item is None:
+ raise StopIteration
+ if not item.isempty(ignore_comments):
+ break
+ # else ignore empty lines and comments
+ if not isinstance(item, Comment):
+ if not self.ispyf and isinstance(item, Line) \
+ and not item.is_f2py_directive \
+ and ';' in item.get_line():
+ # ;-separator not recognized in pyf-mode
+ items = []
+ for line in item.get_line().split(';'):
+ line = line.strip()
+ items.append(item.copy(line, apply_map=True))
+ items.reverse()
+ for newitem in items:
+ self.fifo_item.insert(0, newitem)
+ return fifo_item_pop(0)
+ return item
+ # collect subsequent comments to one comment instance
+ comments = []
+ start = item.span[0]
+ while isinstance(item, Comment):
+ comments.append(item.comment)
+ end = item.span[1]
+ while 1:
+ try:
+ item = fifo_item_pop(0)
+ except IndexError:
+ item = self.get_source_item()
+ if item is None or not item.isempty(ignore_comments):
+ break
+ if item is None:
+ break # hold raising StopIteration for the next call.
+ if item is not None:
+ self.fifo_item.insert(0,item)
+ return self.comment_item('\n'.join(comments), start, end)
+
+ # Interface to returned items:
+
+ def line_item(self, line, startlineno, endlineno, label, errmessage=None):
+ if errmessage is None:
+ return Line(line, (startlineno, endlineno), label, self)
+ return SyntaxErrorLine(line, (startlineno, endlineno),
+ label, self, errmessage)
+
+ def multiline_item(self, prefix, lines, suffix,
+ startlineno, endlineno, errmessage=None):
+ if errmessage is None:
+ return MultiLine(prefix, lines, suffix, (startlineno, endlineno), self)
+ return SyntaxErrorMultiLine(prefix, lines, suffix,
+ (startlineno, endlineno), self, errmessage)
+
+ def comment_item(self, comment, startlineno, endlineno):
+ return Comment(comment, (startlineno, endlineno), self)
+
+ # For handling messages:
+
+ def show_message(self, message, stream = sys.stdout):
+ stream.write(message+'\n')
+ stream.flush()
+ return
+
+ def format_message(self, kind, message, startlineno, endlineno,
+ startcolno=0, endcolno=-1):
+ back_index = {'warning':2,'error':3,'info':0}.get(kind.lower(),3)
+ r = ['%s while processing %r (mode=%r)..' % (kind, self.id, self.mode)]
+ for i in range(max(1,startlineno-back_index),startlineno):
+ r.append('%5d:%s' % (i,self.source_lines[i-1]))
+ for i in range(startlineno,min(endlineno+back_index,len(self.source_lines))+1):
+ if i==0 and not self.source_lines:
+ break
+ linenostr = '%5d:' % (i)
+ if i==endlineno:
+ sourceline = self.source_lines[i-1]
+ l0 = linenostr+sourceline[:startcolno]
+ if endcolno==-1:
+ l1 = sourceline[startcolno:]
+ l2 = ''
+ else:
+ l1 = sourceline[startcolno:endcolno]
+ l2 = sourceline[endcolno:]
+ r.append('%s%s%s <== %s' % (l0,yellow_text(l1),l2,red_text(message)))
+ else:
+ r.append(linenostr+ self.source_lines[i-1])
+ return '\n'.join(r)
+
+ def format_error_message(self, message, startlineno, endlineno,
+ startcolno=0, endcolno=-1):
+ return self.format_message('ERROR',message, startlineno,
+ endlineno, startcolno, endcolno)
+
+ def format_warning_message(self, message, startlineno, endlineno,
+ startcolno=0, endcolno=-1):
+ return self.format_message('WARNING',message, startlineno,
+ endlineno, startcolno, endcolno)
+
+ def error(self, message, item=None):
+ if item is None:
+ m = self.format_error_message(message, len(self.source_lines)-2, len(self.source_lines))
+ else:
+ m = self.format_error_message(message, item.span[0], item.span[1])
+ self.show_message(m)
+ return
+
+ def warning(self, message, item=None):
+ if item is None:
+ m = self.format_warning_message(message, len(self.source_lines)-2, len(self.source_lines))
+ else:
+ m = self.format_warning_message(message, item.span[0], item.span[1])
+ self.show_message(m)
+ return
+
+ # Auxiliary methods for processing raw source lines:
+
+ def handle_cf2py_start(self, line):
+ """
+ f2py directives can be used only in Fortran codes.
+ They are ignored when used inside .pyf files.
+ """
+ if not line or self.ispyf: return line
+ if self.isfix:
+ if line[0] in '*cC!#':
+ if line[1:5].lower() == 'f2py':
+ line = 5*' ' + line[5:]
+ self.f2py_comment_lines.append(self.linecount)
+ if self.isfix77:
+ return line
+ m = _cf2py_re.match(line)
+ if m:
+ newline = m.group('indent')+5*' '+m.group('rest')
+ self.f2py_comment_lines.append(self.linecount)
+ assert len(newline)==len(line),`newlinel,line`
+ return newline
+ return line
+
+ def handle_inline_comment(self, line, lineno, quotechar=None):
+ if quotechar is None and '!' not in line and \
+ '"' not in line and "'" not in line:
+ return line, quotechar
+ i = line.find('!')
+ put_item = self.fifo_item.append
+ if quotechar is None and i!=-1:
+ # first try a quick method
+ newline = line[:i]
+ if '"' not in newline and '\'' not in newline:
+ if self.isfix77 or not line[i:].startswith('!f2py'):
+ put_item(self.comment_item(line[i:], lineno, lineno))
+ return newline, quotechar
+ # handle cases where comment char may be a part of a character content
+ #splitter = LineSplitter(line, quotechar)
+ #items = [item for item in splitter]
+ #newquotechar = splitter.quotechar
+ items, newquotechar = splitquote(line, quotechar)
+
+ noncomment_items = []
+ noncomment_items_append = noncomment_items.append
+ n = len(items)
+ commentline = None
+ for k in range(n):
+ item = items[k]
+ if isinstance(item, String) or '!' not in item:
+ noncomment_items_append(item)
+ continue
+ j = item.find('!')
+ noncomment_items_append(item[:j])
+ items[k] = item[j:]
+ commentline = ''.join(items[k:])
+ break
+ if commentline is not None:
+ if commentline.startswith('!f2py'):
+ # go to next iteration:
+ newline = ''.join(noncomment_items) + commentline[5:]
+ self.f2py_comment_lines.append(lineno)
+ return self.handle_inline_comment(newline, lineno, quotechar)
+ put_item(self.comment_item(commentline, lineno, lineno))
+ return ''.join(noncomment_items), newquotechar
+
+ def handle_multilines(self, line, startlineno, mlstr):
+ i = line.find(mlstr)
+ if i != -1:
+ prefix = line[:i]
+ # skip fake multiline starts
+ p,k = prefix,0
+ while p.endswith('\\'):
+ p,k = p[:-1],k+1
+ if k % 2: return
+ if i != -1 and '!' not in prefix:
+ # Note character constans like 'abc"""123',
+ # so multiline prefix should better not contain `'' or `"' not `!'.
+ for quote in '"\'':
+ if prefix.count(quote) % 2:
+ message = self.format_warning_message(\
+ 'multiline prefix contains odd number of %r characters' \
+ % (quote), startlineno, startlineno,
+ 0, len(prefix))
+ self.show_message(message, sys.stderr)
+
+ suffix = None
+ multilines = []
+ line = line[i+3:]
+ while line is not None:
+ j = line.find(mlstr)
+ if j != -1 and '!' not in line[:j]:
+ multilines.append(line[:j])
+ suffix = line[j+3:]
+ break
+ multilines.append(line)
+ line = self.get_single_line()
+ if line is None:
+ message = self.format_error_message(\
+ 'multiline block never ends', startlineno,
+ startlineno, i)
+ return self.multiline_item(\
+ prefix,multilines,suffix,\
+ startlineno, self.linecount, message)
+ suffix,qc = self.handle_inline_comment(suffix, self.linecount)
+ # no line continuation allowed in multiline suffix
+ if qc is not None:
+ message = self.format_message(\
+ 'ASSERTION FAILURE(pyf)',
+ 'following character continuation: %r, expected None.' % (qc),
+ startlineno, self.linecount)
+ self.show_message(message, sys.stderr)
+ # XXX: should we do line.replace('\\'+mlstr[0],mlstr[0])
+ # for line in multilines?
+ return self.multiline_item(prefix,multilines,suffix,
+ startlineno, self.linecount)
+
+ # The main method of interpreting raw source lines within
+ # the following contexts: f77, fixed f90, free f90, pyf.
+
+ def get_source_item(self):
+ """
+ a source item is ..
+ - a fortran line
+ - a list of continued fortran lines
+ - a multiline - lines inside triple-qoutes, only when in ispyf mode
+ """
+ get_single_line = self.get_single_line
+ line = get_single_line()
+ if line is None: return
+ startlineno = self.linecount
+ line = self.handle_cf2py_start(line)
+ is_f2py_directive = startlineno in self.f2py_comment_lines
+
+ label = None
+ if self.ispyf:
+ # handle multilines
+ for mlstr in ['"""',"'''"]:
+ r = self.handle_multilines(line, startlineno, mlstr)
+ if r: return r
+
+ if self.isfix:
+ label = line[:5].strip().lower()
+ if label.endswith(':'): label = label[:-1].strip()
+ if not line.strip():
+ # empty line
+ return self.line_item(line[6:],startlineno,self.linecount,label)
+ if _is_fix_comment(line):
+ return self.comment_item(line, startlineno, startlineno)
+ for i in range(5):
+ if line[i] not in _spacedigits:
+ message = 'non-space/digit char %r found in column %i'\
+ ' of fixed Fortran code' % (line[i],i+1)
+ if self.isfix90:
+ message = message + ', switching to free format mode'
+ message = self.format_warning_message(\
+ message,startlineno, self.linecount)
+ self.show_message(message, sys.stderr)
+ self.set_mode(True, False)
+ else:
+ return self.line_item(line[6:], startlineno, self.linecount,
+ label, self.format_error_message(\
+ message, startlineno, self.linecount))
+
+ if self.isfix77 and not is_f2py_directive:
+ lines = [line[6:72]]
+ while _is_fix_cont(self.get_next_line()):
+ # handle fix format line continuations for F77 code
+ line = get_single_line()
+ lines.append(line[6:72])
+ return self.line_item(''.join(lines),startlineno,self.linecount,label)
+
+ handle_inline_comment = self.handle_inline_comment
+
+ if self.isfix90 and not is_f2py_directive:
+ # handle inline comment
+ newline,qc = handle_inline_comment(line[6:], startlineno)
+ lines = [newline]
+ next_line = self.get_next_line()
+ while _is_fix_cont(next_line) or _is_fix_comment(next_line):
+ # handle fix format line continuations for F90 code.
+ # mixing fix format and f90 line continuations is not allowed
+ # nor detected, just eject warnings.
+ line2 = get_single_line()
+ if _is_fix_comment(line2):
+ # handle fix format comments inside line continuations
+ citem = self.comment_item(line2,self.linecount,self.linecount)
+ self.fifo_item.append(citem)
+ else:
+ newline, qc = self.handle_inline_comment(line2[6:],
+ self.linecount, qc)
+ lines.append(newline)
+ next_line = self.get_next_line()
+ # no character continuation should follows now
+ if qc is not None:
+ message = self.format_message(\
+ 'ASSERTION FAILURE(fix90)',
+ 'following character continuation: %r, expected None.'\
+ % (qc), startlineno, self.linecount)
+ self.show_message(message, sys.stderr)
+ if len(lines)>1:
+ for i in range(len(lines)):
+ l = lines[i]
+ if l.rstrip().endswith('&'):
+ message = self.format_warning_message(\
+ 'f90 line continuation character `&\' detected'\
+ ' in fix format code',
+ startlineno + i, startlineno + i, l.rfind('&')+5)
+ self.show_message(message, sys.stderr)
+ return self.line_item(''.join(lines),startlineno,
+ self.linecount,label)
+ start_index = 0
+ if self.isfix90:
+ start_index = 6
+
+ lines = []
+ lines_append = lines.append
+ put_item = self.fifo_item.append
+ qc = None
+ while line is not None:
+ if start_index: # fix format code
+ line,qc = handle_inline_comment(line[start_index:],
+ self.linecount,qc)
+ is_f2py_directive = self.linecount in self.f2py_comment_lines
+ else:
+ line_lstrip = line.lstrip()
+ if lines:
+ if line_lstrip.startswith('!'):
+ # check for comment line within line continuation
+ put_item(self.comment_item(line_lstrip,
+ self.linecount, self.linecount))
+ line = get_single_line()
+ continue
+ else:
+ # first line, check for a f90 label
+ m = _f90label_re.match(line)
+ if m:
+ assert not label,`label,m.group('label')`
+ label = m.group('label').strip()
+ if label.endswith(':'): label = label[:-1].strip()
+ if not self.ispyf: label = label.lower()
+ line = line[m.end():]
+ line,qc = handle_inline_comment(line, self.linecount, qc)
+ is_f2py_directive = self.linecount in self.f2py_comment_lines
+
+ i = line.rfind('&')
+ if i!=-1:
+ line_i1_rstrip = line[i+1:].rstrip()
+ if not lines:
+ # first line
+ if i == -1 or line_i1_rstrip:
+ lines_append(line)
+ break
+ lines_append(line[:i])
+ line = get_single_line()
+ continue
+ if i == -1 or line_i1_rstrip:
+ # no line continuation follows
+ i = len(line)
+ k = -1
+ if i != -1:
+ # handle the beggining of continued line
+ k = line[:i].find('&')
+ if k != 1 and line[:k].lstrip():
+ k = -1
+ lines_append(line[k+1:i])
+ if i==len(line):
+ break
+ line = get_single_line()
+
+ if qc is not None:
+ message = self.format_message('ASSERTION FAILURE(free)',
+ 'following character continuation: %r, expected None.' % (qc),
+ startlineno, self.linecount)
+ self.show_message(message, sys.stderr)
+ return self.line_item(''.join(lines),startlineno,self.linecount,label)
+
+ ## FortranReaderBase
+
+# Fortran file and string readers:
+
+class FortranFileReader(FortranReaderBase):
+
+ def __init__(self, filename,
+ include_dirs = None):
+ isfree, isstrict = get_source_info(filename)
+ self.id = filename
+ self.file = open(filename,'r')
+ FortranReaderBase.__init__(self, self.file, isfree, isstrict)
+ if include_dirs is None:
+ self.include_dirs.insert(0, os.path.dirname(filename))
+ else:
+ self.include_dirs = include_dirs[:]
+ return
+
+ def close_source(self):
+ self.file.close()
+
+class FortranStringReader(FortranReaderBase):
+
+ def __init__(self, string, isfree, isstrict, include_dirs = None):
+ self.id = 'string-'+str(id(string))
+ source = StringIO(string)
+ FortranReaderBase.__init__(self, source, isfree, isstrict)
+ if include_dirs is not None:
+ self.include_dirs = include_dirs[:]
+ return
+
+# Testing:
+
+def test_f77():
+ string_f77 = """
+c12346 comment
+ subroutine foo
+ call foo
+ 'bar
+a 'g
+ abc=2
+cf2py call me ! hey
+ call you ! hi
+ end
+ '"""
+ reader = FortranStringReader(string_f77,False,True)
+ for item in reader:
+ print item
+
+ filename = tempfile.mktemp()+'.f'
+ f = open(filename,'w')
+ f.write(string_f77)
+ f.close()
+
+ reader = FortranFileReader(filename)
+ for item in reader:
+ print item
+
+def test_pyf():
+ string_pyf = """\
+python module foo
+ interface
+ beginml '''1st line
+ 2nd line
+ end line'''endml='tere!fake comment'!should be a comment
+ a = 2
+ 'charc\"onstant' ''' single line mline '''a='hi!fake comment'!should be a comment
+ a=\\\\\\\\\\'''not a multiline'''
+ !blah='''never ending multiline
+ b=3! hey, fake line continuation:&
+ c=4& !line cont
+ &45
+ thisis_label_2 : c = 3
+ xxif_isotropic_2 : if ( string_upper_compare ( o%opt_aniso, 'ISOTROPIC' ) ) then
+ g=3
+ endif
+ end interface
+ 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()
+end python module foo
+! end of file
+"""
+ reader = FortranStringReader(string_pyf,True, True)
+ for item in reader:
+ print item
+
+def test_fix90():
+ string_fix90 = """\
+ subroutine foo
+cComment
+ 1234 a = 3 !inline comment
+ b = 3
+!
+ !4!line cont. with comment symbol
+ &5
+ a = 3!f2py.14 ! pi!
+! KDMO
+ write (obj%print_lun, *) ' KDMO : '
+ write (obj%print_lun, *) ' COORD = ',coord, ' BIN_WID = ', &
+ obj%bin_wid,' VEL_DMO = ', obj%vel_dmo
+ end subroutine foo
+ subroutine
+
+ & foo
+ end
+"""
+ reader = FortranStringReader(string_fix90,False, False)
+ for item in reader:
+ print item
+
+def simple_main():
+ for filename in sys.argv[1:]:
+ print 'Processing',filename
+ reader = FortranFileReader(filename)
+ for item in reader:
+ print >> sys.stdout, item
+ sys.stdout.flush()
+ pass
+
+def profile_main():
+ import hotshot, hotshot.stats
+ prof = hotshot.Profile("readfortran.prof")
+ prof.runcall(simple_main)
+ prof.close()
+ stats = hotshot.stats.load("readfortran.prof")
+ stats.strip_dirs()
+ stats.sort_stats('time', 'calls')
+ stats.print_stats(30)
+
+if __name__ == "__main__":
+ #test_pyf()
+ #test_fix90()
+ #profile_main()
+ simple_main()
diff --git a/numpy/f2py/lib/parser/sourceinfo.py b/numpy/f2py/lib/parser/sourceinfo.py
new file mode 100644
index 000000000..7eb980251
--- /dev/null
+++ b/numpy/f2py/lib/parser/sourceinfo.py
@@ -0,0 +1,81 @@
+"""
+Provides get_source_info(<filename>) function to determine the format
+(free|fixed|strict|pyf) of a Fortran file.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['get_source_info']
+
+import re
+import os
+import sys
+
+_has_f_extension = re.compile(r'.*[.](for|ftn|f77|f)\Z',re.I).match
+_has_f_header = re.compile(r'-[*]-\s*fortran\s*-[*]-',re.I).search
+_has_f90_header = re.compile(r'-[*]-\s*f90\s*-[*]-',re.I).search
+_has_fix_header = re.compile(r'-[*]-\s*fix\s*-[*]-',re.I).search
+_free_f90_start = re.compile(r'[^c*!]\s*[^\s\d\t]',re.I).match
+
+def get_source_info(filename):
+ """
+ Determine if fortran file is
+ - in fix format and contains Fortran 77 code -> return False, True
+ - in fix format and contains Fortran 90 code -> return False, False
+ - in free format and contains Fortran 90 code -> return True, False
+ - in free format and contains signatures (.pyf) -> return True, True
+ """
+ base,ext = os.path.splitext(filename)
+ if ext=='.pyf':
+ return True, True
+ isfree = False
+ isstrict = False
+ f = open(filename,'r')
+ firstline = f.readline()
+ f.close()
+ if _has_f_extension(filename) and \
+ not (_has_f90_header(firstline) or _has_fix_header(firstline)):
+ isstrict = True
+ elif is_free_format(filename) and not _has_fix_header(firstline):
+ isfree = True
+ return isfree,isstrict
+
+def is_free_format(file):
+ """Check if file is in free format Fortran."""
+ # f90 allows both fixed and free format, assuming fixed unless
+ # signs of free format are detected.
+ isfree = False
+ f = open(file,'r')
+ line = f.readline()
+ n = 10000 # the number of non-comment lines to scan for hints
+ if _has_f_header(line):
+ n = 0
+ elif _has_f90_header(line):
+ n = 0
+ isfree = True
+ contline = False
+ while n>0 and line:
+ line = line.rstrip()
+ if line and line[0]!='!':
+ n -= 1
+ if line[0]!='\t' and _free_f90_start(line[:5]) or line[-1:]=='&':
+ isfree = True
+ break
+ line = f.readline()
+ f.close()
+ return isfree
+
+def simple_main():
+ for filename in sys.argv[1:]:
+ isfree, isstrict = get_source_info(filename)
+ print '%s: isfree=%s, isstrict=%s' % (filename, isfree, isstrict)
+
+if __name__ == '__main__':
+ simple_main()
diff --git a/numpy/f2py/lib/parser/splitline.py b/numpy/f2py/lib/parser/splitline.py
new file mode 100644
index 000000000..9d4a40fc5
--- /dev/null
+++ b/numpy/f2py/lib/parser/splitline.py
@@ -0,0 +1,426 @@
+#!/usr/bin/env python
+"""
+Defines LineSplitter and helper functions.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['String','string_replace_map','splitquote','splitparen']
+
+import re
+
+class String(str): pass
+class ParenString(str): pass
+
+def split2(line, lower=False):
+ """
+ Split line into non-string part and into a start of a string part.
+ Returns 2-tuple. The second item either is empty string or start
+ of a string part.
+ """
+ return LineSplitter(line,lower=lower).split2()
+
+_f2py_str_findall = re.compile(r"_F2PY_STRING_CONSTANT_\d+_").findall
+_is_name = re.compile(r'\w*\Z',re.I).match
+_is_simple_str = re.compile(r'\w*\Z',re.I).match
+_f2py_findall = re.compile(r'(_F2PY_STRING_CONSTANT_\d+_|F2PY_EXPR_TUPLE_\d+)').findall
+
+class string_replace_dict(dict):
+ """
+ Dictionary object that is callable for applying map returned
+ by string_replace_map() function.
+ """
+ def __call__(self, line):
+ for k in _f2py_findall(line):
+ line = line.replace(k, self[k])
+ return line
+
+def string_replace_map(line, lower=False,
+ _cache={'index':0,'pindex':0}):
+ """
+ 1) Replaces string constants with symbol `'_F2PY_STRING_CONSTANT_<index>_'`
+ 2) Replaces (expression) with symbol `(F2PY_EXPR_TUPLE_<index>)`
+ Returns a new line and the replacement map.
+ """
+ items = []
+ string_map = string_replace_dict()
+ rev_string_map = {}
+ for item in splitquote(line, lower=lower)[0]:
+ if isinstance(item, String) and not _is_simple_str(item[1:-1]):
+ key = rev_string_map.get(item)
+ if key is None:
+ _cache['index'] += 1
+ index = _cache['index']
+ key = "_F2PY_STRING_CONSTANT_%s_" % (index)
+ it = item[1:-1]
+ string_map[key] = it
+ rev_string_map[it] = key
+ items.append(item[0]+key+item[-1])
+ else:
+ items.append(item)
+ newline = ''.join(items)
+ items = []
+ expr_keys = []
+ for item in splitparen(newline):
+ if isinstance(item, ParenString) and not _is_name(item[1:-1]):
+ key = rev_string_map.get(item)
+ if key is None:
+ _cache['pindex'] += 1
+ index = _cache['pindex']
+ key = 'F2PY_EXPR_TUPLE_%s' % (index)
+ it = item[1:-1].strip()
+ string_map[key] = it
+ rev_string_map[it] = key
+ expr_keys.append(key)
+ items.append(item[0]+key+item[-1])
+ else:
+ items.append(item)
+ found_keys = set()
+ for k in expr_keys:
+ v = string_map[k]
+ l = _f2py_str_findall(v)
+ if l:
+ found_keys = found_keys.union(l)
+ for k1 in l:
+ v = v.replace(k1, string_map[k1])
+ string_map[k] = v
+ for k in found_keys:
+ del string_map[k]
+ return ''.join(items), string_map
+
+def splitquote(line, stopchar=None, lower=False, quotechars = '"\''):
+ """
+ Fast LineSplitter
+ """
+ items = []
+ i = 0
+ while 1:
+ try:
+ char = line[i]; i += 1
+ except IndexError:
+ break
+ l = []
+ l_append = l.append
+ nofslashes = 0
+ if stopchar is None:
+ # search for string start
+ while 1:
+ if char in quotechars and not nofslashes % 2:
+ stopchar = char
+ i -= 1
+ break
+ if char=='\\':
+ nofslashes += 1
+ else:
+ nofslashes = 0
+ l_append(char)
+ try:
+ char = line[i]; i += 1
+ except IndexError:
+ break
+ if not l: continue
+ item = ''.join(l)
+ if lower: item = item.lower()
+ items.append(item)
+ continue
+ if char==stopchar:
+ # string starts with quotechar
+ l_append(char)
+ try:
+ char = line[i]; i += 1
+ except IndexError:
+ if l:
+ item = String(''.join(l))
+ items.append(item)
+ break
+ # else continued string
+ while 1:
+ if char==stopchar and not nofslashes % 2:
+ l_append(char)
+ stopchar = None
+ break
+ if char=='\\':
+ nofslashes += 1
+ else:
+ nofslashes = 0
+ l_append(char)
+ try:
+ char = line[i]; i += 1
+ except IndexError:
+ break
+ if l:
+ item = String(''.join(l))
+ items.append(item)
+ return items, stopchar
+
+class LineSplitterBase:
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ item = ''
+ while not item:
+ item = self.get_item() # get_item raises StopIteration
+ return item
+
+class LineSplitter(LineSplitterBase):
+ """ Splits a line into non strings and strings. E.g.
+ abc=\"123\" -> ['abc=','\"123\"']
+ Handles splitting lines with incomplete string blocks.
+ """
+ def __init__(self, line,
+ quotechar = None,
+ lower=False,
+ ):
+ self.fifo_line = [c for c in line]
+ self.fifo_line.reverse()
+ self.quotechar = quotechar
+ self.lower = lower
+
+ def split2(self):
+ """
+ Split line until the first start of a string.
+ """
+ try:
+ item1 = self.get_item()
+ except StopIteration:
+ return '',''
+ i = len(item1)
+ l = self.fifo_line[:]
+ l.reverse()
+ item2 = ''.join(l)
+ return item1,item2
+
+ def get_item(self):
+ fifo_pop = self.fifo_line.pop
+ try:
+ char = fifo_pop()
+ except IndexError:
+ raise StopIteration
+ fifo_append = self.fifo_line.append
+ quotechar = self.quotechar
+ l = []
+ l_append = l.append
+
+ nofslashes = 0
+ if quotechar is None:
+ # search for string start
+ while 1:
+ if char in '"\'' and not nofslashes % 2:
+ self.quotechar = char
+ fifo_append(char)
+ break
+ if char=='\\':
+ nofslashes += 1
+ else:
+ nofslashes = 0
+ l_append(char)
+ try:
+ char = fifo_pop()
+ except IndexError:
+ break
+ item = ''.join(l)
+ if self.lower: item = item.lower()
+ return item
+
+ if char==quotechar:
+ # string starts with quotechar
+ l_append(char)
+ try:
+ char = fifo_pop()
+ except IndexError:
+ return String(''.join(l))
+ # else continued string
+ while 1:
+ if char==quotechar and not nofslashes % 2:
+ l_append(char)
+ self.quotechar = None
+ break
+ if char=='\\':
+ nofslashes += 1
+ else:
+ nofslashes = 0
+ l_append(char)
+ try:
+ char = fifo_pop()
+ except IndexError:
+ break
+ return String(''.join(l))
+
+def splitparen(line,paren='()'):
+ """
+ Fast LineSplitterParen.
+ """
+ stopchar = None
+ startchar, endchar = paren[0],paren[1]
+
+ items = []
+ i = 0
+ while 1:
+ try:
+ char = line[i]; i += 1
+ except IndexError:
+ break
+ nofslashes = 0
+ l = []
+ l_append = l.append
+ if stopchar is None:
+ # search for parenthesis start
+ while 1:
+ if char==startchar and not nofslashes % 2:
+ stopchar = endchar
+ i -= 1
+ break
+ if char=='\\':
+ nofslashes += 1
+ else:
+ nofslashes = 0
+ l_append(char)
+ try:
+ char = line[i]; i += 1
+ except IndexError:
+ break
+ item = ''.join(l)
+ else:
+ nofstarts = 0
+ while 1:
+ if char==stopchar and not nofslashes % 2 and nofstarts==1:
+ l_append(char)
+ stopchar = None
+ break
+ if char=='\\':
+ nofslashes += 1
+ else:
+ nofslashes = 0
+ if char==startchar:
+ nofstarts += 1
+ elif char==endchar:
+ nofstarts -= 1
+ l_append(char)
+ try:
+ char = line[i]; i += 1
+ except IndexError:
+ break
+ item = ParenString(''.join(l))
+ items.append(item)
+ return items
+
+class LineSplitterParen(LineSplitterBase):
+ """ Splits a line into strings and strings with parenthesis. E.g.
+ a(x) = b(c,d) -> ['a','(x)',' = b','(c,d)']
+ """
+ def __init__(self, line, paren = '()'):
+ self.fifo_line = [c for c in line]
+ self.fifo_line.reverse()
+ self.startchar = paren[0]
+ self.endchar = paren[1]
+ self.stopchar = None
+
+ def get_item(self):
+ fifo_pop = self.fifo_line.pop
+ try:
+ char = fifo_pop()
+ except IndexError:
+ raise StopIteration
+ fifo_append = self.fifo_line.append
+ startchar = self.startchar
+ endchar = self.endchar
+ stopchar = self.stopchar
+ l = []
+ l_append = l.append
+
+ nofslashes = 0
+ if stopchar is None:
+ # search for parenthesis start
+ while 1:
+ if char==startchar and not nofslashes % 2:
+ self.stopchar = endchar
+ fifo_append(char)
+ break
+ if char=='\\':
+ nofslashes += 1
+ else:
+ nofslashes = 0
+ l_append(char)
+ try:
+ char = fifo_pop()
+ except IndexError:
+ break
+ item = ''.join(l)
+ return item
+
+ nofstarts = 0
+ while 1:
+ if char==stopchar and not nofslashes % 2 and nofstarts==1:
+ l_append(char)
+ self.stopchar = None
+ break
+ if char=='\\':
+ nofslashes += 1
+ else:
+ nofslashes = 0
+ if char==startchar:
+ nofstarts += 1
+ elif char==endchar:
+ nofstarts -= 1
+ l_append(char)
+ try:
+ char = fifo_pop()
+ except IndexError:
+ break
+ return ParenString(''.join(l))
+
+def test():
+ splitter = LineSplitter('abc\\\' def"12\\"3""56"dfad\'a d\'')
+ l = [item for item in splitter]
+ assert l==['abc\\\' def','"12\\"3"','"56"','dfad','\'a d\''],`l`
+ assert splitter.quotechar is None
+ l,stopchar=splitquote('abc\\\' def"12\\"3""56"dfad\'a d\'')
+ assert l==['abc\\\' def','"12\\"3"','"56"','dfad','\'a d\''],`l`
+ assert stopchar is None
+
+ splitter = LineSplitter('"abc123&')
+ l = [item for item in splitter]
+ assert l==['"abc123&'],`l`
+ assert splitter.quotechar=='"'
+ l,stopchar = splitquote('"abc123&')
+ assert l==['"abc123&'],`l`
+ assert stopchar=='"'
+
+ splitter = LineSplitter(' &abc"123','"')
+ l = [item for item in splitter]
+ assert l==[' &abc"','123']
+ assert splitter.quotechar is None
+ l,stopchar = splitquote(' &abc"123','"')
+ assert l==[' &abc"','123']
+ assert stopchar is None
+
+ l = split2('')
+ assert l==('',''),`l`
+ l = split2('12')
+ assert l==('12',''),`l`
+ l = split2('1"a"//"b"')
+ assert l==('1','"a"//"b"'),`l`
+ l = split2('"ab"')
+ assert l==('','"ab"'),`l`
+
+ splitter = LineSplitterParen('a(b) = b(x,y(1)) b\((a)\)')
+ l = [item for item in splitter]
+ assert l==['a', '(b)', ' = b', '(x,y(1))', ' b\\(', '(a)', '\\)'],`l`
+ l = splitparen('a(b) = b(x,y(1)) b\((a)\)')
+ assert l==['a', '(b)', ' = b', '(x,y(1))', ' b\\(', '(a)', '\\)'],`l`
+
+ l = string_replace_map('a()')
+ print l
+ print 'ok'
+
+if __name__ == '__main__':
+ test()
diff --git a/numpy/f2py/lib/parser/statements.py b/numpy/f2py/lib/parser/statements.py
new file mode 100644
index 000000000..b37948faf
--- /dev/null
+++ b/numpy/f2py/lib/parser/statements.py
@@ -0,0 +1,1856 @@
+"""
+Fortran single line statements.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['GeneralAssignment',
+ 'Assignment','PointerAssignment','Assign','Call','Goto','ComputedGoto','AssignedGoto',
+ 'Continue','Return','Stop','Print','Read','Read0','Read1','Write','Flush','Wait',
+ 'Contains','Allocate','Deallocate','ModuleProcedure','Access','Public','Private',
+ 'Close','Cycle','Backspace','Endfile','Rewind','Open','Format','Save',
+ 'Data','Nullify','Use','Exit','Parameter','Equivalence','Dimension','Target',
+ 'Pointer','Protected','Volatile','Value','ArithmeticIf','Intrinsic',
+ 'Inquire','Sequence','External','Namelist','Common','Optional','Intent',
+ 'Entry','Import','ForallStmt','SpecificBinding','GenericBinding',
+ 'FinalBinding','Allocatable','Asynchronous','Bind','Else','ElseIf',
+ 'Case','WhereStmt','ElseWhere','Enumerator','FortranName','Threadsafe',
+ 'Depend','Check','CallStatement','CallProtoArgument','Pause']
+
+import re
+import sys
+
+from base_classes import Statement, Variable
+
+# Auxiliary tools
+
+from utils import split_comma, specs_split_comma, AnalyzeError, ParseError,\
+ get_module_file, parse_bind, parse_result, is_name
+
+class StatementWithNamelist(Statement):
+ """
+ <statement> [ :: ] <name-list>
+ """
+ def process_item(self):
+ if self.item.has_map():
+ self.isvalid = False
+ return
+ if hasattr(self,'stmtname'):
+ clsname = self.stmtname
+ else:
+ clsname = self.__class__.__name__
+ line = self.item.get_line()[len(clsname):].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = items = []
+ for item in split_comma(line):
+ if not is_name(item):
+ self.isvalid = False
+ return
+ items.append(item)
+ return
+
+ def tofortran(self,isfix=None):
+ if hasattr(self,'stmtname'):
+ clsname = self.stmtname.upper()
+ else:
+ clsname = self.__class__.__name__.upper()
+ s = ', '.join(self.items)
+ if s:
+ s = ' ' + s
+ return self.get_indent_tab(isfix=isfix) + clsname + s
+
+# Execution statements
+
+class GeneralAssignment(Statement):
+ """
+ <variable> = <expr>
+ <pointer variable> => <expr>
+ """
+
+ match = re.compile(r'\w[^=]*\s*=\>?').match
+ item_re = re.compile(r'(?P<variable>\w[^=]*)\s*(?P<sign>=\>?)\s*(?P<expr>.*)\Z',re.I).match
+ _repr_attr_names = ['variable','sign','expr'] + Statement._repr_attr_names
+
+ def process_item(self):
+ m = self.item_re(self.item.get_line())
+ if not m:
+ self.isvalid = False
+ return
+ self.sign = sign = m.group('sign')
+ if isinstance(self, Assignment) and sign != '=':
+ self.isvalid = False
+ return
+ elif isinstance(self, PointerAssignment) and sign != '=>':
+ self.isvalid = False
+ return
+ else:
+ if sign=='=>':
+ self.__class__ = PointerAssignment
+ else:
+ self.__class__ = Assignment
+ apply_map = self.item.apply_map
+ self.variable = apply_map(m.group('variable').replace(' ',''))
+ self.expr = apply_map(m.group('expr'))
+ return
+
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + '%s %s %s' \
+ % (self.variable, self.sign, self.expr)
+
+ def analyze(self): return
+
+class Assignment(GeneralAssignment):
+ pass
+
+class PointerAssignment(GeneralAssignment):
+ pass
+
+class Assign(Statement):
+ """
+ ASSIGN <label> TO <int-variable-name>
+ """
+ modes = ['fix77']
+ match = re.compile(r'assign\s*\d+\s*to\s*\w+\s*\Z',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[6:].lstrip()
+ i = line.lower().find('to')
+ assert not self.item.has_map()
+ self.items = [line[:i].rstrip(),line[i+2:].lstrip()]
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'ASSIGN %s TO %s' \
+ % (self.items[0], self.items[1])
+ def analyze(self): return
+
+class Call(Statement):
+ """Call statement class
+ CALL <procedure-designator> [ ( [ <actual-arg-spec-list> ] ) ]
+
+ <procedure-designator> = <procedure-name>
+ | <proc-component-ref>
+ | <data-ref> % <binding-name>
+
+ <actual-arg-spec> = [ <keyword> = ] <actual-arg>
+ <actual-arg> = <expr>
+ | <variable>
+ | <procedure-name>
+ | <proc-component-ref>
+ | <alt-return-spec>
+ <alt-return-spec> = * <label>
+
+ <proc-component-ref> = <variable> % <procedure-component-name>
+
+ <variable> = <designator>
+
+ Call instance has attributes:
+ designator
+ arg_list
+ """
+ match = re.compile(r'call\b', re.I).match
+
+ def process_item(self):
+ item = self.item
+ apply_map = item.apply_map
+ line = item.get_line()[4:].strip()
+ i = line.find('(')
+ items = []
+ if i==-1:
+ self.designator = apply_map(line).strip()
+ else:
+ j = line.find(')')
+ if j == -1 or len(line)-1 != j:
+ self.isvalid = False
+ return
+ self.designator = apply_map(line[:i]).strip()
+ items = split_comma(line[i+1:-1], item)
+ self.items = items
+ return
+
+ def tofortran(self, isfix=None):
+ s = self.get_indent_tab(isfix=isfix) + 'CALL '+str(self.designator)
+ if self.items:
+ s += '('+', '.join(map(str,self.items))+ ')'
+ return s
+
+ def analyze(self):
+ a = self.programblock.a
+ variables = a.variables
+ if hasattr(a, 'external'):
+ external = a.external
+ if self.designator in external:
+ print >> sys.stderr, 'Need to analyze:',self
+ return
+
+class Goto(Statement):
+ """
+ GO TO <label>
+ """
+ match = re.compile(r'go\s*to\s*\d+\s*\Z', re.I).match
+
+ def process_item(self):
+ assert not self.item.has_map()
+ self.label = self.item.get_line()[2:].lstrip()[2:].lstrip()
+ return
+
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'GO TO %s' % (self.label)
+ def analyze(self): return
+
+class ComputedGoto(Statement):
+ """
+ GO TO ( <label-list> ) [ , ] <scalar-int-expr>
+ """
+ match = re.compile(r'go\s*to\s*\(',re.I).match
+ def process_item(self):
+ apply_map = self.item.apply_map
+ line = self.item.get_line()[2:].lstrip()[2:].lstrip()
+ i = line.index(')')
+ self.items = split_comma(line[1:i], self.item)
+ line = line[i+1:].lstrip()
+ if line.startswith(','):
+ line = line[1:].lstrip()
+ self.expr = apply_map(line)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'GO TO (%s) %s' \
+ % (', '.join(self.items), self.expr)
+ def analyze(self): return
+
+class AssignedGoto(Statement):
+ """
+ GO TO <int-variable-name> [ ( <label> [ , <label> ]... ) ]
+ """
+ modes = ['fix77']
+ match = re.compile(r'go\s*to\s*\w+\s*\(?',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[2:].lstrip()[2:].lstrip()
+ i = line.find('(')
+ if i==-1:
+ self.varname = line
+ self.items = []
+ return
+ self.varname = line[:i].rstrip()
+ assert line[-1]==')',`line`
+ self
+ self.items = split_comma(line[i+1:-1], self.item)
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ if self.items:
+ return tab + 'GO TO %s (%s)' \
+ % (self.varname, ', '.join(self.items))
+ return tab + 'GO TO %s' % (self.varname)
+ def analyze(self): return
+
+class Continue(Statement):
+ """
+ CONTINUE
+ """
+ match = re.compile(r'continue\Z',re.I).match
+
+ def process_item(self):
+ self.label = self.item.label
+ return
+
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(deindent=True) + 'CONTINUE'
+
+ def analyze(self): return
+
+class Return(Statement):
+ """
+ RETURN [ <scalar-int-expr> ]
+ """
+ match = re.compile(r'return\b',re.I).match
+
+ def process_item(self):
+ self.expr = self.item.apply_map(self.item.get_line()[6:].lstrip())
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ if self.expr:
+ return tab + 'RETURN %s' % (self.expr)
+ return tab + 'RETURN'
+
+ def analyze(self): return
+
+class Stop(Statement):
+ """
+ STOP [ <stop-code> ]
+ <stop-code> = <scalar-char-constant> | <1-5-digit>
+ """
+ match = re.compile(r'stop\s*(\'\w*\'|"\w*"|\d+|)\Z',re.I).match
+
+ def process_item(self):
+ self.code = self.item.apply_map(self.item.get_line()[4:].lstrip())
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ if self.code:
+ return tab + 'STOP %s' % (self.code)
+ return tab + 'STOP'
+
+ def analyze(self): return
+
+class Print(Statement):
+ """
+ PRINT <format> [, <output-item-list>]
+ <format> = <default-char-expr> | <label> | *
+
+ <output-item> = <expr> | <io-implied-do>
+ <io-implied-do> = ( <io-implied-do-object-list> , <implied-do-control> )
+ <io-implied-do-object> = <input-item> | <output-item>
+ <implied-do-control> = <do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ]
+ <input-item> = <variable> | <io-implied-do>
+ """
+ match = re.compile(r'print\s*(\'\w*\'|\"\w*\"|\d+|[*]|\b\w)', re.I).match
+
+ def process_item(self):
+ item = self.item
+ apply_map = item.apply_map
+ line = item.get_line()[5:].lstrip()
+ items = split_comma(line, item)
+ self.format = items[0]
+ self.items = items[1:]
+ return
+
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'PRINT %s' \
+ % (', '.join([self.format]+self.items))
+ def analyze(self): return
+
+class Read(Statement):
+ """
+Read0: READ ( <io-control-spec-list> ) [ <input-item-list> ]
+
+ <io-control-spec-list> = [ UNIT = ] <io-unit>
+ | [ FORMAT = ] <format>
+ | [ NML = ] <namelist-group-name>
+ | ADVANCE = <scalar-default-char-expr>
+ ...
+
+Read1: READ <format> [, <input-item-list>]
+ <format> == <default-char-expr> | <label> | *
+ """
+ match = re.compile(r'read\b\s*[\w(*\'"]', re.I).match
+
+ def process_item(self):
+ item = self.item
+ line = item.get_line()[4:].lstrip()
+ if line.startswith('('):
+ self.__class__ = Read0
+ else:
+ self.__class__ = Read1
+ self.process_item()
+ return
+ def analyze(self): return
+
+class Read0(Read):
+
+ def process_item(self):
+ item = self.item
+ line = item.get_line()[4:].lstrip()
+ i = line.find(')')
+ self.specs = specs_split_comma(line[1:i], item)
+ self.items = split_comma(line[i+1:], item)
+ return
+
+ def tofortran(self, isfix=None):
+ s = self.get_indent_tab(isfix=isfix) + 'READ (%s)' % (', '.join(self.specs))
+ if self.items:
+ return s + ' ' + ', '.join(self.items)
+ return s
+
+class Read1(Read):
+
+ def process_item(self):
+ item = self.item
+ line = item.get_line()[4:].lstrip()
+ items = split_comma(line, item)
+ self.format = items[0]
+ self.items = items[1:]
+ return
+
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'READ ' \
+ + ', '.join([self.format]+self.items)
+
+class Write(Statement):
+ """
+ WRITE ( io-control-spec-list ) [<output-item-list>]
+ """
+ match = re.compile(r'write\s*\(', re.I).match
+ def process_item(self):
+ item = self.item
+ line = item.get_line()[5:].lstrip()
+ i = line.find(')')
+ assert i != -1, `line`
+ self.specs = specs_split_comma(line[1:i], item)
+ self.items = split_comma(line[i+1:], item)
+ return
+
+ def tofortran(self, isfix=None):
+ s = self.get_indent_tab(isfix=isfix) + 'WRITE (%s)' % ', '.join(self.specs)
+ if self.items:
+ s += ' ' + ', '.join(self.items)
+ return s
+ def analyze(self): return
+
+
+class Flush(Statement):
+ """
+ FLUSH <file-unit-number>
+ FLUSH ( <flush-spec-list> )
+ <flush-spec> = [ UNIT = ] <file-unit-number>
+ | IOSTAT = <scalar-int-variable>
+ | IOMSG = <iomsg-variable>
+ | ERR = <label>
+ """
+ match = re.compile(r'flush\b',re.I).match
+
+ def process_item(self):
+ line = self.item.get_line()[5:].lstrip()
+ if not line:
+ self.isvalid = False
+ return
+ if line.startswith('('):
+ assert line[-1] == ')', `line`
+ self.specs = specs_split_comma(line[1:-1],self.item)
+ else:
+ self.specs = specs_split_comma(line,self.item)
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ return tab + 'FLUSH (%s)' % (', '.join(self.specs))
+ def analyze(self): return
+
+class Wait(Statement):
+ """
+ WAIT ( <wait-spec-list> )
+ <wait-spec> = [ UNIT = ] <file-unit-number>
+ | END = <label>
+ | EOR = <label>
+ | ERR = <label>
+ | ID = <scalar-int-expr>
+ | IOMSG = <iomsg-variable>
+ | IOSTAT = <scalar-int-variable>
+
+ """
+ match = re.compile(r'wait\s*\(.*\)\Z',re.I).match
+ def process_item(self):
+ self.specs = specs_split_comma(\
+ self.item.get_line()[4:].lstrip()[1:-1], self.item)
+ return
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ return tab + 'WAIT (%s)' % (', '.join(self.specs))
+ def analyze(self): return
+
+class Contains(Statement):
+ """
+ CONTAINS
+ """
+ match = re.compile(r'contains\Z',re.I).match
+ def process_item(self): return
+ def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) + 'CONTAINS'
+
+class Allocate(Statement):
+ """
+ ALLOCATE ( [ <type-spec> :: ] <allocation-list> [ , <alloc-opt-list> ] )
+ <alloc-opt> = STAT = <stat-variable>
+ | ERRMSG = <errmsg-variable>
+ | SOURCE = <source-expr>
+ <allocation> = <allocate-object> [ ( <allocate-shape-spec-list> ) ]
+ """
+ match = re.compile(r'allocate\s*\(.*\)\Z',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[8:].lstrip()[1:-1].strip()
+ item2 = self.item.copy(line, True)
+ line2 = item2.get_line()
+ i = line2.find('::')
+ if i != -1:
+ spec = item2.apply_map(line2[:i].rstrip())
+ from block_statements import type_spec
+ stmt = None
+ for cls in type_spec:
+ if cls.match(spec):
+ stmt = cls(self, item2.copy(spec))
+ if stmt.isvalid:
+ break
+ if stmt is not None and stmt.isvalid:
+ spec = stmt
+ else:
+ self.warning('TODO: unparsed type-spec' + `spec`)
+ line2 = line2[i+2:].lstrip()
+ else:
+ spec = None
+ self.spec = spec
+ self.items = specs_split_comma(line2, item2)
+ return
+
+ def tofortran(self, isfix=None):
+ t = ''
+ if self.spec:
+ t = self.spec.tostr() + ' :: '
+ return self.get_indent_tab(isfix=isfix) \
+ + 'ALLOCATE (%s%s)' % (t,', '.join(self.items))
+ def analyze(self): return
+
+class Deallocate(Statement):
+ """
+ DEALLOCATE ( <allocate-object-list> [ , <dealloc-opt-list> ] )
+ <allocate-object> = <variable-name>
+ | <structure-component>
+ <structure-component> = <data-ref>
+ <dealloc-opt> = STAT = <stat-variable>
+ | ERRMSG = <errmsg-variable>
+ """
+ match = re.compile(r'deallocate\s*\(.*\)\Z',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[10:].lstrip()[1:-1].strip()
+ self.items = specs_split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) \
+ + 'DEALLOCATE (%s)' % (', '.join(self.items))
+ def analyze(self): return
+
+class ModuleProcedure(Statement):
+ """
+ [ MODULE ] PROCEDURE <procedure-name-list>
+ """
+ match = re.compile(r'(module\s*|)procedure\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()
+ m = self.match(line)
+ assert m,`line`
+ items = split_comma(line[m.end():].strip(), self.item)
+ for n in items:
+ if not is_name(n):
+ self.isvalid = False
+ return
+ self.items = items
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ return tab + 'MODULE PROCEDURE %s' % (', '.join(self.items))
+
+ def analyze(self):
+ module_procedures = self.parent.a.module_procedures
+ module_procedures.extend(self.items)
+ # XXX: add names to parent_provides
+ return
+
+class Access(Statement):
+ """
+ <access-spec> [ [::] <access-id-list>]
+ <access-spec> = PUBLIC | PRIVATE
+ <access-id> = <use-name> | <generic-spec>
+ """
+ match = re.compile(r'(public|private)\b',re.I).match
+ def process_item(self):
+ clsname = self.__class__.__name__.lower()
+ line = self.item.get_line()
+ if not line.lower().startswith(clsname):
+ self.isvalid = False
+ return
+ line = line[len(clsname):].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = split_comma(line, self.item)
+ return
+
+ def tofortran(self, isfix=None):
+ clsname = self.__class__.__name__.upper()
+ tab = self.get_indent_tab(isfix=isfix)
+ if self.items:
+ return tab + clsname + ' ' + ', '.join(self.items)
+ return tab + clsname
+
+ def analyze(self):
+ clsname = self.__class__.__name__
+ l = getattr(self.parent.a, clsname.lower() + '_id_list')
+ if self.items:
+ for name in self.items:
+ if name not in l: l.append(name)
+ else:
+ if '' not in l:
+ l.append('')
+ return
+
+class Public(Access):
+ is_public = True
+class Private(Access):
+ is_public = False
+
+class Close(Statement):
+ """
+ CLOSE ( <close-spec-list> )
+ <close-spec> = [ UNIT = ] <file-unit-number>
+ | IOSTAT = <scalar-int-variable>
+ | IOMSG = <iomsg-variable>
+ | ERR = <label>
+ | STATUS = <scalar-default-char-expr>
+ """
+ match = re.compile(r'close\s*\(.*\)\Z',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[5:].lstrip()[1:-1].strip()
+ self.specs = specs_split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ return tab + 'CLOSE (%s)' % (', '.join(self.specs))
+ def analyze(self): return
+
+class Cycle(Statement):
+ """
+ CYCLE [ <do-construct-name> ]
+ """
+ match = re.compile(r'cycle\b\s*\w*\s*\Z',re.I).match
+ def process_item(self):
+ self.name = self.item.get_line()[5:].lstrip()
+ return
+ def tofortran(self, isfix=None):
+ if self.name:
+ return self.get_indent_tab(isfix=isfix) + 'CYCLE ' + self.name
+ return self.get_indent_tab(isfix=isfix) + 'CYCLE'
+ def analyze(self): return
+
+class FilePositioningStatement(Statement):
+ """
+ REWIND <file-unit-number>
+ REWIND ( <position-spec-list> )
+ <position-spec-list> = [ UNIT = ] <file-unit-number>
+ | IOMSG = <iomsg-variable>
+ | IOSTAT = <scalar-int-variable>
+ | ERR = <label>
+ The same for BACKSPACE, ENDFILE.
+ """
+ match = re.compile(r'(rewind|backspace|endfile)\b',re.I).match
+
+ def process_item(self):
+ clsname = self.__class__.__name__.lower()
+ line = self.item.get_line()
+ if not line.lower().startswith(clsname):
+ self.isvalid = False
+ return
+ line = line[len(clsname):].lstrip()
+ if line.startswith('('):
+ assert line[-1]==')',`line`
+ spec = line[1:-1].strip()
+ else:
+ spec = line
+ self.specs = specs_split_comma(spec, self.item)
+ return
+
+ def tofortran(self, isfix=None):
+ clsname = self.__class__.__name__.upper()
+ return self.get_indent_tab(isfix=isfix) + clsname + ' (%s)' % (', '.join(self.specs))
+ def analyze(self): return
+
+class Backspace(FilePositioningStatement): pass
+
+class Endfile(FilePositioningStatement): pass
+
+class Rewind(FilePositioningStatement): pass
+
+class Open(Statement):
+ """
+ OPEN ( <connect-spec-list> )
+ <connect-spec> = [ UNIT = ] <file-unit-number>
+ | ACCESS = <scalar-default-char-expr>
+ | ..
+ """
+ match = re.compile(r'open\s*\(.*\)\Z',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[4:].lstrip()[1:-1].strip()
+ self.specs = specs_split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'OPEN (%s)' % (', '.join(self.specs))
+ def analyze(self): return
+
+class Format(Statement):
+ """
+ FORMAT <format-specification>
+ <format-specification> = ( [ <format-item-list> ] )
+ <format-item> = [ <r> ] <data-edit-descr>
+ | <control-edit-descr>
+ | <char-string-edit-descr>
+ | [ <r> ] ( <format-item-list> )
+ <data-edit-descr> = I <w> [ . <m> ]
+ | B <w> [ . <m> ]
+ ...
+ <r|w|m|d|e> = <int-literal-constant>
+ <v> = <signed-int-literal-constant>
+ <control-edit-descr> = <position-edit-descr>
+ | [ <r> ] /
+ | :
+ ...
+ <position-edit-descr> = T <n>
+ | TL <n>
+ ...
+ <sign-edit-descr> = SS | SP | S
+ ...
+
+ """
+ match = re.compile(r'format\s*\(.*\)\Z', re.I).match
+ def process_item(self):
+ item = self.item
+ if not item.label:
+ # R1001:
+ self.warning('R1001: FORMAT statement must be labeled but got %r.' \
+ % (item.label))
+ line = item.get_line()[6:].lstrip()
+ assert line[0]+line[-1]=='()',`line`
+ self.specs = split_comma(line[1:-1], item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'FORMAT (%s)' % (', '.join(self.specs))
+ def analyze(self): return
+
+class Save(Statement):
+ """
+ SAVE [ [ :: ] <saved-entity-list> ]
+ <saved-entity> = <object-name>
+ | <proc-pointer-name>
+ | / <common-block-name> /
+ <proc-pointer-name> = <name>
+ <object-name> = <name>
+ """
+ match = re.compile(r'save\b',re.I).match
+ def process_item(self):
+ assert not self.item.has_map()
+ line = self.item.get_line()[4:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ items = []
+ for s in line.split(','):
+ s = s.strip()
+ if not s: continue
+ if s.startswith('/'):
+ assert s.endswith('/'),`s`
+ n = s[1:-1].strip()
+ assert is_name(n),`n`
+ items.append('/%s/' % (n))
+ elif is_name(s):
+ items.append(s)
+ else:
+ self.isvalid = False
+ return
+ self.items = items
+ return
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ if not self.items:
+ return tab + 'SAVE'
+ return tab + 'SAVE %s' % (', '.join(self.items))
+ def analyze(self): return
+
+class Data(Statement):
+ """
+ DATA <data-stmt-set> [ [ , ] <data-stmt-set> ]...
+ <data-stmt-set> = <data-stmt-object-list> / <data-stmt-value-list> /
+ <data-stmt-object> = <variable> | <data-implied-do>
+ <data-implied-do> = ( <data-i-do-object-list> , <data-i-do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ] )
+ <data-i-do-object> = <array-element> | <scalar-structure-component> | <data-implied-do>
+ <data-i-do-variable> = <scalar-int-variable>
+ <variable> = <designator>
+ <designator> = <object-name>
+ | <array-element>
+ | <array-section>
+ | <structure-component>
+ | <substring>
+ <array-element> = <data-ref>
+ <array-section> = <data-ref> [ ( <substring-range> ) ]
+
+ """
+ match = re.compile(r'data\b',re.I).match
+
+ def process_item(self):
+ line = self.item.get_line()[4:].lstrip()
+ stmts = []
+ self.isvalid = False
+ while line:
+ i = line.find('/')
+ if i==-1: return
+ j = line.find('/',i+1)
+ if j==-1: return
+ l1, l2 = line[:i].rstrip(),line[i+1:j].strip()
+ l1 = split_comma(l1, self.item)
+ l2 = split_comma(l2, self.item)
+ stmts.append((l1,l2))
+ line = line[j+1:].lstrip()
+ if line.startswith(','):
+ line = line[1:].lstrip()
+ self.stmts = stmts
+ self.isvalid = True
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ l = []
+ for o,v in self.stmts:
+ l.append('%s / %s /' %(', '.join(o),', '.join(v)))
+ return tab + 'DATA ' + ' '.join(l)
+ def analyze(self): return
+
+class Nullify(Statement):
+ """
+ NULLIFY ( <pointer-object-list> )
+ <pointer-object> = <variable-name>
+ """
+ match = re.compile(r'nullify\s*\(.*\)\Z',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[7:].lstrip()[1:-1].strip()
+ self.items = split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'NULLIFY (%s)' % (', '.join(self.items))
+ def analyze(self): return
+
+class Use(Statement):
+ """
+ USE [ [ , <module-nature> ] :: ] <module-name> [ , <rename-list> ]
+ USE [ [ , <module-nature> ] :: ] <module-name> , ONLY : [ <only-list> ]
+ <module-nature> = INTRINSIC | NON_INTRINSIC
+ <rename> = <local-name> => <use-name>
+ | OPERATOR ( <local-defined-operator> ) => OPERATOR ( <use-defined-operator> )
+ <only> = <generic-spec> | <only-use-name> | <rename>
+ <only-use-name> = <use-name>
+ """
+ match = re.compile(r'use\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[3:].lstrip()
+ nature = ''
+ if line.startswith(','):
+ i = line.find('::')
+ nature = line[1:i].strip().upper()
+ line = line[i+2:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ if nature and not is_name(nature):
+ self.isvalid = False
+ return
+ self.nature = nature
+ i = line.find(',')
+ self.isonly = False
+ if i==-1:
+ self.name = line
+ self.items = []
+ else:
+ self.name = line[:i].rstrip()
+ line = line[i+1:].lstrip()
+ if line.lower().startswith('only') and line[4:].lstrip().startswith(':'):
+ self.isonly = True
+ line = line[4:].lstrip()[1:].lstrip()
+ self.items = split_comma(line, self.item)
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ s = 'USE'
+ if self.nature:
+ s += ' ' + self.nature + ' ::'
+ s += ' ' + self.name
+ if self.isonly:
+ s += ', ONLY:'
+ elif self.items:
+ s += ','
+ if self.items:
+ s += ' ' + ', '.join(self.items)
+ return tab + s
+
+ def analyze(self):
+ use = self.parent.a.use
+ if use.has_key(self.name):
+ return
+
+ modules = self.top.a.module
+ if not modules.has_key(self.name):
+ fn = None
+ for d in self.reader.include_dirs:
+ fn = get_module_file(self.name, d)
+ if fn is not None:
+ break
+ if fn is not None:
+ from readfortran import FortranFileReader
+ from parsefortran import FortranParser
+ self.info('looking module information from %r' % (fn))
+ reader = FortranFileReader(fn)
+ parser = FortranParser(reader)
+ parser.parse()
+ parser.block.a.module.update(modules)
+ parser.analyze()
+ modules.update(parser.block.a.module)
+
+ if not modules.has_key(self.name):
+ self.warning('no information about the module %r in use statement' % (self.name))
+ return
+
+ module = modules[self.name]
+ use_provides = self.parent.a.use_provides
+ print use
+
+ return
+
+class Exit(Statement):
+ """
+ EXIT [ <do-construct-name> ]
+ """
+ match = re.compile(r'exit\b\s*\w*\s*\Z',re.I).match
+ def process_item(self):
+ self.name = self.item.get_line()[4:].lstrip()
+ return
+ def tofortran(self, isfix=None):
+ if self.name:
+ return self.get_indent_tab(isfix=isfix) + 'EXIT ' + self.name
+ return self.get_indent_tab(isfix=isfix) + 'EXIT'
+ def analyze(self): return
+
+class Parameter(Statement):
+ """
+ PARAMETER ( <named-constant-def-list> )
+ <named-constant-def> = <named-constant> = <initialization-expr>
+ """
+ match = re.compile(r'parameter\s*\(.*\)\Z', re.I).match
+ def process_item(self):
+ line = self.item.get_line()[9:].lstrip()[1:-1].strip()
+ self.items = split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'PARAMETER (%s)' % (', '.join(self.items))
+ def analyze(self):
+ for item in self.items:
+ i = item.find('=')
+ assert i!=-1,`item`
+ name = item[:i].rstrip()
+ value = item[i+1:].lstrip()
+ var = self.get_variable(name)
+ var.update('parameter')
+ var.set_init(value)
+ return
+
+class Equivalence(Statement):
+ """
+ EQUIVALENCE <equivalence-set-list>
+ <equivalence-set> = ( <equivalence-object> , <equivalence-object-list> )
+ <equivalence-object> = <variable-name> | <array-element> | <substring>
+ """
+ match = re.compile(r'equivalence\s*\(.*\)\Z', re.I).match
+ def process_item(self):
+ items = []
+ for s in self.item.get_line()[11:].lstrip().split(','):
+ s = s.strip()
+ assert s[0]+s[-1]=='()',`s,self.item.get_line()`
+ s = ', '.join(split_comma(s[1:-1], self.item))
+ items.append('('+s+')')
+ self.items = items
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'EQUIVALENCE %s' % (', '.join(self.items))
+ def analyze(self): return
+
+class Dimension(Statement):
+ """
+ DIMENSION [ :: ] <array-name> ( <array-spec> ) [ , <array-name> ( <array-spec> ) ]...
+
+ """
+ match = re.compile(r'dimension\b', re.I).match
+ def process_item(self):
+ line = self.item.get_line()[9:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'DIMENSION %s' % (', '.join(self.items))
+ def analyze(self):
+ for line in self.items:
+ i = line.find('(')
+ assert i!=-1 and line.endswith(')'),`line`
+ name = line[:i].rstrip()
+ array_spec = split_comma(line[i+1:-1].strip(), self.item)
+ var = self.get_variable(name)
+ var.set_bounds(array_spec)
+ return
+
+class Target(Statement):
+ """
+ TARGET [ :: ] <object-name> ( <array-spec> ) [ , <object-name> ( <array-spec> ) ]...
+
+ """
+ match = re.compile(r'target\b', re.I).match
+ def process_item(self):
+ line = self.item.get_line()[6:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'TARGET %s' % (', '.join(self.items))
+ def analyze(self):
+ for line in self.items:
+ i = line.find('(')
+ assert i!=-1 and line.endswith(')'),`line`
+ name = line[:i].rstrip()
+ array_spec = split_comma(line[i+1:-1].strip(), self.item)
+ var = self.get_variable(name)
+ var.set_bounds(array_spec)
+ var.update('target')
+ return
+
+
+class Pointer(Statement):
+ """
+ POINTER [ :: ] <pointer-decl-list>
+ <pointer-decl> = <object-name> [ ( <deferred-shape-spec-list> ) ]
+ | <proc-entity-name>
+
+ """
+ match = re.compile(r'pointer\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[7:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'POINTER %s' % (', '.join(self.items))
+ def analyze(self):
+ for line in self.items:
+ i = line.find('(')
+ if i==-1:
+ name = line
+ array_spec = None
+ else:
+ assert line.endswith(')'),`line`
+ name = line[:i].rstrip()
+ array_spec = split_comma(line[i+1:-1].strip(), self.item)
+ var = self.get_variable(name)
+ var.set_bounds(array_spec)
+ var.update('pointer')
+ return
+
+class Protected(StatementWithNamelist):
+ """
+ PROTECTED [ :: ] <entity-name-list>
+ """
+ match = re.compile(r'protected\b',re.I).match
+ def analyze(self):
+ for name in self.items:
+ var = self.get_variable(name)
+ var.update('protected')
+ return
+
+class Volatile(StatementWithNamelist):
+ """
+ VOLATILE [ :: ] <object-name-list>
+ """
+ match = re.compile(r'volatile\b',re.I).match
+ def analyze(self):
+ for name in self.items:
+ var = self.get_variable(name)
+ var.update('volatile')
+ return
+
+class Value(StatementWithNamelist):
+ """
+ VALUE [ :: ] <dummy-arg-name-list>
+ """
+ match = re.compile(r'value\b',re.I).match
+ def analyze(self):
+ for name in self.items:
+ var = self.get_variable(name)
+ var.update('value')
+ return
+
+class ArithmeticIf(Statement):
+ """
+ IF ( <scalar-numeric-expr> ) <label> , <label> , <label>
+ """
+ match = re.compile(r'if\s*\(.*\)\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\Z', re.I).match
+ def process_item(self):
+ line = self.item.get_line()[2:].lstrip()
+ line,l2,l3 = line.rsplit(',',2)
+ i = line.rindex(')')
+ l1 = line[i+1:]
+ self.expr = self.item.apply_map(line[1:i]).strip()
+ self.labels = [l1.strip(),l2.strip(),l3.strip()]
+ return
+
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'IF (%s) %s' \
+ % (self.expr,', '.join(self.labels))
+ def analyze(self): return
+
+class Intrinsic(StatementWithNamelist):
+ """
+ INTRINSIC [ :: ] <intrinsic-procedure-name-list>
+ """
+ match = re.compile(r'intrinsic\b',re.I).match
+ def analyze(self):
+ for name in self.items:
+ var = self.get_variable(name)
+ var.update('intrinsic')
+ return
+
+class Inquire(Statement):
+ """
+ INQUIRE ( <inquire-spec-list> )
+ INQUIRE ( IOLENGTH = <scalar-int-variable> ) <output-item-list>
+
+ <inquire-spec> = [ UNIT = ] <file-unit-number>
+ | FILE = <file-name-expr>
+ ...
+ <output-item> = <expr>
+ | <io-implied-do>
+ """
+ match = re.compile(r'inquire\s*\(',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[7:].lstrip()
+ i = line.index(')')
+ self.specs = specs_split_comma(line[1:i].strip(), self.item)
+ self.items = split_comma(line[i+1:].lstrip(), self.item)
+ return
+ def tofortran(self, isfix=None):
+ if self.items:
+ return self.get_indent_tab(isfix=isfix) + 'INQUIRE (%s) %s' \
+ % (', '.join(self.specs), ', '.join(self.items))
+ return self.get_indent_tab(isfix=isfix) + 'INQUIRE (%s)' \
+ % (', '.join(self.specs))
+ def analyze(self): return
+
+class Sequence(Statement):
+ """
+ SEQUENCE
+ """
+ match = re.compile(r'sequence\Z',re.I).match
+ def process_item(self):
+ return
+ def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) + 'SEQUENCE'
+ def analyze(self):
+ self.parent.update_attributes('SEQUENCE')
+ return
+
+class External(StatementWithNamelist):
+ """
+ EXTERNAL [ :: ] <external-name-list>
+ """
+ match = re.compile(r'external\b', re.I).match
+ def analyze(self):
+ for name in self.items:
+ var = self.get_variable(name)
+ var.update('external')
+ return
+
+
+class Namelist(Statement):
+ """
+ NAMELIST / <namelist-group-name> / <namelist-group-object-list> [ [ , ] / <namelist-group-name> / <namelist-group-object-list> ]...
+ <namelist-group-object> = <variable-name>
+ """
+ match = re.compile(r'namelist\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[8:].lstrip()
+ items = []
+ while line:
+ assert line.startswith('/'),`line`
+ i = line.find('/',1)
+ assert i!=-1,`line`
+ name = line[:i+1]
+ line = line[i+1:].lstrip()
+ i = line.find('/')
+ if i==-1:
+ items.append((name,line))
+ line = ''
+ continue
+ s = line[:i].rstrip()
+ if s.endswith(','):
+ s = s[:-1].rstrip()
+ items.append((name,s))
+ line = line[i+1:].lstrip()
+ self.items = items
+ return
+
+ def tofortran(self, isfix=None):
+ l = []
+ for name,s in self.items:
+ l.append('%s %s' % (name,s))
+ tab = self.get_indent_tab(isfix=isfix)
+ return tab + 'NAMELIST ' + ', '.join(l)
+
+class Common(Statement):
+ """
+ COMMON [ / [ <common-block-name> ] / ] <common-block-object-list> \
+ [ [ , ] / [ <common-block-name> ] / <common-block-object-list> ]...
+ <common-block-object> = <variable-name> [ ( <explicit-shape-spec-list> ) ]
+ | <proc-pointer-name>
+ """
+ match = re.compile(r'common\b',re.I).match
+ def process_item(self):
+ item = self.item
+ line = item.get_line()[6:].lstrip()
+ items = []
+ while line:
+ if not line.startswith('/'):
+ name = ''
+ assert not items,`line`
+ else:
+ i = line.find('/',1)
+ assert i!=-1,`line`
+ name = line[1:i].strip()
+ line = line[i+1:].lstrip()
+ i = line.find('/')
+ if i==-1:
+ items.append((name,split_comma(line, item)))
+ line = ''
+ continue
+ s = line[:i].rstrip()
+ if s.endswith(','):
+ s = s[:-1].rstrip()
+ items.append((name,split_comma(s,item)))
+ line = line[i:].lstrip()
+ self.items = items
+ return
+ def tofortran(self, isfix=None):
+ l = []
+ for name,s in self.items:
+ s = ', '.join(s)
+ if name:
+ l.append('/ %s / %s' % (name,s))
+ else:
+ l.append(s)
+ tab = self.get_indent_tab(isfix=isfix)
+ return tab + 'COMMON ' + ' '.join(l)
+ def analyze(self):
+ for cname, items in self.items:
+ for item in items:
+ i = item.find('(')
+ if i!=-1:
+ assert item.endswith(')'),`item`
+ name = item[:i].rstrip()
+ shape = split_comma(item[i+1:-1].strip(), self.item)
+ else:
+ name = item
+ shape = None
+ var = self.get_variable(name)
+ if shape is not None:
+ var.set_bounds(shape)
+ # XXX: add name,var to parent_provides
+ return
+
+class Optional(StatementWithNamelist):
+ """
+ OPTIONAL [ :: ] <dummy-arg-name-list>
+ <dummy-arg-name> = <name>
+ """
+ match = re.compile(r'optional\b',re.I).match
+ def analyze(self):
+ for name in self.items:
+ var = self.get_variable(name)
+ var.update('optional')
+ return
+
+class Intent(Statement):
+ """
+ INTENT ( <intent-spec> ) [ :: ] <dummy-arg-name-list>
+ <intent-spec> = IN | OUT | INOUT
+
+ generalization for pyf-files:
+ INTENT ( <intent-spec-list> ) [ :: ] <dummy-arg-name-list>
+ <intent-spec> = IN | OUT | INOUT | CACHE | HIDE | OUT = <name>
+ """
+ match = re.compile(r'intent\s*\(',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[6:].lstrip()
+ i = line.find(')')
+ self.specs = specs_split_comma(line[1:i], self.item, upper=True)
+ line = line[i+1:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = [s.strip() for s in line.split(',')]
+ for n in self.items:
+ if not is_name(n):
+ self.isvalid = False
+ return
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'INTENT (%s) %s' \
+ % (', '.join(self.specs), ', '.join(self.items))
+ def analyze(self):
+ for name in self.items:
+ var = self.get_variable(name)
+ var.set_intent(self.specs)
+ return
+
+
+class Entry(Statement):
+ """
+ ENTRY <entry-name> [ ( [ <dummy-arg-list> ] ) [ <suffix> ] ]
+ <suffix> = <proc-language-binding-spec> [ RESULT ( <result-name> ) ]
+ | RESULT ( <result-name> ) [ <proc-language-binding-spec> ]
+ <proc-language-binding-spec> = <language-binding-spec>
+ <language-binding-spec> = BIND ( C [ , NAME = <scalar-char-initialization-expr> ] )
+ <dummy-arg> = <dummy-arg-name> | *
+ """
+ match = re.compile(r'entry\b', re.I).match
+ def process_item(self):
+ line = self.item.get_line()[5:].lstrip()
+ m = re.match(r'\w+', line)
+ name = line[:m.end()]
+ line = line[m.end():].lstrip()
+ if line.startswith('('):
+ i = line.find(')')
+ assert i!=-1,`line`
+ items = split_comma(line[1:i], self.item)
+ line = line[i+1:].lstrip()
+ else:
+ items = []
+ self.bind, line = parse_bind(line, self.item)
+ self.result, line = parse_result(line, self.item)
+ if line:
+ assert self.bind is None,`self.bind`
+ self.bind, line = parse_bind(line, self.item)
+ assert not line,`line`
+ self.name = name
+ self.items = items
+ return
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ s = tab + 'ENTRY '+self.name
+ if self.items:
+ s += ' (%s)' % (', '.join(self.items))
+ if self.result:
+ s += ' RESULT (%s)' % (self.result)
+ if self.bind:
+ s += ' BIND (%s)' % (', '.join(self.bind))
+ return s
+
+class Import(StatementWithNamelist):
+ """
+ IMPORT [ [ :: ] <import-name-list> ]
+ """
+ match = re.compile(r'import(\b|\Z)',re.I).match
+
+class Forall(Statement):
+ """
+ FORALL <forall-header> <forall-assignment-stmt>
+ <forall-header> = ( <forall-triplet-spec-list> [ , <scalar-mask-expr> ] )
+ <forall-triplet-spec> = <index-name> = <subscript> : <subscript> [ : <stride> ]
+ <subscript|stride> = <scalar-int-expr>
+ <forall-assignment-stmt> = <assignment-stmt> | <pointer-assignment-stmt>
+ """
+ match = re.compile(r'forall\s*\(.*\).*=', re.I).match
+ def process_item(self):
+ line = self.item.get_line()[6:].lstrip()
+ i = line.index(')')
+
+ line0 = line[1:i]
+ line = line[i+1:].lstrip()
+ stmt = GeneralAssignment(self, self.item.copy(line, True))
+ if stmt.isvalid:
+ self.content = [stmt]
+ else:
+ self.isvalid = False
+ return
+
+ specs = []
+ mask = ''
+ for l in split_comma(line0,self.item):
+ j = l.find('=')
+ if j==-1:
+ assert not mask,`mask,l`
+ mask = l
+ continue
+ assert j!=-1,`l`
+ index = l[:j].rstrip()
+ it = self.item.copy(l[j+1:].lstrip())
+ l = it.get_line()
+ k = l.split(':')
+ if len(k)==3:
+ s1, s2, s3 = map(it.apply_map,
+ [k[0].strip(),k[1].strip(),k[2].strip()])
+ else:
+ assert len(k)==2,`k`
+ s1, s2 = map(it.apply_map,
+ [k[0].strip(),k[1].strip()])
+ s3 = '1'
+ specs.append((index,s1,s2,s3))
+
+ self.specs = specs
+ self.mask = mask
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ l = []
+ for index,s1,s2,s3 in self.specs:
+ s = '%s = %s : %s' % (index,s1,s2)
+ if s3!='1':
+ s += ' : %s' % (s3)
+ l.append(s)
+ s = ', '.join(l)
+ if self.mask:
+ s += ', ' + self.mask
+ return tab + 'FORALL (%s) %s' % \
+ (s, str(self.content[0]).lstrip())
+ def analyze(self): return
+
+ForallStmt = Forall
+
+class SpecificBinding(Statement):
+ """
+ PROCEDURE [ ( <interface-name> ) ] [ [ , <binding-attr-list> ] :: ] <binding-name> [ => <procedure-name> ]
+ <binding-attr> = PASS [ ( <arg-name> ) ]
+ | NOPASS
+ | NON_OVERRIDABLE
+ | DEFERRED
+ | <access-spec>
+ <access-spec> = PUBLIC | PRIVATE
+ """
+ match = re.compile(r'procedure\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[9:].lstrip()
+ if line.startswith('('):
+ i = line.index(')')
+ name = line[1:i].strip()
+ line = line[i+1:].lstrip()
+ else:
+ name = ''
+ self.iname = name
+ if line.startswith(','):
+ line = line[1:].lstrip()
+ i = line.find('::')
+ if i != -1:
+ attrs = split_comma(line[:i], self.item)
+ line = line[i+2:].lstrip()
+ else:
+ attrs = []
+ attrs1 = []
+ for attr in attrs:
+ if is_name(attr):
+ attr = attr.upper()
+ else:
+ i = attr.find('(')
+ assert i!=-1 and attr.endswith(')'),`attr`
+ attr = '%s (%s)' % (attr[:i].rstrip().upper(), attr[i+1:-1].strip())
+ attrs1.append(attr)
+ self.attrs = attrs1
+ i = line.find('=')
+ if i==-1:
+ self.name = line
+ self.bname = ''
+ else:
+ self.name = line[:i].rstrip()
+ self.bname = line[i+1:].lstrip()[1:].lstrip()
+ return
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ s = 'PROCEDURE '
+ if self.iname:
+ s += '(' + self.iname + ') '
+ if self.attrs:
+ s += ', ' + ', '.join(self.attrs) + ' :: '
+ if self.bname:
+ s += '%s => %s' % (self.name, self.bname)
+ else:
+ s += self.name
+ return tab + s
+
+class GenericBinding(Statement):
+ """
+ GENERIC [ , <access-spec> ] :: <generic-spec> => <binding-name-list>
+ """
+ match = re.compile(r'generic\b.*::.*=\>.*\Z', re.I).match
+ def process_item(self):
+ line = self.item.get_line()[7:].lstrip()
+ if line.startswith(','):
+ line = line[1:].lstrip()
+ i = line.index('::')
+ self.aspec = line[:i].rstrip().upper()
+ line = line[i+2:].lstrip()
+ i = line.index('=>')
+ self.spec = self.item.apply_map(line[:i].rstrip())
+ self.items = split_comma(line[i+2:].lstrip())
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ s = 'GENERIC'
+ if self.aspec:
+ s += ', '+self.aspec
+ s += ' :: ' + self.spec + ' => ' + ', '.join(self.items)
+ return tab + s
+
+
+class FinalBinding(StatementWithNamelist):
+ """
+ FINAL [ :: ] <final-subroutine-name-list>
+ """
+ stmtname = 'final'
+ match = re.compile(r'final\b', re.I).match
+
+class Allocatable(Statement):
+ """
+ ALLOCATABLE [ :: ] <object-name> [ ( <deferred-shape-spec-list> ) ] [ , <object-name> [ ( <deferred-shape-spec-list> ) ] ]...
+ """
+ match = re.compile(r'allocatable\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[11:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'ALLOCATABLE ' + ', '.join(self.items)
+ def analyze(self):
+ for line in self.items:
+ i = line.find('(')
+ if i==-1:
+ name = line
+ array_spec = None
+ else:
+ assert line.endswith(')')
+ name = line[:i].rstrip()
+ array_spec = split_comma(line[i+1:-1], self.item)
+ var = self.get_variable(name)
+ var.update('allocatable')
+ if array_spec is not None:
+ var.set_bounds(array_spec)
+ return
+
+class Asynchronous(StatementWithNamelist):
+ """
+ ASYNCHRONOUS [ :: ] <object-name-list>
+ """
+ match = re.compile(r'asynchronous\b',re.I).match
+ def analyze(self):
+ for name in self.items:
+ var = self.get_variable(name)
+ var.update('asynchronous')
+ return
+
+
+class Bind(Statement):
+ """
+ <language-binding-spec> [ :: ] <bind-entity-list>
+ <language-binding-spec> = BIND ( C [ , NAME = <scalar-char-initialization-expr> ] )
+ <bind-entity> = <entity-name> | / <common-block-name> /
+ """
+ match = re.compile(r'bind\s*\(.*\)',re.I).match
+ def process_item(self):
+ line = self.item.line
+ self.specs, line = parse_bind(line, self.item)
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ items = []
+ for item in split_comma(line, self.item):
+ if item.startswith('/'):
+ assert item.endswith('/'),`item`
+ item = '/ ' + item[1:-1].strip() + ' /'
+ items.append(item)
+ self.items = items
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'BIND (%s) %s' %\
+ (', '.join(self.specs), ', '.join(self.items))
+
+# IF construct statements
+
+class Else(Statement):
+ """
+ ELSE [<if-construct-name>]
+ """
+ match = re.compile(r'else\b\s*\w*\s*\Z',re.I).match
+
+ def process_item(self):
+ item = self.item
+ self.name = item.get_line()[4:].strip()
+ parent_name = getattr(self.parent,'name','')
+ if self.name and self.name!=parent_name:
+ self.warning('expected if-construct-name %r but got %r, skipping.'\
+ % (parent_name, self.name))
+ self.isvalid = False
+ return
+
+ def tofortran(self, isfix=None):
+ if self.name:
+ return self.get_indent_tab(deindent=True) + 'ELSE ' + self.name
+ return self.get_indent_tab(deindent=True) + 'ELSE'
+
+ def analyze(self): return
+
+class ElseIf(Statement):
+ """
+ ELSE IF ( <scalar-logical-expr> ) THEN [ <if-construct-name> ]
+ """
+ match = re.compile(r'else\s*if\s*\(.*\)\s*then\s*\w*\s*\Z',re.I).match
+
+ def process_item(self):
+ item = self.item
+ line = item.get_line()[4:].lstrip()[2:].lstrip()
+ i = line.find(')')
+ assert line[0]=='('
+ self.expr = item.apply_map(line[1:i])
+ self.name = line[i+1:].lstrip()[4:].strip()
+ parent_name = getattr(self.parent,'name','')
+ if self.name and self.name!=parent_name:
+ self.warning('expected if-construct-name %r but got %r, skipping.'\
+ % (parent_name, self.name))
+ self.isvalid = False
+ return
+
+ def tofortran(self, isfix=None):
+ s = ''
+ if self.name:
+ s = ' ' + self.name
+ return self.get_indent_tab(deindent=True) + 'ELSE IF (%s) THEN%s' \
+ % (self.expr, s)
+
+ def analyze(self): return
+
+# SelectCase construct statements
+
+class Case(Statement):
+ """
+ CASE <case-selector> [ <case-constract-name> ]
+ <case-selector> = ( <case-value-range-list> ) | DEFAULT
+ <case-value-range> = <case-value>
+ | <case-value> :
+ | : <case-value>
+ | <case-value> : <case-value>
+ <case-value> = <scalar-(int|char|logical)-initialization-expr>
+ """
+ match = re.compile(r'case\b\s*(\(.*\)|DEFAULT)\s*\w*\Z',re.I).match
+ def process_item(self):
+ #assert self.parent.__class__.__name__=='Select',`self.parent.__class__`
+ line = self.item.get_line()[4:].lstrip()
+ if line.startswith('('):
+ i = line.find(')')
+ items = split_comma(line[1:i].strip(), self.item)
+ line = line[i+1:].lstrip()
+ else:
+ assert line.lower().startswith('default'),`line`
+ items = []
+ line = line[7:].lstrip()
+ for i in range(len(items)):
+ it = self.item.copy(items[i])
+ rl = []
+ for r in it.get_line().split(':'):
+ rl.append(it.apply_map(r.strip()))
+ items[i] = rl
+ self.items = items
+ self.name = line
+ parent_name = getattr(self.parent, 'name', '')
+ if self.name and self.name!=parent_name:
+ self.warning('expected case-construct-name %r but got %r, skipping.'\
+ % (parent_name, self.name))
+ self.isvalid = False
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ s = 'CASE'
+ if self.items:
+ l = []
+ for item in self.items:
+ l.append((' : '.join(item)).strip())
+ s += ' ( %s )' % (', '.join(l))
+ else:
+ s += ' DEFAULT'
+ if self.name:
+ s += ' ' + self.name
+ return s
+ def analyze(self): return
+
+# Where construct statements
+
+class Where(Statement):
+ """
+ WHERE ( <mask-expr> ) <where-assignment-stmt>
+ """
+ match = re.compile(r'where\s*\(.*\)\s*\w.*\Z',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[5:].lstrip()
+ i = line.index(')')
+ self.expr = self.item.apply_map(line[1:i].strip())
+ line = line[i+1:].lstrip()
+ newitem = self.item.copy(line)
+ cls = Assignment
+ if cls.match(line):
+ stmt = cls(self, newitem)
+ if stmt.isvalid:
+ self.content = [stmt]
+ return
+ self.isvalid = False
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ return tab + 'WHERE ( %s ) %s' % (self.expr, str(self.content[0]).lstrip())
+ def analyze(self): return
+
+WhereStmt = Where
+
+class ElseWhere(Statement):
+ """
+ ELSE WHERE ( <mask-expr> ) [ <where-construct-name> ]
+ ELSE WHERE [ <where-construct-name> ]
+ """
+ match = re.compile(r'else\s*where\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[4:].lstrip()[5:].lstrip()
+ self.expr = None
+ if line.startswith('('):
+ i = line.index(')')
+ assert i != -1,`line`
+ self.expr = self.item.apply_map(line[1:i].strip())
+ line = line[i+1:].lstrip()
+ self.name = line
+ parent_name = getattr(self.parent,'name','')
+ if self.name and not self.name==parent_name:
+ self.warning('expected where-construct-name %r but got %r, skipping.'\
+ % (parent_name, self.name))
+ self.isvalid = False
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ s = 'ELSE WHERE'
+ if self.expr is not None:
+ s += ' ( %s )' % (self.expr)
+ if self.name:
+ s += ' ' + self.name
+ return tab + s
+ def analyze(self): return
+
+# Enum construct statements
+
+class Enumerator(Statement):
+ """
+ ENUMERATOR [ :: ] <enumerator-list>
+ <enumerator> = <named-constant> [ = <scalar-int-initialization-expr> ]
+ """
+ match = re.compile(r'enumerator\b',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[10:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = split_comma(line, self.item)
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'ENUMERATOR ' + ', '.join(self.items)
+
+# F2PY specific statements
+
+class FortranName(Statement):
+ """
+ FORTRANNAME <name>
+ """
+ match = re.compile(r'fortranname\s*\w+\Z',re.I).match
+ def process_item(self):
+ self.value = self.item.get_line()[11:].lstrip()
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'FORTRANNAME ' + self.value
+
+class Threadsafe(Statement):
+ """
+ THREADSAFE
+ """
+ match = re.compile(r'threadsafe\Z',re.I).match
+ def process_item(self):
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'THREADSAFE'
+
+class Depend(Statement):
+ """
+ DEPEND ( <name-list> ) [ :: ] <dummy-arg-name-list>
+
+ """
+ match = re.compile(r'depend\s*\(',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[6:].lstrip()
+ i = line.find(')')
+ self.depends = split_comma(line[1:i].strip(), self.item)
+ line = line[i+1:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = split_comma(line)
+ return
+
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'DEPEND ( %s ) %s' \
+ % (', '.join(self.depends), ', '.join(self.items))
+
+class Check(Statement):
+ """
+ CHECK ( <c-int-scalar-expr> ) [ :: ] <name>
+
+ """
+ match = re.compile(r'check\s*\(',re.I).match
+ def process_item(self):
+ line = self.item.get_line()[5:].lstrip()
+ i = line.find(')')
+ assert i!=-1,`line`
+ self.expr = self.item.apply_map(line[1:i].strip())
+ line = line[i+1:].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.value = line
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'CHECK ( %s ) %s' \
+ % (self.expr, self.value)
+
+class CallStatement(Statement):
+ """
+ CALLSTATEMENT <c-expr>
+ """
+ match = re.compile(r'callstatement\b', re.I).match
+ def process_item(self):
+ self.expr = self.item.apply_map(self.item.get_line()[13:].lstrip())
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'CALLSTATEMENT ' + self.expr
+
+class CallProtoArgument(Statement):
+ """
+ CALLPROTOARGUMENT <c-type-spec-list>
+ """
+ match = re.compile(r'callprotoargument\b', re.I).match
+ def process_item(self):
+ self.specs = self.item.apply_map(self.item.get_line()[17:].lstrip())
+ return
+ def tofortran(self, isfix=None):
+ return self.get_indent_tab(isfix=isfix) + 'CALLPROTOARGUMENT ' + self.specs
+
+# Non-standard statements
+
+class Pause(Statement):
+ """
+ PAUSE [ <char-literal-constant|int-literal-constant> ]
+ """
+ match = re.compile(r'pause\s*(\d+|\'\w*\'|"\w*"|)\Z', re.I).match
+ def process_item(self):
+ self.value = self.item.apply_map(self.item.get_line()[5:].lstrip())
+ return
+ def tofortran(self, isfix=None):
+ if self.value:
+ return self.get_indent_tab(isfix=isfix) + 'PAUSE ' + self.value
+ return self.get_indent_tab(isfix=isfix) + 'PAUSE'
+ def analyze(self): return
diff --git a/numpy/f2py/lib/parser/test_Fortran2003.py b/numpy/f2py/lib/parser/test_Fortran2003.py
new file mode 100644
index 000000000..a8aae6081
--- /dev/null
+++ b/numpy/f2py/lib/parser/test_Fortran2003.py
@@ -0,0 +1,2101 @@
+from numpy.testing import *
+
+from Fortran2003 import *
+from api import get_reader
+
+###############################################################################
+############################### SECTION 2 ####################################
+###############################################################################
+
+class test_Program(NumpyTestCase): # R201
+
+ def check_simple(self):
+ reader = get_reader('''\
+ subroutine foo
+ end subroutine foo
+ subroutine bar
+ end
+ ''')
+ cls = Program
+ a = cls(reader)
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a), 'SUBROUTINE foo\nEND SUBROUTINE foo\nSUBROUTINE bar\nEND SUBROUTINE bar')
+
+class test_Specification_Part(NumpyTestCase): # R204
+
+ def check_simple(self):
+ from api import get_reader
+ reader = get_reader('''\
+ integer a''')
+ cls = Specification_Part
+ a = cls(reader)
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'INTEGER :: a')
+ assert_equal(repr(a), "Specification_Part(Type_Declaration_Stmt(Intrinsic_Type_Spec('INTEGER', None), None, Entity_Decl(Name('a'), None, None, None)))")
+
+###############################################################################
+############################### SECTION 3 ####################################
+###############################################################################
+
+class test_Name(NumpyTestCase): # R304
+
+ def check_name(self):
+ a = Name('a')
+ assert isinstance(a,Name),`a`
+ a = Name('a2')
+ assert isinstance(a,Name),`a`
+ a = Designator('a')
+ assert isinstance(a,Name),`a`
+ a = Constant('a')
+ assert isinstance(a,Name),`a`
+ a = Expr('a')
+ assert isinstance(a,Name),`a`
+
+###############################################################################
+############################### SECTION 4 ####################################
+###############################################################################
+
+class test_Type_Param_Value(NumpyTestCase): # 402
+
+ def check_type_param_value(self):
+ cls = Type_Param_Value
+ a = cls('*')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'*')
+ assert_equal(repr(a),"Type_Param_Value('*')")
+
+ a = cls(':')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),':')
+
+ a = cls('1+2')
+ assert isinstance(a,Level_2_Expr),`a`
+ assert_equal(str(a),'1 + 2')
+
+class test_Intrinsic_Type_Spec(NumpyTestCase): # R403
+
+ def check_intrinsic_type_spec(self):
+ cls = Intrinsic_Type_Spec
+ a = cls('INTEGER')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'INTEGER')
+ assert_equal(repr(a), "Intrinsic_Type_Spec('INTEGER', None)")
+
+ a = cls('Integer*2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'INTEGER*2')
+
+ a = cls('real*2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'REAL*2')
+
+ a = cls('logical*2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'LOGICAL*2')
+
+ a = cls('complex*2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'COMPLEX*2')
+
+ a = cls('character*2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'CHARACTER*2')
+
+ a = cls('double complex')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'DOUBLE COMPLEX')
+
+ a = cls('double precision')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'DOUBLE PRECISION')
+
+class test_Kind_Selector(NumpyTestCase): # R404
+
+ def check_kind_selector(self):
+ cls = Kind_Selector
+ a = cls('(1)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(KIND = 1)')
+ assert_equal(repr(a),"Kind_Selector('(', Int_Literal_Constant('1', None), ')')")
+
+ a = cls('(kind=1+2)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(KIND = 1 + 2)')
+
+ a = cls('* 1')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'*1')
+
+class test_Signed_Int_Literal_Constant(NumpyTestCase): # R405
+
+ def check_int_literal_constant(self):
+ cls = Signed_Int_Literal_Constant
+ a = cls('1')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1')
+ assert_equal(repr(a),"%s('1', None)" % (cls.__name__))
+
+ a = cls('+ 21_2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'+ 21_2')
+ assert_equal(repr(a),"%s('+ 21', '2')" % (cls.__name__))
+
+ a = cls('-21_SHORT')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'-21_SHORT')
+
+ a = cls('21_short')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'21_short')
+
+ a = cls('+1976354279568241_8')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'+1976354279568241_8')
+
+class test_Int_Literal_Constant(NumpyTestCase): # R406
+
+ def check_int_literal_constant(self):
+ cls = Int_Literal_Constant
+ a = cls('1')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1')
+ assert_equal(repr(a),"%s('1', None)" % (cls.__name__))
+
+ a = cls('21_2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'21_2')
+ assert_equal(repr(a),"%s('21', '2')" % (cls.__name__))
+
+ a = cls('21_SHORT')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'21_SHORT')
+
+ a = cls('21_short')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'21_short')
+
+ a = cls('1976354279568241_8')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1976354279568241_8')
+
+class test_Binary_Constant(NumpyTestCase): # R412
+
+ def check_boz_literal_constant(self):
+ cls = Boz_Literal_Constant
+ bcls = Binary_Constant
+ a = cls('B"01"')
+ assert isinstance(a,bcls),`a`
+ assert_equal(str(a),'B"01"')
+ assert_equal(repr(a),"%s('B\"01\"')" % (bcls.__name__))
+
+class test_Octal_Constant(NumpyTestCase): # R413
+
+ def check_boz_literal_constant(self):
+ cls = Boz_Literal_Constant
+ ocls = Octal_Constant
+ a = cls('O"017"')
+ assert isinstance(a,ocls),`a`
+ assert_equal(str(a),'O"017"')
+ assert_equal(repr(a),"%s('O\"017\"')" % (ocls.__name__))
+
+class test_Hex_Constant(NumpyTestCase): # R414
+
+ def check_boz_literal_constant(self):
+ cls = Boz_Literal_Constant
+ zcls = Hex_Constant
+ a = cls('Z"01A"')
+ assert isinstance(a,zcls),`a`
+ assert_equal(str(a),'Z"01A"')
+ assert_equal(repr(a),"%s('Z\"01A\"')" % (zcls.__name__))
+
+class test_Signed_Real_Literal_Constant(NumpyTestCase): # R416
+
+ def check_signed_real_literal_constant(self):
+ cls = Signed_Real_Literal_Constant
+ a = cls('12.78')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'12.78')
+ assert_equal(repr(a),"%s('12.78', None)" % (cls.__name__))
+
+ a = cls('+12.78_8')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'+12.78_8')
+ assert_equal(repr(a),"%s('+12.78', '8')" % (cls.__name__))
+
+ a = cls('- 12.')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'- 12.')
+
+ a = cls('1.6E3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6E3')
+
+ a = cls('+1.6E3_8')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'+1.6E3_8')
+
+ a = cls('1.6D3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6D3')
+
+ a = cls('-1.6E-3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'-1.6E-3')
+ a = cls('1.6E+3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6E+3')
+
+ a = cls('3E4')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'3E4')
+
+ a = cls('.123')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'.123')
+
+ a = cls('+1.6E-3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'+1.6E-3')
+
+ a = cls('10.9E7_QUAD')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'10.9E7_QUAD')
+
+ a = cls('-10.9e-17_quad')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'-10.9E-17_quad')
+
+class test_Real_Literal_Constant(NumpyTestCase): # R417
+
+ def check_real_literal_constant(self):
+ cls = Real_Literal_Constant
+ a = cls('12.78')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'12.78')
+ assert_equal(repr(a),"%s('12.78', None)" % (cls.__name__))
+
+ a = cls('12.78_8')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'12.78_8')
+ assert_equal(repr(a),"%s('12.78', '8')" % (cls.__name__))
+
+ a = cls('12.')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'12.')
+
+ a = cls('1.6E3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6E3')
+
+ a = cls('1.6E3_8')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6E3_8')
+
+ a = cls('1.6D3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6D3')
+
+ a = cls('1.6E-3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6E-3')
+ a = cls('1.6E+3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6E+3')
+
+ a = cls('3E4')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'3E4')
+
+ a = cls('.123')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'.123')
+
+ a = cls('1.6E-3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'1.6E-3')
+
+ a = cls('10.9E7_QUAD')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'10.9E7_QUAD')
+
+ a = cls('10.9e-17_quad')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'10.9E-17_quad')
+
+ a = cls('0.0D+0')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'0.0D+0')
+
+class test_Char_Selector(NumpyTestCase): # R424
+
+ def check_char_selector(self):
+ cls = Char_Selector
+ a = cls('(len=2, kind=8)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(LEN = 2, KIND = 8)')
+ assert_equal(repr(a),"Char_Selector(Int_Literal_Constant('2', None), Int_Literal_Constant('8', None))")
+
+
+ a = cls('(2, kind=8)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(LEN = 2, KIND = 8)')
+
+ a = cls('(2, 8)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(LEN = 2, KIND = 8)')
+
+ a = cls('(kind=8)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(KIND = 8)')
+
+ a = cls('(kind=8,len=2)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(LEN = 2, KIND = 8)')
+
+class test_Complex_Literal_Constant(NumpyTestCase): # R421
+
+ def check_complex_literal_constant(self):
+ cls = Complex_Literal_Constant
+ a = cls('(1.0, -1.0)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(1.0, -1.0)')
+ assert_equal(repr(a),"Complex_Literal_Constant(Signed_Real_Literal_Constant('1.0', None), Signed_Real_Literal_Constant('-1.0', None))")
+
+ a = cls('(3,3.1E6)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(3, 3.1E6)')
+
+ a = cls('(4.0_4, 3.6E7_8)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(4.0_4, 3.6E7_8)')
+
+ a = cls('( 0., PI)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(0., PI)')
+
+
+class test_Type_Name(NumpyTestCase): # C424
+
+ def check_simple(self):
+ cls = Type_Name
+ a = cls('a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a')
+ assert_equal(repr(a),"Type_Name('a')")
+
+ self.assertRaises(NoMatchError,cls,'integer')
+ self.assertRaises(NoMatchError,cls,'doubleprecision')
+
+class test_Length_Selector(NumpyTestCase): # R425
+
+ def check_length_selector(self):
+ cls = Length_Selector
+ a = cls('( len = *)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(LEN = *)')
+ assert_equal(repr(a),"Length_Selector('(', Type_Param_Value('*'), ')')")
+
+ a = cls('*2,')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'*2')
+
+class test_Char_Length(NumpyTestCase): # R426
+
+ def check_char_length(self):
+ cls = Char_Length
+ a = cls('(1)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(1)')
+ assert_equal(repr(a),"Char_Length('(', Int_Literal_Constant('1', None), ')')")
+
+ a = cls('1')
+ assert isinstance(a,Int_Literal_Constant),`a`
+ assert_equal(str(a),'1')
+
+ a = cls('(*)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(*)')
+
+ a = cls('(:)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(:)')
+
+class test_Char_Literal_Constant(NumpyTestCase): # R427
+
+ def check_char_literal_constant(self):
+ cls = Char_Literal_Constant
+ a = cls('NIH_"DO"')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'NIH_"DO"')
+ assert_equal(repr(a),'Char_Literal_Constant(\'"DO"\', \'NIH\')')
+
+ a = cls("'DO'")
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),"'DO'")
+ assert_equal(repr(a),'Char_Literal_Constant("\'DO\'", None)')
+
+ a = cls("'DON''T'")
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),"'DON''T'")
+
+ a = cls('"DON\'T"')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'"DON\'T"')
+
+ a = cls('""')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'""')
+
+ a = cls("''")
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),"''")
+
+ a = cls('"hey ha(ada)\t"')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'"hey ha(ada)\t"')
+
+class test_Logical_Literal_Constant(NumpyTestCase): # R428
+
+ def check_logical_literal_constant(self):
+ cls = Logical_Literal_Constant
+ a = cls('.TRUE.')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'.TRUE.')
+ assert_equal(repr(a),"%s('.TRUE.', None)" % (cls.__name__))
+
+ a = cls('.True.')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'.TRUE.')
+
+ a = cls('.FALSE.')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'.FALSE.')
+
+ a = cls('.TRUE._HA')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'.TRUE._HA')
+
+class test_Derived_Type_Stmt(NumpyTestCase): # R430
+
+ def check_simple(self):
+ cls = Derived_Type_Stmt
+ a = cls('type a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'TYPE :: a')
+ assert_equal(repr(a),"Derived_Type_Stmt(None, Type_Name('a'), None)")
+
+ a = cls('type ::a(b,c)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'TYPE :: a(b, c)')
+
+ a = cls('type, private, abstract::a(b,c)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'TYPE, PRIVATE, ABSTRACT :: a(b, c)')
+
+class test_Type_Name(NumpyTestCase): # C423
+
+ def check_simple(self):
+ cls = Type_Name
+ a = cls('a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a')
+ assert_equal(repr(a),"Type_Name('a')")
+
+class test_Type_Attr_Spec(NumpyTestCase): # R431
+
+ def check_simple(self):
+ cls = Type_Attr_Spec
+ a = cls('abstract')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'ABSTRACT')
+ assert_equal(repr(a),"Type_Attr_Spec('ABSTRACT')")
+
+ a = cls('bind (c )')
+ assert isinstance(a, Language_Binding_Spec),`a`
+ assert_equal(str(a),'BIND(C)')
+
+ a = cls('extends(a)')
+ assert isinstance(a, Type_EXTENDS_Parent_Type_Name),`a`
+ assert_equal(str(a),'EXTENDS(a)')
+
+ a = cls('private')
+ assert isinstance(a, Access_Spec),`a`
+ assert_equal(str(a),'PRIVATE')
+
+
+class test_End_Type_Stmt(NumpyTestCase): # R433
+
+ def check_simple(self):
+ cls = End_Type_Stmt
+ a = cls('end type')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'END TYPE')
+ assert_equal(repr(a),"End_Type_Stmt('TYPE', None)")
+
+ a = cls('end type a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'END TYPE a')
+
+class test_Sequence_Stmt(NumpyTestCase): # R434
+
+ def check_simple(self):
+ cls = Sequence_Stmt
+ a = cls('sequence')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'SEQUENCE')
+ assert_equal(repr(a),"Sequence_Stmt('SEQUENCE')")
+
+class test_Type_Param_Def_Stmt(NumpyTestCase): # R435
+
+ def check_simple(self):
+ cls = Type_Param_Def_Stmt
+ a = cls('integer ,kind :: a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'INTEGER, KIND :: a')
+ assert_equal(repr(a),"Type_Param_Def_Stmt(None, Type_Param_Attr_Spec('KIND'), Name('a'))")
+
+ a = cls('integer*2 ,len :: a=3, b=2+c')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'INTEGER*2, LEN :: a = 3, b = 2 + c')
+
+class test_Type_Param_Decl(NumpyTestCase): # R436
+
+ def check_simple(self):
+ cls = Type_Param_Decl
+ a = cls('a=2')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a = 2')
+ assert_equal(repr(a),"Type_Param_Decl(Name('a'), '=', Int_Literal_Constant('2', None))")
+
+ a = cls('a')
+ assert isinstance(a, Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Type_Param_Attr_Spec(NumpyTestCase): # R437
+
+ def check_simple(self):
+ cls = Type_Param_Attr_Spec
+ a = cls('kind')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'KIND')
+ assert_equal(repr(a),"Type_Param_Attr_Spec('KIND')")
+
+ a = cls('len')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'LEN')
+
+class test_Component_Attr_Spec(NumpyTestCase): # R441
+
+ def check_simple(self):
+ cls = Component_Attr_Spec
+ a = cls('pointer')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'POINTER')
+ assert_equal(repr(a),"Component_Attr_Spec('POINTER')")
+
+ a = cls('allocatable')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'ALLOCATABLE')
+
+ a = cls('dimension(a)')
+ assert isinstance(a, Dimension_Component_Attr_Spec),`a`
+ assert_equal(str(a),'DIMENSION(a)')
+
+ a = cls('private')
+ assert isinstance(a, Access_Spec),`a`
+ assert_equal(str(a),'PRIVATE')
+
+class test_Component_Decl(NumpyTestCase): # R442
+
+ def check_simple(self):
+ cls = Component_Decl
+ a = cls('a(1)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(1)')
+ assert_equal(repr(a),"Component_Decl(Name('a'), Explicit_Shape_Spec(None, Int_Literal_Constant('1', None)), None, None)")
+
+ a = cls('a(1)*(3)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(1)*(3)')
+
+ a = cls('a(1)*(3) = 2')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(1)*(3) = 2')
+
+ a = cls('a(1) => NULL')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(1) => NULL')
+
+class test_Final_Binding(NumpyTestCase): # R454
+
+ def check_simple(self):
+ cls = Final_Binding
+ a = cls('final a, b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'FINAL :: a, b')
+ assert_equal(repr(a),"Final_Binding('FINAL', Final_Subroutine_Name_List(',', (Name('a'), Name('b'))))")
+
+ a = cls('final::a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'FINAL :: a')
+
+class test_Derived_Type_Spec(NumpyTestCase): # R455
+
+ def check_simple(self):
+ cls = Derived_Type_Spec
+ a = cls('a(b)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a(b)')
+ assert_equal(repr(a),"Derived_Type_Spec(Type_Name('a'), Name('b'))")
+
+ a = cls('a(b,c,g=1)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a(b, c, g = 1)')
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+ a = cls('a()')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a()')
+
+class test_Type_Param_Spec(NumpyTestCase): # R456
+
+ def check_type_param_spec(self):
+ cls = Type_Param_Spec
+ a = cls('a=1')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a = 1')
+ assert_equal(repr(a),"Type_Param_Spec(Name('a'), Int_Literal_Constant('1', None))")
+
+ a = cls('k=a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'k = a')
+
+ a = cls('k=:')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'k = :')
+
+class test_Type_Param_Spec_List(NumpyTestCase): # R456-list
+
+ def check_type_param_spec_list(self):
+ cls = Type_Param_Spec_List
+
+ a = cls('a,b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a, b')
+ assert_equal(repr(a),"Type_Param_Spec_List(',', (Name('a'), Name('b')))")
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+
+ a = cls('k=a,c,g=1')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'k = a, c, g = 1')
+
+class test_Structure_Constructor_2(NumpyTestCase): # R457.b
+
+ def check_simple(self):
+ cls = Structure_Constructor_2
+ a = cls('k=a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'k = a')
+ assert_equal(repr(a),"Structure_Constructor_2(Name('k'), Name('a'))")
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Structure_Constructor(NumpyTestCase): # R457
+
+ def check_structure_constructor(self):
+ cls = Structure_Constructor
+ a = cls('t()')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'t()')
+ assert_equal(repr(a),"Structure_Constructor(Type_Name('t'), None)")
+
+ a = cls('t(s=1, a)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'t(s = 1, a)')
+
+ a = cls('a=k')
+ assert isinstance(a,Structure_Constructor_2),`a`
+ assert_equal(str(a),'a = k')
+ assert_equal(repr(a),"Structure_Constructor_2(Name('a'), Name('k'))")
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Component_Spec(NumpyTestCase): # R458
+
+ def check_simple(self):
+ cls = Component_Spec
+ a = cls('k=a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'k = a')
+ assert_equal(repr(a),"Component_Spec(Name('k'), Name('a'))")
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+ a = cls('a % b')
+ assert isinstance(a, Proc_Component_Ref),`a`
+ assert_equal(str(a),'a % b')
+
+ a = cls('s =a % b')
+ assert isinstance(a, Component_Spec),`a`
+ assert_equal(str(a),'s = a % b')
+
+class test_Component_Spec_List(NumpyTestCase): # R458-list
+
+ def check_simple(self):
+ cls = Component_Spec_List
+ a = cls('k=a, b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'k = a, b')
+ assert_equal(repr(a),"Component_Spec_List(',', (Component_Spec(Name('k'), Name('a')), Name('b')))")
+
+ a = cls('k=a, c')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'k = a, c')
+
+class test_Array_Constructor(NumpyTestCase): # R465
+
+ def check_simple(self):
+ cls = Array_Constructor
+ a = cls('(/a/)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(/a/)')
+ assert_equal(repr(a),"Array_Constructor('(/', Name('a'), '/)')")
+
+ a = cls('[a]')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'[a]')
+ assert_equal(repr(a),"Array_Constructor('[', Name('a'), ']')")
+
+ a = cls('[integer::a]')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'[INTEGER :: a]')
+
+ a = cls('[integer::a,b]')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'[INTEGER :: a, b]')
+
+class test_Ac_Spec(NumpyTestCase): # R466
+
+ def check_ac_spec(self):
+ cls = Ac_Spec
+ a = cls('integer ::')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'INTEGER ::')
+ assert_equal(repr(a),"Ac_Spec(Intrinsic_Type_Spec('INTEGER', None), None)")
+
+ a = cls('integer :: a,b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'INTEGER :: a, b')
+
+ a = cls('a,b')
+ assert isinstance(a,Ac_Value_List),`a`
+ assert_equal(str(a),'a, b')
+
+ a = cls('integer :: a, (a, b, n = 1, 5)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'INTEGER :: a, (a, b, n = 1, 5)')
+
+class test_Ac_Value_List(NumpyTestCase): # R469-list
+
+ def check_ac_value_list(self):
+ cls = Ac_Value_List
+ a = cls('a, b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a, b')
+ assert_equal(repr(a),"Ac_Value_List(',', (Name('a'), Name('b')))")
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Ac_Implied_Do(NumpyTestCase): # R470
+
+ def check_ac_implied_do(self):
+ cls = Ac_Implied_Do
+ a = cls('( a, b, n = 1, 5 )')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(a, b, n = 1, 5)')
+ assert_equal(repr(a),"Ac_Implied_Do(Ac_Value_List(',', (Name('a'), Name('b'))), Ac_Implied_Do_Control(Name('n'), [Int_Literal_Constant('1', None), Int_Literal_Constant('5', None)]))")
+
+class test_Ac_Implied_Do_Control(NumpyTestCase): # R471
+
+ def check_ac_implied_do_control(self):
+ cls = Ac_Implied_Do_Control
+ a = cls('n = 3, 5')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'n = 3, 5')
+ assert_equal(repr(a),"Ac_Implied_Do_Control(Name('n'), [Int_Literal_Constant('3', None), Int_Literal_Constant('5', None)])")
+
+ a = cls('n = 3+1, 5, 1')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'n = 3 + 1, 5, 1')
+
+###############################################################################
+############################### SECTION 5 ####################################
+###############################################################################
+
+class test_Type_Declaration_Stmt(NumpyTestCase): # R501
+
+ def check_simple(self):
+ cls = Type_Declaration_Stmt
+ a = cls('integer a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a), 'INTEGER :: a')
+ assert_equal(repr(a), "Type_Declaration_Stmt(Intrinsic_Type_Spec('INTEGER', None), None, Entity_Decl(Name('a'), None, None, None))")
+
+ a = cls('integer ,dimension(2):: a*3')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a), 'INTEGER, DIMENSION(2) :: a*3')
+
+ a = cls('real a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a), 'REAL :: a')
+ assert_equal(repr(a), "Type_Declaration_Stmt(Intrinsic_Type_Spec('REAL', None), None, Entity_Decl(Name('a'), None, None, None))")
+
+ a = cls('REAL A( LDA, * ), B( LDB, * )')
+ assert isinstance(a, cls),`a`
+
+ a = cls('DOUBLE PRECISION ALPHA, BETA')
+ assert isinstance(a, cls),`a`
+
+class test_Declaration_Type_Spec(NumpyTestCase): # R502
+
+ def check_simple(self):
+ cls = Declaration_Type_Spec
+ a = cls('Integer*2')
+ assert isinstance(a, Intrinsic_Type_Spec),`a`
+ assert_equal(str(a), 'INTEGER*2')
+
+ a = cls('type(foo)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a), 'TYPE(foo)')
+ assert_equal(repr(a), "Declaration_Type_Spec('TYPE', Type_Name('foo'))")
+
+class test_Attr_Spec(NumpyTestCase): # R503
+
+ def check_simple(self):
+ cls = Attr_Spec
+ a = cls('allocatable')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a), 'ALLOCATABLE')
+
+ a = cls('dimension(a)')
+ assert isinstance(a, Dimension_Attr_Spec),`a`
+ assert_equal(str(a),'DIMENSION(a)')
+
+class test_Dimension_Attr_Spec(NumpyTestCase): # R503.d
+
+ def check_simple(self):
+ cls = Dimension_Attr_Spec
+ a = cls('dimension(a)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'DIMENSION(a)')
+ assert_equal(repr(a),"Dimension_Attr_Spec('DIMENSION', Explicit_Shape_Spec(None, Name('a')))")
+
+class test_Intent_Attr_Spec(NumpyTestCase): # R503.f
+
+ def check_simple(self):
+ cls = Intent_Attr_Spec
+ a = cls('intent(in)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'INTENT(IN)')
+ assert_equal(repr(a),"Intent_Attr_Spec('INTENT', Intent_Spec('IN'))")
+
+class test_Entity_Decl(NumpyTestCase): # 504
+
+ def check_simple(self):
+ cls = Entity_Decl
+ a = cls('a(1)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(1)')
+ assert_equal(repr(a),"Entity_Decl(Name('a'), Explicit_Shape_Spec(None, Int_Literal_Constant('1', None)), None, None)")
+
+ a = cls('a(1)*(3)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(1)*(3)')
+
+ a = cls('a(1)*(3) = 2')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(1)*(3) = 2')
+
+class test_Access_Spec(NumpyTestCase): # R508
+
+ def check_simple(self):
+ cls = Access_Spec
+ a = cls('private')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PRIVATE')
+ assert_equal(repr(a),"Access_Spec('PRIVATE')")
+
+ a = cls('public')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PUBLIC')
+
+class test_Language_Binding_Spec(NumpyTestCase): # R509
+
+ def check_simple(self):
+ cls = Language_Binding_Spec
+ a = cls('bind(c)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'BIND(C)')
+ assert_equal(repr(a),'Language_Binding_Spec(None)')
+
+ a = cls('bind(c, name="hey")')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'BIND(C, NAME = "hey")')
+
+class test_Explicit_Shape_Spec(NumpyTestCase): # R511
+
+ def check_simple(self):
+ cls = Explicit_Shape_Spec
+ a = cls('a:b')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a : b')
+ assert_equal(repr(a),"Explicit_Shape_Spec(Name('a'), Name('b'))")
+
+ a = cls('a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a')
+
+class test_Upper_Bound(NumpyTestCase): # R513
+
+ def check_simple(self):
+ cls = Upper_Bound
+ a = cls('a')
+ assert isinstance(a, Name),`a`
+ assert_equal(str(a),'a')
+
+ self.assertRaises(NoMatchError,cls,'*')
+
+class test_Assumed_Shape_Spec(NumpyTestCase): # R514
+
+ def check_simple(self):
+ cls = Assumed_Shape_Spec
+ a = cls(':')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),':')
+ assert_equal(repr(a),'Assumed_Shape_Spec(None, None)')
+
+ a = cls('a :')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a :')
+
+class test_Deferred_Shape_Spec(NumpyTestCase): # R515
+
+ def check_simple(self):
+ cls = Deferred_Shape_Spec
+ a = cls(':')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),':')
+ assert_equal(repr(a),'Deferred_Shape_Spec(None, None)')
+
+
+class test_Assumed_Size_Spec(NumpyTestCase): # R516
+
+ def check_simple(self):
+ cls = Assumed_Size_Spec
+ a = cls('*')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'*')
+ assert_equal(repr(a),'Assumed_Size_Spec(None, None)')
+
+ a = cls('1:*')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'1 : *')
+
+ a = cls('a,1:*')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a, 1 : *')
+
+ a = cls('a:b,1:*')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a : b, 1 : *')
+
+class test_Access_Stmt(NumpyTestCase): # R518
+
+ def check_simple(self):
+ cls = Access_Stmt
+ a = cls('private')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PRIVATE')
+ assert_equal(repr(a),"Access_Stmt('PRIVATE', None)")
+
+ a = cls('public a,b')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PUBLIC :: a, b')
+
+ a = cls('public ::a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PUBLIC :: a')
+
+class test_Parameter_Stmt(NumpyTestCase): # R538
+
+ def check_simple(self):
+ cls = Parameter_Stmt
+ a = cls('parameter(a=1)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PARAMETER(a = 1)')
+ assert_equal(repr(a),"Parameter_Stmt('PARAMETER', Named_Constant_Def(Name('a'), Int_Literal_Constant('1', None)))")
+
+ a = cls('parameter(a=1, b=a+2)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PARAMETER(a = 1, b = a + 2)')
+
+ a = cls('PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PARAMETER(ONE = 1.0D+0, ZERO = 0.0D+0)')
+
+class test_Named_Constant_Def(NumpyTestCase): # R539
+
+ def check_simple(self):
+ cls = Named_Constant_Def
+ a = cls('a=1')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a = 1')
+ assert_equal(repr(a),"Named_Constant_Def(Name('a'), Int_Literal_Constant('1', None))")
+
+class test_Pointer_Decl(NumpyTestCase): # R541
+
+ def check_simple(self):
+ cls = Pointer_Decl
+ a = cls('a(:)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(:)')
+ assert_equal(repr(a),"Pointer_Decl(Name('a'), Deferred_Shape_Spec(None, None))")
+
+ a = cls('a(:,:)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(:, :)')
+
+class test_Implicit_Stmt(NumpyTestCase): # R549
+
+ def check_simple(self):
+ cls = Implicit_Stmt
+ a = cls('implicitnone')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'IMPLICIT NONE')
+ assert_equal(repr(a),"Implicit_Stmt('IMPLICIT NONE', None)")
+
+ a = cls('implicit real(a-d), double precision(r-t,x), type(a) (y-z)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'IMPLICIT REAL(A - D), DOUBLE PRECISION(R - T, X), TYPE(a)(Y - Z)')
+
+class test_Implicit_Spec(NumpyTestCase): # R550
+
+ def check_simple(self):
+ cls = Implicit_Spec
+ a = cls('integer (a-z)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'INTEGER(A - Z)')
+ assert_equal(repr(a),"Implicit_Spec(Intrinsic_Type_Spec('INTEGER', None), Letter_Spec('A', 'Z'))")
+
+ a = cls('double complex (r,d-g)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'DOUBLE COMPLEX(R, D - G)')
+
+class test_Letter_Spec(NumpyTestCase): # R551
+
+ def check_simple(self):
+ cls = Letter_Spec
+ a = cls('a-z')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'A - Z')
+ assert_equal(repr(a),"Letter_Spec('A', 'Z')")
+
+ a = cls('d')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'D')
+
+class test_Equivalence_Stmt(NumpyTestCase): # R554
+
+ def check_simple(self):
+ cls = Equivalence_Stmt
+ a = cls('equivalence (a, b ,z)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'EQUIVALENCE(a, b, z)')
+ assert_equal(repr(a),"Equivalence_Stmt('EQUIVALENCE', Equivalence_Set(Name('a'), Equivalence_Object_List(',', (Name('b'), Name('z')))))")
+
+ a = cls('equivalence (a, b ,z),(b,l)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'EQUIVALENCE(a, b, z), (b, l)')
+
+class test_Common_Stmt(NumpyTestCase): # R557
+
+ def check_simple(self):
+ cls = Common_Stmt
+ a = cls('common a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'COMMON // a')
+ assert_equal(repr(a),"Common_Stmt([(None, Name('a'))])")
+
+ a = cls('common // a,b')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'COMMON // a, b')
+
+ a = cls('common /name/ a,b')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'COMMON /name/ a, b')
+
+ a = cls('common /name/ a,b(4,5) // c, /ljuks/ g(2)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'COMMON /name/ a, b(4, 5) // c /ljuks/ g(2)')
+
+class test_Common_Block_Object(NumpyTestCase): # R558
+
+ def check_simple(self):
+ cls = Common_Block_Object
+ a = cls('a(2)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(2)')
+ assert_equal(repr(a),"Common_Block_Object(Name('a'), Explicit_Shape_Spec(None, Int_Literal_Constant('2', None)))")
+
+ a = cls('a')
+ assert isinstance(a, Name),`a`
+ assert_equal(str(a),'a')
+
+
+###############################################################################
+############################### SECTION 6 ####################################
+###############################################################################
+
+class test_Substring(NumpyTestCase): # R609
+
+ def check_simple(self):
+ cls = Substring
+ a = cls('a(:)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(:)')
+ assert_equal(repr(a),"Substring(Name('a'), Substring_Range(None, None))")
+
+ a = cls('a(1:2)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a(1 : 2)')
+ assert_equal(repr(a),"Substring(Name('a'), Substring_Range(Int_Literal_Constant('1', None), Int_Literal_Constant('2', None)))")
+
+
+class test_Substring_Range(NumpyTestCase): # R611
+
+ def check_simple(self):
+ cls = Substring_Range
+ a = cls(':')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),':')
+ assert_equal(repr(a),"Substring_Range(None, None)")
+
+ a = cls('a+1:')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a + 1 :')
+
+ a = cls('a+1: c/foo(g)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a + 1 : c / foo(g)')
+
+ a = cls('a:b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a : b')
+ assert_equal(repr(a),"Substring_Range(Name('a'), Name('b'))")
+
+ a = cls('a:')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a :')
+
+ a = cls(':b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),': b')
+
+
+class test_Data_Ref(NumpyTestCase): # R612
+
+ def check_data_ref(self):
+ cls = Data_Ref
+ a = cls('a%b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a % b')
+ assert_equal(repr(a),"Data_Ref('%', (Name('a'), Name('b')))")
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Part_Ref(NumpyTestCase): # R613
+
+ def check_part_ref(self):
+ cls = Part_Ref
+ a = cls('a')
+ assert isinstance(a, Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Type_Param_Inquiry(NumpyTestCase): # R615
+
+ def check_simple(self):
+ cls = Type_Param_Inquiry
+ a = cls('a % b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a % b')
+ assert_equal(repr(a),"Type_Param_Inquiry(Name('a'), '%', Name('b'))")
+
+
+class test_Array_Section(NumpyTestCase): # R617
+
+ def check_array_section(self):
+ cls = Array_Section
+ a = cls('a(:)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a(:)')
+ assert_equal(repr(a),"Array_Section(Name('a'), Substring_Range(None, None))")
+
+ a = cls('a(2:)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a(2 :)')
+
+
+class test_Section_Subscript(NumpyTestCase): # R619
+
+ def check_simple(self):
+ cls = Section_Subscript
+
+ a = cls('1:2')
+ assert isinstance(a, Subscript_Triplet),`a`
+ assert_equal(str(a),'1 : 2')
+
+ a = cls('zzz')
+ assert isinstance(a, Name),`a`
+ assert_equal(str(a),'zzz')
+
+class test_Section_Subscript_List(NumpyTestCase): # R619-list
+
+ def check_simple(self):
+ cls = Section_Subscript_List
+ a = cls('a,2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a, 2')
+ assert_equal(repr(a),"Section_Subscript_List(',', (Name('a'), Int_Literal_Constant('2', None)))")
+
+ a = cls('::1')
+ assert isinstance(a,Subscript_Triplet),`a`
+ assert_equal(str(a),': : 1')
+
+ a = cls('::1, 3')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),': : 1, 3')
+
+class test_Subscript_Triplet(NumpyTestCase): # R620
+
+ def check_simple(self):
+ cls = Subscript_Triplet
+ a = cls('a:b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a : b')
+ assert_equal(repr(a),"Subscript_Triplet(Name('a'), Name('b'), None)")
+
+ a = cls('a:b:1')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a : b : 1')
+
+ a = cls(':')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),':')
+
+ a = cls('::5')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),': : 5')
+
+ a = cls(':5')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),': 5')
+
+ a = cls('a+1 :')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a + 1 :')
+
+class test_Alloc_Opt(NumpyTestCase): # R624
+
+ def check_simple(self):
+ cls = Alloc_Opt
+ a = cls('stat=a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'STAT = a')
+ assert_equal(repr(a),"Alloc_Opt('STAT', Name('a'))")
+
+class test_Nullify_Stmt(NumpyTestCase): # R633
+
+ def check_simple(self):
+ cls = Nullify_Stmt
+ a = cls('nullify (a)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'NULLIFY(a)')
+ assert_equal(repr(a),"Nullify_Stmt('NULLIFY', Name('a'))")
+
+ a = cls('nullify (a,c)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'NULLIFY(a, c)')
+
+###############################################################################
+############################### SECTION 7 ####################################
+###############################################################################
+
+class test_Primary(NumpyTestCase): # R701
+
+ def check_simple(self):
+ cls = Primary
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+ a = cls('(a)')
+ assert isinstance(a,Parenthesis),`a`
+ assert_equal(str(a),'(a)')
+
+ a = cls('1')
+ assert isinstance(a,Int_Literal_Constant),`a`
+ assert_equal(str(a),'1')
+
+ a = cls('1.')
+ assert isinstance(a,Real_Literal_Constant),`a`
+ assert_equal(str(a),'1.')
+
+ a = cls('(1, n)')
+ assert isinstance(a,Complex_Literal_Constant),`a`
+ assert_equal(str(a),'(1, n)')
+
+ a = cls('.true.')
+ assert isinstance(a,Logical_Literal_Constant),`a`
+ assert_equal(str(a),'.TRUE.')
+
+ a = cls('"hey a()c"')
+ assert isinstance(a,Char_Literal_Constant),`a`
+ assert_equal(str(a),'"hey a()c"')
+
+ a = cls('b"0101"')
+ assert isinstance(a,Binary_Constant),`a`
+ assert_equal(str(a),'B"0101"')
+
+ a = cls('o"0107"')
+ assert isinstance(a,Octal_Constant),`a`
+ assert_equal(str(a),'O"0107"')
+
+ a = cls('z"a107"')
+ assert isinstance(a,Hex_Constant),`a`
+ assert_equal(str(a),'Z"A107"')
+
+ a = cls('a % b')
+ assert isinstance(a,Data_Ref),`a`
+ assert_equal(str(a),'a % b')
+
+ a = cls('a(:)')
+ assert isinstance(a,Array_Section),`a`
+ assert_equal(str(a),'a(:)')
+
+ a = cls('0.0E-1')
+ assert isinstance(a,Real_Literal_Constant),`a`
+ assert_equal(str(a),'0.0E-1')
+
+class test_Parenthesis(NumpyTestCase): # R701.h
+
+ def check_simple(self):
+ cls = Parenthesis
+ a = cls('(a)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(a)')
+ assert_equal(repr(a),"Parenthesis('(', Name('a'), ')')")
+
+ a = cls('(a+1)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(a + 1)')
+
+ a = cls('((a))')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'((a))')
+
+ a = cls('(a+(a+c))')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(a + (a + c))')
+
+class test_Level_1_Expr(NumpyTestCase): # R702
+
+ def check_simple(self):
+ cls = Level_1_Expr
+ a = cls('.hey. a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'.HEY. a')
+ assert_equal(repr(a),"Level_1_Expr('.HEY.', Name('a'))")
+
+ self.assertRaises(NoMatchError,cls,'.not. a')
+
+class test_Mult_Operand(NumpyTestCase): # R704
+
+ def check_simple(self):
+ cls = Mult_Operand
+ a = cls('a**b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a ** b')
+ assert_equal(repr(a),"Mult_Operand(Name('a'), '**', Name('b'))")
+
+ a = cls('a**2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a ** 2')
+
+ a = cls('(a+b)**2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'(a + b) ** 2')
+
+ a = cls('0.0E-1')
+ assert isinstance(a,Real_Literal_Constant),`a`
+ assert_equal(str(a),'0.0E-1')
+
+class test_Add_Operand(NumpyTestCase): # R705
+
+ def check_simple(self):
+ cls = Add_Operand
+ a = cls('a*b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a * b')
+ assert_equal(repr(a),"Add_Operand(Name('a'), '*', Name('b'))")
+
+ a = cls('a/b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a / b')
+
+ a = cls('a**b')
+ assert isinstance(a,Mult_Operand),`a`
+ assert_equal(str(a),'a ** b')
+
+ a = cls('0.0E-1')
+ assert isinstance(a,Real_Literal_Constant),`a`
+ assert_equal(str(a),'0.0E-1')
+
+class test_Level_2_Expr(NumpyTestCase): # R706
+
+ def check_simple(self):
+ cls = Level_2_Expr
+ a = cls('a+b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a + b')
+ assert_equal(repr(a),"Level_2_Expr(Name('a'), '+', Name('b'))")
+
+ a = cls('a-b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a - b')
+
+ a = cls('a+b+c')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a + b + c')
+
+ a = cls('+a')
+ assert isinstance(a,Level_2_Unary_Expr),`a`
+ assert_equal(str(a),'+ a')
+
+ a = cls('+1')
+ assert isinstance(a,Level_2_Unary_Expr),`a`
+ assert_equal(str(a),'+ 1')
+
+ a = cls('+a+b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'+ a + b')
+
+ a = cls('0.0E-1')
+ assert isinstance(a,Real_Literal_Constant),`a`
+ assert_equal(str(a),'0.0E-1')
+
+
+class test_Level_2_Unary_Expr(NumpyTestCase):
+
+ def check_simple(self):
+ cls = Level_2_Unary_Expr
+ a = cls('+a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'+ a')
+ assert_equal(repr(a),"Level_2_Unary_Expr('+', Name('a'))")
+
+ a = cls('-a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'- a')
+
+ a = cls('+1')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'+ 1')
+
+ a = cls('0.0E-1')
+ assert isinstance(a,Real_Literal_Constant),`a`
+ assert_equal(str(a),'0.0E-1')
+
+
+class test_Level_3_Expr(NumpyTestCase): # R710
+
+ def check_simple(self):
+ cls = Level_3_Expr
+ a = cls('a//b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a // b')
+ assert_equal(repr(a),"Level_3_Expr(Name('a'), '//', Name('b'))")
+
+ a = cls('"a"//"b"')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'"a" // "b"')
+
+class test_Level_4_Expr(NumpyTestCase): # R712
+
+ def check_simple(self):
+ cls = Level_4_Expr
+ a = cls('a.eq.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .EQ. b')
+ assert_equal(repr(a),"Level_4_Expr(Name('a'), '.EQ.', Name('b'))")
+
+ a = cls('a.ne.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .NE. b')
+
+ a = cls('a.lt.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .LT. b')
+
+ a = cls('a.gt.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .GT. b')
+
+ a = cls('a.ge.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .GE. b')
+
+ a = cls('a==b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a == b')
+
+ a = cls('a/=b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a /= b')
+
+ a = cls('a<b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a < b')
+
+ a = cls('a<=b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a <= b')
+
+ a = cls('a>=b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a >= b')
+
+ a = cls('a>b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a > b')
+
+class test_And_Operand(NumpyTestCase): # R714
+
+ def check_simple(self):
+ cls = And_Operand
+ a = cls('.not.a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'.NOT. a')
+ assert_equal(repr(a),"And_Operand('.NOT.', Name('a'))")
+
+class test_Or_Operand(NumpyTestCase): # R715
+
+ def check_simple(self):
+ cls = Or_Operand
+ a = cls('a.and.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .AND. b')
+ assert_equal(repr(a),"Or_Operand(Name('a'), '.AND.', Name('b'))")
+
+
+class test_Equiv_Operand(NumpyTestCase): # R716
+
+ def check_simple(self):
+ cls = Equiv_Operand
+ a = cls('a.or.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .OR. b')
+ assert_equal(repr(a),"Equiv_Operand(Name('a'), '.OR.', Name('b'))")
+
+
+class test_Level_5_Expr(NumpyTestCase): # R717
+
+ def check_simple(self):
+ cls = Level_5_Expr
+ a = cls('a.eqv.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .EQV. b')
+ assert_equal(repr(a),"Level_5_Expr(Name('a'), '.EQV.', Name('b'))")
+
+ a = cls('a.neqv.b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .NEQV. b')
+
+ a = cls('a.eq.b')
+ assert isinstance(a,Level_4_Expr),`a`
+ assert_equal(str(a),'a .EQ. b')
+
+class test_Expr(NumpyTestCase): # R722
+
+ def check_simple(self):
+ cls = Expr
+ a = cls('a .op. b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a .OP. b')
+ assert_equal(repr(a),"Expr(Name('a'), '.OP.', Name('b'))")
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+ a = cls('3.e2')
+ assert isinstance(a,Real_Literal_Constant),`a`
+
+ a = cls('0.0E-1')
+ assert isinstance(a,Real_Literal_Constant),`a`
+ assert_equal(str(a),'0.0E-1')
+
+ self.assertRaises(NoMatchError,Scalar_Int_Expr,'a,b')
+
+class test_Assignment_Stmt(NumpyTestCase): # R734
+
+ def check_simple(self):
+ cls = Assignment_Stmt
+ a = cls('a = b')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a = b')
+ assert_equal(repr(a),"Assignment_Stmt(Name('a'), '=', Name('b'))")
+
+ a = cls('a(3:4) = b+c')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a(3 : 4) = b + c')
+
+ a = cls('a%c = b+c')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'a % c = b + c')
+
+class test_Proc_Component_Ref(NumpyTestCase): # R741
+
+ def check_proc_component_ref(self):
+ cls = Proc_Component_Ref
+ a = cls('a % b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a % b')
+ assert_equal(repr(a),"Proc_Component_Ref(Name('a'), '%', Name('b'))")
+
+class test_Where_Stmt(NumpyTestCase): # R743
+
+ def check_simple(self):
+ cls = Where_Stmt
+ a = cls('where (a) c=2')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'WHERE (a) c = 2')
+ assert_equal(repr(a),"Where_Stmt(Name('a'), Assignment_Stmt(Name('c'), '=', Int_Literal_Constant('2', None)))")
+
+class test_Where_Construct_Stmt(NumpyTestCase): # R745
+
+ def check_simple(self):
+ cls = Where_Construct_Stmt
+ a = cls('where (a)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'WHERE (a)')
+ assert_equal(repr(a),"Where_Construct_Stmt(Name('a'))")
+
+
+###############################################################################
+############################### SECTION 8 ####################################
+###############################################################################
+
+class test_Continue_Stmt(NumpyTestCase): # R848
+
+ def check_simple(self):
+ cls = Continue_Stmt
+ a = cls('continue')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'CONTINUE')
+ assert_equal(repr(a),"Continue_Stmt('CONTINUE')")
+
+###############################################################################
+############################### SECTION 9 ####################################
+###############################################################################
+
+class test_Io_Unit(NumpyTestCase): # R901
+
+ def check_simple(self):
+ cls = Io_Unit
+ a = cls('*')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'*')
+
+ a = cls('a')
+ assert isinstance(a, Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Write_Stmt(NumpyTestCase): # R911
+
+ def check_simple(self):
+ cls = Write_Stmt
+ a = cls('write (123)"hey"')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'WRITE(UNIT = 123) "hey"')
+ assert_equal(repr(a),'Write_Stmt(Io_Control_Spec_List(\',\', (Io_Control_Spec(\'UNIT\', Int_Literal_Constant(\'123\', None)),)), Char_Literal_Constant(\'"hey"\', None))')
+
+class test_Print_Stmt(NumpyTestCase): # R912
+
+ def check_simple(self):
+ cls = Print_Stmt
+ a = cls('print 123')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PRINT 123')
+ assert_equal(repr(a),"Print_Stmt(Label('123'), None)")
+
+ a = cls('print *,"a=",a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PRINT *, "a=", a')
+
+class test_Io_Control_Spec(NumpyTestCase): # R913
+
+ def check_simple(self):
+ cls = Io_Control_Spec
+ a = cls('end=123')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'END = 123')
+ assert_equal(repr(a),"Io_Control_Spec('END', Label('123'))")
+
+class test_Io_Control_Spec_List(NumpyTestCase): # R913-list
+
+ def check_simple(self):
+ cls = Io_Control_Spec_List
+ a = cls('end=123')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'END = 123')
+ assert_equal(repr(a),"Io_Control_Spec_List(',', (Io_Control_Spec('END', Label('123')),))")
+
+ a = cls('123')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'UNIT = 123')
+
+ a = cls('123,*')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'UNIT = 123, FMT = *')
+
+ a = cls('123,fmt=a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'UNIT = 123, FMT = a')
+
+ if 0:
+ # see todo note in Io_Control_Spec_List
+ a = cls('123,a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'UNIT = 123, NML = a')
+
+class test_Format(NumpyTestCase): # R914
+
+ def check_simple(self):
+ cls = Format
+ a = cls('*')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'*')
+ assert_equal(repr(a),"Format('*')")
+
+ a = cls('a')
+ assert isinstance(a, Name),`a`
+ assert_equal(str(a),'a')
+
+ a = cls('123')
+ assert isinstance(a, Label),`a`
+ assert_equal(str(a),'123')
+
+class test_Wait_Stmt(NumpyTestCase): # R921
+
+ def check_simple(self):
+ cls = Wait_Stmt
+ a = cls('wait (123)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'WAIT(UNIT = 123)')
+
+class test_Wait_Spec(NumpyTestCase): # R922
+
+ def check_simple(self):
+ cls = Wait_Spec
+ a = cls('123')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'UNIT = 123')
+ assert_equal(repr(a),"Wait_Spec('UNIT', Int_Literal_Constant('123', None))")
+
+ a = cls('err=1')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'ERR = 1')
+
+###############################################################################
+############################### SECTION 10 ####################################
+###############################################################################
+
+
+###############################################################################
+############################### SECTION 11 ####################################
+###############################################################################
+
+class test_Use_Stmt(NumpyTestCase): # R1109
+
+ def check_simple(self):
+ cls = Use_Stmt
+ a = cls('use a')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'USE :: a')
+ assert_equal(repr(a),"Use_Stmt(None, Name('a'), '', None)")
+
+ a = cls('use :: a, c=>d')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'USE :: a, c => d')
+
+ a = cls('use :: a, operator(.hey.)=>operator(.hoo.)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'USE :: a, OPERATOR(.HEY.) => OPERATOR(.HOO.)')
+
+ a = cls('use, intrinsic :: a, operator(.hey.)=>operator(.hoo.), c=>g')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'USE, INTRINSIC :: a, OPERATOR(.HEY.) => OPERATOR(.HOO.), c => g')
+
+class test_Module_Nature(NumpyTestCase): # R1110
+
+ def check_simple(self):
+ cls = Module_Nature
+ a = cls('intrinsic')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'INTRINSIC')
+ assert_equal(repr(a),"Module_Nature('INTRINSIC')")
+
+ a = cls('non_intrinsic')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'NON_INTRINSIC')
+
+###############################################################################
+############################### SECTION 12 ####################################
+###############################################################################
+
+class test_Function_Reference(NumpyTestCase): # R1217
+
+ def check_simple(self):
+ cls = Function_Reference
+ a = cls('f()')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'f()')
+ assert_equal(repr(a),"Function_Reference(Name('f'), None)")
+
+ a = cls('f(2,k=1,a)')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'f(2, k = 1, a)')
+
+
+class test_Procedure_Designator(NumpyTestCase): # R1219
+
+ def check_procedure_designator(self):
+ cls = Procedure_Designator
+ a = cls('a%b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a % b')
+ assert_equal(repr(a),"Procedure_Designator(Name('a'), '%', Name('b'))")
+
+class test_Actual_Arg_Spec(NumpyTestCase): # R1220
+
+ def check_simple(self):
+ cls = Actual_Arg_Spec
+ a = cls('k=a')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'k = a')
+ assert_equal(repr(a),"Actual_Arg_Spec(Name('k'), Name('a'))")
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Actual_Arg_Spec_List(NumpyTestCase):
+
+ def check_simple(self):
+ cls = Actual_Arg_Spec_List
+ a = cls('a,b')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'a, b')
+ assert_equal(repr(a),"Actual_Arg_Spec_List(',', (Name('a'), Name('b')))")
+
+ a = cls('a = k')
+ assert isinstance(a,Actual_Arg_Spec),`a`
+ assert_equal(str(a),'a = k')
+
+ a = cls('a = k,b')
+ assert isinstance(a,Actual_Arg_Spec_List),`a`
+ assert_equal(str(a),'a = k, b')
+
+ a = cls('a')
+ assert isinstance(a,Name),`a`
+ assert_equal(str(a),'a')
+
+class test_Alt_Return_Spec(NumpyTestCase): # R1222
+
+ def check_alt_return_spec(self):
+ cls = Alt_Return_Spec
+ a = cls('* 123')
+ assert isinstance(a,cls),`a`
+ assert_equal(str(a),'*123')
+ assert_equal(repr(a),"Alt_Return_Spec(Label('123'))")
+
+class test_Prefix(NumpyTestCase): # R1227
+
+ def check_simple(self):
+ cls = Prefix
+ a = cls('pure recursive')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PURE RECURSIVE')
+ assert_equal(repr(a), "Prefix(' ', (Prefix_Spec('PURE'), Prefix_Spec('RECURSIVE')))")
+
+ a = cls('integer * 2 pure')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'INTEGER*2 PURE')
+
+class test_Prefix_Spec(NumpyTestCase): # R1228
+
+ def check_simple(self):
+ cls = Prefix_Spec
+ a = cls('pure')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PURE')
+ assert_equal(repr(a),"Prefix_Spec('PURE')")
+
+ a = cls('elemental')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'ELEMENTAL')
+
+ a = cls('recursive')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'RECURSIVE')
+
+ a = cls('integer * 2')
+ assert isinstance(a, Intrinsic_Type_Spec),`a`
+ assert_equal(str(a),'INTEGER*2')
+
+class test_Subroutine_Subprogram(NumpyTestCase): # R1231
+
+ def check_simple(self):
+ from api import get_reader
+ reader = get_reader('''\
+ subroutine foo
+ end subroutine foo''')
+ cls = Subroutine_Subprogram
+ a = cls(reader)
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'SUBROUTINE foo\nEND SUBROUTINE foo')
+ assert_equal(repr(a),"Subroutine_Subprogram(Subroutine_Stmt(None, Name('foo'), None, None), End_Subroutine_Stmt('SUBROUTINE', Name('foo')))")
+
+ reader = get_reader('''\
+ subroutine foo
+ integer a
+ end subroutine foo''')
+ cls = Subroutine_Subprogram
+ a = cls(reader)
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'SUBROUTINE foo\n INTEGER :: a\nEND SUBROUTINE foo')
+
+class test_Subroutine_Stmt(NumpyTestCase): # R1232
+
+ def check_simple(self):
+ cls = Subroutine_Stmt
+ a = cls('subroutine foo')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'SUBROUTINE foo')
+ assert_equal(repr(a),"Subroutine_Stmt(None, Name('foo'), None, None)")
+
+ a = cls('pure subroutine foo')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PURE SUBROUTINE foo')
+
+ a = cls('pure subroutine foo(a,b)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'PURE SUBROUTINE foo(a, b)')
+
+ a = cls('subroutine foo() bind(c)')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'SUBROUTINE foo BIND(C)')
+
+class test_End_Subroutine_Stmt(NumpyTestCase): # R1234
+
+ def check_simple(self):
+ cls = End_Subroutine_Stmt
+ a = cls('end subroutine foo')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'END SUBROUTINE foo')
+ assert_equal(repr(a),"End_Subroutine_Stmt('SUBROUTINE', Name('foo'))")
+
+ a = cls('end')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'END SUBROUTINE')
+
+ a = cls('endsubroutine')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'END SUBROUTINE')
+
+class test_Return_Stmt(NumpyTestCase): # R1236
+
+ def check_simple(self):
+ cls = Return_Stmt
+ a = cls('return')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a), 'RETURN')
+ assert_equal(repr(a), 'Return_Stmt(None)')
+
+class test_Contains(NumpyTestCase): # R1237
+
+ def check_simple(self):
+ cls = Contains_Stmt
+ a = cls('Contains')
+ assert isinstance(a, cls),`a`
+ assert_equal(str(a),'CONTAINS')
+ assert_equal(repr(a),"Contains_Stmt('CONTAINS')")
+
+if 1:
+ nof_needed_tests = 0
+ nof_needed_match = 0
+ total_needs = 0
+ total_classes = 0
+ for name in dir():
+ obj = eval(name)
+ if not isinstance(obj, ClassType): continue
+ if not issubclass(obj, Base): continue
+ clsname = obj.__name__
+ if clsname.endswith('Base'): continue
+ total_classes += 1
+ subclass_names = obj.__dict__.get('subclass_names',None)
+ use_names = obj.__dict__.get('use_names',None)
+ if not use_names: continue
+ match = obj.__dict__.get('match',None)
+ try:
+ test_cls = eval('test_%s' % (clsname))
+ except NameError:
+ test_cls = None
+ total_needs += 1
+ if match is None:
+ if test_cls is None:
+ #print 'Needs tests:', clsname
+ print 'Needs match implementation:', clsname
+ nof_needed_tests += 1
+ nof_needed_match += 1
+ else:
+ print 'Needs match implementation:', clsname
+ nof_needed_match += 1
+ else:
+ if test_cls is None:
+ #print 'Needs tests:', clsname
+ nof_needed_tests += 1
+ continue
+ print '-----'
+ print 'Nof match implementation needs:',nof_needed_match,'out of',total_needs
+ print 'Nof tests needs:',nof_needed_tests,'out of',total_needs
+ print 'Total number of classes:',total_classes
+ print '-----'
+
+if __name__ == "__main__":
+ NumpyTest().run()
diff --git a/numpy/f2py/lib/parser/test_parser.py b/numpy/f2py/lib/parser/test_parser.py
new file mode 100644
index 000000000..9f1767a1a
--- /dev/null
+++ b/numpy/f2py/lib/parser/test_parser.py
@@ -0,0 +1,496 @@
+"""
+Test parsing single Fortran lines.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+from numpy.testing import *
+from block_statements import *
+from readfortran import Line, FortranStringReader
+
+
+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__)
+
+class test_Statements(NumpyTestCase):
+
+ def check_assignment(self):
+ assert_equal(parse(Assignment,'a=b'), 'a = b')
+ assert_equal(parse(PointerAssignment,'a=>b'), 'a => b')
+ assert_equal(parse(Assignment,'a (2)=b(n,m)'), 'a(2) = b(n,m)')
+ assert_equal(parse(Assignment,'a % 2(2,4)=b(a(i))'), 'a%2(2,4) = b(a(i))')
+
+ def check_assign(self):
+ assert_equal(parse(Assign,'assign 10 to a'),'ASSIGN 10 TO a')
+
+ def check_call(self):
+ assert_equal(parse(Call,'call a'),'CALL a')
+ assert_equal(parse(Call,'call a()'),'CALL a')
+ assert_equal(parse(Call,'call a(1)'),'CALL a(1)')
+ assert_equal(parse(Call,'call a(1,2)'),'CALL a(1, 2)')
+ assert_equal(parse(Call,'call a % 2 ( n , a+1 )'),'CALL a % 2(n, a+1)')
+
+ def check_goto(self):
+ assert_equal(parse(Goto,'go to 19'),'GO TO 19')
+ assert_equal(parse(Goto,'goto 19'),'GO TO 19')
+ assert_equal(parse(ComputedGoto,'goto (1, 2 ,3) a+b(2)'),
+ 'GO TO (1, 2, 3) a+b(2)')
+ assert_equal(parse(ComputedGoto,'goto (1, 2 ,3) , a+b(2)'),
+ 'GO TO (1, 2, 3) a+b(2)')
+ assert_equal(parse(AssignedGoto,'goto a'),'GO TO a')
+ assert_equal(parse(AssignedGoto,'goto a ( 1 )'),'GO TO a (1)')
+ assert_equal(parse(AssignedGoto,'goto a ( 1 ,2)'),'GO TO a (1, 2)')
+
+ def check_continue(self):
+ assert_equal(parse(Continue,'continue'),'CONTINUE')
+
+ def check_return(self):
+ assert_equal(parse(Return,'return'),'RETURN')
+ assert_equal(parse(Return,'return a'),'RETURN a')
+ assert_equal(parse(Return,'return a+1'),'RETURN a+1')
+ assert_equal(parse(Return,'return a(c, a)'),'RETURN a(c, a)')
+
+ def check_stop(self):
+ assert_equal(parse(Stop,'stop'),'STOP')
+ assert_equal(parse(Stop,'stop 1'),'STOP 1')
+ assert_equal(parse(Stop,'stop "a"'),'STOP "a"')
+ assert_equal(parse(Stop,'stop "a b"'),'STOP "a b"')
+
+ def check_print(self):
+ assert_equal(parse(Print, 'print*'),'PRINT *')
+ assert_equal(parse(Print, 'print "a b( c )"'),'PRINT "a b( c )"')
+ assert_equal(parse(Print, 'print 12, a'),'PRINT 12, a')
+ assert_equal(parse(Print, 'print 12, a , b'),'PRINT 12, a, b')
+ assert_equal(parse(Print, 'print 12, a(c,1) , b'),'PRINT 12, a(c,1), b')
+
+ def check_read(self):
+ assert_equal(parse(Read, 'read ( 10 )'),'READ (10)')
+ assert_equal(parse(Read, 'read ( 10 ) a '),'READ (10) a')
+ assert_equal(parse(Read, 'read ( 10 ) a , b'),'READ (10) a, b')
+ assert_equal(parse(Read, 'read *'),'READ *')
+ assert_equal(parse(Read, 'read 12'),'READ 12')
+ assert_equal(parse(Read, 'read "a b"'),'READ "a b"')
+ assert_equal(parse(Read, 'read "a b",a'),'READ "a b", a')
+ assert_equal(parse(Read, 'read * , a'),'READ *, a')
+ assert_equal(parse(Read, 'read "hey a" , a'),'READ "hey a", a')
+ assert_equal(parse(Read, 'read * , a , b'),'READ *, a, b')
+ assert_equal(parse(Read, 'read ( unit =10 )'),'READ (UNIT = 10)')
+
+ def check_write(self):
+ assert_equal(parse(Write, 'write ( 10 )'),'WRITE (10)')
+ assert_equal(parse(Write, 'write ( 10 , a )'),'WRITE (10, a)')
+ assert_equal(parse(Write, 'write ( 10 ) b'),'WRITE (10) b')
+ assert_equal(parse(Write, 'write ( 10 ) a(1) , b+2'),'WRITE (10) a(1), b+2')
+ assert_equal(parse(Write, 'write ( unit=10 )'),'WRITE (UNIT = 10)')
+
+ def check_flush(self):
+ assert_equal(parse(Flush, 'flush 10'),'FLUSH (10)')
+ assert_equal(parse(Flush, 'flush (10)'),'FLUSH (10)')
+ assert_equal(parse(Flush, 'flush (UNIT = 10)'),'FLUSH (UNIT = 10)')
+ assert_equal(parse(Flush, 'flush (10, err= 23)'),'FLUSH (10, ERR = 23)')
+
+ def check_wait(self):
+ assert_equal(parse(Wait, 'wait(10)'),'WAIT (10)')
+ assert_equal(parse(Wait, 'wait(10,err=129)'),'WAIT (10, ERR = 129)')
+
+ def check_contains(self):
+ assert_equal(parse(Contains, 'contains'),'CONTAINS')
+
+ def check_allocate(self):
+ assert_equal(parse(Allocate, 'allocate (a)'), 'ALLOCATE (a)')
+ assert_equal(parse(Allocate, \
+ 'allocate (a, stat=b)'), 'ALLOCATE (a, STAT = b)')
+ assert_equal(parse(Allocate, 'allocate (a,b(:1))'), 'ALLOCATE (a, b(:1))')
+ assert_equal(parse(Allocate, \
+ 'allocate (real(8)::a)'), 'ALLOCATE (REAL(KIND=8) :: a)')
+ def check_deallocate(self):
+ assert_equal(parse(Deallocate, 'deallocate (a)'), 'DEALLOCATE (a)')
+ assert_equal(parse(Deallocate, 'deallocate (a, stat=b)'), 'DEALLOCATE (a, STAT = b)')
+
+ def check_moduleprocedure(self):
+ assert_equal(parse(ModuleProcedure,\
+ 'ModuleProcedure a'), 'MODULE PROCEDURE a')
+ assert_equal(parse(ModuleProcedure,\
+ 'module procedure a , b'), 'MODULE PROCEDURE a, b')
+
+ def check_access(self):
+ assert_equal(parse(Public,'Public'),'PUBLIC')
+ assert_equal(parse(Public,'public a'),'PUBLIC a')
+ assert_equal(parse(Public,'public :: a'),'PUBLIC a')
+ assert_equal(parse(Public,'public a,b,c'),'PUBLIC a, b, c')
+ assert_equal(parse(Public,'public :: a(:,:)'),'PUBLIC a(:,:)')
+ assert_equal(parse(Private,'private'),'PRIVATE')
+ assert_equal(parse(Private,'private :: a'),'PRIVATE a')
+
+ def check_close(self):
+ assert_equal(parse(Close,'close (12)'),'CLOSE (12)')
+ assert_equal(parse(Close,'close (12, err=99)'),'CLOSE (12, ERR = 99)')
+ assert_equal(parse(Close,'close (12, status = a(1,2))'),'CLOSE (12, STATUS = a(1,2))')
+
+ def check_cycle(self):
+ assert_equal(parse(Cycle,'cycle'),'CYCLE')
+ assert_equal(parse(Cycle,'cycle ab'),'CYCLE ab')
+
+ def check_rewind(self):
+ assert_equal(parse(Rewind,'rewind 1'),'REWIND (1)')
+ assert_equal(parse(Rewind,'rewind (1)'),'REWIND (1)')
+ assert_equal(parse(Rewind,'rewind (1, err = 123)'),'REWIND (1, ERR = 123)')
+
+ def check_backspace(self):
+ assert_equal(parse(Backspace,'backspace 1'),'BACKSPACE (1)')
+ assert_equal(parse(Backspace,'backspace (1)'),'BACKSPACE (1)')
+ assert_equal(parse(Backspace,'backspace (1, err = 123)'),'BACKSPACE (1, ERR = 123)')
+
+ def check_endfile(self):
+ assert_equal(parse(Endfile,'endfile 1'),'ENDFILE (1)')
+ assert_equal(parse(Endfile,'endfile (1)'),'ENDFILE (1)')
+ assert_equal(parse(Endfile,'endfile (1, err = 123)'),'ENDFILE (1, ERR = 123)')
+
+ def check_open(self):
+ assert_equal(parse(Open,'open (1)'),'OPEN (1)')
+ assert_equal(parse(Open,'open (1, err = 123)'),'OPEN (1, ERR = 123)')
+
+ def check_format(self):
+ assert_equal(parse(Format,'1: format ()'),'1: FORMAT ()')
+ assert_equal(parse(Format,'199 format (1)'),'199: FORMAT (1)')
+ assert_equal(parse(Format,'2 format (1 , SS)'),'2: FORMAT (1, ss)')
+
+ def check_save(self):
+ assert_equal(parse(Save,'save'), 'SAVE')
+ assert_equal(parse(Save,'save :: a'), 'SAVE a')
+ assert_equal(parse(Save,'save a,b'), 'SAVE a, b')
+
+ def check_data(self):
+ assert_equal(parse(Data,'data a /b/'), 'DATA a / b /')
+ assert_equal(parse(Data,'data a , c /b/'), 'DATA a, c / b /')
+ assert_equal(parse(Data,'data a /b ,c/'), 'DATA a / b, c /')
+ assert_equal(parse(Data,'data a /b/ c,e /d/'), 'DATA a / b / c, e / d /')
+ assert_equal(parse(Data,'data a(1,2) /b/'), 'DATA a(1,2) / b /')
+ assert_equal(parse(Data,'data a /b, c(1)/'), 'DATA a / b, c(1) /')
+
+ def check_nullify(self):
+ assert_equal(parse(Nullify,'nullify(a)'),'NULLIFY (a)')
+ assert_equal(parse(Nullify,'nullify(a ,b)'),'NULLIFY (a, b)')
+
+ def check_use(self):
+ assert_equal(parse(Use, 'use a'), 'USE a')
+ assert_equal(parse(Use, 'use :: a'), 'USE a')
+ assert_equal(parse(Use, 'use, intrinsic:: a'), 'USE INTRINSIC :: a')
+ assert_equal(parse(Use, 'use :: a ,only: b'), 'USE a, ONLY: b')
+ assert_equal(parse(Use, 'use :: a , only: b=>c'), 'USE a, ONLY: b=>c')
+ assert_equal(parse(Use, 'use :: a , b=>c'), 'USE a, b=>c')
+ assert_equal(parse(Use,\
+ 'use :: a , only: operator(+) , b'),\
+ 'USE a, ONLY: operator(+), b')
+
+ def check_exit(self):
+ assert_equal(parse(Exit,'exit'),'EXIT')
+ assert_equal(parse(Exit,'exit ab'),'EXIT ab')
+
+ def check_parameter(self):
+ assert_equal(parse(Parameter,'parameter (a = b(1,2))'),
+ 'PARAMETER (a = b(1,2))')
+ assert_equal(parse(Parameter,'parameter (a = b(1,2) , b=1)'),
+ 'PARAMETER (a = b(1,2), b=1)')
+
+ def check_equivalence(self):
+ assert_equal(parse(Equivalence,'equivalence (a , b)'),'EQUIVALENCE (a, b)')
+ assert_equal(parse(Equivalence,'equivalence (a , b) , ( c, d(1) , g )'),
+ 'EQUIVALENCE (a, b), (c, d(1), g)')
+
+ def check_dimension(self):
+ assert_equal(parse(Dimension,'dimension a(b)'),'DIMENSION a(b)')
+ assert_equal(parse(Dimension,'dimension::a(b)'),'DIMENSION a(b)')
+ assert_equal(parse(Dimension,'dimension a(b) , c(d)'),'DIMENSION a(b), c(d)')
+ assert_equal(parse(Dimension,'dimension a(b,c)'),'DIMENSION a(b,c)')
+
+ def check_target(self):
+ assert_equal(parse(Target,'target a(b)'),'TARGET a(b)')
+ assert_equal(parse(Target,'target::a(b)'),'TARGET a(b)')
+ assert_equal(parse(Target,'target a(b) , c(d)'),'TARGET a(b), c(d)')
+ assert_equal(parse(Target,'target a(b,c)'),'TARGET a(b,c)')
+
+ def check_pointer(self):
+ assert_equal(parse(Pointer,'pointer a=b'),'POINTER a=b')
+ assert_equal(parse(Pointer,'pointer :: a=b'),'POINTER a=b')
+ assert_equal(parse(Pointer,'pointer a=b, c=d(1,2)'),'POINTER a=b, c=d(1,2)')
+
+ def check_protected(self):
+ assert_equal(parse(Protected,'protected a'),'PROTECTED a')
+ assert_equal(parse(Protected,'protected::a'),'PROTECTED a')
+ assert_equal(parse(Protected,'protected a , b'),'PROTECTED a, b')
+
+ def check_volatile(self):
+ assert_equal(parse(Volatile,'volatile a'),'VOLATILE a')
+ assert_equal(parse(Volatile,'volatile::a'),'VOLATILE a')
+ assert_equal(parse(Volatile,'volatile a , b'),'VOLATILE a, b')
+
+ def check_value(self):
+ assert_equal(parse(Value,'value a'),'VALUE a')
+ assert_equal(parse(Value,'value::a'),'VALUE a')
+ assert_equal(parse(Value,'value a , b'),'VALUE a, b')
+
+ def check_arithmeticif(self):
+ assert_equal(parse(ArithmeticIf,'if (a) 1,2,3'),'IF (a) 1, 2, 3')
+ assert_equal(parse(ArithmeticIf,'if (a(1)) 1,2,3'),'IF (a(1)) 1, 2, 3')
+ assert_equal(parse(ArithmeticIf,'if (a(1,2)) 1,2,3'),'IF (a(1,2)) 1, 2, 3')
+
+ def check_intrinsic(self):
+ assert_equal(parse(Intrinsic,'intrinsic a'),'INTRINSIC a')
+ assert_equal(parse(Intrinsic,'intrinsic::a'),'INTRINSIC a')
+ assert_equal(parse(Intrinsic,'intrinsic a , b'),'INTRINSIC a, b')
+
+ def check_inquire(self):
+ assert_equal(parse(Inquire, 'inquire (1)'),'INQUIRE (1)')
+ assert_equal(parse(Inquire, 'inquire (1, err=123)'),'INQUIRE (1, ERR = 123)')
+ assert_equal(parse(Inquire, 'inquire (iolength=a) b'),'INQUIRE (IOLENGTH = a) b')
+ assert_equal(parse(Inquire, 'inquire (iolength=a) b ,c(1,2)'),
+ 'INQUIRE (IOLENGTH = a) b, c(1,2)')
+
+ def check_sequence(self):
+ assert_equal(parse(Sequence, 'sequence'),'SEQUENCE')
+
+ def check_external(self):
+ assert_equal(parse(External,'external a'),'EXTERNAL a')
+ assert_equal(parse(External,'external::a'),'EXTERNAL a')
+ assert_equal(parse(External,'external a , b'),'EXTERNAL a, b')
+
+ def check_common(self):
+ assert_equal(parse(Common, 'common a'),'COMMON a')
+ assert_equal(parse(Common, 'common a , b'),'COMMON a, b')
+ assert_equal(parse(Common, 'common a , b(1,2)'),'COMMON a, b(1,2)')
+ assert_equal(parse(Common, 'common // a'),'COMMON a')
+ assert_equal(parse(Common, 'common / name/ a'),'COMMON / name / a')
+ assert_equal(parse(Common, 'common / name/ a , c'),'COMMON / name / a, c')
+ assert_equal(parse(Common, 'common / name/ a /foo/ c(1) ,d'),
+ 'COMMON / name / a / foo / c(1), d')
+ assert_equal(parse(Common, 'common / name/ a, /foo/ c(1) ,d'),
+ 'COMMON / name / a / foo / c(1), d')
+
+ def check_optional(self):
+ assert_equal(parse(Optional,'optional a'),'OPTIONAL a')
+ assert_equal(parse(Optional,'optional::a'),'OPTIONAL a')
+ assert_equal(parse(Optional,'optional a , b'),'OPTIONAL a, b')
+
+ def check_intent(self):
+ assert_equal(parse(Intent,'intent (in) a'),'INTENT (IN) a')
+ assert_equal(parse(Intent,'intent(in)::a'),'INTENT (IN) a')
+ assert_equal(parse(Intent,'intent(in) a , b'),'INTENT (IN) a, b')
+ assert_equal(parse(Intent,'intent (in, out) a'),'INTENT (IN, OUT) a')
+
+ def check_entry(self):
+ assert_equal(parse(Entry,'entry a'), 'ENTRY a')
+ assert_equal(parse(Entry,'entry a()'), 'ENTRY a')
+ assert_equal(parse(Entry,'entry a(b)'), 'ENTRY a (b)')
+ assert_equal(parse(Entry,'entry a(b,*)'), 'ENTRY a (b, *)')
+ assert_equal(parse(Entry,'entry a bind(c , name="a b")'),
+ 'ENTRY a BIND (C, NAME = "a b")')
+ assert_equal(parse(Entry,'entry a result (b)'), 'ENTRY a RESULT (b)')
+ assert_equal(parse(Entry,'entry a bind(d) result (b)'),
+ 'ENTRY a RESULT (b) BIND (D)')
+ assert_equal(parse(Entry,'entry a result (b) bind( c )'),
+ 'ENTRY a RESULT (b) BIND (C)')
+ assert_equal(parse(Entry,'entry a(b,*) result (g)'),
+ 'ENTRY a (b, *) RESULT (g)')
+
+ def check_import(self):
+ assert_equal(parse(Import,'import'),'IMPORT')
+ assert_equal(parse(Import,'import a'),'IMPORT a')
+ assert_equal(parse(Import,'import::a'),'IMPORT a')
+ assert_equal(parse(Import,'import a , b'),'IMPORT a, b')
+
+ def check_forall(self):
+ assert_equal(parse(ForallStmt,'forall (i = 1:n(k,:) : 2) a(i) = i*i*b(i)'),
+ 'FORALL (i = 1 : n(k,:) : 2) a(i) = i*i*b(i)')
+ assert_equal(parse(ForallStmt,'forall (i=1:n,j=2:3) a(i) = b(i,i)'),
+ 'FORALL (i = 1 : n, j = 2 : 3) a(i) = b(i,i)')
+ assert_equal(parse(ForallStmt,'forall (i=1:n,j=2:3, 1+a(1,2)) a(i) = b(i,i)'),
+ 'FORALL (i = 1 : n, j = 2 : 3, 1+a(1,2)) a(i) = b(i,i)')
+
+ def check_specificbinding(self):
+ assert_equal(parse(SpecificBinding,'procedure a'),'PROCEDURE a')
+ assert_equal(parse(SpecificBinding,'procedure :: a'),'PROCEDURE a')
+ assert_equal(parse(SpecificBinding,'procedure , NOPASS :: a'),'PROCEDURE , NOPASS :: a')
+ assert_equal(parse(SpecificBinding,'procedure , public, pass(x ) :: a'),'PROCEDURE , PUBLIC, PASS (x) :: a')
+ assert_equal(parse(SpecificBinding,'procedure(n) a'),'PROCEDURE (n) a')
+ assert_equal(parse(SpecificBinding,'procedure(n),pass :: a'),
+ 'PROCEDURE (n) , PASS :: a')
+ assert_equal(parse(SpecificBinding,'procedure(n) :: a'),
+ 'PROCEDURE (n) a')
+ assert_equal(parse(SpecificBinding,'procedure a= >b'),'PROCEDURE a => b')
+ assert_equal(parse(SpecificBinding,'procedure(n),pass :: a =>c'),
+ 'PROCEDURE (n) , PASS :: a => c')
+
+ def check_genericbinding(self):
+ assert_equal(parse(GenericBinding,'generic :: a=>b'),'GENERIC :: a => b')
+ assert_equal(parse(GenericBinding,'generic, public :: a=>b'),'GENERIC, PUBLIC :: a => b')
+ assert_equal(parse(GenericBinding,'generic, public :: a(1,2)=>b ,c'),
+ 'GENERIC, PUBLIC :: a(1,2) => b, c')
+
+ def check_finalbinding(self):
+ assert_equal(parse(FinalBinding,'final a'),'FINAL a')
+ assert_equal(parse(FinalBinding,'final::a'),'FINAL a')
+ assert_equal(parse(FinalBinding,'final a , b'),'FINAL a, b')
+
+ def check_allocatable(self):
+ assert_equal(parse(Allocatable,'allocatable a'),'ALLOCATABLE a')
+ assert_equal(parse(Allocatable,'allocatable :: a'),'ALLOCATABLE a')
+ assert_equal(parse(Allocatable,'allocatable a (1,2)'),'ALLOCATABLE a (1,2)')
+ assert_equal(parse(Allocatable,'allocatable a (1,2) ,b'),'ALLOCATABLE a (1,2), b')
+
+ def check_asynchronous(self):
+ assert_equal(parse(Asynchronous,'asynchronous a'),'ASYNCHRONOUS a')
+ assert_equal(parse(Asynchronous,'asynchronous::a'),'ASYNCHRONOUS a')
+ assert_equal(parse(Asynchronous,'asynchronous a , b'),'ASYNCHRONOUS a, b')
+
+ def check_bind(self):
+ assert_equal(parse(Bind,'bind(c) a'),'BIND (C) a')
+ assert_equal(parse(Bind,'bind(c) :: a'),'BIND (C) a')
+ assert_equal(parse(Bind,'bind(c) a ,b'),'BIND (C) a, b')
+ assert_equal(parse(Bind,'bind(c) /a/'),'BIND (C) / a /')
+ assert_equal(parse(Bind,'bind(c) /a/ ,b'),'BIND (C) / a /, b')
+ assert_equal(parse(Bind,'bind(c,name="hey") a'),'BIND (C, NAME = "hey") a')
+
+ def check_else(self):
+ assert_equal(parse(Else,'else'),'ELSE')
+ assert_equal(parse(ElseIf,'else if (a) then'),'ELSE IF (a) THEN')
+ assert_equal(parse(ElseIf,'else if (a.eq.b(1,2)) then'),
+ 'ELSE IF (a.eq.b(1,2)) THEN')
+
+ def check_case(self):
+ assert_equal(parse(Case,'case (1)'),'CASE ( 1 )')
+ assert_equal(parse(Case,'case (1:)'),'CASE ( 1 : )')
+ assert_equal(parse(Case,'case (:1)'),'CASE ( : 1 )')
+ assert_equal(parse(Case,'case (1:2)'),'CASE ( 1 : 2 )')
+ assert_equal(parse(Case,'case (a(1,2))'),'CASE ( a(1,2) )')
+ assert_equal(parse(Case,'case ("ab")'),'CASE ( "ab" )')
+ assert_equal(parse(Case,'case default'),'CASE DEFAULT')
+ assert_equal(parse(Case,'case (1:2 ,3:4)'),'CASE ( 1 : 2, 3 : 4 )')
+ assert_equal(parse(Case,'case (a(1,:):)'),'CASE ( a(1,:) : )')
+ assert_equal(parse(Case,'case default'),'CASE DEFAULT')
+
+ def check_where(self):
+ assert_equal(parse(WhereStmt,'where (1) a=1'),'WHERE ( 1 ) a = 1')
+ assert_equal(parse(WhereStmt,'where (a(1,2)) a=1'),'WHERE ( a(1,2) ) a = 1')
+
+ def check_elsewhere(self):
+ assert_equal(parse(ElseWhere,'else where'),'ELSE WHERE')
+ assert_equal(parse(ElseWhere,'elsewhere (1)'),'ELSE WHERE ( 1 )')
+ assert_equal(parse(ElseWhere,'elsewhere(a(1,2))'),'ELSE WHERE ( a(1,2) )')
+
+ def check_enumerator(self):
+ assert_equal(parse(Enumerator,'enumerator a'), 'ENUMERATOR a')
+ assert_equal(parse(Enumerator,'enumerator:: a'), 'ENUMERATOR a')
+ assert_equal(parse(Enumerator,'enumerator a,b'), 'ENUMERATOR a, b')
+ assert_equal(parse(Enumerator,'enumerator a=1'), 'ENUMERATOR a=1')
+ assert_equal(parse(Enumerator,'enumerator a=1 , b=c(1,2)'), 'ENUMERATOR a=1, b=c(1,2)')
+
+ def check_fortranname(self):
+ assert_equal(parse(FortranName,'fortranname a'),'FORTRANNAME a')
+
+ def check_threadsafe(self):
+ assert_equal(parse(Threadsafe,'threadsafe'),'THREADSAFE')
+
+ def check_depend(self):
+ assert_equal(parse(Depend,'depend( a) b'), 'DEPEND ( a ) b')
+ assert_equal(parse(Depend,'depend( a) ::b'), 'DEPEND ( a ) b')
+ assert_equal(parse(Depend,'depend( a,c) b,e'), 'DEPEND ( a, c ) b, e')
+
+ def check_check(self):
+ assert_equal(parse(Check,'check(1) a'), 'CHECK ( 1 ) a')
+ assert_equal(parse(Check,'check(1) :: a'), 'CHECK ( 1 ) a')
+ assert_equal(parse(Check,'check(b(1,2)) a'), 'CHECK ( b(1,2) ) a')
+ assert_equal(parse(Check,'check(a>1) :: a'), 'CHECK ( a>1 ) a')
+
+ def check_callstatement(self):
+ assert_equal(parse(CallStatement,'callstatement (*func)()',isstrict=1),
+ 'CALLSTATEMENT (*func)()')
+ assert_equal(parse(CallStatement,'callstatement i=1;(*func)()',isstrict=1),
+ 'CALLSTATEMENT i=1;(*func)()')
+
+ def check_callprotoargument(self):
+ assert_equal(parse(CallProtoArgument,'callprotoargument int(*), double'),
+ 'CALLPROTOARGUMENT int(*), double')
+
+ def check_pause(self):
+ assert_equal(parse(Pause,'pause'),'PAUSE')
+ assert_equal(parse(Pause,'pause 1'),'PAUSE 1')
+ assert_equal(parse(Pause,'pause "hey"'),'PAUSE "hey"')
+ assert_equal(parse(Pause,'pause "hey pa"'),'PAUSE "hey pa"')
+
+ def check_integer(self):
+ assert_equal(parse(Integer,'integer'),'INTEGER')
+ assert_equal(parse(Integer,'integer*4'),'INTEGER*4')
+ assert_equal(parse(Integer,'integer*4 a'),'INTEGER*4 a')
+ assert_equal(parse(Integer,'integer*4, a'),'INTEGER*4 a')
+ assert_equal(parse(Integer,'integer*4 a ,b'),'INTEGER*4 a, b')
+ assert_equal(parse(Integer,'integer*4 :: a ,b'),'INTEGER*4 a, b')
+ assert_equal(parse(Integer,'integer*4 a(1,2)'),'INTEGER*4 a(1,2)')
+ assert_equal(parse(Integer,'integer*4 :: a(1,2),b'),'INTEGER*4 a(1,2), b')
+ assert_equal(parse(Integer,'integer*4 external :: a'),
+ 'INTEGER*4, external :: a')
+ assert_equal(parse(Integer,'integer*4, external :: a'),
+ 'INTEGER*4, external :: a')
+ assert_equal(parse(Integer,'integer*4 external , intent(in) :: a'),
+ 'INTEGER*4, external, intent(in) :: a')
+ assert_equal(parse(Integer,'integer(kind=4)'),'INTEGER(KIND=4)')
+ assert_equal(parse(Integer,'integer ( kind = 4)'),'INTEGER(KIND=4)')
+ assert_equal(parse(Integer,'integer(kind=2+2)'),'INTEGER(KIND=2+2)')
+ assert_equal(parse(Integer,'integer(kind=f(4,5))'),'INTEGER(KIND=f(4,5))')
+
+ def check_character(self):
+ assert_equal(parse(Character,'character'),'CHARACTER')
+ assert_equal(parse(Character,'character*2'),'CHARACTER(LEN=2)')
+ assert_equal(parse(Character,'character**'),'CHARACTER(LEN=*)')
+ assert_equal(parse(Character,'character*(2)'),'CHARACTER(LEN=2)')
+ assert_equal(parse(Character,'character*(len =2)'),'CHARACTER(LEN=2)')
+ assert_equal(parse(Character,'character*(len =2),'),'CHARACTER(LEN=2)')
+ assert_equal(parse(Character,'character*(len =:)'),'CHARACTER(LEN=:)')
+ assert_equal(parse(Character,'character(len =2)'),'CHARACTER(LEN=2)')
+ assert_equal(parse(Character,'character(2)'),'CHARACTER(LEN=2)')
+ assert_equal(parse(Character,'character(kind=2)'),'CHARACTER(KIND=2)')
+ assert_equal(parse(Character,'character(kind=2,len=3)'),
+ 'CHARACTER(LEN=3, KIND=2)')
+ assert_equal(parse(Character,'character(lEN=3,kind=2)'),
+ 'CHARACTER(LEN=3, KIND=2)')
+ assert_equal(parse(Character,'character(len=3,kind=2)', isstrict=True),
+ 'CHARACTER(LEN=3, KIND=2)')
+ assert_equal(parse(Character,'chaRACTER(len=3,kind=fA(1,2))', isstrict=True),
+ 'CHARACTER(LEN=3, KIND=fA(1,2))')
+ assert_equal(parse(Character,'character(len=3,kind=fA(1,2))'),
+ 'CHARACTER(LEN=3, KIND=fa(1,2))')
+
+ def check_implicit(self):
+ assert_equal(parse(Implicit,'implicit none'),'IMPLICIT NONE')
+ assert_equal(parse(Implicit,'implicit'),'IMPLICIT NONE')
+ assert_equal(parse(Implicit,'implicit integer (i-m)'),
+ 'IMPLICIT INTEGER ( i-m )')
+ assert_equal(parse(Implicit,'implicit integer (i-m,p,q-r)'),
+ 'IMPLICIT INTEGER ( i-m, p, q-r )')
+ assert_equal(parse(Implicit,'implicit integer (i-m), real (z)'),
+ 'IMPLICIT INTEGER ( i-m ), REAL ( z )')
+
+if __name__ == "__main__":
+ NumpyTest().run()
diff --git a/numpy/f2py/lib/parser/typedecl_statements.py b/numpy/f2py/lib/parser/typedecl_statements.py
new file mode 100644
index 000000000..7414a6d2d
--- /dev/null
+++ b/numpy/f2py/lib/parser/typedecl_statements.py
@@ -0,0 +1,563 @@
+"""
+Fortran type declaration statements.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['Integer', 'Real', 'DoublePrecision', 'Complex', 'DoubleComplex',
+ 'Character', 'Logical', 'Byte', 'TypeStmt','Class',
+ 'intrinsic_type_spec', 'declaration_type_spec',
+ 'Implicit']
+
+import re
+import string
+from base_classes import Statement, BeginStatement, EndStatement,\
+ AttributeHolder, Variable
+from utils import split_comma, AnalyzeError, name_re, is_entity_decl, is_name, CHAR_BIT, parse_array_spec
+
+# Intrinsic type specification statements
+
+class TypeDeclarationStatement(Statement):
+ """
+ <declaration-type-spec> [ [, <attr-spec>] :: ] <entity-decl-list>
+ <declaration-type-spec> = <intrinsic-type-spec>
+ | TYPE ( <derived-type-spec> )
+ | CLASS ( <derived-type-spec> )
+ | CLASS ( * )
+
+ <derived-type-spec> = <type-name> [ ( <type-param-spec-list> ) ]
+ <type-param-spec> = [ <keyword> = ] <type-param-value>
+ <type-param-value> = <scalar-int-expr> | * | :
+
+ <intrinsic-type-spec> = INTEGER [<kind-selector>]
+ | REAL [<kind-selector>]
+ | DOUBLE PRECISION
+ | COMPLEX [<kind-selector>]
+ | CHARACTER [<char-selector>]
+ | LOGICAL [<kind-selector>]
+
+ <kind-selector> = ( [ KIND = ] <scalar-int-initialization-expr> )
+ EXTENSION:
+ <kind-selector> = ( [ KIND = ] <scalar-int-initialization-expr> )
+ | * <length>
+
+ <char-selector> = <length-selector>
+ | ( LEN = <type-param-value>, KIND = <scalar-int-initialization-expr> )
+ | ( <type-param-value>, [ KIND = ] <scalar-int-initialization-expr> )
+ | ( KIND = <scalar-int-initialization-expr> [, LEN = <type-param-value>] )
+ <length-selector> = ( [ LEN = ] <type-param-value> )
+ | * <char-length> [ , ]
+ <char-length> = ( <type-param-value> ) | <scalar-int-literal-constant>
+
+ <attr-spec> = <access-spec> | ALLOCATABLE | ASYNCHRONOUS
+ | DIMENSION ( <array-spec> ) | EXTERNAL
+ | INTENT ( <intent-spec> ) | INTRINSIC
+ | <language-binding-spec> | OPTIONAL
+ | PARAMETER | POINTER | PROTECTED | SAVE
+ | TARGET | VALUE | VOLATILE
+ <entity-decl> = <object-name> [ ( <array-spec> ) ] [ * <char-length> ] [ <initialization> ]
+ | <function-name> [ * <char-length> ]
+ <initialization> = = <initialization-expr>
+ | => NULL
+ <access-spec> = PUBLIC | PRIVATE
+ <language-binding-spec> = BIND ( C [ , NAME = <scalar-char-initialization-expr>] )
+ <array-spec> = <explicit-shape-spec-list>
+ | <assumed-shape-spec-list>
+ | <deferred-shape-spec-list>
+ | <assumed-size-spec>
+ <explicit-shape-spec> = [ <lower-bound> : ] <upper-bound>
+ <assumed-shape-spec> = [ <lower-bound> ] :
+ <deferred-shape-spec> = :
+ <assumed-size-spec> = [ <explicit-shape-spec-list> , ] [ <lower-bound> : ] *
+ <bound> = <specification-expr>
+
+ <int-literal-constant> = <digit-string> [ _ <kind-param> ]
+ <digit-string> = <digit> [ <digit> ]..
+ <kind-param> = <digit-string> | <scalar-int-constant-name>
+ """
+ _repr_attr_names = ['selector','attrspec','entity_decls'] + Statement._repr_attr_names
+
+ def process_item(self):
+ item = self.item
+ apply_map = item.apply_map
+ clsname = self.__class__.__name__.lower()
+ line = item.get_line()
+ from block_statements import Function
+
+ if not line.lower().startswith(clsname):
+ i = 0
+ j = 0
+ for c in line:
+ i += 1
+ if c==' ': continue
+ j += 1
+ if j==len(clsname):
+ break
+ line = line[:i].replace(' ','') + line[i:]
+
+ assert line.lower().startswith(clsname),`line,clsname`
+ line = line[len(clsname):].lstrip()
+
+ if line.startswith('('):
+ i = line.find(')')
+ selector = apply_map(line[:i+1].strip())
+ line = line[i+1:].lstrip()
+ elif line.startswith('*'):
+ selector = '*'
+ line = line[1:].lstrip()
+ if line.startswith('('):
+ i = line.find(')')
+ selector += apply_map(line[:i+1].rstrip())
+ line = line[i+1:].lstrip()
+ else:
+ m = re.match(r'\d+(_\w+|)|[*]',line)
+ if not m:
+ self.isvalid = False
+ return
+ i = m.end()
+ selector += line[:i].rstrip()
+ line = line[i:].lstrip()
+ else:
+ selector = ''
+
+ fm = Function.match(line)
+ if fm:
+ l2 = line[:fm.end()]
+ m2 = re.match(r'.*?\b(?P<name>\w+)\Z',l2)
+ if not m2:
+ self.isvalid = False
+ return
+ fname = m2.group('name')
+ fitem = item.copy(clsname+selector+' :: '+fname,
+ apply_map=True)
+ self.parent.put_item(fitem)
+ item.clone(line)
+ self.isvalid = False
+ return
+
+ if line.startswith(','):
+ line = line[1:].lstrip()
+
+ self.raw_selector = selector
+ if isinstance(self, Character):
+ self.selector = self._parse_char_selector(selector)
+ else:
+ self.selector = self._parse_kind_selector(selector)
+
+ i = line.find('::')
+ if i==-1:
+ self.attrspec = []
+ self.entity_decls = split_comma(line, self.item)
+ else:
+ self.attrspec = split_comma(line[:i].rstrip(), self.item)
+ self.entity_decls = split_comma(line[i+2:].lstrip(), self.item)
+ for entity in self.entity_decls:
+ if not is_entity_decl(entity):
+ self.isvalid = False
+ return
+
+ if isinstance(self.parent, Function) \
+ and self.parent.name in self.entity_decls:
+ assert self.parent.typedecl is None,`self.parent.typedecl`
+ self.parent.typedecl = self
+ self.ignore = True
+ if isinstance(self, Type):
+ self.name = self.selector[1].lower()
+ assert is_name(self.name),`self.name`
+ else:
+ self.name = clsname
+ return
+
+ def _parse_kind_selector(self, selector):
+ if not selector:
+ return '',''
+ length,kind = '',''
+ if selector.startswith('*'):
+ length = selector[1:].lstrip()
+ else:
+ assert selector[0]+selector[-1]=='()',`selector`
+ l = selector[1:-1].strip()
+ if l.lower().startswith('kind'):
+ l = l[4:].lstrip()
+ assert l.startswith('='),`l`
+ kind = l[1:].lstrip()
+ else:
+ kind = l
+ return length,kind
+
+ def _parse_char_selector(self, selector):
+ if not selector:
+ return '',''
+ if selector.startswith('*'):
+ l = selector[1:].lstrip()
+ if l.startswith('('):
+ if l.endswith(','): l = l[:-1].rstrip()
+ assert l.endswith(')'),`l`
+ l = l[1:-1].strip()
+ if l.lower().startswith('len'):
+ l = l[3:].lstrip()[1:].lstrip()
+ kind=''
+ else:
+ assert selector[0]+selector[-1]=='()',`selector`
+ l = split_comma(selector[1:-1].strip(), self.item)
+ if len(l)==1:
+ l = l[0]
+ if l.lower().startswith('len'):
+ l=l[3:].lstrip()
+ assert l.startswith('='),`l`
+ l=l[1:].lstrip()
+ kind = ''
+ elif l.lower().startswith('kind'):
+ kind = l[4:].lstrip()[1:].lstrip()
+ l = ''
+ else:
+ kind = ''
+ else:
+ assert len(l)==2
+ if l[0].lower().startswith('len'):
+ assert l[1].lower().startswith('kind'),`l`
+ kind = l[1][4:].lstrip()[1:].lstrip()
+ l = l[0][3:].lstrip()[1:].lstrip()
+ elif l[0].lower().startswith('kind'):
+ assert l[1].lower().startswith('len'),`l`
+ kind = l[0][4:].lstrip()[1:].lstrip()
+ l = l[1][3:].lstrip()[1:].lstrip()
+ else:
+ if l[1].lower().startswith('kind'):
+ kind = l[1][4:].lstrip()[1:].lstrip()
+ l = l[0]
+ else:
+ kind = l[1]
+ l = l[0]
+ return l,kind
+
+ def tostr(self):
+ clsname = self.__class__.__name__.upper()
+ s = ''
+ length, kind = self.selector
+ if isinstance(self, Character):
+ if length and kind:
+ s += '(LEN=%s, KIND=%s)' % (length,kind)
+ elif length:
+ s += '(LEN=%s)' % (length)
+ elif kind:
+ s += '(KIND=%s)' % (kind)
+ else:
+ if isinstance(self, Type):
+ s += '(%s)' % (kind)
+ else:
+ if length:
+ s += '*%s' % (length)
+ if kind:
+ s += '(KIND=%s)' % (kind)
+
+ return clsname + s
+
+ def tofortran(self,isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ s = self.tostr()
+ if self.attrspec:
+ s += ', ' + ', '.join(self.attrspec)
+ if self.entity_decls:
+ s += ' ::'
+ if self.entity_decls:
+ s += ' ' + ', '.join(self.entity_decls)
+ return tab + s
+
+ def __str__(self):
+ return self.tofortran()
+
+ def __eq__(self, other):
+ if self.__class__ is not other.__class__:
+ return False
+ return self.selector==other.selector
+
+ def astypedecl(self):
+ if self.entity_decls or self.attrspec:
+ return self.__class__(self.parent, self.item.copy(self.tostr()))
+ return self
+
+ def analyze(self):
+ if not self.entity_decls:
+ return
+ variables = self.parent.a.variables
+ typedecl = self.astypedecl()
+ attrspec = self.attrspec[:]
+ try:
+ access_spec = [a for a in attrspec if a.lower() in ['private','public']][0]
+ attrspec.remove(access_spec)
+ except IndexError:
+ access_spec = None
+ for item in self.entity_decls:
+ name, array_spec, char_length, value = self._parse_entity(item)
+ var = self.parent.get_variable(name)
+ var.add_parent(self)
+ if char_length:
+ var.set_length(char_length)
+ else:
+ var.set_type(typedecl)
+ var.update(self.attrspec)
+ if array_spec:
+ var.set_bounds(array_spec)
+ if value:
+ var.set_init(value)
+ if access_spec is not None:
+ l = getattr(self.parent.a,access_spec.lower() + '_id_list')
+ l.append(name)
+ var.analyze()
+ return
+
+ def _parse_entity(self, line):
+ m = name_re(line)
+ assert m,`line,self.item,self.__class__.__name__`
+ name = line[:m.end()]
+ line = line[m.end():].lstrip()
+ array_spec = None
+ item = self.item.copy(line)
+ line = item.get_line()
+ if line.startswith('('):
+ i = line.find(')')
+ assert i!=-1,`line`
+ array_spec = parse_array_spec(line[1:i].strip(), item)
+ line = line[i+1:].lstrip()
+ char_length = None
+ if line.startswith('*'):
+ i = line.find('=')
+ if i==-1:
+ char_length = item.apply_map(line[1:].lstrip())
+ line = ''
+ else:
+ char_length = item.apply_map(line[1:i].strip())
+ line = line[i:]
+ value = None
+ if line.startswith('='):
+ value = item.apply_map(line[1:].lstrip())
+ return name, array_spec, char_length, value
+
+ def get_zero_value(self):
+ raise NotImplementedError,`self.__class__.__name__`
+
+ def assign_expression(self, name, value):
+ return '%s = %s' % (name, value)
+
+ def get_kind(self):
+ return self.selector[1] or self.default_kind
+
+ def get_length(self):
+ return self.selector[0] or 1
+
+ def get_byte_size(self):
+ length, kind = self.selector
+ if length: return int(length)
+ if kind: return int(kind)
+ return self.default_kind
+
+ def get_bit_size(self):
+ return CHAR_BIT * int(self.get_byte_size())
+
+ def is_intrinsic(self): return not isinstance(self,(Type,Class))
+ def is_derived(self): return isinstance(self,Type)
+
+ def is_numeric(self): return isinstance(self,(Integer,Real, DoublePrecision,Complex,DoubleComplex,Byte))
+ def is_nonnumeric(self): return isinstance(self,(Character,Logical))
+
+
+class Integer(TypeDeclarationStatement):
+ match = re.compile(r'integer\b',re.I).match
+ default_kind = 4
+
+ def get_zero_value(self):
+ kind = self.get_kind()
+ if kind==self.default_kind: return '0'
+ return '0_%s' % (kind)
+
+class Real(TypeDeclarationStatement):
+ match = re.compile(r'real\b',re.I).match
+ default_kind = 4
+
+ def get_zero_value(self):
+ kind = self.get_kind()
+ if kind==self.default_kind: return '0.0'
+ return '0_%s' % (kind)
+
+class DoublePrecision(TypeDeclarationStatement):
+ match = re.compile(r'double\s*precision\b',re.I).match
+ default_kind = 8
+
+ def get_byte_size(self):
+ return self.default_kind
+
+ def get_zero_value(self):
+ return '0.0D0'
+
+class Complex(TypeDeclarationStatement):
+ match = re.compile(r'complex\b',re.I).match
+ default_kind = 4
+
+ def get_byte_size(self):
+ length, kind = self.selector
+ if length: return int(length)
+ if kind: return 2*int(kind)
+ return 2*self.default_kind
+
+ def get_zero_value(self):
+ kind = self.get_kind()
+ if kind==self.default_kind: return '(0.0, 0.0)'
+ return '(0.0_%s, 0.0_%s)' % (kind, kind)
+
+ def get_part_typedecl(self):
+ bz = self.get_byte_size()/2
+ return Real(self.parent, self.item.copy('REAL*%s' % (bz)))
+
+class DoubleComplex(TypeDeclarationStatement):
+ # not in standard
+ match = re.compile(r'double\s*complex\b',re.I).match
+ default_kind = 8
+
+ def get_byte_size(self):
+ return 2*self.default_kind
+
+ def get_zero_value(self):
+ return '(0.0D0,0.0D0)'
+
+class Logical(TypeDeclarationStatement):
+ match = re.compile(r'logical\b',re.I).match
+ default_kind = 4
+
+ def get_zero_value(self):
+ return ".FALSE."
+
+class Character(TypeDeclarationStatement):
+ match = re.compile(r'character\b',re.I).match
+ default_kind = 1
+
+ def get_bit_size(self):
+ length = self.get_length()
+ if length=='*':
+ return 0 # model for character*(*)
+ return CHAR_BIT * int(length) * int(self.get_kind())
+
+ def get_zero_value(self):
+ return "''"
+
+class Byte(TypeDeclarationStatement):
+ # not in standard
+ match = re.compile(r'byte\b',re.I).match
+ default_kind = 1
+
+ def get_zero_value(self):
+ return '0'
+
+class Type(TypeDeclarationStatement):
+ match = re.compile(r'type\s*\(', re.I).match
+
+ def get_zero_value(self):
+ type_decl = self.get_type_decl(self.name)
+ component_names = type_decl.a.component_names
+ components = type_decl.a.components
+ l = []
+ for name in component_names:
+ var = components[name]
+ l.append(var.typedecl.get_zero_value())
+ return '%s(%s)' % (type_decl.name, ', '.join(l))
+
+ def get_kind(self):
+ # See 4.5.2, page 48
+ raise NotImplementedError,`self.__class__.__name__`
+
+ def get_bit_size(self):
+ return self.get_type_decl(self.name).get_bit_size()
+
+TypeStmt = Type
+
+class Class(TypeDeclarationStatement):
+ match = re.compile(r'class\s*\(', re.I).match
+
+class Implicit(Statement):
+ """
+ IMPLICIT <implicit-spec-list>
+ IMPLICIT NONE
+ <implicit-spec> = <declaration-type-spec> ( <letter-spec-list> )
+ <letter-spec> = <letter> [ - <letter> ]
+ """
+ match = re.compile(r'implicit\b',re.I).match
+
+ letters = string.lowercase
+
+ def process_item(self):
+ line = self.item.get_line()[8:].lstrip()
+ if line.lower()=='none':
+ self.items = []
+ return
+ items = []
+ for item in split_comma(line, self.item):
+ i = item.find('(')
+ assert i!=-1 and item.endswith(')'),`item`
+ specs = []
+ for spec in split_comma(item[i+1:-1].strip(), self.item):
+ if '-' in spec:
+ s,e = spec.lower().split('-')
+ s = s.strip()
+ e = e.strip()
+ assert s in self.letters and e in self.letters,`s,e`
+ else:
+ e = s = spec.lower().strip()
+ assert s in self.letters,`s,e`
+ specs.append((s,e))
+ tspec = item[:i].rstrip()
+ stmt = None
+ for cls in declaration_type_spec:
+ if cls.match(tspec):
+ stmt = cls(self, self.item.copy(tspec))
+ if stmt.isvalid:
+ break
+ assert stmt is not None,`item,line`
+ items.append((stmt,specs))
+ self.items = items
+ return
+
+ def tofortran(self, isfix=None):
+ tab = self.get_indent_tab(isfix=isfix)
+ if not self.items:
+ return tab + 'IMPLICIT NONE'
+ l = []
+ for stmt,specs in self.items:
+ l1 = []
+ for s,e in specs:
+ if s==e:
+ l1.append(s)
+ else:
+ l1.append(s + '-' + e)
+ l.append('%s ( %s )' % (stmt.tostr(), ', '.join(l1)))
+ return tab + 'IMPLICIT ' + ', '.join(l)
+
+ def analyze(self):
+ implicit_rules = self.parent.a.implicit_rules
+ if not self.items:
+ if implicit_rules:
+ self.warning('overriding previously set implicit rule mapping'\
+ ' %r.' % (implicit_rules))
+ self.parent.a.implicit_rules = None
+ return
+ if implicit_rules is None:
+ self.warning('overriding previously set IMPLICIT NONE')
+ self.parent.a.implicit_rules = implicit_rules = {}
+ for stmt,specs in self.items:
+ for s,e in specs:
+ for l in string.lowercase[string.lowercase.index(s.lower()):\
+ string.lowercase.index(e.lower())+1]:
+ implicit_rules[l] = stmt
+ return
+
+intrinsic_type_spec = [ \
+ Integer , Real,
+ DoublePrecision, Complex, DoubleComplex, Character, Logical, Byte
+ ]
+declaration_type_spec = intrinsic_type_spec + [ TypeStmt, Class ]
diff --git a/numpy/f2py/lib/parser/utils.py b/numpy/f2py/lib/parser/utils.py
new file mode 100644
index 000000000..ac2cfce8e
--- /dev/null
+++ b/numpy/f2py/lib/parser/utils.py
@@ -0,0 +1,177 @@
+"""
+Various utility functions.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['split_comma', 'specs_split_comma',
+ 'ParseError','AnalyzeError',
+ 'get_module_file','parse_bind','parse_result','is_name','parse_array_spec',
+ 'CHAR_BIT','str2stmt']
+
+import re
+import os, glob
+
+class ParseError(Exception):
+ pass
+
+class AnalyzeError(Exception):
+ pass
+
+is_name = re.compile(r'^[a-z_]\w*$',re.I).match
+name_re = re.compile(r'[a-z_]\w*',re.I).match
+is_entity_decl = re.compile(r'^[a-z_]\w*',re.I).match
+is_int_literal_constant = re.compile(r'^\d+(_\w+|)$').match
+
+def split_comma(line, item = None, comma=',', keep_empty=False):
+ items = []
+ if item is None:
+ for s in line.split(comma):
+ s = s.strip()
+ if not s and not keep_empty: continue
+ items.append(s)
+ return items
+ newitem = item.copy(line, True)
+ apply_map = newitem.apply_map
+ for s in newitem.get_line().split(comma):
+ s = apply_map(s).strip()
+ if not s and not keep_empty: continue
+ items.append(s)
+ return items
+
+def parse_array_spec(line, item = None):
+ items = []
+ for spec in split_comma(line, item):
+ items.append(tuple(split_comma(spec, item, comma=':', keep_empty=True)))
+ return items
+
+def specs_split_comma(line, item = None, upper=False):
+ specs0 = split_comma(line, item)
+ specs = []
+ for spec in specs0:
+ i = spec.find('=')
+ if i!=-1:
+ kw = spec[:i].strip().upper()
+ v = spec[i+1:].strip()
+ specs.append('%s = %s' % (kw, v))
+ else:
+ if upper:
+ spec = spec.upper()
+ specs.append(spec)
+ return specs
+
+def parse_bind(line, item = None):
+ if not line.lower().startswith('bind'):
+ return None, line
+ if item is not None:
+ newitem = item.copy(line, apply_map=True)
+ newline = newitem.get_line()
+ else:
+ newitem = None
+ newline = newline[4:].lstrip()
+ i = newline.find(')')
+ assert i!=-1,`newline`
+ args = []
+ for a in specs_split_comma(newline[1:i].strip(), newitem, upper=True):
+ args.append(a)
+ rest = newline[i+1:].lstrip()
+ if item is not None:
+ rest = newitem.apply_map(rest)
+ return args, rest
+
+def parse_result(line, item = None):
+ if not line.lower().startswith('result'):
+ return None, line
+ line = line[6:].lstrip()
+ i = line.find(')')
+ assert i != -1,`line`
+ name = line[1:i].strip()
+ assert is_name(name),`name`
+ return name, line[i+1:].lstrip()
+
+def filter_stmts(content, classes):
+ """ Pop and return classes instances from content.
+ """
+ stmts = []
+ indices = []
+ for i in range(len(content)):
+ stmt = content[i]
+ if isinstance(stmt, classes):
+ stmts.append(stmt)
+ indices.append(i)
+ indices.reverse()
+ for i in indices:
+ del content[i]
+ return stmts
+
+
+def get_module_files(directory, _cache={}):
+ if _cache.has_key(directory):
+ return _cache[directory]
+ module_line = re.compile(r'(\A|^)module\s+(?P<name>\w+)\s*(!.*|)$',re.I | re.M)
+ d = {}
+ for fn in glob.glob(os.path.join(directory,'*.f90')):
+ f = open(fn,'r')
+ for name in module_line.findall(f.read()):
+ name = name[1]
+ if d.has_key(name):
+ print d[name],'already defines',name
+ continue
+ d[name] = fn
+ _cache[directory] = d
+ return d
+
+def get_module_file(name, directory, _cache={}):
+ fn = _cache.get(name, None)
+ if fn is not None:
+ return fn
+ if name.endswith('_module'):
+ f1 = os.path.join(directory,name[:-7]+'.f90')
+ if os.path.isfile(f1):
+ _cache[name] = fn
+ return f1
+ pattern = re.compile(r'\s*module\s+(?P<name>[a-z]\w*)', re.I).match
+ for fn in glob.glob(os.path.join(directory,'*.f90')):
+ f = open(fn,'r')
+ for line in f:
+ m = pattern(line)
+ if m and m.group('name')==name:
+ _cache[name] = fn
+ f.close()
+ return fn
+ f.close()
+ return
+
+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 get_char_bit():
+ import numpy
+ one = numpy.ubyte(1)
+ two = numpy.ubyte(2)
+ n = numpy.ubyte(2)
+ i = 1
+ while n>=two:
+ n <<= one
+ i += 1
+ return i
+
+CHAR_BIT = get_char_bit()
diff --git a/numpy/f2py/lib/py_wrap.py b/numpy/f2py/lib/py_wrap.py
new file mode 100644
index 000000000..47c8437ad
--- /dev/null
+++ b/numpy/f2py/lib/py_wrap.py
@@ -0,0 +1,128 @@
+__all__ = ['PythonWrapperModule']
+
+import re
+import os
+import sys
+
+from parser.api import *
+from wrapper_base import *
+from py_wrap_type import *
+from py_wrap_subprogram import *
+
+class PythonWrapperModule(WrapperBase):
+
+ main_template = '''\
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+#include "Python.h"
+
+#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API
+#include "numpy/arrayobject.h"
+#include "numpy/arrayscalars.h"
+
+%(header_list)s
+
+%(typedef_list)s
+
+%(extern_list)s
+
+%(c_code_list)s
+
+%(capi_code_list)s
+
+%(objdecl_list)s
+
+static PyObject *f2py_module;
+
+static PyMethodDef f2py_module_methods[] = {
+ %(module_method_list)s
+ {NULL,NULL,0,NULL}
+};
+
+PyMODINIT_FUNC init%(modulename)s(void) {
+ f2py_module = Py_InitModule("%(modulename)s", f2py_module_methods);
+ import_array();
+ if (PyErr_Occurred()) {
+ PyErr_SetString(PyExc_ImportError, "failed to load array module.");
+ goto capi_err;
+ }
+ %(module_init_list)s
+ return;
+capi_err:
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_RuntimeError, "failed to initialize %(modulename)s module.");
+ }
+ return;
+}
+#ifdef __cplusplus
+}
+#endif
+'''
+
+ main_fortran_template = '''\
+%(fortran_code_list)s
+'''
+
+
+
+ def __init__(self, modulename):
+ WrapperBase.__init__(self)
+ self.modulename = modulename
+ self.cname = 'f2py_' + modulename
+
+ self.defined_cpp_code = []
+ self.defined_c_code = []
+ self.defined_types = []
+ self.defined_capi_codes = []
+
+
+ self.header_list = []
+ self.typedef_list = []
+ self.extern_list = []
+ self.objdecl_list = []
+ self.c_code_list = []
+ self.capi_code_list = []
+
+ self.module_method_list = []
+ self.module_init_list = []
+
+ self.fortran_code_list = []
+
+ self.list_names = ['header', 'typedef', 'extern', 'objdecl',
+ 'c_code','capi_code','module_method','module_init',
+ 'fortran_code']
+ self.isf90 = False
+ return
+
+ def add(self, block):
+ if isinstance(block, BeginSource):
+ for name, moduleblock in block.a.module.items():
+ self.add(moduleblock)
+ #for name, subblock in block.a.external_subprogram.items():
+ # self.add(subblock)
+ elif isinstance(block, Subroutine):
+ PythonCAPISubProgram(self, block)
+ elif isinstance(block, Function):
+ fcode = block.subroutine_wrapper_code()
+ self.fortran_code_list.append(fcode)
+ wrapper_block = block.subroutine_wrapper()
+ PythonCAPISubProgram(self, wrapper_block)
+ elif isinstance(block, Module):
+ self.isf90 = True
+ for name,declblock in block.a.type_decls.items():
+ self.add(declblock)
+ for name,subblock in block.a.module_subprogram.items():
+ self.add(subblock)
+ elif isinstance(block, tuple([TypeDecl]+declaration_type_spec)):
+ if isinstance(block, (TypeDecl, TypeStmt)):
+ self.isf90 = True
+ PythonCAPIType(self, block)
+ else:
+ raise NotImplementedError,`block.__class__.__name__`
+ return
+
+ def c_code(self):
+ return self.apply_attributes(self.main_template)
+ def fortran_code(self):
+ return self.apply_attributes(self.main_fortran_template)
diff --git a/numpy/f2py/lib/py_wrap_subprogram.py b/numpy/f2py/lib/py_wrap_subprogram.py
new file mode 100644
index 000000000..8dd0c3efb
--- /dev/null
+++ b/numpy/f2py/lib/py_wrap_subprogram.py
@@ -0,0 +1,210 @@
+__all__ = ['PythonCAPISubProgram']
+
+import sys
+
+from parser.api import TypeDecl, TypeStmt, Module
+from wrapper_base import *
+from py_wrap_type import *
+
+class PythonCAPISubProgram(WrapperBase):
+ """
+ Fortran subprogram hooks.
+ """
+
+ header_template_f77 = '''\
+#define %(name)s_f F_FUNC(%(name)s, %(NAME)s)
+'''
+ extern_template_f77 = '''\
+extern void %(name)s_f(%(ctype_args_f_clist)s);
+'''
+ objdecl_template_doc = '''\
+static char %(cname)s__doc[] = "";
+'''
+ module_method_template = '''\
+{"%(pyname)s", (PyCFunction)%(cname)s, METH_VARARGS | METH_KEYWORDS, %(cname)s__doc},'''
+
+ capi_code_template = '''\
+static PyObject* %(cname)s(PyObject *capi_self, PyObject *capi_args, PyObject *capi_keywds) {
+ PyObject * volatile capi_buildvalue = NULL;
+ volatile int f2py_success = 1;
+ %(decl_list)s
+ static char *capi_kwlist[] = {%(kw_clist+optkw_clist+extrakw_clist+["NULL"])s};
+ if (PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,
+ "%(pyarg_format_elist)s",
+ %(["capi_kwlist"]+pyarg_obj_clist)s)) {
+ %(frompyobj_list)s
+ %(call_list)s
+ f2py_success = !PyErr_Occurred();
+ if (f2py_success) {
+ %(pyobjfrom_list)s
+ capi_buildvalue = Py_BuildValue("%(return_format_elist)s"
+ %(return_obj_clist)s);
+ %(clean_pyobjfrom_list)s
+ }
+ %(clean_call_list)s
+ %(clean_frompyobj_list)s
+ }
+ return capi_buildvalue;
+}
+'''
+
+ header_template_module = '''
+#define %(name)s_f (*%(name)s_func_ptr)
+#define %(init_func)s_f F_FUNC(%(init_func)s, %(INIT_FUNC)s)
+'''
+ typedef_template_module = '''
+typedef void (*%(name)s_functype)(%(ctype_args_f_clist)s);
+typedef void (*%(init_func)s_c_functype)(%(name)s_functype);
+'''
+ extern_template_module = '''\
+extern void %(init_func)s_f(%(init_func)s_c_functype);
+static %(name)s_functype %(name)s_func_ptr;
+'''
+ objdecl_template_module = '''
+'''
+ fortran_code_template_module = '''
+ subroutine %(init_func)s(init_func_c)
+ use %(mname)s
+ external init_func_c
+ call init_func_c(%(name)s)
+ end
+'''
+ c_code_template_module = '''
+static void %(init_func)s_c(%(name)s_functype func_ptr) {
+ %(name)s_func_ptr = func_ptr;
+}
+'''
+ module_init_template_module = '''
+%(init_func)s_f(%(init_func)s_c);
+'''
+
+ def __init__(self, parent, block):
+ WrapperBase.__init__(self)
+ self.name = name = pyname = block.name
+ self.cname = cname = '%s_%s' % (parent.cname,name)
+
+ defined = parent.defined_capi_codes
+ if cname in defined:
+ return
+ defined.append(cname)
+
+ self.info('Generating interface for %s %s: %s' % (parent.modulename, block.__class__.__name__, cname))
+ self.parent = parent
+
+ if pyname.startswith('f2pywrap_'):
+ pyname = pyname[9:]
+ self.pyname = pyname
+
+ self.header_template = ''
+ self.extern_template = ''
+ self.module_init_template = ''
+ self.typedef_template = ''
+ self.c_code_template = ''
+ self.objdecl_template = ''
+ self.fortran_code_template = ''
+
+ WrapperCPPMacro(parent, 'F_FUNC')
+
+ if isinstance(block.parent, Module):
+ self.mname = block.parent.name
+ self.init_func = '%s_init' % (name)
+ self.typedef_template += self.typedef_template_module
+ self.header_template += self.header_template_module
+ self.fortran_code_template += self.fortran_code_template_module
+ self.module_init_template += self.module_init_template_module
+ self.objdecl_template += self.objdecl_template_module
+ self.c_code_template += self.c_code_template_module
+ self.extern_template += self.extern_template_module
+ else:
+ self.extern_template += self.extern_template_f77
+ self.header_template += self.header_template_f77
+
+ self.objdecl_template += self.objdecl_template_doc
+
+ self.decl_list = []
+ self.kw_list = []
+ self.optkw_list = []
+ self.extrakw_list = []
+ self.pyarg_format_list = []
+ self.pyarg_obj_list = []
+ self.frompyobj_list = []
+ self.call_list = []
+ self.pyobjfrom_list = []
+ self.return_format_list = []
+ self.return_obj_list = []
+ self.buildvalue_list = []
+ self.clean_pyobjfrom_list = []
+ self.clean_call_list = []
+ self.clean_frompyobj_list = []
+
+ args_f = []
+ extra_args_f = []
+ ctype_args_f = []
+ extra_ctype_args_f = []
+ argindex = -1
+ for argname in block.args:
+ argindex += 1
+ var = block.a.variables[argname]
+ typedecl = var.get_typedecl()
+ PythonCAPIType(parent, typedecl)
+ ti = PyTypeInterface(typedecl)
+ if var.is_intent_in():
+ self.kw_list.append('"%s"' % (argname))
+
+ if var.is_scalar():
+ if isinstance(typedecl, TypeStmt):
+ if var.is_intent_in():
+ self.pyarg_format_list.append('O&')
+ self.pyarg_obj_list.append('\npyobj_to_%s_inplace, &%s' % (ti.ctype, argname))
+ else:
+ self.frompyobj_list.append('%s = (%s*)pyobj_from_%s(NULL);' % (argname,ti.otype,ti.ctype))
+ if not var.is_intent_out():
+ self.clean_frompyobj_list.append('Py_DECREF(%s);' % (argname))
+ self.decl_list.append('%s* %s = NULL;' % (ti.otype, argname))
+ args_f.append('%s->data' % (argname)) # is_scalar
+ ctype_args_f.append(ti.ctype)
+ else:
+ if var.is_intent_in():
+ self.pyarg_format_list.append('O&')
+ self.pyarg_obj_list.append('\npyobj_to_%s, &%s' % (ti.ctype, argname))
+ assert not isinstance(typedecl, TypeDecl)
+ if ti.ctype=='f2py_string0':
+ if not var.is_intent_in():
+ assert not var.is_intent_out(),'intent(out) not implemented for "%s"' % (var)
+ self.decl_list.append('%s %s = {NULL,0};' % (ti.ctype, argname))
+ args_f.append('%s.data' % argname) # is_scalar
+ ctype_args_f.append('char*')
+ extra_ctype_args_f.append('int')
+ extra_args_f.append('%s.len' % argname)
+ self.clean_frompyobj_list.append(\
+ 'if (%s.len) free(%s.data);' % (argname,argname))
+ else:
+ self.decl_list.append('%s %s;' % (ti.ctype, argname))
+ args_f.append('&'+argname) # is_scalar
+ ctype_args_f.append(ti.ctype+'*')
+ if var.is_intent_out(): # and is_scalar
+ if isinstance(typedecl, TypeStmt):
+ self.return_format_list.append('N')
+ self.return_obj_list.append('\n%s' % (argname))
+ else:
+ self.return_format_list.append('O&')
+ self.return_obj_list.append('\npyobj_from_%s, &%s' % (ti.ctype, argname))
+ else:
+ print `ti,var.dimension,var.bounds`
+ assert var.is_scalar(),'array support not implemented: "%s"' % (var)
+
+ self.call_list.append('%s_f(%s);' % (name,', '.join(args_f+extra_args_f)))
+
+ self.ctype_args_f_list = ctype_args_f + extra_ctype_args_f
+ if not self.ctype_args_f_list:
+ self.ctype_args_f_list.append('void')
+
+
+ self.clean_pyobjfrom_list.reverse()
+ self.clean_call_list.reverse()
+ self.clean_frompyobj_list.reverse()
+
+ if self.return_obj_list: self.return_obj_list.insert(0,'')
+
+ parent.apply_templates(self)
+ return
diff --git a/numpy/f2py/lib/py_wrap_type.py b/numpy/f2py/lib/py_wrap_type.py
new file mode 100644
index 000000000..7b90e7ed1
--- /dev/null
+++ b/numpy/f2py/lib/py_wrap_type.py
@@ -0,0 +1,753 @@
+__all__ = ['PythonCAPIType', 'PyTypeInterface']
+
+from wrapper_base import *
+from parser.api import CHAR_BIT, Module, declaration_type_spec, \
+ TypeDecl, TypeStmt, Subroutine, Function, Integer, Real,\
+ DoublePrecision, Complex, DoubleComplex, Logical, Character, \
+ Byte
+
+class PyTypeInterface:
+
+ def __init__(self, typedecl):
+ if isinstance(typedecl, TypeStmt):
+ typedecl = typedecl.get_type_decl(typedecl.name)
+ self._typedecl = typedecl
+ if isinstance(typedecl, TypeDecl):
+ self.name = name = typedecl.name
+ tname = 'f2py_type_%s_' % (name)
+ else:
+ if isinstance(typedecl,(Integer,Byte)):
+ tname = 'npy_int'
+ elif isinstance(typedecl,(Real, DoublePrecision)):
+ tname = 'npy_float'
+ elif isinstance(typedecl,(Complex, DoubleComplex)):
+ tname = 'npy_complex'
+ elif isinstance(typedecl,Logical):
+ tname = 'f2py_bool'
+ elif isinstance(typedecl,Character):
+ tname = 'f2py_string'
+ else:
+ raise NotImplementedError,`typedecl.__class__`
+ bitsize = typedecl.get_bit_size()
+ self.ctype = ctype = '%s%s' % (tname,bitsize)
+ self.bits = bitsize
+ self.bytes = bitsize / CHAR_BIT
+
+ if isinstance(typedecl, TypeDecl):
+ self.otype = '%sObject' % (ctype)
+ self.ftype = 'TYPE(%s)' % (name)
+ return
+ def __repr__(self): return '%s(%r)' % (self.__class__.__name__, self._typedecl)
+ def __str__(self):
+ s = []
+ for k,v in self.__dict__.items():
+ if k.startswith('_'): continue
+ s.append('%s=%s' % (k,v))
+ return 'PyTypeInterface(%s)' % (', '.join(s))
+
+class PythonCAPIType(WrapperBase):
+ """
+ Fortran type hooks.
+ """
+ def __init__(self, parent, typedecl):
+ WrapperBase.__init__(self)
+ if isinstance(typedecl, tuple(declaration_type_spec)):
+ if isinstance(typedecl, TypeStmt):
+ type_decl = typedecl.get_type_decl(typedecl.name)
+ assert type_decl is not None,"%s %s" % (typedecl,typedecl.name)
+ PythonCAPIDerivedType(parent, type_decl)
+ else:
+ PythonCAPIIntrinsicType(parent, typedecl)
+ elif isinstance(typedecl, TypeDecl):
+ PythonCAPIDerivedType(parent, typedecl)
+ else:
+ raise NotImplementedError,`self.__class__,typedecl.__class__`
+ return
+
+class PythonCAPIIntrinsicType(WrapperBase):
+ """
+ Fortran intrinsic type hooks.
+ """
+
+ capi_code_template_scalar = '''
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
+ PyObject* obj = PyArrayScalar_New(%(Cls)s);
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_from_%(ctype)s(value=%%"%(CTYPE)s_FMT")\\n",*value);
+#endif
+ if (obj==NULL) /* TODO: set exception */ return NULL;
+ PyArrayScalar_ASSIGN(obj,%(Cls)s,*value);
+ return obj;
+}
+
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (obj==NULL) ;
+ else if (PyArray_IsScalar(obj,%(Cls)s)) {
+ *value = PyArrayScalar_VAL(obj,%(Cls)s);
+ return_value = 1;
+ }
+ else if (PySequence_Check(obj)) {
+ if (PySequence_Size(obj)==1)
+ return_value = pyobj_to_%(ctype)s(PySequence_GetItem(obj,0),value);
+ } else {
+ PyObject* sc = Py%(Cls)sArrType_Type.tp_new(
+ &Py%(Cls)sArrType_Type,Py_BuildValue("(O)",obj),NULL);
+ if (sc==NULL) ;
+ else if (PyArray_IsScalar(sc, Generic))
+ return_value = pyobj_to_%(ctype)s(sc,value);
+ else
+ return_value = pyobj_to_%(ctype)s(PyArray_ScalarFromObject(sc),value);
+ }
+ if (!return_value && !PyErr_Occurred()) {
+ PyObject* r = PyString_FromString("Failed to convert ");
+ PyString_ConcatAndDel(&r, PyObject_Repr(PyObject_Type(obj)));
+ PyString_ConcatAndDel(&r, PyString_FromString(" to C %(ctype)s"));
+ PyErr_SetObject(PyExc_TypeError,r);
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ if (PyErr_Occurred()) {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s: PyErr_Occurred()=%%p\\n", PyErr_Occurred());
+ } else {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s: value=%%"%(CTYPE)s_FMT"\\n", *value);
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ }
+#endif
+ return return_value;
+}
+'''
+
+ capi_code_template_complex_scalar = '''
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
+ PyObject* obj = PyArrayScalar_New(%(Cls)s);
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_from_%(ctype)s(value=(%%"%(FCTYPE)s_FMT",%%"%(FCTYPE)s_FMT"))\\n",value->real, value->imag);
+#endif
+ if (obj==NULL) /* TODO: set exception */ return NULL;
+ PyArrayScalar_ASSIGN(obj,%(Cls)s,*value);
+ return obj;
+}
+
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (obj==NULL) ;
+ else if (PyArray_IsScalar(obj,%(Cls)s)) {
+ value->real = PyArrayScalar_VAL(obj,%(Cls)s).real;
+ value->imag = PyArrayScalar_VAL(obj,%(Cls)s).imag;
+ return_value = 1;
+ }
+ else if (PySequence_Check(obj)) {
+ if (PySequence_Size(obj)==1)
+ return_value = pyobj_to_%(ctype)s(PySequence_GetItem(obj,0),value);
+ else if (PySequence_Size(obj)==2) {
+ return_value = pyobj_to_%(fctype)s(PySequence_GetItem(obj,0),&(value->real))
+ && pyobj_to_%(fctype)s(PySequence_GetItem(obj,1),&(value->imag));
+ }
+ } else {
+ PyObject* sc = Py%(Cls)sArrType_Type.tp_new(
+ &Py%(Cls)sArrType_Type,Py_BuildValue("(O)",obj),NULL);
+ if (sc==NULL) ;
+ else if (PyArray_IsScalar(sc, Generic))
+ return_value = pyobj_to_%(ctype)s(sc,value);
+ else
+ return_value = pyobj_to_%(ctype)s(PyArray_ScalarFromObject(sc),value);
+ }
+ if (!return_value && !PyErr_Occurred()) {
+ PyObject* r = PyString_FromString("Failed to convert ");
+ PyString_ConcatAndDel(&r, PyObject_Repr(PyObject_Type(obj)));
+ PyString_ConcatAndDel(&r, PyString_FromString(" to C %(ctype)s"));
+ PyErr_SetObject(PyExc_TypeError,r);
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ if (PyErr_Occurred()) {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s: PyErr_Occurred()=%%p\\n", PyErr_Occurred());
+ } else {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s: value=(%%"%(FCTYPE)s_FMT",%%"%(FCTYPE)s_FMT")\\n",
+ value->real, value->imag);
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ }
+#endif
+ return return_value;
+}
+'''
+
+ capi_code_template_logical_scalar = '''
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_from_%(ctype)s(value=%%"%(ICTYPE)s_FMT")\\n",*value);
+#endif
+ if (*value) {
+ PyArrayScalar_RETURN_TRUE;
+ } else {
+ PyArrayScalar_RETURN_FALSE;
+ }
+}
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (obj==NULL) ;
+ else if (PyArray_IsScalar(obj,Bool)) {
+ *value = PyArrayScalar_VAL(obj,Bool);
+ return_value = 1;
+ } else {
+ switch (PyObject_IsTrue(obj)) {
+ case 0: *value = 0; return_value = 1; break;
+ case -1: break;
+ default: *value = 1; return_value = 1;
+ }
+ }
+ if (!return_value && !PyErr_Occurred()) {
+ PyObject* r = PyString_FromString("Failed to convert ");
+ PyString_ConcatAndDel(&r, PyObject_Repr(PyObject_Type(obj)));
+ PyString_ConcatAndDel(&r, PyString_FromString(" to C %(ctype)s"));
+ PyErr_SetObject(PyExc_TypeError,r);
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ if (PyErr_Occurred()) {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s: PyErr_Occurred()=%%p\\n", PyErr_Occurred());
+ } else {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s: value=%%"%(ICTYPE)s_FMT"\\n", *value);
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ }
+#endif
+ return return_value;
+}
+'''
+ capi_code_template_string_scalar = '''
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_from_%(ctype)s(value->data=\'%%s\')\\n",value->data);
+#endif
+ PyArray_Descr* descr = PyArray_DescrNewFromType(NPY_STRING);
+ descr->elsize = %(bytes)s;
+ PyObject* obj = PyArray_Scalar(value->data, descr, NULL);
+ if (obj==NULL) /* TODO: set exception */ return NULL;
+ return obj;
+}
+
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (PyString_Check(obj)) {
+ int s = PyString_GET_SIZE(obj);
+ memset(value->data, (int)\' \',%(bytes)s);
+ return_value = !! strncpy(value->data,PyString_AS_STRING(obj),%(bytes)s);
+ if (return_value && s<%(bytes)s) {
+ memset(value->data + s, (int)\' \',%(bytes)s-s);
+ }
+ } else {
+ return_value = pyobj_to_%(ctype)s(PyObject_Str(obj), value);
+ }
+ if (!return_value && !PyErr_Occurred()) {
+ PyObject* r = PyString_FromString("Failed to convert ");
+ PyString_ConcatAndDel(&r, PyObject_Repr(PyObject_Type(obj)));
+ PyString_ConcatAndDel(&r, PyString_FromString(" to C %(ctype)s"));
+ PyErr_SetObject(PyExc_TypeError,r);
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ if (PyErr_Occurred()) {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s: PyErr_Occurred()=%%p\\n", PyErr_Occurred());
+ } else {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s: value->data=\'%%s\'\\n", value->data);
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ }
+#endif
+ return return_value;
+}
+'''
+ capi_code_template_string0_scalar = '''
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_from_%(ctype)s(value->len=%%d, value->data=\'%%s\')\\n",value->len, value->data);
+#endif
+ PyArray_Descr* descr = PyArray_DescrNewFromType(NPY_STRING);
+ descr->elsize = value->len;
+ PyObject* obj = PyArray_Scalar(value->data, descr, NULL);
+ if (obj==NULL) /* TODO: set exception */ return NULL;
+ return obj;
+}
+
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (PyString_Check(obj)) {
+ value->len = PyString_GET_SIZE(obj);
+ value->data = malloc(value->len*sizeof(char));
+ return_value = !! strncpy(value->data,PyString_AS_STRING(obj),value->len);
+ } else {
+ return_value = pyobj_to_%(ctype)s(PyObject_Str(obj), value);
+ }
+ if (!return_value && !PyErr_Occurred()) {
+ PyObject* r = PyString_FromString("Failed to convert ");
+ PyString_ConcatAndDel(&r, PyObject_Repr(PyObject_Type(obj)));
+ PyString_ConcatAndDel(&r, PyString_FromString(" to C %(ctype)s"));
+ PyErr_SetObject(PyExc_TypeError,r);
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ if (PyErr_Occurred()) {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s: PyErr_Occurred()=%%p\\n", PyErr_Occurred());
+ } else {
+ if (return_value)
+ fprintf(stderr,"pyobj_to_%(ctype)s: value->len=%%d, value->data=\'%%s\'\\n", value->len, value->data);
+ else
+ fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+ }
+#endif
+ return return_value;
+}
+'''
+ def __init__(self, parent, typedecl):
+ WrapperBase.__init__(self)
+ self.name = name = typedecl.name
+ ti = PyTypeInterface(typedecl)
+ self.ctype = ctype = ti.ctype
+
+ defined = parent.defined_types
+ if ctype in defined:
+ return
+ defined.append(ctype)
+
+ self.info('Generating interface for %s: %s' % (typedecl.__class__.__name__, ctype))
+ self.parent = parent
+ if isinstance(typedecl, (Integer,Byte,Real,DoublePrecision)):
+ self.Cls = ctype[4].upper() + ctype[5:]
+ self.capi_code_template = self.capi_code_template_scalar
+ elif isinstance(typedecl, (Complex,DoubleComplex)):
+ self.Cls = ctype[4].upper() + ctype[5:]
+ PythonCAPIIntrinsicType(parent, typedecl.get_part_typedecl())
+ ti1 = PyTypeInterface(typedecl.get_part_typedecl())
+ self.fctype = ti1.ctype
+ self.capi_code_template = self.capi_code_template_complex_scalar
+ elif isinstance(typedecl, Logical):
+ self.ictype = 'npy_int%s' % (typedecl.get_bit_size())
+ self.header_template = '#define %(ctype)s %(ictype)s'
+ self.capi_code_template = self.capi_code_template_logical_scalar
+ elif isinstance(typedecl, Character):
+ self.bits = bits = typedecl.get_bit_size()
+ if bits:
+ self.bytes = bits/CHAR_BIT
+ self.header_template = '''
+#include <string.h>
+typedef struct { char data[%(bytes)s]; } %(ctype)s;
+'''
+ self.capi_code_template = self.capi_code_template_string_scalar
+ else:
+ self.header_template = '''
+#include <string.h>
+typedef struct { char* data; size_t len; } %(ctype)s;
+'''
+ self.capi_code_template = self.capi_code_template_string0_scalar
+ else:
+ raise NotImplementedError,`name,ctype`
+ parent.apply_templates(self)
+ return
+
+class PythonCAPIDerivedType(WrapperBase):
+ """
+ Fortran 90 derived type hooks.
+ """
+
+ header_template_wrapper = '''\
+#define %(otype)s_Check(obj) \\
+ PyObject_TypeCheck((PyObject*)obj, &%(otype)sType)
+#define %(init_func)s_f \\
+ F_FUNC(%(init_func)s,%(INIT_FUNC)s)
+'''
+
+ typedef_template_wrapper = '''\
+typedef void * %(ctype)s;
+typedef struct {
+ PyObject_HEAD
+ %(ptrstruct_list)s
+ %(ctype)s data;
+} %(otype)s;
+typedef void (*%(init_func)s_c_functype)(%(init_func_c_ctype_arg_clist)s);
+'''
+
+ typedef_template_importer = '''\
+typedef void * %(ctype)s;
+typedef struct {
+ PyObject_HEAD
+ %(ptrstruct_list)s
+ %(ctype)s data;
+} %(otype)s;
+typedef int (*pyobj_to_%(ctype)s_inplace_functype)(PyObject*, %(otype)s** );
+typedef int (*pyobj_to_%(ctype)s_functype)(PyObject*, %(otype)s* );
+typedef PyObject* (*pyobj_from_%(ctype)s_functype)(%(ctype)s*);
+#define %(otype)sType (*(PyTypeObject *)PyArray_API[0])
+#define pyobj_from_%(ctype)s ((pyobj_from_%(ctype)s_functype)PyArray_API[1])
+#define pyobj_to_%(ctype)s_inplace ((pyobj_to_%(ctype)s_inplace_functype)PyArray_API[2])
+'''
+
+ extern_template_wrapper = '''\
+static PyTypeObject %(otype)sType;
+extern void %(init_func)s_f(%(init_func)s_c_functype, void*, %(ctype)s);
+'''
+
+ objdecl_template_wrapper = '''\
+static PyMethodDef %(otype)s_methods[] = {
+ %(type_method_list)s
+ {NULL} /* Sentinel */
+};
+
+static PyGetSetDef %(otype)s_getseters[] = {
+ %(type_getseters_list)s
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject %(otype)sType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "%(modulename)s.%(name)s", /*tp_name*/
+ sizeof(%(otype)s), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)%(otype)s_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ %(otype)s_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ "Fortran derived type %(name)s objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ %(otype)s_methods, /* tp_methods */
+ 0 /*%(otype)s_members*/, /* tp_members */
+ %(otype)s_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)%(otype)s_init, /* tp_init */
+ 0, /* tp_alloc */
+ %(otype)s_new, /* tp_new */
+};
+
+void *F2PY_%(otype)s_API[] = {
+ (void *) &%(otype)sType,
+ (void *) pyobj_from_%(ctype)s,
+ (void *) pyobj_to_%(ctype)s_inplace
+};
+'''
+
+ objdecl_template_importer = '''\
+static void **F2PY_%(otype)s_API;
+'''
+ module_init_template_wrapper = '''\
+if (PyType_Ready(&%(otype)sType) < 0) goto capi_err;
+PyModule_AddObject(f2py_module, "%(name)s", (PyObject *)&%(otype)sType);
+{
+ PyObject* c_api = PyCObject_FromVoidPtr((void *)F2PY_%(otype)s_API, NULL);
+ PyModule_AddObject(f2py_module, "_%(NAME)s_API", c_api);
+ if (PyErr_Occurred()) goto capi_err;
+}
+'''
+ module_init_template_importer = '''\
+{
+ PyObject *c_api = NULL;
+ PyObject *wrappermodule = PyImport_ImportModule("%(wrappermodulename)s");
+ if (wrappermodule == NULL) goto capi_%(name)s_err;
+ c_api = PyObject_GetAttrString(wrappermodule, "_%(NAME)s_API");
+ if (c_api == NULL) {Py_DECREF(wrappermodule); goto capi_%(name)s_err;}
+ if (PyCObject_Check(c_api)) {
+ F2PY_%(otype)s_API = (void **)PyCObject_AsVoidPtr(c_api);
+ }
+ Py_DECREF(c_api);
+ Py_DECREF(wrappermodule);
+ if (F2PY_%(otype)s_API != NULL) goto capi_%(name)s_ok;
+capi_%(name)s_err:
+ PyErr_Print();
+ PyErr_SetString(PyExc_ImportError, "%(wrappermodulename)s failed to import");
+ return;
+capi_%(name)s_ok:
+ c_api = PyCObject_FromVoidPtr((void *)F2PY_%(otype)s_API, NULL);
+ PyModule_AddObject(f2py_module, "_%(NAME)s_API", c_api);
+ if (PyErr_Occurred()) goto capi_err;
+}
+'''
+
+ c_code_template_wrapper = '''\
+static void %(init_func)s_c(
+ %(init_func_c_arg_clist)s) {
+ %(init_func_c_body_list)s
+}
+'''
+
+ capi_code_template_wrapper = '''\
+static void %(otype)s_dealloc(%(otype)s* self) {
+ if (self->data)
+ PyMem_Free(self->data);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+static int pyobj_to_%(ctype)s_inplace(PyObject *obj,
+ %(otype)s** value_ptr) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (%(otype)s_Check(obj)) {
+ *value_ptr = (%(otype)s*)obj;
+ return_value = 1;
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s: return_value=%%d, PyErr_Occurred()=%%p\\n", return_value, PyErr_Occurred());
+#endif
+ return return_value;
+}
+
+static int pyobj_to_%(ctype)s(PyObject *obj,
+ %(ctype)s* value_ptr) {
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+ if (%(otype)s_Check(obj)) {
+ if (!memcpy(value_ptr,((%(otype)s *)obj)->data, %(bytes)s)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "failed to copy %(name)s instance memory to %(ctype)s object.");
+ } else {
+ return_value = 1;
+ }
+ }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"pyobj_to_%(ctype)s: return_value=%%d, PyErr_Occurred()=%%p\\n", return_value, PyErr_Occurred());
+#endif
+ return return_value;
+}
+
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value_ptr) {
+ %(otype)s* obj = (%(otype)s*)(%(otype)sType.tp_alloc(&%(otype)sType, 0));
+ if (obj == NULL)
+ return NULL;
+ obj->data = PyMem_Malloc(%(bytes)s);
+ if (obj->data == NULL) {
+ Py_DECREF(obj);
+ return PyErr_NoMemory();
+ }
+ if (value_ptr) {
+ if (!memcpy(obj->data, value_ptr, %(bytes)s)) {
+ PyErr_SetString(PyExc_MemoryError,
+ "failed to copy %(ctype)s object memory to %(name)s instance.");
+ }
+ }
+ %(init_func)s_f(%(init_func)s_c, obj, obj->data);
+ return (PyObject*)obj;
+}
+
+static PyObject * %(otype)s_new(PyTypeObject *type,
+ PyObject *args, PyObject *kwds)
+{
+ return pyobj_from_%(ctype)s(NULL);
+}
+
+static int %(otype)s_init(%(otype)s *self,
+ PyObject *capi_args, PyObject *capi_kwds)
+{
+ int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"%(otype)s_init()\\n");
+#endif
+ if (!PyArg_ParseTuple(capi_args,"%(attr_format_elist)s"
+ %(attr_init_clist)s))
+ return_value = -1;
+
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+ fprintf(stderr,"%(otype)s_init: return_value=%%d, PyErr_Occurred()=%%p\\n", return_value, PyErr_Occurred());
+#endif
+ return return_value;
+}
+
+static PyObject * %(otype)s_as_tuple(%(otype)s * self) {
+ return Py_BuildValue("%(as_tuple_format_elist)s"
+ %(as_tuple_arg_clist)s);
+}
+
+static PyObject * %(otype)s_repr(PyObject * self) {
+ PyObject* r = PyString_FromString("%(name)s(");
+ PyString_ConcatAndDel(&r, PyObject_Repr(%(otype)s_as_tuple((%(otype)s*)self)));
+ PyString_ConcatAndDel(&r, PyString_FromString(")"));
+ return r;
+}
+
+%(getset_func_list)s
+'''
+
+ fortran_code_template_wrapper = '''\
+ subroutine %(init_func)s(init_func_c, self, obj)
+ %(use_stmt_list)s
+ %(type_decl_list)s
+ external init_func_c
+! self is %(otype)s
+ external self
+ %(ftype)s obj
+ call init_func_c(%(init_func_f_arg_clist)s)
+ end
+'''
+
+ #module_method_template = ''''''
+
+ _defined = []
+ def __init__(self, parent, typedecl):
+ WrapperBase.__init__(self)
+ ti = PyTypeInterface(typedecl)
+ self.ctype = ctype = ti.ctype
+ defined = parent.defined_types
+ if ctype in defined:
+ return
+ defined.append(ctype)
+
+
+
+ implement_wrappers = True
+ if isinstance(typedecl.parent,Module) and typedecl.parent.name!=parent.modulename:
+ implement_wrappers = False
+ self.info('Using api for %s.%s: %s' % (parent.modulename, typedecl.name, ctype))
+ self.wrappermodulename = typedecl.parent.name
+ else:
+ self.info('Generating interface for %s.%s: %s' % (parent.modulename, typedecl.name, ctype))
+
+ parent.isf90 = True
+ self.parent = parent
+ self.name = name = typedecl.name
+ self.otype = otype = ti.otype
+ self.ctype = ctype = ti.ctype
+ self.ctype_ptrs = self.ctype + '_ptrs'
+ self.ftype = ti.ftype
+ self.bytes = bytes = ti.bytes
+
+ if not implement_wrappers:
+ self.typedef_template = self.typedef_template_importer
+ self.objdecl_template = self.objdecl_template_importer
+ self.module_init_template = self.module_init_template_importer
+ else:
+ self.header_template = self.header_template_wrapper
+ self.typedef_template = self.typedef_template_wrapper
+ self.extern_template = self.extern_template_wrapper
+ self.objdecl_template = self.objdecl_template_wrapper
+ self.module_init_template = self.module_init_template_wrapper
+ self.c_code_template = self.c_code_template_wrapper
+ self.capi_code_template = self.capi_code_template_wrapper
+ self.fortran_code_template = self.fortran_code_template_wrapper
+ WrapperCPPMacro(parent, 'F_FUNC')
+
+ self.init_func_f_arg_list = ['self']
+ self.init_func_c_arg_list = ['%s *self' % (otype)]
+ self.init_func_c_ctype_arg_list = ['%s *' % (otype)]
+ self.init_func_c_body_list = []
+ self.ptrstruct_list = []
+ self.attr_decl_list = []
+ self.attr_format_list = []
+ self.attr_init_list = []
+ self.as_tuple_format_list = []
+ self.as_tuple_arg_list = []
+ self.getset_func_list = []
+ self.type_getseters_list = []
+ for n in typedecl.a.component_names:
+ v = typedecl.a.components[n]
+ t = v.get_typedecl()
+ ti1 = PyTypeInterface(t)
+ PythonCAPIType(parent, t)
+ ct = ti1.ctype
+ parent.add(t)
+ self.ptrstruct_list.append('%s* %s_ptr;' % (ct, n))
+ self.init_func_f_arg_list.append('obj %% %s' % (n))
+ self.init_func_c_arg_list.append('\n%s * %s_ptr' % (ct, n))
+ self.init_func_c_ctype_arg_list.append('\n%s *' % (ct))
+ self.init_func_c_body_list.append('''\
+if (!((void*)%(n)s_ptr >= self->data
+ && (void*)%(n)s_ptr < self->data + %(bytes)s ))
+ fprintf(stderr,"INCONSISTENCY IN %(name)s WRAPPER: "
+ "self->data=%%p <= %(n)s_ptr=%%p < self->data+%(bytes)s=%%p\\n",
+ self->data, %(n)s_ptr, self->data + %(bytes)s);
+self->%(n)s_ptr = %(n)s_ptr;
+''' % (locals()))
+ self.attr_format_list.append('O&')
+ self.attr_init_list.append('\npyobj_to_%s, self->%s_ptr' % (ct,n))
+ self.as_tuple_format_list.append('O&')
+ self.as_tuple_arg_list.append('\npyobj_from_%s, self->%s_ptr' % (ct, n))
+ self.getset_func_list.append('''\
+static PyObject * %(otype)s_get_%(n)s(%(otype)s *self,
+ void *closure) {
+ return pyobj_from_%(ct)s(self->%(n)s_ptr);
+}
+static int %(otype)s_set_%(n)s(%(otype)s *self,
+ PyObject *value, void *closure)
+{
+ if (value == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "Cannot delete %(name)s attribute %(n)s");
+ return -1;
+ }
+ if (pyobj_to_%(ct)s(value, self->%(n)s_ptr))
+ return 0;
+ return -1;
+}
+''' % (locals()))
+ self.type_getseters_list.append('{"%(n)s",(getter)%(otype)s_get_%(n)s, (setter)%(otype)s_set_%(n)s,\n "component %(n)s",NULL},' % (locals()))
+ if self.attr_init_list: self.attr_init_list.insert(0,'')
+ if self.as_tuple_arg_list: self.as_tuple_arg_list.insert(0,'')
+ self.init_func = self.ctype + '_init'
+
+ self.type_method_list = []
+ self.type_method_list.append('{"as_tuple",(PyCFunction)%(otype)s_as_tuple,METH_NOARGS,\n "Return %(name)s components as tuple."},' % (self.__dict__))
+
+ self.use_stmt_list = []
+ self.type_decl_list = []
+ if isinstance(typedecl.parent, Module):
+ self.use_stmt_list.append('use %s' % (typedecl.parent.name))
+ elif isinstance(typedecl.parent, (Subroutine, Function)):
+ self.type_decl_list.append(typedecl.asfix())
+ else:
+ raise NotImplementedError,'types declared in '+typedecl.parent.__class__.__name__
+ parent.apply_templates(self)
+ return
diff --git a/numpy/f2py/lib/setup.py b/numpy/f2py/lib/setup.py
new file mode 100644
index 000000000..cd63b07cd
--- /dev/null
+++ b/numpy/f2py/lib/setup.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('lib',parent_package,top_path)
+ config.add_subpackage('parser')
+ config.add_data_files('*.txt','parser/*.txt')
+ config.add_data_dir('src')
+ return config
+
+if __name__ == "__main__":
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/numpy/f2py/lib/src/F_FUNC.cpp b/numpy/f2py/lib/src/F_FUNC.cpp
new file mode 100644
index 000000000..edaa98064
--- /dev/null
+++ b/numpy/f2py/lib/src/F_FUNC.cpp
@@ -0,0 +1,34 @@
+#if defined(PREPEND_FORTRAN)
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) _##F
+#else
+#define F_FUNC(f,F) _##f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) _##F##_
+#else
+#define F_FUNC(f,F) _##f##_
+#endif
+#endif
+#else
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F
+#else
+#define F_FUNC(f,F) f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F##_
+#else
+#define F_FUNC(f,F) f##_
+#endif
+#endif
+#endif
+#if defined(UNDERSCORE_G77)
+#define F_FUNC_US(f,F) F_FUNC(f##_,F##_)
+#else
+#define F_FUNC_US(f,F) F_FUNC(f,F)
+#endif
diff --git a/numpy/f2py/lib/src/pyobj_to_string_len.c b/numpy/f2py/lib/src/pyobj_to_string_len.c
new file mode 100644
index 000000000..306c961a3
--- /dev/null
+++ b/numpy/f2py/lib/src/pyobj_to_string_len.c
@@ -0,0 +1,11 @@
+int pyobj_to_string_len(PyObject* obj, f2py_string* value, size_t length) {
+ if (PyString_Check(obj)) {
+ if (strncpy((char*)value,PyString_AS_STRING(obj), length))
+ return 1;
+ }
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError,
+ "Failed to convert python object to C f2py_string.");
+ }
+ return 0;
+}
diff --git a/numpy/f2py/lib/tests/test_derived_scalar.py b/numpy/f2py/lib/tests/test_derived_scalar.py
new file mode 100644
index 000000000..c57778020
--- /dev/null
+++ b/numpy/f2py/lib/tests/test_derived_scalar.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+"""
+Tests for intent(in,out) derived type arguments in Fortran subroutine's.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import os
+import sys
+from numpy.testing import *
+set_package_path()
+from lib.main import build_extension, compile
+restore_path()
+
+fortran_code = '''
+subroutine foo(a)
+ type myt
+ integer flag
+ end type myt
+ type(myt) a
+!f2py intent(in,out) a
+ a % flag = a % flag + 1
+end
+function foo2(a)
+ type myt
+ integer flag
+ end type myt
+ type(myt) a
+ type(myt) foo2
+ foo2 % flag = a % flag + 2
+end
+'''
+
+m, = compile(fortran_code, 'test_derived_scalar_ext')
+
+from numpy import *
+
+class test_m(NumpyTestCase):
+
+ def check_foo_simple(self, level=1):
+ a = m.myt(2)
+ assert_equal(a.flag,2)
+ assert isinstance(a,m.myt),`a`
+ r = m.foo(a)
+ assert isinstance(r,m.myt),`r`
+ assert r is a
+ assert_equal(r.flag,3)
+ assert_equal(a.flag,3)
+
+ a.flag = 5
+ assert_equal(r.flag,5)
+
+ #s = m.foo((5,))
+
+ def check_foo2_simple(self, level=1):
+ a = m.myt(2)
+ assert_equal(a.flag,2)
+ assert isinstance(a,m.myt),`a`
+ r = m.foo2(a)
+ assert isinstance(r,m.myt),`r`
+ assert r is not a
+ assert_equal(a.flag,2)
+ assert_equal(r.flag,4)
+
+
+if __name__ == "__main__":
+ NumpyTest().run()
diff --git a/numpy/f2py/lib/tests/test_module_module.py b/numpy/f2py/lib/tests/test_module_module.py
new file mode 100644
index 000000000..4d242ed54
--- /dev/null
+++ b/numpy/f2py/lib/tests/test_module_module.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+"""
+Tests for module with scalar derived types and subprograms.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import os
+import sys
+from numpy.testing import *
+
+set_package_path()
+from lib.main import build_extension, compile
+restore_path()
+
+fortran_code = '''
+module test_module_module_ext2
+ type rat
+ integer n,d
+ end type rat
+ contains
+ subroutine foo2()
+ print*,"In foo2"
+ end subroutine foo2
+end module
+module test_module_module_ext
+ contains
+ subroutine foo
+ use test_module_module_ext2
+ print*,"In foo"
+ call foo2
+ end subroutine foo
+ subroutine bar(a)
+ use test_module_module_ext2
+ type(rat) a
+ print*,"In bar,a=",a
+ end subroutine bar
+end module test_module_module_ext
+'''
+
+m,m2 = compile(fortran_code, modulenames=['test_module_module_ext',
+ 'test_module_module_ext2',
+ ])
+
+from numpy import *
+
+class test_m(NumpyTestCase):
+
+ def check_foo_simple(self, level=1):
+ foo = m.foo
+ foo()
+
+if __name__ == "__main__":
+ NumpyTest().run()
diff --git a/numpy/f2py/lib/tests/test_module_scalar.py b/numpy/f2py/lib/tests/test_module_scalar.py
new file mode 100644
index 000000000..e11a1e0ae
--- /dev/null
+++ b/numpy/f2py/lib/tests/test_module_scalar.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+"""
+Tests for module with scalar derived types and subprograms.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import os
+import sys
+from numpy.testing import *
+set_package_path()
+from lib.main import build_extension, compile
+restore_path()
+
+fortran_code = '''
+module test_module_scalar_ext
+
+ contains
+ subroutine foo(a)
+ integer a
+!f2py intent(in,out) a
+ a = a + 1
+ end subroutine foo
+ function foo2(a)
+ integer a
+ integer foo2
+ foo2 = a + 2
+ end function foo2
+end module test_module_scalar_ext
+'''
+
+m, = compile(fortran_code, modulenames = ['test_module_scalar_ext'])
+
+from numpy import *
+
+class test_m(NumpyTestCase):
+
+ def check_foo_simple(self, level=1):
+ foo = m.foo
+ r = foo(2)
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,3)
+
+ def check_foo2_simple(self, level=1):
+ foo2 = m.foo2
+ r = foo2(2)
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,4)
+
+if __name__ == "__main__":
+ NumpyTest().run()
diff --git a/numpy/f2py/lib/tests/test_scalar_function_in.py b/numpy/f2py/lib/tests/test_scalar_function_in.py
new file mode 100644
index 000000000..9c5cd8aba
--- /dev/null
+++ b/numpy/f2py/lib/tests/test_scalar_function_in.py
@@ -0,0 +1,532 @@
+#!/usr/bin/env python
+"""
+Tests for intent(in) arguments in subroutine-wrapped Fortran functions.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import os
+import sys
+from numpy.testing import *
+
+set_package_path()
+from lib.main import build_extension, compile
+restore_path()
+
+fortran_code = '''\
+! -*- f77 -*-
+ function fooint1(a)
+ integer*1 a
+ integer*1 fooint1
+ fooint1 = a + 1
+ end
+ function fooint2(a)
+ integer*2 a
+ integer*2 fooint2
+ fooint2 = a + 1
+ end
+ function fooint4(a)
+ integer*4 a
+ integer*4 fooint4
+ fooint4 = a + 1
+ end
+ function fooint8(a)
+ integer*8 a
+ integer*8 fooint8
+ fooint8 = a + 1
+ end
+ function foofloat4(a)
+ real*4 a
+ real*4 foofloat4
+ foofloat4 = a + 1.0e0
+ end
+ function foofloat8(a)
+ real*8 a
+ real*8 foofloat8
+ foofloat8 = a + 1.0d0
+ end
+ function foocomplex8(a)
+ complex*8 a
+ complex*8 foocomplex8
+ foocomplex8 = a + 1.0e0
+ end
+ function foocomplex16(a)
+ complex*16 a
+ complex*16 foocomplex16
+ foocomplex16 = a + 1.0d0
+ end
+ function foobool1(a)
+ logical*1 a
+ logical*1 foobool1
+ foobool1 = .not. a
+ end
+ function foobool2(a)
+ logical*2 a
+ logical*2 foobool2
+ foobool2 = .not. a
+ end
+ function foobool4(a)
+ logical*4 a
+ logical*4 foobool4
+ foobool4 = .not. a
+ end
+ function foobool8(a)
+ logical*8 a
+ logical*8 foobool8
+ foobool8 = .not. a
+ end
+ function foostring1(a)
+ character*1 a
+ character*1 foostring1
+ foostring1 = "1"
+ end
+ function foostring5(a)
+ character*5 a
+ character*5 foostring5
+ foostring5 = a
+ foostring5(1:2) = "12"
+ end
+! function foostringstar(a)
+! character*(*) a
+! character*(*) foostringstar
+! if (len(a).gt.0) then
+! foostringstar = a
+! foostringstar(1:1) = "1"
+! endif
+! end
+'''
+
+m, = compile(fortran_code, 'test_scalar_function_in_ext')
+
+from numpy import *
+
+class test_m(NumpyTestCase):
+
+ def check_foo_integer1(self, level=1):
+ i = int8(2)
+ e = int8(3)
+ func = m.fooint1
+ assert isinstance(i,int8),`type(i)`
+ r = func(i)
+ assert isinstance(r,int8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ for intx in [int64,int16,int32]:
+ r = func(intx(2))
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_integer2(self, level=1):
+ i = int16(2)
+ e = int16(3)
+ func = m.fooint2
+ assert isinstance(i,int16),`type(i)`
+ r = func(i)
+ assert isinstance(r,int16),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ for intx in [int8,int64,int32]:
+ r = func(intx(2))
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_integer4(self, level=1):
+ i = int32(2)
+ e = int32(3)
+ func = m.fooint4
+ assert isinstance(i,int32),`type(i)`
+ r = func(i)
+ assert isinstance(r,int32),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ for intx in [int8,int16,int64]:
+ r = func(intx(2))
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_integer8(self, level=1):
+ i = int64(2)
+ e = int64(3)
+ func = m.fooint8
+ assert isinstance(i,int64),`type(i)`
+ r = func(i)
+ assert isinstance(r,int64),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ for intx in [int8,int16,int32]:
+ r = func(intx(2))
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_real4(self, level=1):
+ i = float32(2)
+ e = float32(3)
+ func = m.foofloat4
+ assert isinstance(i,float32),`type(i)`
+ r = func(i)
+ assert isinstance(r,float32),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e+float32(0.2))
+
+ r = func(float64(2.0))
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_real8(self, level=1):
+ i = float64(2)
+ e = float64(3)
+ func = m.foofloat8
+ assert isinstance(i,float64),`type(i)`
+ r = func(i)
+ assert isinstance(r,float64),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e+float64(0.2))
+
+ r = func(float32(2.0))
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_complex8(self, level=1):
+ i = complex64(2)
+ e = complex64(3)
+ func = m.foocomplex8
+ assert isinstance(i,complex64),`type(i)`
+ r = func(i)
+ assert isinstance(r,complex64),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e+complex64(0.2))
+
+ r = func(2+1j)
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e+complex64(1j))
+
+ r = func(complex128(2.0))
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2,3])
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e+complex64(3j))
+
+ self.assertRaises(TypeError,lambda :func([2,1,3]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_complex16(self, level=1):
+ i = complex128(2)
+ e = complex128(3)
+ func = m.foocomplex16
+ assert isinstance(i,complex128),`type(i)`
+ r = func(i)
+ assert isinstance(r,complex128),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e+complex128(0.2))
+
+ r = func(2+1j)
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e+complex128(1j))
+
+ r = func([2])
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2,3])
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e+complex128(3j))
+
+ r = func(complex64(2.0))
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func([2,1,3]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_bool1(self, level=1):
+ i = bool8(True)
+ e = bool8(False)
+ func = m.foobool1
+ assert isinstance(i,bool8),`type(i)`
+ r = func(i)
+ assert isinstance(r,bool8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ for tv in [1,2,2.1,-1j,[0],True]:
+ r = func(tv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,e)
+
+ for fv in [0,0.0,0j,False,(),{},[]]:
+ r = func(fv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,not e)
+
+ def check_foo_bool2(self, level=1):
+ i = bool8(True)
+ e = bool8(False)
+ func = m.foobool2
+ assert isinstance(i,bool8),`type(i)`
+ r = func(i)
+ assert isinstance(r,bool8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ for tv in [1,2,2.1,-1j,[0],True]:
+ r = func(tv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,e)
+
+ for fv in [0,0.0,0j,False,(),{},[]]:
+ r = func(fv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,not e)
+
+ def check_foo_bool4(self, level=1):
+ i = bool8(True)
+ e = bool8(False)
+ func = m.foobool4
+ assert isinstance(i,bool8),`type(i)`
+ r = func(i)
+ assert isinstance(r,bool8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ for tv in [1,2,2.1,-1j,[0],True]:
+ r = func(tv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,e)
+
+ for fv in [0,0.0,0j,False,(),{},[]]:
+ r = func(fv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,not e)
+
+ def check_foo_bool8(self, level=1):
+ i = bool8(True)
+ e = bool8(False)
+ func = m.foobool8
+ assert isinstance(i,bool8),`type(i)`
+ r = func(i)
+ assert isinstance(r,bool8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ for tv in [1,2,2.1,-1j,[0],True]:
+ r = func(tv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,e)
+
+ for fv in [0,0.0,0j,False,(),{},[]]:
+ r = func(fv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,not e)
+
+ def check_foo_string1(self, level=1):
+ i = string0('a')
+ e = string0('1')
+ func = m.foostring1
+ assert isinstance(i,string0),`type(i)`
+ r = func(i)
+ assert isinstance(r,string0),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func('ab')
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,e)
+
+ r = func('')
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,e)
+
+ def check_foo_string5(self, level=1):
+ i = string0('abcde')
+ e = string0('12cde')
+ func = m.foostring5
+ assert isinstance(i,string0),`type(i)`
+ r = func(i)
+ assert isinstance(r,string0),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func('abc')
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,'12c ')
+
+ r = func('abcdefghi')
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,'12cde')
+
+ r = func([1])
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,'12] ')
+
+ def _check_foo_string0(self, level=1):
+ i = string0('abcde')
+ e = string0('12cde')
+ func = m.foostringstar
+ r = func('abcde')
+ assert_equal(r,'1bcde')
+ r = func('')
+ assert_equal(r,'')
+
+if __name__ == "__main__":
+ NumpyTest().run()
diff --git a/numpy/f2py/lib/tests/test_scalar_in_out.py b/numpy/f2py/lib/tests/test_scalar_in_out.py
new file mode 100644
index 000000000..b73036848
--- /dev/null
+++ b/numpy/f2py/lib/tests/test_scalar_in_out.py
@@ -0,0 +1,529 @@
+#!/usr/bin/env python
+"""
+Tests for intent(in,out) arguments in Fortran subroutine's.
+
+-----
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License. See http://scipy.org.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+import os
+import sys
+from numpy.testing import *
+
+set_package_path()
+from lib.main import build_extension, compile
+restore_path()
+
+fortran_code = '''
+ subroutine fooint1(a)
+ integer*1 a
+!f2py intent(in,out) a
+ a = a + 1
+ end
+ subroutine fooint2(a)
+ integer*2 a
+!f2py intent(in,out) a
+ a = a + 1
+ end
+ subroutine fooint4(a)
+ integer*4 a
+!f2py intent(in,out) a
+ a = a + 1
+ end
+ subroutine fooint8(a)
+ integer*8 a
+!f2py intent(in,out) a
+ a = a + 1
+ end
+ subroutine foofloat4(a)
+ real*4 a
+!f2py intent(in,out) a
+ a = a + 1.0e0
+ end
+ subroutine foofloat8(a)
+ real*8 a
+!f2py intent(in,out) a
+ a = a + 1.0d0
+ end
+ subroutine foocomplex8(a)
+ complex*8 a
+!f2py intent(in,out) a
+ a = a + 1.0e0
+ end
+ subroutine foocomplex16(a)
+ complex*16 a
+!f2py intent(in,out) a
+ a = a + 1.0d0
+ end
+ subroutine foobool1(a)
+ logical*1 a
+!f2py intent(in,out) a
+ a = .not. a
+ end
+ subroutine foobool2(a)
+ logical*2 a
+!f2py intent(in,out) a
+ a = .not. a
+ end
+ subroutine foobool4(a)
+ logical*4 a
+!f2py intent(in,out) a
+ a = .not. a
+ end
+ subroutine foobool8(a)
+ logical*8 a
+!f2py intent(in,out) a
+ a = .not. a
+ end
+ subroutine foostring1(a)
+ character*1 a
+!f2py intent(in,out) a
+ a = "1"
+ end
+ subroutine foostring5(a)
+ character*5 a
+!f2py intent(in,out) a
+ a(1:2) = "12"
+ end
+ subroutine foostringstar(a)
+ character*(*) a
+!f2py intent(in,out) a
+ if (len(a).gt.0) then
+ a(1:1) = "1"
+ endif
+ end
+'''
+
+m, = compile(fortran_code, 'test_scalar_in_out_ext', source_ext = '.f')
+
+from numpy import *
+
+class test_m(NumpyTestCase):
+
+ def check_foo_integer1(self, level=1):
+ i = int8(2)
+ e = int8(3)
+ func = m.fooint1
+ assert isinstance(i,int8),`type(i)`
+ r = func(i)
+ assert isinstance(r,int8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ for intx in [int64,int16,int32]:
+ r = func(intx(2))
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,int8),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_integer2(self, level=1):
+ i = int16(2)
+ e = int16(3)
+ func = m.fooint2
+ assert isinstance(i,int16),`type(i)`
+ r = func(i)
+ assert isinstance(r,int16),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ for intx in [int8,int64,int32]:
+ r = func(intx(2))
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,int16),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_integer4(self, level=1):
+ i = int32(2)
+ e = int32(3)
+ func = m.fooint4
+ assert isinstance(i,int32),`type(i)`
+ r = func(i)
+ assert isinstance(r,int32),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ for intx in [int8,int16,int64]:
+ r = func(intx(2))
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,int32),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_integer8(self, level=1):
+ i = int64(2)
+ e = int64(3)
+ func = m.fooint8
+ assert isinstance(i,int64),`type(i)`
+ r = func(i)
+ assert isinstance(r,int64),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ for intx in [int8,int16,int32]:
+ r = func(intx(2))
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,int64),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_real4(self, level=1):
+ i = float32(2)
+ e = float32(3)
+ func = m.foofloat4
+ assert isinstance(i,float32),`type(i)`
+ r = func(i)
+ assert isinstance(r,float32),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e+float32(0.2))
+
+ r = func(float64(2.0))
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,float32),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_real8(self, level=1):
+ i = float64(2)
+ e = float64(3)
+ func = m.foofloat8
+ assert isinstance(i,float64),`type(i)`
+ r = func(i)
+ assert isinstance(r,float64),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e+float64(0.2))
+
+ r = func(float32(2.0))
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,float64),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func(2.2j))
+ self.assertRaises(TypeError,lambda :func([2,1]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_complex8(self, level=1):
+ i = complex64(2)
+ e = complex64(3)
+ func = m.foocomplex8
+ assert isinstance(i,complex64),`type(i)`
+ r = func(i)
+ assert isinstance(r,complex64),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e+complex64(0.2))
+
+ r = func(2+1j)
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e+complex64(1j))
+
+ r = func(complex128(2.0))
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2])
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2,3])
+ assert isinstance(r,complex64),`type(r)`
+ assert_equal(r,e+complex64(3j))
+
+ self.assertRaises(TypeError,lambda :func([2,1,3]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_complex16(self, level=1):
+ i = complex128(2)
+ e = complex128(3)
+ func = m.foocomplex16
+ assert isinstance(i,complex128),`type(i)`
+ r = func(i)
+ assert isinstance(r,complex128),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func(2)
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.0)
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e)
+
+ r = func(2.2)
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e+complex128(0.2))
+
+ r = func(2+1j)
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e+complex128(1j))
+
+ r = func([2])
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e)
+
+ r = func([2,3])
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e+complex128(3j))
+
+ r = func(complex64(2.0))
+ assert isinstance(r,complex128),`type(r)`
+ assert_equal(r,e)
+
+ self.assertRaises(TypeError,lambda :func([2,1,3]))
+ self.assertRaises(TypeError,lambda :func({}))
+
+ def check_foo_bool1(self, level=1):
+ i = bool8(True)
+ e = bool8(False)
+ func = m.foobool1
+ assert isinstance(i,bool8),`type(i)`
+ r = func(i)
+ assert isinstance(r,bool8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ for tv in [1,2,2.1,-1j,[0],True]:
+ r = func(tv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,e)
+
+ for fv in [0,0.0,0j,False,(),{},[]]:
+ r = func(fv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,not e)
+
+ def check_foo_bool2(self, level=1):
+ i = bool8(True)
+ e = bool8(False)
+ func = m.foobool2
+ assert isinstance(i,bool8),`type(i)`
+ r = func(i)
+ assert isinstance(r,bool8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ for tv in [1,2,2.1,-1j,[0],True]:
+ r = func(tv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,e)
+
+ for fv in [0,0.0,0j,False,(),{},[]]:
+ r = func(fv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,not e)
+
+ def check_foo_bool4(self, level=1):
+ i = bool8(True)
+ e = bool8(False)
+ func = m.foobool4
+ assert isinstance(i,bool8),`type(i)`
+ r = func(i)
+ assert isinstance(r,bool8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ for tv in [1,2,2.1,-1j,[0],True]:
+ r = func(tv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,e)
+
+ for fv in [0,0.0,0j,False,(),{},[]]:
+ r = func(fv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,not e)
+
+ def check_foo_bool8(self, level=1):
+ i = bool8(True)
+ e = bool8(False)
+ func = m.foobool8
+ assert isinstance(i,bool8),`type(i)`
+ r = func(i)
+ assert isinstance(r,bool8),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ for tv in [1,2,2.1,-1j,[0],True]:
+ r = func(tv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,e)
+
+ for fv in [0,0.0,0j,False,(),{},[]]:
+ r = func(fv)
+ assert isinstance(r,bool8),`type(r)`
+ assert_equal(r,not e)
+
+ def check_foo_string1(self, level=1):
+ i = string0('a')
+ e = string0('1')
+ func = m.foostring1
+ assert isinstance(i,string0),`type(i)`
+ r = func(i)
+ assert isinstance(r,string0),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func('ab')
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,e)
+
+ r = func('')
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,e)
+
+ def check_foo_string5(self, level=1):
+ i = string0('abcde')
+ e = string0('12cde')
+ func = m.foostring5
+ assert isinstance(i,string0),`type(i)`
+ r = func(i)
+ assert isinstance(r,string0),`type(r)`
+ assert i is not r,`id(i),id(r)`
+ assert_equal(r,e)
+
+ r = func('abc')
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,'12c ')
+
+ r = func('abcdefghi')
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,'12cde')
+
+ r = func([1])
+ assert isinstance(r,string0),`type(r)`
+ assert_equal(r,'12] ')
+
+ def check_foo_string0(self, level=1):
+ i = string0('abcde')
+ e = string0('12cde')
+ func = m.foostringstar
+ r = func('abcde')
+ assert_equal(r,'1bcde')
+ r = func('')
+ assert_equal(r,'')
+
+if __name__ == "__main__":
+ NumpyTest().run()
diff --git a/numpy/f2py/lib/wrapper_base.py b/numpy/f2py/lib/wrapper_base.py
new file mode 100644
index 000000000..3164e817f
--- /dev/null
+++ b/numpy/f2py/lib/wrapper_base.py
@@ -0,0 +1,178 @@
+import os
+import sys
+import re
+
+__all__ = ['WrapperBase','WrapperCPPMacro','WrapperCCode']
+
+class WrapperBase:
+
+ def __init__(self):
+ self.srcdir = os.path.join(os.path.dirname(__file__),'src')
+ return
+ def warning(self, message):
+ print >> sys.stderr, message
+ def info(self, message):
+ print >> sys.stderr, message
+
+ def get_resource_content(self, name, ext):
+ if name.startswith('pyobj_to_'):
+ try:
+ return self.generate_pyobj_to_ctype_c(name[9:])
+ except NotImplementedError:
+ pass
+ elif name.startswith('pyobj_from_'):
+ try:
+ return self.generate_pyobj_from_ctype_c(name[11:])
+ except NotImplementedError:
+ pass
+ generator_mth_name = 'generate_' + name + ext.replace('.','_')
+ generator_mth = getattr(self, generator_mth_name, lambda : None)
+ body = generator_mth()
+ if body is not None:
+ return body
+ fn = os.path.join(self.srcdir,name+ext)
+ if os.path.isfile(fn):
+ f = open(fn,'r')
+ body = f.read()
+ f.close()
+ return body
+ self.warning('No such file: %r' % (fn))
+ return
+
+ def get_dependencies(self, code):
+ l = []
+ for uses in re.findall(r'(?<=depends:)([,\w\s.]+)', code, re.I):
+ for use in uses.split(','):
+ use = use.strip()
+ if not use: continue
+ l.append(use)
+ return l
+
+ def resolve_dependencies(self, parent, body):
+ assert isinstance(body, str),type(body)
+ for d in self.get_dependencies(body):
+ if d.endswith('.cpp'):
+ WrapperCPPMacro(parent, d[:-4])
+ elif d.endswith('.c'):
+ WrapperCCode(parent, d[:-2])
+ else:
+ self.warning('Unknown dependence: %r.' % (d))
+ return
+
+ def apply_attributes(self, template):
+ """
+ Apply instance attributes to template string.
+
+ Replace rules for attributes:
+ _list - will be joined with newline
+ _clist - _list will be joined with comma
+ _elist - _list will be joined
+ ..+.. - attributes will be added
+ [..] - will be evaluated
+ """
+ replace_names = set(re.findall(r'[ ]*%\(.*?\)s', template))
+ d = {}
+ for name in replace_names:
+ tab = ' ' * (len(name)-len(name.lstrip()))
+ name = name.lstrip()[2:-2]
+ names = name.split('+')
+ joinsymbol = '\n'
+ attrs = None
+ for n in names:
+ realname = n.strip()
+ if n.endswith('_clist'):
+ joinsymbol = ', '
+ realname = realname[:-6] + '_list'
+ elif n.endswith('_elist'):
+ joinsymbol = ''
+ realname = realname[:-6] + '_list'
+ realname_lower = realname.lower()
+ parent = getattr(self,'parent',None)
+ if hasattr(self, realname):
+ attr = getattr(self, realname)
+ elif hasattr(self, realname_lower):
+ attr = getattr(self, realname_lower).upper()
+ elif hasattr(parent, realname):
+ attr = getattr(parent, realname)
+ elif hasattr(parent, realname_lower):
+ attr = getattr(parent, realname_lower).upper()
+ elif realname.startswith('['):
+ attr = eval(realname)
+ else:
+ self.warning('Undefined %r attribute: %r' % (self.__class__.__name__, realname))
+ continue
+ if attrs is None:
+ attrs = attr
+ else:
+ attrs += attr
+ if isinstance(attrs, list):
+ attrs = joinsymbol.join(attrs)
+ d[name] = str(attrs).replace('\n','\n'+tab)
+ return template % d
+
+ def apply_templates(self, child):
+ for n in self.list_names:
+ l = getattr(self,n + '_list')
+ c = child.apply_attributes(getattr(child, n+'_template',''))
+ if c:
+ l.append(c)
+ return
+
+class WrapperCPPMacro(WrapperBase):
+ """
+ CPP macros
+ """
+ def __init__(self, parent, name):
+ WrapperBase.__init__(self)
+ defined = parent.defined_cpp_code
+ if name in defined:
+ return
+ defined.append(name)
+
+ body = self.get_resource_content(name,'.cpp')
+ if body is None:
+ self.warning('Failed to get CPP macro %r content.' % (name))
+ return
+ self.resolve_dependencies(parent, body)
+ parent.header_list.append(body)
+ return
+
+class WrapperCCode(WrapperBase):
+ """
+ C code
+ """
+ def __init__(self, parent, name):
+ WrapperBase.__init__(self)
+ defined = parent.defined_c_code
+ if name in defined:
+ return
+ defined.append(name)
+
+ body = self.get_resource_content(name,'.c')
+ if body is None:
+ self.warning('Failed to get C code %r content.' % (name))
+ return
+ if isinstance(body, dict):
+ for k,v in body.items():
+ self.resolve_dependencies(parent, v)
+ for k,v in body.items():
+ l = getattr(parent,k+'_list')
+ l.append(v)
+ else:
+ self.resolve_dependencies(parent, body)
+ parent.c_code_list.append(body)
+ return
+
+ def generate_pyobj_to_ctype_c(self, ctype):
+ from generate_pyobj_tofrom_funcs import pyobj_to_npy_scalar, pyobj_to_f2py_string
+ if ctype.startswith('npy_'):
+ return pyobj_to_npy_scalar(ctype)
+ elif ctype.startswith('f2py_string'):
+ return pyobj_to_f2py_string(ctype)
+ raise NotImplementedError,`ctype`
+
+ def generate_pyobj_from_ctype_c(self, ctype):
+ from generate_pyobj_tofrom_funcs import pyobj_from_npy_scalar
+ if ctype.startswith('npy_'):
+ return pyobj_from_npy_scalar(ctype)
+ raise NotImplementedError,`ctype`