[Numpy-svn] r3417 - trunk/numpy/f2py/lib/parser

numpy-svn at scipy.org numpy-svn at scipy.org
Mon Oct 30 13:21:37 CST 2006


Author: pearu
Date: 2006-10-30 13:21:25 -0600 (Mon, 30 Oct 2006)
New Revision: 3417

Added:
   trunk/numpy/f2py/lib/parser/test_statements2.py
Modified:
   trunk/numpy/f2py/lib/parser/Fortran2003.py
   trunk/numpy/f2py/lib/parser/api.py
   trunk/numpy/f2py/lib/parser/expressions.py
   trunk/numpy/f2py/lib/parser/pattern_tools.py
   trunk/numpy/f2py/lib/parser/readfortran.py
   trunk/numpy/f2py/lib/parser/splitline.py
   trunk/numpy/f2py/lib/parser/statements2.py
   trunk/numpy/f2py/lib/parser/test_expressions.py
Log:
F2PY: Cont. unifying Fortran stmt and expr parsers.

Modified: trunk/numpy/f2py/lib/parser/Fortran2003.py
===================================================================
--- trunk/numpy/f2py/lib/parser/Fortran2003.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/Fortran2003.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -9,9 +9,11 @@
         Base_classes[cls.__name__] = cls
 
 
-if 0: # Optimize subclass tree:
+if 1: # Optimize subclass tree:
 
     def _rpl_list(clsname):
+        if not Base_classes.has_key(clsname):
+            return [] # remove this code when all classes are implemented
         cls = Base_classes[clsname]
         if cls.__dict__.has_key('match'): return [clsname]
         l = []
@@ -29,11 +31,12 @@
             for n1 in _rpl_list(n):
                 if n1 not in opt_subclass_names:  opt_subclass_names.append(n1)
         if not opt_subclass_names==cls.subclass_names:
-            #print cls.__name__,':',', '.join(cls.subclass_names),'->',', '.join(opt_subclass_names)
+            print cls.__name__,':',', '.join(cls.subclass_names),'->',', '.join(opt_subclass_names)
             cls.subclass_names[:] = opt_subclass_names
         #else:
         #    print cls.__name__,':',opt_subclass_names
 
+
 # Initialize Base.subclasses dictionary:
 for clsname, cls in Base_classes.items():
     subclass_names = getattr(cls, 'subclass_names', None)
@@ -50,19 +53,21 @@
         else:
             print '%s not implemented needed by %s' % (n,clsname)
 
-if 1:
+if 0:
     for cls in Base_classes.values():
         subclasses = Base.subclasses.get(cls.__name__,[])
         subclasses_names = [c.__name__ for c in subclasses]
         subclass_names = getattr(cls,'subclass_names', [])
         use_names = getattr(cls,'use_names',[])
         for n in subclasses_names:
+            break
             if n not in subclass_names:
                 print '%s needs to be added to %s subclasses_name list' % (n,cls.__name__)
         for n in subclass_names:
+            break
             if n not in subclasses_names:
                 print '%s needs to be added to %s subclass_name list' % (n,cls.__name__)
-        for n in use_names:
+        for n in use_names:            
             if not Base_classes.has_key(n):
                 print '%s not defined used by %s' % (n, cls.__name__)
 #import pprint

Modified: trunk/numpy/f2py/lib/parser/api.py
===================================================================
--- trunk/numpy/f2py/lib/parser/api.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/api.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -18,17 +18,7 @@
 # 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.
-    """
+def get_reader(input, isfree=None, isstrict=None, include_dirs = None):
     import os
     import re
     from readfortran import FortranFileReader, FortranStringReader
@@ -61,9 +51,21 @@
                                      include_dirs = include_dirs)
     else:
         raise TypeError,'Expected string or filename input but got %s' % (type(input))
+    return reader
+
+def parse(input, isfree=None, isstrict=None, include_dirs = None):
+    """ Parse input and return Statement tree.
+
+    input            --- string or filename.
+    isfree, isstrict --- specify input Fortran format.
+                         Defaults are True, False, respectively, or
+                         determined from input.
+    include_dirs     --- list of include directories.
+                         Default contains current working directory
+                         and the directory of file name.
+    """
+    reader = get_reader(input, isfree, isstrict, include_dirs)
     parser = FortranParser(reader)
     parser.parse()
     parser.analyze()
     return parser.block
-
-    

Modified: trunk/numpy/f2py/lib/parser/expressions.py
===================================================================
--- trunk/numpy/f2py/lib/parser/expressions.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/expressions.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -15,6 +15,7 @@
 import re
 from splitline import string_replace_map
 import pattern_tools as pattern
+from readfortran import FortranReaderBase
 
 ############################# Base classes ################################
 
@@ -22,11 +23,23 @@
     pass
 
 class Base(object):
-
+    """
+    """
     subclasses = {}
 
     def __new__(cls, string):
         #print '__new__:',cls.__name__,`string`
+        if isinstance(string, FortranReaderBase) and not issubclass(cls, BlockBase):
+            reader = string
+            item = reader.get_item()
+            try:
+                obj = cls(item.line)
+            except NoMatchError:
+                obj = None
+            if obj is None:
+                reader.put_item(item)
+                return
+            return obj
         match = cls.__dict__.get('match', None)
         if match is not None:
             result = cls.match(string)
@@ -53,6 +66,11 @@
         raise NoMatchError,'%s: %r' % (cls.__name__, string)
 
     findall = staticmethod(re.compile(r'(_F2PY_STRING_CONSTANT_\d+_|F2PY_EXPR_TUPLE_\d+)').findall)
+    def apply_map(line, repmap):
+        for k in Base.findall(line):
+            line = line.replace(k, repmap[k])
+        return line
+    apply_map = staticmethod(apply_map)
     
     def init_list(self, *items):
         self.items = items
@@ -76,21 +94,42 @@
             return self.torepr()
         return '%s(%r)' % (self.__class__.__name__, self.string)
 
+class BlockBase(Base):
+    """
+    <block-base> = <subcls>
+                     [ <subcls> ]...
+                     [ <endcls> ]
+    """
+    def match(reader, subcls, endcls):
+        content = []
+        return content,
+        
+    def init(self, content):
+        self.content = content
+        return
+    def tostr(self):
+        return '\n'.join(map(str, self.content))
+    def torepr(self):
+        return '\n'.join(map(repr, self.content))
+    def get_content(reader, content_class, end_class):
+        #for content_class.sub
+        pass
+    
 class SequenceBase(Base):
     """
     <sequence-base> = <obj>, <obj> [ , <obj> ]...
     """
     def match(separator, subcls, string):
         line, repmap = string_replace_map(string)
-        if separator not in line:
-            return
+        if isinstance(separator, str):
+            splitted = line.split(separator)
+        else:
+            splitted = separator[1].split(line)
+            separator = separator[0]
+        if len(splitted)<=1: return
         lst = []
-        for p in line.split(separator):
-            p = p.strip()
-            for k in Base.findall(p):
-                p = p.replace(k,repmap[k])
-            lst.append(subcls(p))
-        #if len(lst)==1: return lst[0]
+        for p in splitted:
+            lst.append(subcls(repmap(p.strip())))
         return separator, tuple(lst)
     match = staticmethod(match)
     def init(self, separator, items):
@@ -100,6 +139,7 @@
     def tostr(self):
         s = self.separator
         if s==',': s = s + ' '
+        elif s==' ': pass
         else: s = ' ' + s + ' '
         return s.join(map(str, self.items))
     def torepr(self): return '%s(%r, %r)' % (self.__class__.__name__, self.separator, self.items)
@@ -160,6 +200,16 @@
     def torepr(self):
         return '%s(%r, %r, %r)' % (self.__class__.__name__,self.lhs, self.op, self.rhs)
 
+class SeparatorBase(BinaryOpBase):
+    """
+    <shape-base> = <lhs> : <rhs>
+    """
+    def init(self, lhs, rhs):
+        self.lhs = lhs
+        self.op = ':'
+        self.rhs = rhs
+        return
+
 class KeywordValueBase(BinaryOpBase):
     """
     <keyword-value-base> = <keyword> = <rhs>
@@ -257,7 +307,43 @@
     def tostr(self): return str(self.string)
     def torepr(self): return '%s(%r)' % (self.__class__.__name__, self.string)
 
+class STRINGBase(StringBase):
+    """
+    <STRING-base> = <XYZ>
+    """
+    match = staticmethod(StringBase.match)
+    def init(self, string):
+        self.string = string.upper()
+        return
 
+class EndStmtBase(Base):
+    """
+    <end-stmt-base> = END [ <stmt> [ <stmt-name>] ]
+    """
+    def match(stmt_type, stmt_name, string):
+        start = string[:3].upper()
+        if start != 'END': return
+        line = string[3:].lstrip()
+        start = line[:len(stmt_type)].upper()
+        if start:
+            if start != stmt_type: return
+            line = line[len(stmt_type):].lstrip()
+        else:
+            line = ''
+        if line:
+            return stmt_type, stmt_name(line)
+        return stmt_type, None
+    match = staticmethod(match)
+    def init(self, stmt_type, stmt_name):
+        self.type, self.name = stmt_type, stmt_name
+        return
+    def tostr(self):
+        if self.name is not None:
+            return 'END %s %s' % (self.type, self.name)
+        return 'END %s' % (self.type)
+    def torepr(self):
+        return '%s(%r, %r)' % (self.__class__.__name__, self.type, self.name)
+
 ##################################################
 
 class Name(StringBase):
@@ -355,6 +441,7 @@
                               | [ <kind-param> _ ] \" <rep-char> \"
     """
     subclass_names = []
+    rep = pattern.char_literal_constant
     def match(string):
         if string[-1] not in '"\'': return
         if string[-1]=='"':
@@ -543,7 +630,8 @@
                 | <type-param-name>
                 | ( <expr> )
     """
-    subclass_names = ['Constant', 'Parenthesis', 'Designator','Array_Constructor','Structure_Constructor',
+    subclass_names = ['Constant', 'Parenthesis', 'Designator','Array_Constructor',
+                      'Structure_Constructor',
                       'Function_Reference', 'Type_Param_Inquiry', 'Type_Param_Name', 
                        ]
 
@@ -756,7 +844,7 @@
     <ac-do-variable> = <scalar-int-variable>
     <ac-do-variable> shall be a named variable    
     """
-    subclass_names = ['Name']
+    subclass_names = ['Scalar_Int_Variable']
 
 class Type_Spec(Base):
     """
@@ -1045,12 +1133,18 @@
     """
     subclass_names = ['Scalar_Variable_Name', 'Array_Element', 'Scalar_Structure_Component', 'Scalar_Constant']
 
-class Scalar_Variable_Name(Base):
+class Variable_Name(Base):
     """
-    <scalar-variable-name> = <name>
+    <variable-name> = <name>
     """
     subclass_names = ['Name']
 
+class Scalar_Variable_Name(Base):
+    """
+    <scalar-variable-name> = <variable-name>
+    """
+    subclass_names = ['Variable_Name']
+
 class Scalar_Structure_Component(Base):
     """
     <scalar-structure-component> = <structure-component>

Modified: trunk/numpy/f2py/lib/parser/pattern_tools.py
===================================================================
--- trunk/numpy/f2py/lib/parser/pattern_tools.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/pattern_tools.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -70,6 +70,9 @@
     def match(self, string):
         return self.get_compiled().match(string)
 
+    def search(self, string):
+        return self.get_compiled().search(string)
+
     def rsplit(self, string):
         """
         Return (<lhs>, <pattern_match>, <rhs>) where
@@ -182,6 +185,11 @@
             label = '<%s>' % (label)
         return Pattern(label, self.pattern, optional=self.optional, flags=self._flags)
 
+    def __call__(self, string):
+        m = self.match(string)
+        if m is None: return
+        return m.group()
+
 # Predefined patterns
 
 letter = Pattern('<letter>','[A-Z]',flags=re.I)
@@ -245,6 +253,10 @@
 int_constant = int_literal_constant | boz_literal_constant | named_constant
 char_constant = char_literal_constant | named_constant
 
+# assume that replace_string_map is applied:
+part_ref = name + ~((r'[(]' + name + r'[)]'))
+data_ref = part_ref + ~~~(r'[%]' + part_ref)
+primary = constant | name | data_ref | (r'[(]' + name + r'[)]')
 
 power_op = Pattern('<power-op>','[*]{2}')
 mult_op = Pattern('<mult-op>','[*/]')
@@ -271,6 +283,9 @@
 keyword = name
 keyword_equal = keyword + '='
 
+
+
+
 abs_constant = abs(constant)
 abs_literal_constant = abs(literal_constant)
 abs_int_literal_constant = abs(int_literal_constant)
@@ -296,6 +311,23 @@
 intrinsic_type_name = Pattern('<intrinsic-type-name>',r'(INTEGER|REAL|COMPLEX|LOGICAL|CHARACTER|DOUBLE\s*COMPLEX|DOUBLE\s*PRECISION|BYTE)',flags=re.I)
 abs_intrinsic_type_name = abs(intrinsic_type_name)
 
+access_spec = Pattern('<access-spec>',r'PUBLIC|PRIVATE',flags=re.I)
+abs_access_spec = abs(access_spec)
+
+attr_spec = Pattern('<attr-spec>',r'ALLOCATABLE|ASYNCHRONOUS|EXTERNAL|INTENT|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|SAVE|TARGET|VALUE|VOLATILE',flags=re.I)
+abs_attr_spec = abs(attr_spec)
+
+dimension = Pattern('<dimension>',r'DIMENSION', flags=re.I)
+abs_dimension = abs(dimension)
+
+intent = Pattern('<intent>', r'INTENT', flags=re.I)
+abs_intent = abs(intent)
+
+intent_spec = Pattern('<intent-spec>', r'INOUT|IN|OUT', flags=re.I)
+abs_intent_spec = abs(intent_spec)
+
+subroutine = Pattern('<subroutine>', r'SUBROUTINE', flags=re.I)
+
 def _test():
     assert name.match('a1_a')
     assert abs(name).match('a1_a')

Modified: trunk/numpy/f2py/lib/parser/readfortran.py
===================================================================
--- trunk/numpy/f2py/lib/parser/readfortran.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/readfortran.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -260,6 +260,17 @@
         self.put_single_line(line)
         return line
 
+    # Parser methods:
+    def get_item(self):
+        try:
+            return self.next(ignore_comments = True)
+        except StopIteration:
+            pass
+        return
+
+    def put_item(self):
+        self.fifo_item.insert(0, item)
+        return
     # Iterator methods:
 
     def __iter__(self):

Modified: trunk/numpy/f2py/lib/parser/splitline.py
===================================================================
--- trunk/numpy/f2py/lib/parser/splitline.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/splitline.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -30,7 +30,18 @@
 _f2py_str_findall = re.compile(r"_F2PY_STRING_CONSTANT_\d+_").findall
 _is_name = re.compile(r'\w*\Z',re.I).match
 _is_simple_str = re.compile(r'\w*\Z',re.I).match
+_f2py_findall = re.compile(r'(_F2PY_STRING_CONSTANT_\d+_|F2PY_EXPR_TUPLE_\d+)').findall
 
+class string_replace_dict(dict):
+    """
+    Dictionary object that is callable for applying map returned
+    by string_replace_map() function.
+    """
+    def __call__(self, line):
+        for k in _f2py_findall(line):
+            line = line.replace(k, self[k])
+        return line
+
 def string_replace_map(line, lower=False,
                        _cache={'index':0,'pindex':0}):
     """
@@ -39,7 +50,7 @@
     Returns a new line and the replacement map.
     """
     items = []
-    string_map = {}
+    string_map = string_replace_dict()
     rev_string_map = {}
     for item in splitquote(line, lower=lower)[0]:
         if isinstance(item, String) and not _is_simple_str(item[1:-1]):

Modified: trunk/numpy/f2py/lib/parser/statements2.py
===================================================================
--- trunk/numpy/f2py/lib/parser/statements2.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/statements2.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -6,6 +6,7 @@
     <program> = <program-unit>
                   [ <program-unit> ] ...
     """
+    subclass_names = []
     use_names = ['Program_Unit']
 
 class Program_Unit(Base):
@@ -32,10 +33,11 @@
                                [ <internal-subprogram-part> ]
                             <end-function-stmt>
     """
+    subclass_names = []
     use_names = ['Function_Stmt', 'Specification_Part', 'Execution_Part',
                  'Internal_Subprogram_Part', 'End_Function_Stmt']
 
-class Subroutine_Subprogram(Base):
+class Subroutine_Subprogram(BlockBase):
     """
     <subroutine-subprogram> = <subroutine-stmt>
                                  [ <specification-part> ]
@@ -43,35 +45,97 @@
                                  [ <internal-subprogram-part> ]
                               <end-subroutine-stmt>
     """
+    subclass_names = []
     use_names = ['Subroutine_Stmt', 'Specification_Part', 'Execution_Part',
                  'Internal_Subprogram_Part', 'End_Subroutine_Stmt']
+    def match(reader):
+        item = get_item(reader)
+        line = item.line
+        content = []
+        try:
+            start_stmt = Subroutine_Stmt(line)
+        except NoMatchError:
+            start_stmt = None
+        if start_stmt is None:
+            put_item(reader, item)
+            return
+        content.append(start_stmt)
+        content.extend(get_content(reader, Specification_Part, End_Subroutine_Stmt))
+        if isinstance(content[-1], End_Subroutine_Stmt):
+            return content,
+        content.extend(get_content(reader, Execution_Part, End_Subroutine_Stmt))
+        if isinstance(content[-1], End_Subroutine_Stmt):
+            return content,
+        content.extend(get_content(reader, Internal_Subprogram_Part, End_Subroutine_Stmt))
+        assert isinstance(content[-1], End_Subroutine_Stmt),`content[-1]`
+        return content,            
+    match = staticmethod(match)
 
-class Subroutine_Stmt(Base):
+
+
+
+class Prefix(SequenceBase):
     """
-    <subroutine-stmt> = [ <prefix> ] SUBROUTINE <subroutine-name> [ ( [ <dummy-arg-list> ] ) [ <proc-language-binding-spec> ] ]
+    <prefix> = <prefix-spec> [ <prefix-spec> ]..
     """
-    use_names = ['Prefix', 'Subroutine_Name', 'Dummy_Arg_List', 'Proc_Language_Binding_Spec']
+    subclass_names = ['Prefix_Spec']
+    _separator = (' ',re.compile(r'\s+(?=[a-z_])',re.I))
+    def match(string): return SequenceBase.match(Prefix._separator, Prefix_Spec, string)
+    match = staticmethod(match)
 
-class End_Subroutine_Stmt(Base):
+class Prefix_Spec(StringBase):
     """
-    <end-subroutine-stmt> = END [ SUBROUTINE [ <subroutine-name> ] ]
+    <prefix-spec> = <declaration-type-spec>
+                    | RECURSIVE
+                    | PURE
+                    | ELEMENTAL
     """
-    use_names = ['Subroutine_Name']
+    subclass_names = ['Declaration_Type_Spec']
+    def match(string):
+        if len(string)==9:
+            upper = string.upper()
+            if upper in ['RECURSIVE', 'ELEMENTAL']: return upper,
+        elif len(string)==4:
+            upper = string.upper()
+            if upper=='PURE': return upper,
+        return None
+    match = staticmethod(match)
 
-class Specification_Part(Base):
+
+class Specification_Part(BlockBase):
     """
     <specification-part> = [ <use-stmt> ]...
                              [ <import-stmt> ]...
                              [ <implicit-part> ]
                              [ <declaration-construct> ]...
     """
+    subclass_names = []
     use_names = ['Use_Stmt', 'Import_Stmt', 'Implicit_Part', 'Declaration_Construct']
+    def match(reader):
+        content = []
+        for cls in [Declaration_Construct]:
+            item = reader.get_item()
+            while item is not None:
+                obj = None
+                line = item.line
+                try:
+                    obj = cls(line)
+                except NoMatchError:
+                    pass
+                if obj is None:
+                    reader.put_item(item)
+                    break
+                content.append(obj)
+                item = reader.get_item()
+        return content,
+    match = staticmethod(match)
 
 class Implicit_Part(Base):
     """
     <implicit-part> = [ <implicit-part-stmt> ]...
                         <implicit-stmt>
     """
+    subclass_names = []
     use_names = ['Implicit_Part_Stmt', 'Implicit_Stmt']
 
 class Implicit_Part_Stmt(Base):
@@ -107,6 +171,7 @@
 
     <execution-part> shall not contain <end-function-stmt>, <end-program-stmt>, <end-subroutine-stmt>
     """
+    subclass_names = []
     use_names = ['Executable_Construct', 'Execution_Part_Construct']
 
 class Execution_Part_Construct(Base):
@@ -124,6 +189,7 @@
                                    <internal-subprogram>
                                    [ <internal-subprogram> ]...
     """
+    subclass_names = []
     use_names = ['Contains_Stmt', 'Internal_Subprogram']
 
 class Internal_Subprogram(Base):
@@ -217,6 +283,12 @@
                       'Read_Stmt', 'Return_Stmt', 'Rewind_Stmt', 'Stop_Stmt', 'Wait_Stmt',
                       'Where_Stmt', 'Write_Stmt', 'Arithmetic_If_Stmt', 'Computed_Goto_Stmt']
 
+class Int_Constant(Base):
+    subclass_names = ['Constant']
+
+class Scalar_Int_Constant(Base):
+    subclass_names = ['Int_Constant']
+
 class Derived_Type_Def(Base):
     """
     <derived-type-def> = <derived-type-stmt>
@@ -226,6 +298,7 @@
                            [ <type-bound-procedure-part> ]
                            <end-type-stmt>
     """
+    subclass_names = []
     use_names = ['Derived_Type_Stmt', 'Type_Param_Def_Stmt', 'Private_Or_Sequence',
                  'Component_Part', 'Type_Bound_Procedure_Part', 'End_Type_Stmt']
 
@@ -233,6 +306,7 @@
     """
     <derived-type-stmt> = TYPE [ [ , <type-attr-spec-list> ] :: ] <type-name> [ ( <type-param-name-list> ) ]
     """
+    subclass_names = []
     use_names = ['Type_Attr_Spec_List', 'Type_Name', 'Type_Param_Name_List']
 
 class Type_Attr_Spec(Base):
@@ -256,12 +330,14 @@
     """
     <end-type-stmt> = END TYPE [ <type-name> ]
     """
+    subclass_names = []
     use_names = ['Type_Name']
     
 class Sequence_Stmt(Base):
     """
     <sequence-stmt> = SEQUENCE
     """
+    subclass_names = []
     def match(string):
         if len(string) != 8: return
         start = string.upper()
@@ -273,12 +349,14 @@
     """
     <type-param-def-stmt> = INTEGER [ <kind-selector> ] , <type-param-attr-spec> :: <type-param-decl-list>
     """
+    subclass_names = []
     use_names = ['Kind_Selector', 'Type_Param_Attr_Spec', 'Type_Param_Decl_List']
 
 class Type_Param_Decl(Base):
     """
     <type-param-decl> = <type-param-name> [ = <scalar-int-initialization-expr> ]
     """
+    subclass_names = []
     use_names = ['Type_Param_Name', 'Scalar_Int_Initialization_Expr']
 
 class Type_Param_Attr_Spec(Base):
@@ -286,11 +364,13 @@
     <type-param-attr-spec> = KIND
                              | LEN
     """
+    subclass_names = []
 
 class Component_Part(Base):
     """
     <component-part> = [ <component-def-stmt> ]...
     """
+    subclass_names = []
     use_names = ['Component_Def_Stmt']
 
 class Component_Def_Stmt(Base):
@@ -304,6 +384,7 @@
     """
     <data-component-def-stmt> = <declaration-type-spec> [ [ , <component-attr-spec-list> ] :: ] <component-decl-list>
     """
+    subclass_names = []
     use_names = ['Declaration_Type_Spec', 'Component_Attr_Spec_List', 'Component_Decl_List']
 
 class Component_Attr_Spec(Base):
@@ -320,6 +401,7 @@
     """
     <component-decl> = <component-name> [ ( <component-array-spec> ) ] [ * <char-length> ] [ <component-initialization> ]
     """
+    subclass_names = []
     use_names = ['Component_Name', 'Component_Array_Spec', 'Char_Length', 'Component_Initialization']
 
 class Component_Array_Spec(Base):
@@ -334,12 +416,14 @@
     <component-initialization> =  = <initialization-expr>
                                  | => <null-init>
     """
+    subclass_names = []
     use_names = ['Initialization-expr', 'Null_Init']
 
 class Proc_Component_Def_Stmt(Base):
     """
     <proc-component-def-stmt> = PROCEDURE ( [ <proc-interface> ] ) , <proc-component-attr-spec-list> :: <proc-decl-list>
     """
+    subclass_names = []
     use_names = ['Proc_Interface', 'Proc_Component_Attr_Spec_List', 'Proc_Decl_List']
 
 class Proc_Component_Attr_Spec(Base):
@@ -349,12 +433,14 @@
                                  | NOPASS
                                  | <access-spec>
     """
+    subclass_names = []
     use_names = ['Arg_Name', 'Access_Spec']
 
 class Private_Components_Stmt(Base):
     """
     <private-components-stmt> = PRIVATE
     """
+    subclass_names = []
 
 class Type_Bound_Procedure_Part(Base):
     """
@@ -363,12 +449,14 @@
                                       <proc-binding-stmt>
                                       [ <proc-binding-stmt> ]...
     """
+    subclass_names = []
     use_names = ['Contains_Stmt', 'Binding_Private_Stmt', 'Proc_Binding_Stmt']
 
 class Binding_Private_Stmt(Base):
     """
     <binding-private-stmt> = PRIVATE
     """
+    subclass_names = []
 
 class Proc_Binding_Stmt(Base):
     """
@@ -382,12 +470,14 @@
     """
     <specific-binding> = PROCEDURE [ ( <interface-name> ) ] [ [ , <binding-attr-list> ] :: ] <binding-name> [ => <procedure-name> ]
     """
+    subclass_names = []
     use_names = ['Interface_Name', 'Binding_Attr_List', 'Binding_Name', 'Procedure_Name']
 
 class Generic_Binding(Base):
     """
     <generic-binding> = GENERIC [ , <access-spec> ] :: <generic-spec> => <binding-name-list>
     """
+    subclass_names = []
     use_names = ['Access_Spec', 'Generic_Spec', 'Binding_Name_List']
 
 class Binding_Attr(Base):
@@ -397,12 +487,14 @@
                      | NON_OVERRIDABLE
                      | <access-spec>
     """
+    subclass_names = []
     use_names = ['Arg_Name', 'Access_Spec']
 
 class Final_Binding(Base):
     """
     <final-binding> = FINAL [ :: ] <final-subroutine-name-list>
     """
+    subclass_names = []
     use_names = ['Final_Subroutine_Name_List']
 
 #<derived-type-spec>
@@ -418,29 +510,34 @@
                      [ <enumerator-def-stmt> ]...
                      <end-enum-stmt>
     """
+    subclass_names = []
     use_names = ['Enum_Def_Stmt', 'Enumerator_Def_Stmt', 'End_Enum_Stmt']
 
 class Enum_Def_Stmt(Base):
     """
     <enum-def-stmt> = ENUM, BIND(C)
     """
+    subclass_names = []
 
 class Enumerator_Def_Stmt(Base):
     """
     <enumerator-def-stmt> = ENUMERATOR [ :: ] <enumerator-list>
     """
+    subclass_names = []
     use_names = ['Enumerator_List']
 
 class Enumerator(Base):
     """
     <enumerator> = <named-constant> [ = <scalar-int-initialization-expr> ]
     """
+    subclass_names = []
     use_names = ['Named_Constant', 'Scalar_Int_Initialization_Expr']
 
 class End_Enumerator_Stmt(Base):
     """
     <end-enumerator-stmt> = END ENUM
     """
+    subclass_names = []
 
 #<array-constructor>
 #<ac-spec>
@@ -453,8 +550,46 @@
     """
     <type-declaration-stmt> = <declaration-type-spec> [ [ , <attr-spec> ]... :: ] <entity-decl-list>
     """
-    use_names = ['Declaration_Type_Spec', 'Attr_Spec', 'Entity_Decl_List']
+    subclass_names = []
+    use_names = ['Declaration_Type_Spec', 'Attr_Spec_List', 'Entity_Decl_List']
 
+    def match(string):
+        line, repmap = string_replace_map(string)
+        i = line.find(',')
+        if i==-1:
+            i = line.find('::')
+        if i==-1:
+            m = re.search(r'\s[a-z_]',line,re.I)
+            if m is None: return
+            i = m.start()
+        type_spec = Declaration_Type_Spec(repmap(line[:i]))
+        if type_spec is None: return
+        line = line[i:].lstrip()
+        if line.startswith(','):
+            i = line.find('::')
+            if i==-1: return
+            attr_specs = Attr_Spec_List(repmap(line[1:i].strip()))
+            if attr_specs is None: return
+            line = line[i:]
+        else:
+            attr_specs = None
+        if line.startswith('::'):
+            line = line[2:].lstrip()
+        entity_decls = Entity_Decl_List(repmap(line))
+        if entity_decls is None: return
+        return type_spec, attr_specs, entity_decls
+    match = staticmethod(match)
+    def init(self, *args):
+        self.type_spec, self.attr_specs, self.entity_decls = args
+        return
+    def tostr(self):
+        if self.attr_specs is None:
+            return '%s :: %s' % (self.type_spec, self.entity_decls)
+        else:
+            return '%s, %s :: %s' % (self.type_spec, self.attr_specs, self.entity_decls)
+    def torepr(self):
+        return '%s(%r, %r, %r)' % (self.__class__.__name__, self.type_spec, self.attr_specs, self.entity_decls)
+
 class Declaration_Type_Spec(Base):
     """
     <declaration-type-spec> = <intrinsic-type-spec>
@@ -465,8 +600,54 @@
     subclass_names = ['Intrinsic_Type_Spec']
     use_names = ['Derived_Type_Spec']
 
-class Attr_Spec(Base):
+    def match(string):
+        if string[-1] != ')': return
+        start = string[:4].upper()
+        if start == 'TYPE':
+            line = string[4:].lstrip()
+            if not line.startswith('('): return
+            return 'TYPE',Derived_Type_Spec(line[1:-1].strip())
+        start = string[:5].upper()
+        if start == 'CLASS':
+            line = string[5:].lstrip()
+            if not line.startswith('('): return
+            line = line[1:-1].strip()
+            if line=='*': return 'CLASS','*'
+            return 'CLASS', Derived_Type_Spec(line)
+        return
+    match = staticmethod(match)
+    init = Base.init_list
+    def tostr(self): return '%s(%s)' % tuple(map(str,self.items))
+    def torepr(self): return '%s(%r, %r)' % (self.__class__.__name__, self.items[0], self.items[1])
+
+class Dimension_Attr_Spec(CallBase):
     """
+    <dimension-attr-spec> = DIMENSION ( <array-spec> )
+    """
+    subclass_names = []
+    use_names = ['Array_Spec']
+    def match(string): return CallBase.match(pattern.abs_dimension, Array_Spec, string)
+    match = staticmethod(match)
+    def init(self, lhs, rhs):
+        self.lhs = lhs.upper()
+        self.rhs = rhs
+        return
+
+class Intent_Attr_Spec(CallBase):
+    """
+    <intent-attr-spec> = INTENT ( <intent-spec> )
+    """
+    subclass_names = []
+    use_names = ['Intent_Spec']
+    def match(string): return CallBase.match(pattern.abs_intent, Intent_Spec, string)
+    match = staticmethod(match)
+    def init(self, lhs, rhs):
+        self.lhs = lhs.upper()
+        self.rhs = rhs
+        return
+
+class Attr_Spec(STRINGBase):
+    """
     <attr-spec> = <access-spec>
                   | ALLOCATABLE
                   | ASYNCHRONOUS
@@ -484,16 +665,66 @@
                   | VALUE
                   | VOLATILE
     """
-    subclass_names = ['Access_Spec', 'Language_Binding_Spec']
-    use_names = ['Array_Spec', 'Intent_Spec']
+    subclass_names = ['Access_Spec', 'Language_Binding_Spec',
+                      'Dimension_Attr_Spec', 'Intent_Attr_Spec']
+    use_names = []
+    def match(string): return STRINGBase.match(pattern.abs_attr_spec, string)
+    match = staticmethod(match)
 
 class Entity_Decl(Base):
     """
     <entity-decl> = <object-name> [ ( <array-spec> ) ] [ * <char-length> ] [ <initialization> ]
                     | <function-name> [ * <char-length> ]
     """
+    subclass_names = []
     use_names = ['Object_Name', 'Array_Spec', 'Char_Length', 'Initialization', 'Function_Name']
-
+    def match(string):
+        m = pattern.name.match(string)
+        if m is None: return
+        name = Name(m.group())
+        newline = string[m.end():].lstrip()
+        if not newline: return name, None, None, None
+        array_spec = None
+        char_length = None
+        init = None
+        if newline.startswith('('):
+            line, repmap = string_replace_map(newline)
+            i = line.find(')')
+            if i==-1: return
+            array_spec = Array_Spec(repmap(line[1:i].strip()))
+            newline = repmap(line[i+1:].lstrip())
+        if newline.startswith('*'):
+            line, repmap = string_replace_map(newline)
+            i = line.find('=')
+            if i!=-1:
+                char_length = repmap(line[1:i].strip())
+                newline = repmap(newline[i:].lstrip())
+            else:
+                char_length = repmap(newline[1:].strip())
+                newline = ''
+            char_length = Char_Length(char_length)
+        if newline.startswith('='):
+            init = Initialization(newline)
+        else:
+            assert newline=='',`newline`
+        return name, array_spec, char_length, init
+    match = staticmethod(match)
+    def init(self, *args):
+        self.name, self.array_spec, self.char_length, self.init = args
+        return
+    def tostr(self):
+        s = str(self.name)
+        if self.array_spec is not None:
+            s += '(' + str(self.array_spec) + ')'
+        if self.char_length is not None:
+            s += '*' + str(self.char_length)
+        if self.init is not None:
+            s += ' ' + str(self.init)
+        return s
+    def torepr(self):
+        return '%s(%r, %r, %r, %r)' \
+               % (self.__class__.__name__, self.name, self.array_spec, self.char_length, self.init)
+    
 class Object_Name(Base):
     """
     <object-name> = <name>
@@ -505,7 +736,21 @@
     <initialization> =  = <initialization-expr>
                        | => <null-init> 
     """
+    subclass_names = []
     use_names = ['Initialization_Expr', 'Null_Init']
+    def match(string):
+        if string.startswith('=>'):
+            return '=>', Null_Init(string[2:].lstrip())
+        if string.startswith('='):
+            return '=', Initialization_Expr(string[2:].lstrip())
+        return
+    match = staticmethod(match)
+    def init(self, op, rhs):
+        self.op = op
+        self.rhs = rhs
+        return
+    def tostr(self): return '%s %s' % (self.op, self.rhs)
+    def torepr(self): return '%s(%r, %r)' % (self.__class__.__name__, self.op, self.rhs)
 
 class Null_Init(Base):
     """
@@ -515,17 +760,47 @@
     """
     subclass_names = ['Function_Reference']
 
-class Access_Spec(Base):
+class Access_Spec(STRINGBase):
     """
     <access-spec> = PUBLIC
                     | PRIVATE
     """
+    subclass_names = []
+    def match(string): return STRINGBase.match(pattern.abs_access_spec, string)
+    match = staticmethod(match)
 
 class Language_Binding_Spec(Base):
     """
     <language-binding-spec> = BIND ( C [ , NAME = <scalar-char-initialization-expr> ] )
     """
+    subclass_names = []
     use_names = ['Scalar_Char_Initialization_Expr']
+    def match(string):
+        start = string[:4].upper()
+        if start != 'BIND': return
+        line = string[4:].lstrip()
+        if not line or line[0]+line[-1]!='()': return
+        line = line[1:-1].strip()
+        if not line: return
+        start = line[0].upper()
+        if start!='C': return
+        line = line[1:].lstrip()
+        if not line: return None,
+        if not line.startswith(','): return
+        line = line[1:].lstrip()
+        start = line[:4].upper()
+        if start!='NAME': return
+        line=line[4:].lstrip()
+        if not line.startswith('='): return
+        return Scalar_Char_Initialization_Expr(line[1:].lstrip()),
+    match = staticmethod(match)
+    def init(self, name):
+        self.name = name
+    def tostr(self):
+        if self.name is None: return 'BIND(C)'
+        return 'BIND(C, NAME = %s)' % (self.name)
+    def torepr(self):
+        return '%s(%r)' % (self.__class__.__name__, self.name)
 
 class Array_Spec(Base):
     """
@@ -537,13 +812,23 @@
     subclass_names = ['Explicit_Shape_Spec_List', 'Assumed_Shape_Spec_List',
                       'Deferred_Shape_Spec_List', 'Assumed_Size_Spec']
 
-class Explicit_Shape_Spec(Base):
+class Explicit_Shape_Spec(SeparatorBase):
     """
     <explicit-shape-spec> = [ <lower-bound> : ] <upper-bound>
     """
-    use_names = ['Lower_Bound', 'Upper_Bound']
-
-
+    subclass_names = ['Upper_Bound']
+    use_names = ['Lower_Bound']
+    def match(string):
+        line, repmap = string_replace_map(string)
+        if ':' not in line: return
+        lower,upper = line.split(':',1)
+        for k in Base.findall(lower):
+            lower = lower.replace(k, repmap[k])
+        for k in Base.findall(upper):
+            upper = upper.replace(k, repmap[k])
+        return Lower_Bound(lower), Upper_Bound(upper)
+    match = staticmethod(match)
+    
 class Lower_Bound(Base):
     """
     <lower-bound> = <specification-expr>
@@ -560,30 +845,37 @@
     """
     <assumed-shape-spec> = [ <lower-bound> ] :
     """
+    subclass_names = []
     use_names = ['Lower_Bound']
 
 class Deferred_Shape_Spec(Base):
     """
     <deferred_shape_spec> = :
     """
+    subclass_names = []
 
 class Assumed_Size_Spec(Base):
     """
     <assumed-size-spec> = [ <explicit-shape-spec-list> , ] [ <lower-bound> : ] *
     """
+    subclass_names = []
     use_names = ['Explicit_Shape_Spec_List', 'Lower_Bound']
 
-class Intent_Spec(Base):
+class Intent_Spec(STRINGBase):
     """
     <intent-spec> = IN
                     | OUT
                     | INOUT
     """
+    subclass_names = []
+    def match(string): return STRINGBase.match(pattern.abs_intent_spec, string)
+    match = staticmethod(match)
 
 class Access_Stmt(Base):
     """
     <access-stmt> = <access-spec> [ [ :: ] <access-id-list> ]
     """
+    subclass_names = []
     use_names = ['Access_Spec', 'Access_Id_List']
 
 class Access_Id(Base):
@@ -597,4 +889,645 @@
     """
     <allocateble-stmt> = ALLOCATABLE [ :: ] <object-name> [ ( <deferred-shape-spec-list> ) ] [ , <object-name> [ ( <deferred-shape-spec-list> ) ] ]...
     """
+    subclass_names = []
     use_names = ['Object_Name', 'Deferred_Shape_Spec_List']
+
+class Asynchronous_Stmt(Base):
+    """
+    <asynchronous-stmt> = ASYNCHRONOUS [ :: ] <object-name-list>
+    """
+    subclass_names = []
+    use_names = ['Object_Name_List']
+
+class Bind_Stmt(Base):
+    """
+    <bind-stmt> = <language-binding-spec> [ :: ] <bind-entity-list>
+    """
+    use_names = ['Language_Binding_Spec', 'Bind_Entity_List']
+
+class Bind_Entity(Base):
+    """
+    <bind-entity> = <entity-name>
+                    | / <common-block-name> /
+    """
+    subclass_names = ['Entity_Name']
+    use_names = ['Common_Block_Name']
+
+class Data_Stmt(Base):
+    """
+    <data-stmt> = DATA <data-stmt-set> [ [ , ] <data-stmt-set> ]...
+    """
+    subclass_names = []
+    use_names = ['Data_Stmt_Set']
+
+class Data_Stmt_Set(Base):
+    """
+    <data-stmt-set> = <data-stmt-object-list> / <data-stmt-value-list> /
+    """
+    use_names = ['Data_Stmt_Object_List', 'Data_Stmt_Value_List']
+
+class Data_Stmt_Object(Base):
+    """
+    <data-stmt-object> = <variable>
+                         | <data-implied-do>
+    """
+    subclass_names = ['Variable', 'Data_Implied_Do']
+
+class Data_Implied_Do(Base):
+    """
+    <data-implied-do> = ( <data-i-do-object-list> , <data-i-do-variable> = <scalar-int-expr > , <scalar-int-expr> [ , <scalar-int-expr> ] )
+    """
+    subclass_names = []
+    use_names = ['Data_I_Do_Object_List', 'Data_I_Do_Variable', 'Scalar_Int_Expr']
+
+class Data_I_Do_Object(Base):
+    """
+    <data-i-do-object> = <array-element>
+                         | <scalar-structure-component>
+                         | <data-implied-do>
+    """
+    subclass_names = ['Array_Element', 'Scalar_Structure_Component', 'Data_Implied_Do']
+
+class Data_I_Do_Variable(Base):
+    """
+    <data-i-do-variable> = <scalar-int-variable>
+    """
+    subclass_names = ['Scalar_Int_Variable']
+
+class Data_Stmt_Value(Base):
+    """
+    <data-stmt-value> = [ <data-stmt-repeat> * ] <data-stmt-constant>
+    """
+    subclass_names = []
+    use_names = ['Data_Stmt_Repeat', 'Data_Stmt_Constant']
+
+class Data_Stmt_Repeat(Base):
+    """
+    <data-stmt-repeat> = <scalar-int-constant>
+                         | <scalar-int-constant-subobject>
+    """
+    subclass_names = ['Scalar_Int_Constant', 'Scalar_Int_Constant_Subobject']
+
+class Data_Stmt_Constant(Base):
+    """
+    <data-stmt-constant> = <scalar-constant>
+                           | <scalar-constant-subobject>
+                           | <signed-int-literal-constant>
+                           | <signed-real-literal-constant>
+                           | <null-init>
+                           | <structure-constructor>
+    """
+    subclass_names = ['Scalar_Constant', 'Scalar_Constant_Subobject',
+                      'Signed_Int_Literal_Constant', 'Signed_Real_Literal_Constant',
+                      'Null_Init', 'Structure_Constructor']
+
+class Int_Constant_Subobject(Base):
+    """
+    <int-constant-subobject> = <constant-subobject>
+    """
+    subclass_names = ['Constant_Subobject']
+
+class Scalar_Int_Constant_Subobject(Base):
+    subclass_names = ['Int_Constant_Subobject']
+
+class Scalar_Constant_Subobject(Base):
+    subclass_names = ['Constant_Subobject']
+
+class Constant_Subobject(Base):
+    """
+    <constant-subobject> = <designator>
+    """
+    subclass_names = ['Designator']
+
+class Dimension_Stmt(Base):
+    """
+    <dimension-stmt> = DIMENSION [ :: ] <array-name> ( <array-spec> ) [ , <array-name> ( <array-spec> ) ]...
+    """
+    subclass_names = []
+    use_names = ['Array_Name', 'Array_Spec']
+
+class Intent_Stmt(Base):
+    """
+    <intent-stmt> = INTENT ( <intent-spec> ) [ :: ] <dummy-arg-name-list>
+    """
+    subclass_names = []
+    use_names = ['Intent_Spec', 'Dummy_Arg_Name_List']
+
+class Optional_Stmt(Base):
+    """
+    <optional-stmt> = OPTIONAL [ :: ] <dummy-arg-name-list>
+    """
+    subclass_names = []
+    use_names = ['Dummy_Arg_Name_List']
+
+class Parameter_Stmt(Base):
+    """
+    <parameter-stmt> = PARAMETER ( <named-constant-def-list> )
+    """
+    subclass_names = []
+    use_names = ['Named_Constant_Def_List']
+
+class Named_Constant_Def(Base):
+    """
+    <named-constant-def> = <named-constant> = <initialization-expr>
+    """
+    subclass_names = []
+    use_names = ['Named_Constant', 'Initialization_Expr']
+
+class Pointer_Stmt(Base):
+    """
+    <pointer-stmt> = POINTER [ :: ] <pointer-decl-list>
+    """
+    subclass_names = []
+    use_names = ['Pointer_Decl_List']
+
+class Pointer_Decl(Base):
+    """
+    <pointer-decl> = <object-name> [ ( <deferred-shape-spec-list> ) ]
+                     | <proc-entity-name>
+    """
+    use_names = ['Object_Name', 'Deferred_Shape_Spec_List']
+    subclass_names = ['Proc_Entity_Name']
+
+class Protected_Stmt(Base):
+    """
+    <protected-stmt> = PROTECTED [ :: ] <entity-name-list>
+    """
+    subclass_names = []
+    use_names = ['Entity_Name_List']
+
+class Save_Stmt(Base):
+    """
+    <save-stmt> = SAVE [ [ :: ] <saved-entity-list> ]
+    """
+    subclass_names = []
+    use_names = ['Saved_Entity_List']
+
+class Saved_Entity(Base):
+    """
+    <saved-entity> = <object-name>
+                     | <proc-pointer-name>
+                     | / <common-block-name> /
+    """
+    subclass_names = ['Object_Name', 'Proc_Pointer_Name']
+    use_names = ['Common_Block_Name']
+
+class Proc_Pointer_Name(Base):
+    """
+    <proc-pointer-name> = <name>
+    """
+    subclass_names = ['Name']
+
+class Target_Stmt(Base):
+    """
+    <target-stmt> = TARGET [ :: ] <object-name> [ ( <array-spec> ) ] [ , <object-name> [ ( <array-spec> ) ]]
+    """
+    subclass_names = []
+    use_names = ['Object_Name', 'Array_Spec']
+
+class Value_Stmt(Base):
+    """
+    <value-stmt> = VALUE [ :: ] <dummy-arg-name-list>
+    """
+    subclass_names = []
+    use_names = ['Dummy_Arg_Name_List']
+
+class Volatile_Stmt(Base):
+    """
+    <volatile-stmt> = VOLATILE [ :: ] <object-name-list>
+    """
+    subclass_names = []
+    use_names = ['Object_Name_List']
+
+class Implicit_Stmt(Base):
+    """
+    <implicit-stmt> = IMPLICIT <implicit-spec-list>
+                      | IMPLICIT NONE
+    """
+    subclass_names = []
+    use_names = ['Implicit_Spec_List']
+
+class Implicit_Spec(Base):
+    """
+    <implicit-spec> = <declaration-type-spec> ( <letter-spec-list> )
+    """
+    subclass_names = []
+    use_names = ['Declaration_Type_Spec', 'Letter_Spec_List']
+
+class Letter_Spec(Base):
+    """
+    <letter-spec> = <letter> [ - <letter> ]
+    """
+    subclass_names = []
+
+class Namelist_Stmt(Base):
+    """
+    <namelist-stmt> = NAMELIST / <namelist-group-name> / <namelist-group-object-list> [ [ , ] / <namelist-group-name> / <namelist-group-object-list> ]
+    """
+    subclass_names = []
+    use_names = ['Namelist_Group_Name', 'Namelist_Group_Object_List']
+
+class Namelist_Group_Object(Base):
+    """
+    <namelist-group-object> = <variable-name>
+    """
+    subclass_names = ['Variable_Name']
+
+class Equivalence_Stmt(Base):
+    """
+    <equivalence-stmt> = EQUIVALENCE <equivalence-set-list>
+    """
+    subclass_names = []
+    use_names = ['Equivalence_Set_List']
+
+class Equivalence_Set(Base):
+    """
+    <equivalence-set> = ( <equivalence-object> , <equivalence-object-list> )
+    """
+    subclass_names = []
+    use_names = ['Equivalence_Object', 'Equivalence_Object_List']
+
+class Equivalence_Object(Base):
+    """
+    <equivalence-object> = <variable-name>
+                           | <array-element>
+                           | <substring>
+    """
+    subclass_names = ['Variable_Name', 'Array_Element', 'Substring']
+
+class Common_Stmt(Base):
+    """
+    <common-stmt> = COMMON [ / [ <common-block-name> ] / ] <common-block-object-list> [ [ , ] / [ <common-block-name> ] / <common-block-object-list> ]...
+    """
+    subclass_names = []
+    use_names = ['Common_Block_Name', 'Common_Block_Object_List']
+
+class Common_Block_Object(Base):
+    """
+    <common-block-object> = <variable-name> [ ( <explicit-shape-spec-list> ) ]
+                            | <proc-pointer-name>
+    """
+    subclass_names = ['Proc_Pointer_Name']
+    use_names = ['Variable_Name', 'Explicit_Shape_Spec_List']
+
+class Variable_Name(Base):
+    """
+    <variable-name> = <name>
+    """
+    subclass_names = ['Name']
+
+class Int_Variable(Base):
+    """
+    <int-variable> = <variable>
+    """
+    subclass_names = ['Variable']
+
+class Scalar_Int_Variable(Base):
+    """
+    <scalar-int-variable> = <int-variable>
+    """
+    subclass_names = ['Int_Variable']
+
+class Char_Variable(Base):
+    """
+    <char-variable> = <variable>
+    """
+    subclass_names = ['Variable']
+
+class Scalar_Default_Char_Variable(Base):
+    """
+    <scalar-default-char-variable> = <char-variable>
+    """
+    subclass_names = ['Char_Variable']
+
+class Allocate_Stmt(Base):
+    """
+    <allocate-stmt> = ALLOCATE ( [ <type-spec> :: ] <allocation-list> [ , <alloc-opt-list> ] )
+    """
+    subclass_names = []
+    use_names = ['Type_Spec', 'Allocation_List', 'Alloc_Opt_List']
+    
+class Alloc_Opt(Base):
+    """
+    <alloc-opt> = STAT = <stat-variable>
+                  | ERRMSG = <errmsg-variable>
+                  | SOURCE = <source-expr>
+    """
+    subclass_names = []
+    use_names = ['Stat_Variable', 'Errmsg_Variable', 'Source_Expr',
+                 ]
+
+class Stat_Variable(Base):
+    """
+    <stat-variable> = <scalar-int-variable>
+    """
+    subclass_names = ['Scalar_Int_Variable']
+
+class Errmsg_Variable(Base):
+    """
+    <errmsg-variable> = <scalar-default-char-variable>
+    """
+    subclass_names = ['Scalar_Default_Char_Variable']
+
+class Source_Expr(Base):
+    """
+    <source-expr> = <expr>
+    """
+    subclass_names = ['Expr']
+
+class Allocation(Base):
+    """
+    <allocation> = <allocate-object> [ <allocate-shape-spec-list> ]
+                 | <variable-name>
+    """
+    subclass_names = ['Variable_Name']
+    use_names = ['Allocate_Object', 'Allocate_Shape_Spec_List']
+
+class Allocate_Shape_Spec(Base):
+    """
+    <allocate-shape-spec> = [ <lower-bound-expr> : ] <upper-bound-expr>
+    """
+    subclass_names = []
+    use_names = ['Lower_Bound_Expr', 'Upper_Bound_Expr']
+
+class Lower_Bound_Expr(Base):
+    """
+    <lower-bound-expr> = <scalar-int-expr>
+    """
+    subclass_names = ['Scalar_Int_Expr']
+
+class Upper_Bound_Expr(Base):
+    """
+    <upper-bound-expr> = <scalar-int-expr>
+    """
+    subclass_names = ['Scalar_Int_Expr']
+
+class Nullify_Stmt(Base):
+    """
+    <nullify-stmt> = NULLIFY ( <pointer-object-list> )
+    """
+    subclass_names = []
+    use_names = ['Pointer_Object_List']
+
+class Pointer_Object(Base):
+    """
+    <pointer-object> = <variable-name>
+                       | <structure-component>
+                       | <proc-pointer-name>
+    """
+    subclass_names = ['Variable_Name', 'Structure_Component', 'Proc_Pointer_Name']
+
+class Deallocate_Stmt(Base):
+    """
+    <deallocate-stmt> = DEALLOCATE ( <allocate-object-list> [ , <dealloc-opt-list> ] )
+    """
+    subclass_names = []
+    use_names = ['Allocate_Object_List', 'Dealloc_Opt_List']
+
+class Dealloc_Opt(Base):
+    """
+    <dealloc-opt> = STAT = <stat-variable>
+                    | ERRMSG = <errmsg-variable>
+    """
+    subclass_names = []
+    use_names = ['Stat_Variable', 'Errmsg_Variable']
+
+
+class Logical_Expr(Base):
+    """
+    <logical-expr> = <expr>
+    """
+    subclass_names = ['Expr']
+
+class Char_Expr(Base):
+    """
+    <char-expr> = <expr>
+    """
+    subclass_names = ['Expr']
+
+class Default_Char_Expr(Base):
+    """
+    <default-char-expr> = <expr>
+    """
+    subclass_names = ['Expr']
+
+class Int_Expr(Base):
+    """
+    <int-expr> = <expr>
+    """
+    subclass_names = ['Expr']
+
+class Numeric_Expr(Base):
+    """
+    <numeric-expr> = <expr>
+    """
+    subclass_names = ['Expr']
+
+class Specification_Expr(Base):
+    """
+    <specification-expr> = <expr>
+    """
+    subclass_names = ['Expr']
+
+class Char_Initialization_Expr(Base):
+    """
+    <char-initialization-expr> = <expr>
+    """
+    subclass_names = ['Char_Expr']
+
+class Scalar_Char_Initialization_Expr(Base):
+    subclass_names = ['Char_Initialization_Expr']
+
+class Initialization_Expr(Base):
+    """
+    <initialization-expr> = <expr>
+    """
+    subclass_names = ['Expr']
+
+class Int_Initialization_Expr(Base):
+    """
+    <int-initialization-expr> = <expr>
+    """
+    subclass_names = ['Int_Expr']
+
+class Logical_Initialization_Expr(Base):
+    """
+    <logical-initialization-expr> = <expr>
+    """
+    subclass_names = ['Logical_Expr']
+
+class Where_Stmt(Base):
+    """
+    <where-stmt> = WHERE ( <mask-expr> ) <where-assignment-stmt>
+    """
+    subclass_names = []
+    use_names = ['Mask_Expr', 'Where_Assignment_Stmt']
+
+class Where_Construct(Base):
+    """
+    <where-construct> = <where-construct-stmt>
+                              [ <where-body-construct> ]...
+                            [ <masked-elsewhere-stmt>
+                              [ <where-body-construct> ]...
+                            ]...
+                            [ <elsewhere-stmt>
+                              [ <where-body-construct> ]... ]
+                            <end-where-stmt>
+    """
+    subclass_names = []
+    use_names = ['Where_Construct_Stmt', 'Where_Body_Construct',
+                 'Elsewhere_Stmt', 'End_Where_Stmt'
+                 ]
+
+class Where_Construct_Stmt(Base):
+    """
+    <where-construct-stmt> = [ <where-construct-name> : ] WHERE ( <masked-expr> )
+    """
+    subclass_names = []
+    use_names = ['Where_Construct_Name', 'Masked_Expr']
+
+class Where_Body_Construct(Base):
+    """
+    <where-body-construct> = <where-assignment-stmt>
+                             | <where-stmt>
+                             | <where-construct>
+    """
+    subclass_names = ['Where_Assignment_Stmt', 'Where_Stmt', 'Where_Construct']
+
+class Where_Assignment_Stmt(Base):
+    """
+    <where-assignment-stmt> = <assignment-stmt>
+    """
+    subclass_names = ['Assignment_Stmt']
+
+class Mask_Expr(Base):
+    """
+    <mask-expr> = <logical-expr>
+    """
+    subclass_names = ['Logical_Expr']
+
+class Masked_Elsewhere_Stmt(Base):
+    """
+    <masked-elsewhere-stmt> = ELSEWHERE ( <mask-expr> ) [ <where-construct-name> ]
+    """
+    subclass_names = []
+    use_names = ['Mask_Expr', 'Where_Construct_Name']
+
+class Elsewhere_Stmt(Base):
+    """
+    <elsewhere-stmt> = ELSEWHERE [ <where-construct-name> ]
+    """
+    subclass_names = []
+    use_names = ['Where_Construct_Name']
+
+class End_Where_Stmt(Base):
+    """
+    <end-where-stmt> = END WHERE [ <where-construct-name> ]
+    """
+    subclass_names = []
+    use_names = ['Where_Construct_Name']
+
+class Proc_Language_Binding_Spec(Base): # R1125
+    subclass_names = ['Language_Binding_Spec']
+
+
+class Dummy_Arg_Name(Base): # R1226
+    """
+    <dummy-arg-name> = <name>
+    """
+    subclass_names = ['Name']
+
+class Subroutine_Stmt(Base): # R1232
+    """
+    <subroutine-stmt> = [ <prefix> ] SUBROUTINE <subroutine-name> [ ( [ <dummy-arg-list> ] ) [ <proc-language-binding-spec> ] ]
+    """
+    subclass_names = []
+    use_names = ['Prefix', 'Subroutine_Name', 'Dummy_Arg_List', 'Proc_Language_Binding_Spec']
+    def match(string):
+        line, repmap = string_replace_map(string)
+        m = pattern.subroutine.search(line)
+        prefix = line[:m.start()].rstrip() or None
+        if prefix is not None:
+            prefix = Prefix(repmap(prefix))
+        line = line[m.end():].lstrip()
+        m = pattern.name.match(line)
+        if m is None: return
+        name = Subroutine_Name(m.group())
+        line = line[m.end():].lstrip()
+        dummy_args = None
+        if line.startswith('('):
+            i = line.find(')')
+            if i==-1: return
+            dummy_args = line[1:i].strip() or None
+            if dummy_args is not None:
+                dummy_args = Dummy_Arg_List(repmap(dummy_args))
+            line = line[i+1:].lstrip()
+        binding_spec = None
+        if line:
+            binding_spec = Proc_Language_Binding_Spec(repmap(line))
+        return prefix, name, dummy_args, binding_spec
+    match = staticmethod(match)
+    def init(self, *args):
+        self.prefix, self.name, self.dummy_args, self.binding_spec = args
+        return
+    def tostr(self):
+        if self.prefix is not None:
+            s = '%s SUBROUTINE %s' % (self.prefix, self.name)
+        else:
+            s = 'SUBROUTINE %s' % (self.name)
+        if self.dummy_args is not None:
+            s += '(%s)' % (self.dummy_args)
+        if self.binding_spec is not None:
+            s += ' %s' % (self.binding_spec)
+        return s
+    def torepr(self):
+        return '%s(%r, %r, %r, %r)'\
+               % (self.__class__.__name__, self.prefix, self.name, self.dummy_args, self.binding_spec)
+
+class End_Subroutine_Stmt(EndStmtBase): # R1234
+    """
+    <end-subroutine-stmt> = END [ SUBROUTINE [ <subroutine-name> ] ]
+    """
+    subclass_names = []
+    use_names = ['Subroutine_Name']
+    def match(string): return EndStmtBase.match('SUBROUTINE', Subroutine_Name, string)
+    match = staticmethod(match)
+
+class Dummy_Arg(StringBase): # R1233
+    """
+    <dummy-arg> = <dummy-arg-name>
+                  | *
+    """
+    subclass_names = ['Dummy_Arg_Name']
+    def match(string):
+        if string=='*': return '*',
+        return
+    match = staticmethod(match)
+
+# Create *_List classes:
+ClassType = type(Base)
+_names = dir()
+for clsname in _names:
+    cls = eval(clsname)
+    if not (isinstance(cls, ClassType) and issubclass(cls, Base) and not cls.__name__.endswith('Base')): continue
+    names = getattr(cls, 'subclass_names', []) + getattr(cls, 'use_names', [])
+    for n in names:
+        if n in _names: continue
+        if n.endswith('_List'):
+            n = n[:-5]
+            print 'Generating %s_List' % (n)
+            exec '''\
+class %s_List(SequenceBase):
+    subclass_names = [\'%s\']
+    use_names = []
+    def match(string): return SequenceBase.match(r\',\', %s, string)
+    match = staticmethod(match)
+''' % (n, n, n)
+        if n.endswith('_Name'):
+            n = n[:-5]
+            print 'Generating %s_Name' % (n)
+            exec '''\
+class %s_Name(Base):
+    subclass_names = [\'Name\']
+''' % (n)
+

Modified: trunk/numpy/f2py/lib/parser/test_expressions.py
===================================================================
--- trunk/numpy/f2py/lib/parser/test_expressions.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/test_expressions.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -2,7 +2,8 @@
 
 from numpy.testing import *
 
-from expressions import *
+#from expressions import *
+from Fortran2003 import *
 
 class test_Expr(NumpyTestCase):
 
@@ -692,7 +693,7 @@
 class test_Section_Subscript(NumpyTestCase):
 
     def check_simple(self):
-        cls_in = Section_Subscript
+        cls = Section_Subscript
 
         a = cls('1:2')
         assert isinstance(a, Subscript_Triplet),`a`

Added: trunk/numpy/f2py/lib/parser/test_statements2.py
===================================================================
--- trunk/numpy/f2py/lib/parser/test_statements2.py	2006-10-29 07:38:25 UTC (rev 3416)
+++ trunk/numpy/f2py/lib/parser/test_statements2.py	2006-10-30 19:21:25 UTC (rev 3417)
@@ -0,0 +1,189 @@
+from numpy.testing import *
+
+from Fortran2003 import *
+
+class test_Declaration_Type_Spec(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Declaration_Type_Spec
+        a = cls('Integer*2')
+        assert isinstance(a, Intrinsic_Type_Spec),`a`
+        assert_equal(str(a), 'INTEGER*2')
+        
+        a = cls('type(foo)')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a), 'TYPE(foo)')
+        assert_equal(repr(a), "Declaration_Type_Spec('TYPE', Type_Name('foo'))")
+
+class test_Type_Declaration_Stmt(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Type_Declaration_Stmt
+        a = cls('integer a')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a), 'INTEGER :: a')
+        assert_equal(repr(a), "Type_Declaration_Stmt(Intrinsic_Type_Spec('INTEGER', None), None, Entity_Decl(Name('a'), None, None, None))")
+
+        a = cls('integer ,dimension(2):: a*3')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a), 'INTEGER, DIMENSION(2) :: a*3')
+
+class test_Access_Spec(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Access_Spec
+        a = cls('private')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a), 'PRIVATE')
+        assert_equal(repr(a), "Access_Spec('PRIVATE')")
+
+        a = cls('public')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a), 'PUBLIC')
+
+class test_Attr_Spec(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Attr_Spec
+        a = cls('allocatable')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a), 'ALLOCATABLE')
+
+        a = cls('dimension(a)')
+        assert isinstance(a, Dimension_Attr_Spec),`a`
+        assert_equal(str(a),'DIMENSION(a)')
+
+class test_Dimension_Attr_Spec(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Dimension_Attr_Spec
+        a = cls('dimension(a)')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'DIMENSION(a)')
+        assert_equal(repr(a),"Dimension_Attr_Spec('DIMENSION', Name('a'))")
+
+class test_Intent_Attr_Spec(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Intent_Attr_Spec
+        a = cls('intent(in)')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'INTENT(IN)')
+        assert_equal(repr(a),"Intent_Attr_Spec('INTENT', Intent_Spec('IN'))")
+
+class test_Language_Binding_Spec(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Language_Binding_Spec
+        a = cls('bind(c)')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'BIND(C)')
+        assert_equal(repr(a),'Language_Binding_Spec(None)')
+
+        a = cls('bind(c, name="hey")')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'BIND(C, NAME = "hey")')
+
+class test_Entity_Decl(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Entity_Decl
+        a = cls('a(1)')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'a(1)')
+        assert_equal(repr(a),"Entity_Decl(Name('a'), Int_Literal_Constant('1', None), None, None)")
+
+        a = cls('a(1)*(3)')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'a(1)*(3)')
+
+        a = cls('a(1)*(3) = 2')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'a(1)*(3) = 2')
+
+class test_Prefix_Spec(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Prefix_Spec
+        a = cls('pure')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'PURE')
+        assert_equal(repr(a),"Prefix_Spec('PURE')")
+
+        a = cls('elemental')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'ELEMENTAL')
+
+        a = cls('recursive')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'RECURSIVE')
+
+        a = cls('integer * 2')
+        assert isinstance(a, Intrinsic_Type_Spec),`a`
+        assert_equal(str(a),'INTEGER*2')
+
+class test_Prefix(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Prefix
+        a = cls('pure  recursive')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'PURE RECURSIVE')
+        assert_equal(repr(a), "Prefix(' ', (Prefix_Spec('PURE'), Prefix_Spec('RECURSIVE')))")
+
+        a = cls('integer * 2 pure')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'INTEGER*2 PURE')
+
+class test_Subroutine_Stmt(NumpyTestCase):
+
+    def check_simple(self):
+        cls = Subroutine_Stmt
+        a = cls('subroutine foo')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'SUBROUTINE foo')
+        assert_equal(repr(a),"Subroutine_Stmt(None, Name('foo'), None, None)")
+
+        a = cls('pure subroutine foo')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'PURE SUBROUTINE foo')
+
+        a = cls('pure subroutine foo(a,b)')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'PURE SUBROUTINE foo(a, b)')
+
+        a = cls('subroutine foo() bind(c)')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'SUBROUTINE foo BIND(C)')
+
+class test_End_Subroutine_Stmt(NumpyTestCase):
+
+    def check_simple(self):
+        cls = End_Subroutine_Stmt
+        a = cls('end subroutine foo')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'END SUBROUTINE foo')
+        assert_equal(repr(a),"End_Subroutine_Stmt('SUBROUTINE', Name('foo'))")
+
+        a = cls('end')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'END SUBROUTINE')
+
+        a = cls('endsubroutine')
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'END SUBROUTINE')
+
+class test_Specification_Part(NumpyTestCase):
+
+    def check_simple(self):
+        from api import get_reader
+        reader = get_reader('''\
+      integer a''')
+        cls = Specification_Part
+        a = cls(reader)
+        assert isinstance(a, cls),`a`
+        assert_equal(str(a),'INTEGER :: a')
+        assert_equal(repr(a),'INTEGER :: a')
+
+if __name__ == "__main__":
+    NumpyTest().run()



More information about the Numpy-svn mailing list