[Numpy-svn] r3238 - in trunk/numpy/f2py/lib: . parser

numpy-svn at scipy.org numpy-svn at scipy.org
Sun Oct 1 06:49:52 CDT 2006


Author: pearu
Date: 2006-10-01 06:49:23 -0500 (Sun, 01 Oct 2006)
New Revision: 3238

Added:
   trunk/numpy/f2py/lib/parser/
   trunk/numpy/f2py/lib/parser/__init__.py
   trunk/numpy/f2py/lib/parser/api.py
   trunk/numpy/f2py/lib/parser/base_classes.py
   trunk/numpy/f2py/lib/parser/block_statements.py
   trunk/numpy/f2py/lib/parser/doc.txt
   trunk/numpy/f2py/lib/parser/parsefortran.py
   trunk/numpy/f2py/lib/parser/readfortran.py
   trunk/numpy/f2py/lib/parser/sourceinfo.py
   trunk/numpy/f2py/lib/parser/splitline.py
   trunk/numpy/f2py/lib/parser/statements.py
   trunk/numpy/f2py/lib/parser/test_parser.py
   trunk/numpy/f2py/lib/parser/typedecl_statements.py
   trunk/numpy/f2py/lib/parser/utils.py
Removed:
   trunk/numpy/f2py/lib/analyzefortran.py
   trunk/numpy/f2py/lib/base_classes.py
   trunk/numpy/f2py/lib/block_statements.py
   trunk/numpy/f2py/lib/doc.txt
   trunk/numpy/f2py/lib/parsefortran.py
   trunk/numpy/f2py/lib/readfortran.py
   trunk/numpy/f2py/lib/sourceinfo.py
   trunk/numpy/f2py/lib/splitline.py
   trunk/numpy/f2py/lib/statements.py
   trunk/numpy/f2py/lib/test_parser.py
   trunk/numpy/f2py/lib/typedecl_statements.py
   trunk/numpy/f2py/lib/utils.py
Modified:
   trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py
   trunk/numpy/f2py/lib/python_wrapper.py
Log:
F2PY G3: Moved Fortran parser related code to subpackage parser.

Deleted: trunk/numpy/f2py/lib/analyzefortran.py
===================================================================
--- trunk/numpy/f2py/lib/analyzefortran.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/analyzefortran.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,138 +0,0 @@
-#!/usr/bin/env python
-"""
-Defines FortranAnalyzer.
-
-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 at cens.ioc.ee>
-Created: June 2006
-"""
-
-from numpy.distutils.misc_util import yellow_text, red_text
-
-class FortranAnalyzer:
-
-    def __init__(self, block):
-        """
-        block is a BeginSource instance with relevant attributes:
-          name - reader name
-          content - a list of statements
-
-        Statements are either block statements or simple statements.
-
-        Block statements have the following relevant attributes:
-          name - block name
-          blocktype - statement name (equal to lowered statement class name)
-          content - a list of statements
-
-        Block statements may have additional attributes:
-          BeginSource: top
-          Module:
-          PythonModule:
-          Program:
-          BlockData:
-          Interface: isabstract, generic_spec
-          Subroutine: prefix, args, suffix
-          Function: prefix, typedecl, args, suffix
-          Select: expr
-          Where: expr
-          Forall: specs
-          IfThen: expr
-          If: expr
-          Do: endlabel, loopcontrol
-          Associate: associations
-          Type: specs, params
-          Enum:
-
-        Simple statements have various attributes:
-          Assignment: variable, expr
-          PointerAssignment: variable, expr
-          Assign: items
-          Call: designator, items
-          Goto: label
-          ComputedGoto: items, expr
-          AssignedGoto: varname, items
-          Continue: label
-          Return: expr
-          Stop: code
-          Print: format, items
-          Read0: specs, items
-          Read1: format, items
-          Write: specs, items
-          Flush: specs
-          Wait: specs
-          Contains:
-          Allocate: spec, items
-          Deallocate: items
-          ModuleProcedure: items
-          Public | Private: items
-          Close: specs
-          Cycle: name
-          Rewind | Backspace | Endfile: specs
-          Open: specs
-          Format: specs
-          Save: items
-          Data: stmts
-          Nullify: items
-          Use: nature, name, isonly, items
-          Exit: name
-          Parameter: items
-          Equivalence: items
-          Dimension: items
-          Target: items
-          Pointer: items
-          Protected | Volatile | Value | Intrinsic | External | Optional: items
-          ArithmeticIf: expr, labels
-          Inquire: specs, items
-          Sequence:
-          Common: items
-          Intent: specs, items
-          Entry: name, items, result, binds
-          Import: items
-          Forall: specs, content
-          SpecificBinding: iname, attrs, name, bname
-          GenericBinding: aspec, spec, items
-          FinalBinding: items
-          Allocatable: items
-          Asynchronous: items
-          Bind: specs, items
-          Else: name
-          ElseIf: name, expr
-          Case: name, items
-          Else: name
-          ElseIf: name, expr
-          Case: name, items
-          Where: name, expr
-          ElseWhere: name, expr
-          Enumerator: items
-          FortranName: value
-          Threadsafe:
-          Depend: depends, items
-          Check: expr, value
-          CallStatement: expr
-          CallProtoArgument: specs
-          Pause: value
-        """
-        self.block = block
-        print block.item
-    def analyze(self):
-        
-        pass
-
-def simple_main():
-    import sys
-    from parsefortran import FortranParser
-    from readfortran import FortranFileReader
-    for filename in sys.argv[1:]:
-        reader = FortranFileReader(filename)
-        print yellow_text('Processing '+filename+' (mode=%r)' % (reader.mode))
-        parser = FortranParser(reader)
-        block = parser.parse()
-        analyzer = FortranAnalyzer(block)
-        r = analyzer.analyze()
-        print r
-
-if __name__ == "__main__":
-    simple_main()

Deleted: trunk/numpy/f2py/lib/base_classes.py
===================================================================
--- trunk/numpy/f2py/lib/base_classes.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/base_classes.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,691 +0,0 @@
-
-__all__ = ['Statement','BeginStatement','EndStatement']
-
-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
-        return
-
-    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()))
-        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_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
-    def is_required(self): return 'REQUIRED' in self.attributes
-    def is_pointer(self): return 'POINTER' in self.attributes
-
-    def is_array(self): return not not (self.bounds or self.dimension)
-
-    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(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 analyze(self):
-        typedecl = self.get_typedecl()
-        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(depht-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):
-        if self.reader.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 self.reader.isfix:
-                colon = ''
-            else:
-                colon = ':'
-        if s:
-            c = ''
-            if self.reader.isfix:
-                c = ' '
-            tab = tab[len(c+s)+len(colon):]
-            if not tab: tab = ' '
-            tab = c + s + colon + tab
-        return tab
-
-    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 __str__(self):
-        l=[self.get_indent_tab(colon=':') + self.tostr()]
-        for c in self.content:
-            l.append(str(c))
-        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.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):
-        return Statement.get_indent_tab(self, colon=colon, deindent=True)
-
-    def __str__(self):
-        return self.get_indent_tab() + 'END %s %s'\
-               % (self.blocktype.upper(),self.name or '')
-

Deleted: trunk/numpy/f2py/lib/block_statements.py
===================================================================
--- trunk/numpy/f2py/lib/block_statements.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/block_statements.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,1149 +0,0 @@
-"""
-
-"""
-
-import re
-import sys
-
-from base_classes import BeginStatement, EndStatement, Statement,\
-     AttributeHolder, ProgramBlock
-from readfortran import Line
-from utils import filter_stmts, parse_bind, parse_result, AnalyzeError
-
-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'
-        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):
-        pass
-
-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=''):
-        s = ''
-        for name, var in self.a.variables.items():
-            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)
-            raise NotImplementedError,'get type_decl from use modules'
-        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 is_private(self):
-        attributes = self.a.attributes
-        if 'PUBLIC' in attributes: return False
-        if 'PRIVATE' in attributes: return True
-        return
-    def is_public(self): return not self.is_private()
-
-    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 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):
-        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()
-        for name, stmt in self.a.external_subprogram.items():
-            s += stmt.topyf()
-        for name, stmt in self.a.blockdata.items():
-            s += stmt.topyf()
-        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):
-    """
-    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
-                        )
-
-    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 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 +=  HasAttributesStmt.topyf(self, tab=tab+'  ')
-        s +=  HasTypeDecls.topyf(self, tab=tab+'  ')
-        s +=  HasVariables.topyf(self, 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):
-    """ 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):
-    """
-    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
-                ):
-    """
-    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):
-        return intrinsic_type_spec + interface_specification
-
-    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)
-
-        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('interface name conflict with %s, overriding.' % (self.name))
-                parent_provides[self.name] = self
-    
-        return
-
-# Subroutine
-
-class SubProgramStatement(BeginStatement, ProgramBlock,
-                          HasImplicitStmt, HasAttributes,
-                          HasUseStmt,
-                          HasVariables, HasTypeDecls
-                          ):
-    """
-    [ <prefix> ] <FUNCTION|SUBROUTINE> <name> [ ( <args> ) ] [ <suffix> ]
-    """
-    known_attributes = ['PUBLIC', 'PRIVATE']
-
-    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.find(clsname)
-        assert i!=-1,`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 +=  HasTypeDecls.topyf(self, tab=tab+'  ')
-        s +=  HasVariables.topyf(self, tab=tab+'  ')
-        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
-
-# 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*\(').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:]
-        i = line.find(')')
-        expr = line[1:i].strip()
-        line = line[i+1:].strip()
-        if line.lower()=='then':
-            self.isvalid = False
-            return
-        self.expr = expr[1:-1]
-
-        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 __str__(self):
-        return self.get_indent_tab(colon=':') + 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):
-    """
-    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').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 += 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
-
-    def get_f_type(self):
-        return 'TYPE(%s)' % (self.name)
-
-    def get_c_type(self):
-        return 'f2py_type_%s_%s' % (self.name, self.get_bit_size())
-
-    def get_c_name(self):
-        return 'f2py_type_%s' % (self.name)
-
-    def get_c_struct_name(self):
-        return self.get_c_name() + '_struct'
-
-    def get_c_struct(self):
-        l = []
-        for name, var in self.a.components.items():
-            t = var.get_typedecl()
-            l.append('  %s %s;' % (t.get_c_type(), name))
-        return 'typedef struct {\n%s\n} %s;' % ('\n'.join(l), self.get_c_struct_name())
-
-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]
-
-###################################################
-
-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 ]

Deleted: trunk/numpy/f2py/lib/doc.txt
===================================================================
--- trunk/numpy/f2py/lib/doc.txt	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/doc.txt	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,311 +0,0 @@
-
-Created: September 2006
-Author: Pearu Peterson <pearu.peterson at gmail.com>
-
-Structure
-=========
-
-numpy.f2py.lib package contains the following files:
-
-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

Modified: trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py
===================================================================
--- trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -6,7 +6,7 @@
 """
 __all__ = ['pyobj_to_npy_scalar','pyobj_to_f2py_string','pyobj_from_npy_scalar']
 
-from utils import CHAR_BIT
+from parser.api import CHAR_BIT
 
 def pyobj_from_npy_int(ctype):
     ctype_bits = int(ctype[7:])

Deleted: trunk/numpy/f2py/lib/parsefortran.py
===================================================================
--- trunk/numpy/f2py/lib/parsefortran.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/parsefortran.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,194 +0,0 @@
-#!/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 at 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.stdout)
-                reader = reader.reader
-            traceback.print_exc(file=sys.stdout)
-            self.reader.show_message(red_text('STOPPED PARSING'), sys.stdout)
-            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:
-            raise
-        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()
-    

Added: trunk/numpy/f2py/lib/parser/__init__.py
===================================================================
--- trunk/numpy/f2py/lib/parser/__init__.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/parser/__init__.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -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 at cens.ioc.ee>
+Created: Oct 2006
+-----
+"""

Added: trunk/numpy/f2py/lib/parser/api.py
===================================================================
--- trunk/numpy/f2py/lib/parser/api.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/parser/api.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -0,0 +1,53 @@
+"""
+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 at cens.ioc.ee>
+Created: Oct 2006
+-----
+"""
+
+# import all Statement classes:
+from block_statements import *
+
+# CHAR_BIT is used to convert object bit sizes to byte sizes
+from utils import CHAR_BIT
+
+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.
+    """
+    import os
+    from readfortran import FortranFileReader, FortranStringReader
+    from parsefortran import FortranParser
+    if os.path.isfile(input):
+        reader = FortranFileReader(input,
+                                   include_dirs = include_dirs)
+        if isfree is None: reader.isfree
+        if isstrict is None: 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))
+    parser = FortranParser(reader)
+    parser.parse()
+    parser.analyze()
+    return parser.block
+
+    

Copied: trunk/numpy/f2py/lib/parser/base_classes.py (from rev 3235, trunk/numpy/f2py/lib/base_classes.py)
===================================================================
--- trunk/numpy/f2py/lib/base_classes.py	2006-09-29 18:02:25 UTC (rev 3235)
+++ trunk/numpy/f2py/lib/parser/base_classes.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -0,0 +1,702 @@
+"""
+-----
+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 at 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
+        return
+
+    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()))
+        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_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
+    def is_required(self): return 'REQUIRED' in self.attributes
+    def is_pointer(self): return 'POINTER' in self.attributes
+
+    def is_array(self): return not not (self.bounds or self.dimension)
+
+    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(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 analyze(self):
+        typedecl = self.get_typedecl()
+        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(depht-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):
+        if self.reader.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 self.reader.isfix:
+                colon = ''
+            else:
+                colon = ':'
+        if s:
+            c = ''
+            if self.reader.isfix:
+                c = ' '
+            tab = tab[len(c+s)+len(colon):]
+            if not tab: tab = ' '
+            tab = c + s + colon + tab
+        return tab
+
+    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 __str__(self):
+        l=[self.get_indent_tab(colon=':') + self.tostr()]
+        for c in self.content:
+            l.append(str(c))
+        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.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):
+        return Statement.get_indent_tab(self, colon=colon, deindent=True)
+
+    def __str__(self):
+        return self.get_indent_tab() + 'END %s %s'\
+               % (self.blocktype.upper(),self.name or '')
+

Copied: trunk/numpy/f2py/lib/parser/block_statements.py (from rev 3236, trunk/numpy/f2py/lib/block_statements.py)
===================================================================
--- trunk/numpy/f2py/lib/block_statements.py	2006-09-30 21:02:52 UTC (rev 3236)
+++ trunk/numpy/f2py/lib/parser/block_statements.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -0,0 +1,1167 @@
+"""
+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 at cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['BeginSource','Module','PythonModule','Program','BlockData','Interface',
+           'Subroutine','Function','Select','EndWhere','WhereConstruct','ForallConstruct',
+           'IfThen','If','Do','Associate','TypeDecl','Enum']
+
+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'
+        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):
+        pass
+
+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=''):
+        s = ''
+        for name, var in self.a.variables.items():
+            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)
+            raise NotImplementedError,'get type_decl from use modules'
+        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 is_private(self):
+        attributes = self.a.attributes
+        if 'PUBLIC' in attributes: return False
+        if 'PRIVATE' in attributes: return True
+        return
+    def is_public(self): return not self.is_private()
+
+    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 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):
+        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()
+        for name, stmt in self.a.external_subprogram.items():
+            s += stmt.topyf()
+        for name, stmt in self.a.blockdata.items():
+            s += stmt.topyf()
+        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):
+    """
+    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
+                        )
+
+    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 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 +=  HasAttributesStmt.topyf(self, tab=tab+'  ')
+        s +=  HasTypeDecls.topyf(self, tab=tab+'  ')
+        s +=  HasVariables.topyf(self, 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):
+    """ 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):
+    """
+    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
+                ):
+    """
+    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):
+        return intrinsic_type_spec + interface_specification
+
+    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)
+
+        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('interface name conflict with %s, overriding.' % (self.name))
+                parent_provides[self.name] = self
+    
+        return
+
+# Subroutine
+
+class SubProgramStatement(BeginStatement, ProgramBlock,
+                          HasImplicitStmt, HasAttributes,
+                          HasUseStmt,
+                          HasVariables, HasTypeDecls
+                          ):
+    """
+    [ <prefix> ] <FUNCTION|SUBROUTINE> <name> [ ( <args> ) ] [ <suffix> ]
+    """
+    known_attributes = ['PUBLIC', 'PRIVATE']
+
+    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.find(clsname)
+        assert i!=-1,`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 +=  HasTypeDecls.topyf(self, tab=tab+'  ')
+        s +=  HasVariables.topyf(self, tab=tab+'  ')
+        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
+
+# 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*\(').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:]
+        i = line.find(')')
+        expr = line[1:i].strip()
+        line = line[i+1:].strip()
+        if line.lower()=='then':
+            self.isvalid = False
+            return
+        self.expr = expr[1:-1]
+
+        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 __str__(self):
+        return self.get_indent_tab(colon=':') + 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):
+    """
+    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').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 += 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
+
+    def get_f_type(self):
+        return 'TYPE(%s)' % (self.name)
+
+    def get_c_type(self):
+        return 'f2py_type_%s_%s' % (self.name, self.get_bit_size())
+    
+    def get_c_name(self):
+        return 'f2py_type_%s' % (self.name)
+
+    def get_c_struct_name(self):
+        return self.get_c_name() + '_struct'
+
+    def get_c_struct(self):
+        l = []
+        for name, var in self.a.components.items():
+            t = var.get_typedecl()
+            l.append('  %s %s;' % (t.get_c_type(), name))
+        return 'typedef struct {\n%s\n} %s;' % ('\n'.join(l), self.get_c_struct_name())
+
+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 ]

Copied: trunk/numpy/f2py/lib/parser/doc.txt (from rev 3235, trunk/numpy/f2py/lib/doc.txt)
===================================================================
--- trunk/numpy/f2py/lib/doc.txt	2006-09-29 18:02:25 UTC (rev 3235)
+++ trunk/numpy/f2py/lib/parser/doc.txt	2006-10-01 11:49:23 UTC (rev 3238)
@@ -0,0 +1,362 @@
+
+Created: September 2006
+Author: Pearu Peterson <pearu.peterson at 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

Copied: trunk/numpy/f2py/lib/parser/parsefortran.py (from rev 3235, trunk/numpy/f2py/lib/parsefortran.py)

Copied: trunk/numpy/f2py/lib/parser/readfortran.py (from rev 3235, trunk/numpy/f2py/lib/readfortran.py)
===================================================================
--- trunk/numpy/f2py/lib/readfortran.py	2006-09-29 18:02:25 UTC (rev 3235)
+++ trunk/numpy/f2py/lib/parser/readfortran.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -0,0 +1,829 @@
+#!/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 at 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
+
+    # 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()
+
+    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)
+
+    # 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()

Copied: trunk/numpy/f2py/lib/parser/sourceinfo.py (from rev 3235, trunk/numpy/f2py/lib/sourceinfo.py)
===================================================================
--- trunk/numpy/f2py/lib/sourceinfo.py	2006-09-29 18:02:25 UTC (rev 3235)
+++ trunk/numpy/f2py/lib/parser/sourceinfo.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -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 at 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()

Copied: trunk/numpy/f2py/lib/parser/splitline.py (from rev 3235, trunk/numpy/f2py/lib/splitline.py)
===================================================================
--- trunk/numpy/f2py/lib/splitline.py	2006-09-29 18:02:25 UTC (rev 3235)
+++ trunk/numpy/f2py/lib/parser/splitline.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -0,0 +1,416 @@
+#!/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 at 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
+
+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 = {}
+    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()
+

Copied: trunk/numpy/f2py/lib/parser/statements.py (from rev 3235, trunk/numpy/f2py/lib/statements.py)
===================================================================
--- trunk/numpy/f2py/lib/statements.py	2006-09-29 18:02:25 UTC (rev 3235)
+++ trunk/numpy/f2py/lib/parser/statements.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -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 at 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 __str__(self):
+        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() + 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 __str__(self):
+        return self.get_indent_tab() + '%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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        s = self.get_indent_tab() + '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 'Need to analyze:',self
+        print 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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return  self.get_indent_tab() + '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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        s = self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        s = self.get_indent_tab() + '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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self): return self.get_indent_tab() + '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 __str__(self):
+        t = ''
+        if self.spec:
+            t = self.spec.tostr() + ' :: '
+        return self.get_indent_tab() \
+               + '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 __str__(self): return self.get_indent_tab() \
+        + '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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        clsname = self.__class__.__name__.upper()
+        tab = self.get_indent_tab()
+        if self.items:
+            return tab + clsname + ' ' + ', '.join(self.items)
+        return tab + clsname
+
+    def analyze(self):
+        clsname = self.__class__.__name__.upper()
+        if self.items:
+            for name in self.items:
+                var = self.get_variable(name)
+                var.update(clsname)
+        else:
+            self.parent.update_attributes(clsname)
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        if self.name:
+            return self.get_indent_tab() + 'CYCLE ' + self.name
+        return self.get_indent_tab() + '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 __str__(self):
+        clsname = self.__class__.__name__.upper()
+        return self.get_indent_tab() + 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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        tab = self.get_indent_tab()
+        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
+        
+        
+        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 __str__(self):
+        if self.name:
+            return self.get_indent_tab() + 'EXIT ' + self.name
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        if self.items:
+            return self.get_indent_tab() + 'INQUIRE (%s) %s' \
+                   % (', '.join(self.specs), ', '.join(self.items))
+        return self.get_indent_tab() + '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 __str__(self): return self.get_indent_tab() + '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 __str__(self):
+        l = []
+        for name,s in self.items:
+            l.append('%s %s' % (name,s))
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        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()
+        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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        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 __str__(self):
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + 'FORTRANNAME ' + self.value
+
+class Threadsafe(Statement):
+    """
+    THREADSAFE
+    """
+    match = re.compile(r'threadsafe\Z',re.I).match
+    def process_item(self):
+        return
+    def __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        return self.get_indent_tab() + '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 __str__(self):
+        if self.value:
+            return self.get_indent_tab() + 'PAUSE ' + self.value
+        return self.get_indent_tab() + 'PAUSE'
+    def analyze(self): return
+

Copied: trunk/numpy/f2py/lib/parser/test_parser.py (from rev 3235, trunk/numpy/f2py/lib/test_parser.py)
===================================================================
--- trunk/numpy/f2py/lib/test_parser.py	2006-09-29 18:02:25 UTC (rev 3235)
+++ trunk/numpy/f2py/lib/parser/test_parser.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -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 at 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()

Copied: trunk/numpy/f2py/lib/parser/typedecl_statements.py (from rev 3236, trunk/numpy/f2py/lib/typedecl_statements.py)
===================================================================
--- trunk/numpy/f2py/lib/typedecl_statements.py	2006-09-30 21:02:52 UTC (rev 3236)
+++ trunk/numpy/f2py/lib/parser/typedecl_statements.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -0,0 +1,574 @@
+"""
+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 at 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
+
+# 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 __str__(self):
+        tab = self.get_indent_tab()
+        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 __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()
+        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)
+            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 = split_comma(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_bit_size(self):
+        return CHAR_BIT * int(self.get_kind())
+
+    def get_byte_size(self):
+        return self.get_bit_size() / CHAR_BIT
+
+    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_c_type(self):
+        return 'npy_int%s' % (self.get_bit_size())
+
+    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_c_type(self):
+        return 'npy_float%s' % (self.get_bit_size())
+
+    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_zero_value(self):
+        return '0.0D0'
+
+    def get_c_type(self):
+        return 'npy_float%s' % (self.get_bit_size())
+
+class Complex(TypeDeclarationStatement):
+    match = re.compile(r'complex\b',re.I).match
+    default_kind = 4
+
+    def get_kind(self):
+        length, kind = self.selector
+        if kind:
+            return kind
+        if length:
+            return int(length)/2
+        return self.default_kind
+
+    def get_length(self):
+        return 2 * int(self.get_kind())
+
+    def get_bit_size(self):
+        return CHAR_BIT * self.get_length()
+
+    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_c_type(self):
+        return 'npy_complex%s' % (self.get_bit_size())
+
+class DoubleComplex(TypeDeclarationStatement):
+    # not in standard
+    match = re.compile(r'double\s*complex\b',re.I).match
+    default_kind = 8
+
+    def get_kind(self): return self.default_kind
+    def get_length(self): return 2 * self.get_kind()
+    def get_bit_size(self):
+        return CHAR_BIT * self.get_length()
+
+    def get_zero_value(self):
+        return '(0.0D0,0.0D0)'
+
+    def get_c_type(self):
+        return 'npy_complex%s' % (self.get_bit_size())
+
+class Logical(TypeDeclarationStatement):
+    match = re.compile(r'logical\b',re.I).match
+    default_kind = 4
+
+    def get_zero_value(self):
+        return ".FALSE."
+
+    def get_c_type(self):
+        return 'npy_int%s' % (self.get_bit_size())
+
+class Character(TypeDeclarationStatement):
+    match = re.compile(r'character\b',re.I).match
+    default_kind = 1
+
+    def get_bit_size(self):
+        return CHAR_BIT * int(self.get_length()) * int(self.get_kind())
+
+    def get_c_type(self):
+        return 'f2py_string%s' % (self.get_bit_size())
+
+    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'
+
+    def get_c_type(self):
+        return 'npy_int%s' % (self.get_bit_size())
+
+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()
+
+    def get_c_type(self):
+        return self.get_type_decl(self.name).get_c_type()
+    
+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('-')
+                    assert s in self.letters and e in self.letters
+                else:
+                    e = s = spec.lower()
+                    assert s in self.letters
+                specs.append((s,e))
+            self.specs = specs
+            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 __str__(self):
+        tab = self.get_indent_tab()
+        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:
+            s,e = 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 ]

Copied: trunk/numpy/f2py/lib/parser/utils.py (from rev 3235, trunk/numpy/f2py/lib/utils.py)
===================================================================
--- trunk/numpy/f2py/lib/utils.py	2006-09-29 18:02:25 UTC (rev 3235)
+++ trunk/numpy/f2py/lib/parser/utils.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -0,0 +1,171 @@
+"""
+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 at cens.ioc.ee>
+Created: May 2006
+-----
+"""
+
+__all__ = ['split_comma', 'specs_split_comma',
+           'ParseError','AnalyzeError',
+           'get_module_file','parse_bind','parse_result','is_name',
+           '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=','):
+    items = []
+    if item is None:
+        for s in line.split(comma):
+            s = s.strip()
+            if not s: 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: continue
+        items.append(s)
+    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()

Modified: trunk/numpy/f2py/lib/python_wrapper.py
===================================================================
--- trunk/numpy/f2py/lib/python_wrapper.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/python_wrapper.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -5,9 +5,11 @@
 import os
 import sys
 
-from block_statements import *
+from parser.api import *
+
+#from block_statements import *
 #from typedecl_statements import intrinsic_type_spec, Character
-from utils import CHAR_BIT
+#from utils import CHAR_BIT
 
 from wrapper_base import *
 
@@ -596,9 +598,9 @@
 
 
 if __name__ == '__main__':
-    from utils import str2stmt, get_char_bit
-
-    stmt = str2stmt("""
+    #from utils import str2stmt, get_char_bit
+    
+    stmt = parse("""
     module rat
       integer :: i
       type info
@@ -641,7 +643,7 @@
 """
 
     wm = PythonWrapperModule('foo')
-    wm.add(str2stmt(foo_code))
+    wm.add(parse(foo_code))
     #wm.add_fortran_code(foo_code)
     #wm.add_subroutine(str2stmt(foo_code))
     #print wm.c_code()

Deleted: trunk/numpy/f2py/lib/readfortran.py
===================================================================
--- trunk/numpy/f2py/lib/readfortran.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/readfortran.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,824 +0,0 @@
-#!/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 at 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
-
-    # 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()
-
-    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)
-
-    # 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):
-        self.id = 'string-'+str(id(string))
-        source = StringIO(string)
-        FortranReaderBase.__init__(self, source, isfree, isstrict)
-
-# 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()

Deleted: trunk/numpy/f2py/lib/sourceinfo.py
===================================================================
--- trunk/numpy/f2py/lib/sourceinfo.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/sourceinfo.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,71 +0,0 @@
-"""
-Author: Pearu Peterson <pearu at 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    -> False, True
-      - in fix format and contains Fortran 90 code    -> False, False
-      - in free format and contains Fortran 90 code   -> True, False
-      - in free format and contains signatures (.pyf) -> 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()

Deleted: trunk/numpy/f2py/lib/splitline.py
===================================================================
--- trunk/numpy/f2py/lib/splitline.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/splitline.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,415 +0,0 @@
-#!/usr/bin/env python
-"""
-Defines LineSplitter and helper functions.
-
-Copyright 2006 Pearu Peterson all rights reserved,
-Pearu Peterson <pearu at cens.ioc.ee>          
-Permission to use, modify, and distribute this software is given under the
-terms of the LGPL.  See http://www.fsf.org
-
-NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
-$Revision:$
-$Date: 2000/07/31 07:04:03 $
-Pearu Peterson
-"""
-
-__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
-
-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 = {}
-    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
-if __name__ == '__main__':
-    test()
-

Deleted: trunk/numpy/f2py/lib/statements.py
===================================================================
--- trunk/numpy/f2py/lib/statements.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/statements.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,1832 +0,0 @@
-
-import re
-import sys
-
-from base_classes import Statement, Variable
-#from expression import Expression
-
-# 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 __str__(self):
-        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() + 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 __str__(self):
-        return self.get_indent_tab() + '%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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        s = self.get_indent_tab() + '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 'Need to analyze:',self
-        print 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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return  self.get_indent_tab() + '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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        s = self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        s = self.get_indent_tab() + '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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self): return self.get_indent_tab() + '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 __str__(self):
-        t = ''
-        if self.spec:
-            t = self.spec.tostr() + ' :: '
-        return self.get_indent_tab() \
-               + '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 __str__(self): return self.get_indent_tab() \
-        + '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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        clsname = self.__class__.__name__.upper()
-        tab = self.get_indent_tab()
-        if self.items:
-            return tab + clsname + ' ' + ', '.join(self.items)
-        return tab + clsname
-
-    def analyze(self):
-        clsname = self.__class__.__name__.upper()
-        if self.items:
-            for name in self.items:
-                var = self.get_variable(name)
-                var.update(clsname)
-        else:
-            self.parent.update_attributes(clsname)
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        if self.name:
-            return self.get_indent_tab() + 'CYCLE ' + self.name
-        return self.get_indent_tab() + '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 __str__(self):
-        clsname = self.__class__.__name__.upper()
-        return self.get_indent_tab() + 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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        tab = self.get_indent_tab()
-        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
-        
-        
-        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 __str__(self):
-        if self.name:
-            return self.get_indent_tab() + 'EXIT ' + self.name
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        if self.items:
-            return self.get_indent_tab() + 'INQUIRE (%s) %s' \
-                   % (', '.join(self.specs), ', '.join(self.items))
-        return self.get_indent_tab() + '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 __str__(self): return self.get_indent_tab() + '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 __str__(self):
-        l = []
-        for name,s in self.items:
-            l.append('%s %s' % (name,s))
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        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()
-        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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        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 __str__(self):
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + 'FORTRANNAME ' + self.value
-
-class Threadsafe(Statement):
-    """
-    THREADSAFE
-    """
-    match = re.compile(r'threadsafe\Z',re.I).match
-    def process_item(self):
-        return
-    def __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        return self.get_indent_tab() + '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 __str__(self):
-        if self.value:
-            return self.get_indent_tab() + 'PAUSE ' + self.value
-        return self.get_indent_tab() + 'PAUSE'
-    def analyze(self): return
-

Deleted: trunk/numpy/f2py/lib/test_parser.py
===================================================================
--- trunk/numpy/f2py/lib/test_parser.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/test_parser.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,483 +0,0 @@
-
-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(KIND=4)')
-        assert_equal(parse(Integer,'integer*4 a'),'INTEGER(KIND=4) a')
-        assert_equal(parse(Integer,'integer*4, a'),'INTEGER(KIND=4) a')
-        assert_equal(parse(Integer,'integer*4 a ,b'),'INTEGER(KIND=4) a, b')
-        assert_equal(parse(Integer,'integer*4 :: a ,b'),'INTEGER(KIND=4) a, b')
-        assert_equal(parse(Integer,'integer*4 a(1,2)'),'INTEGER(KIND=4) a(1,2)')
-        assert_equal(parse(Integer,'integer*4 :: a(1,2),b'),'INTEGER(KIND=4) a(1,2), b')
-        assert_equal(parse(Integer,'integer*4 external :: a'),
-                     'INTEGER(KIND=4), external :: a')
-        assert_equal(parse(Integer,'integer*4, external :: a'),
-                     'INTEGER(KIND=4), external :: a')
-        assert_equal(parse(Integer,'integer*4 external , intent(in) :: a'),
-                     'INTEGER(KIND=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()

Deleted: trunk/numpy/f2py/lib/typedecl_statements.py
===================================================================
--- trunk/numpy/f2py/lib/typedecl_statements.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/typedecl_statements.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,562 +0,0 @@
-
-__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
-
-# 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 __str__(self):
-        tab = self.get_indent_tab()
-        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 __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()
-        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)
-            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 = split_comma(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_bit_size(self):
-        return CHAR_BIT * int(self.get_kind())
-
-    def get_byte_size(self):
-        return self.get_bit_size() / CHAR_BIT
-
-    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_c_type(self):
-        return 'npy_int%s' % (self.get_bit_size())
-
-    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_c_type(self):
-        return 'npy_float%s' % (self.get_bit_size())
-
-    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_zero_value(self):
-        return '0.0D0'
-
-    def get_c_type(self):
-        return 'npy_float%s' % (self.get_bit_size())
-
-class Complex(TypeDeclarationStatement):
-    match = re.compile(r'complex\b',re.I).match
-    default_kind = 4
-
-    def get_kind(self):
-        length, kind = self.selector
-        if kind:
-            return kind
-        if length:
-            return int(length)/2
-        return self.default_kind
-
-    def get_length(self):
-        return 2 * int(self.get_kind())
-
-    def get_bit_size(self):
-        return CHAR_BIT * self.get_length()
-
-    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_c_type(self):
-        return 'npy_complex%s' % (self.get_bit_size())
-
-class DoubleComplex(TypeDeclarationStatement):
-    # not in standard
-    match = re.compile(r'double\s*complex\b',re.I).match
-    default_kind = 8
-
-    def get_kind(self): return self.default_kind
-    def get_length(self): return 2 * self.get_kind()
-    def get_bit_size(self):
-        return CHAR_BIT * self.get_length()
-
-    def get_zero_value(self):
-        return '(0.0D0,0.0D0)'
-
-    def get_c_type(self):
-        return 'npy_complex%s' % (self.get_bit_size())
-
-class Logical(TypeDeclarationStatement):
-    match = re.compile(r'logical\b',re.I).match
-    default_kind = 4
-
-    def get_zero_value(self):
-        return ".FALSE."
-
-    def get_c_type(self):
-        return 'npy_int%s' % (self.get_bit_size())
-
-class Character(TypeDeclarationStatement):
-    match = re.compile(r'character\b',re.I).match
-    default_kind = 1
-
-    def get_bit_size(self):
-        return CHAR_BIT * int(self.get_length()) * int(self.get_kind())
-
-    def get_c_type(self):
-        return 'f2py_string%s' % (self.get_bit_size())
-
-    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'
-
-    def get_c_type(self):
-        return 'npy_int%s' % (self.get_bit_size())
-
-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()
-
-    def get_c_type(self):
-        return self.get_type_decl(self.name).get_c_type()
-    
-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('-')
-                    assert s in self.letters and e in self.letters
-                else:
-                    e = s = spec.lower()
-                    assert s in self.letters
-                specs.append((s,e))
-            self.specs = specs
-            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 __str__(self):
-        tab = self.get_indent_tab()
-        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:
-            s,e = 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 ]

Deleted: trunk/numpy/f2py/lib/utils.py
===================================================================
--- trunk/numpy/f2py/lib/utils.py	2006-09-30 23:33:23 UTC (rev 3237)
+++ trunk/numpy/f2py/lib/utils.py	2006-10-01 11:49:23 UTC (rev 3238)
@@ -1,154 +0,0 @@
-
-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=','):
-    items = []
-    if item is None:
-        for s in line.split(comma):
-            s = s.strip()
-            if not s: 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: continue
-        items.append(s)
-    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()



More information about the Numpy-svn mailing list