summaryrefslogtreecommitdiff
path: root/numpy/f2py/lib/block.py
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/f2py/lib/block.py')
-rw-r--r--numpy/f2py/lib/block.py368
1 files changed, 177 insertions, 191 deletions
diff --git a/numpy/f2py/lib/block.py b/numpy/f2py/lib/block.py
index b9bafdcff..09d39d0e2 100644
--- a/numpy/f2py/lib/block.py
+++ b/numpy/f2py/lib/block.py
@@ -11,238 +11,241 @@ Created: May 2006
"""
-__all__ = ['Block','Module','PythonModule','Interface',
- 'Subroutine','Function','Type']
+__all__ = ['Block','ModuleBlock','PythonModuleBlock','InterfaceBlock',
+ 'SubroutineBlock','FunctionBlock','TypeBlock', 'ProgramBlock',
+ 'BlockDataBlock','DoBlock','IfThenBlock','SelectBlock',
+ 'StatementBlock']
import re
import sys
from readfortran import Line
-from splitline import split2, string_replace_map
+from splitline import string_replace_map
+from stmt import statements, end_stmts, block_stmts
class Block:
-
- classes = []
- end_re = re.compile(r'\s*end\s*\Z', re.I)
-
- def __init__(self, parent):
+ """
+ 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 instaces
+ from/to Fortran reader.
+ isvalid - boolean, when False, the Block instance will be ignored.
+ """
+
+ classes = {}
+
+ end_re = re.compile(r'end\Z', re.I).match
+
+ def __init__(self, parent, item = None):
+ """
+ parent - Block or FortanParser instance having the
+ following attributes: reader, get_item, put_item
+ item - Line instance containing the beginning of block
+ statement.
+ """
self.parent = parent
- self.isfix77 = parent.isfix77
self.reader = parent.reader
- self.get_item = parent.get_item
- self.put_item = parent.put_item
- self.lower = not self.reader.ispyf
+ self.get_item = parent.get_item # get line function
+ self.put_item = parent.put_item # put line function
self.content = []
self.name = None
+ self.item = item
+ if item is None:
+ return
+ stmt = self.stmt_cls(self, item)
+ self.isvalid = stmt.isvalid
+ if self.isvalid:
+ self.content.append(stmt)
+ self.name = stmt.name
+ self.fill() # read block content
+
def get_name(self):
- if self.__class__ is Block: return '__MAIN__'
- if self.name is None: return ''
+ if self.__class__ is Block: return '__F2PY_MAIN__'
+ if not hasattr(self,'name') or self.name is None: return ''
return self.name
def __str__(self):
- tab = ''
- p = self.parent
- while isinstance(p, Block):
- tab += ' '
- p = p.parent
- name = self.get_name()
- l=[tab+'begin '+self.__class__.__name__ +' '+ name]
+ l=[]
for c in self.content:
l.append(str(c))
- l.append(tab+'end '+self.__class__.__name__ +' '+ name)
return '\n'.join(l)
- def isenditem(self, item):
- line,sline = split2(item.get_line())
- if sline: return False # end statement never contains strings
+ def isstmt(self, item):
+ """
+ Check is item is blocks start statement, if it is, read the block.
+ """
+ line = item.get_line()
+ mode = item.reader.mode
+ classes = self.classes[mode] + statements[self.__class__.__name__]
+ for cls in classes:
+ if issubclass(cls, Block):
+ match_cmd = cls.stmt_cls.start_re
+ else:
+ match_cmd = cls.start_re
+ if match_cmd(line):
+ subblock = cls(self, item)
+ if subblock.isvalid:
+ self.content.append(subblock)
+ return True
+ return False
+
+ def isendblock(self, item):
+ line = item.get_line()
if self.__class__ is Block:
# 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.isfix77:
- m = self.end_re.match(line)
+ if self.reader.isfix77:
+ m = self.end_re(line)
if m:
message = self.reader.format_message(\
'WARNING',
'assuming the end of undefined PROGRAM statement',
item.span[0],item.span[1])
print >> sys.stderr, message
- i = Line('program UNDEFINED',(0,0),None,self.reader)
- p = Program(self,Program.start_re.match(i.get_line()),i)
+ l = Line('program UNDEFINED',(0,0),None,self.reader)
+ p = Program(self,l)
p.content.extend(self.content)
self.content[:] = [p]
- return None
+ return True
return False
- m = self.end_re.match(line)
- if not m: return False
- # check if the block start name matches with the block end name
-
- if m.groupdict().has_key('name'):
- end_name = m.group('name')
- if end_name: end_name = end_name.strip()
- name = self.get_name()
- if end_name and name != end_name:
- message = self.reader.format_message(\
- 'WARNING',
- 'expected the end of %r block but got end of %r'\
- % (name, end_name),
- item.span[0],item.span[1])
- print >> sys.stderr, message
- return True
-
- def isblock(self, item):
- line = item.get_line()
- for cls in self.classes:
- m = cls.start_re.match(line)
- if m:
- subblock = cls(self, m, item)
- self.content.append(subblock)
- subblock.fill()
+ cls = self.end_stmt_cls
+ if cls.start_re(line):
+ stmt = cls(self, item)
+ if stmt.isvalid:
+ self.content.append(stmt)
return True
return False
def fill(self):
+ """
+ Fills blocks content until the end of block statement.
+ """
end_flag = self.__class__ is Block
- item = startitem = self.get_item()
+ item = self.get_item()
while item is not None:
if isinstance(item, Line):
# handle end of a block
- flag = self.isenditem(item)
- if flag: # end of block
+ if self.isendblock(item):
end_flag = True
break
- if flag is None: # fixing the end of undefined start
- item = self.get_item()
- continue
- # handle subblocks
- if self.isblock(item):
- item = self.get_item()
- continue
- # line contains something else
- self.content.append(item)
+ elif not self.isstmt(item):
+ # put unknown item's to content.
+ self.content.append(item)
item = self.get_item()
if not end_flag:
message = self.reader.format_message(\
'WARNING',
- 'failed to find the end of block',
+ 'failed to find the end of block for %s'\
+ % (self.__class__.__name__),
self.item.span[0],self.item.span[1])
print >> sys.stderr, message
sys.stderr.flush()
return
-class CodeBlock(Block):
- def __init__(self, parent, start_re_match, item):
- Block.__init__(self, parent)
- self.name = start_re_match.group('name')
- self.item = item
-
-class Program(CodeBlock):
- classes = []
- start_re = re.compile(r'\s*program\s*((?P<name>\w+)|)', re.I)
- end_re = re.compile(r'\s*end(\s*program(\s*(?P<name>\w+)|)|)\s*\Z', re.I)
-
-
-class Module(CodeBlock):
- classes = []
- start_re = re.compile(r'\s*module\s*(?P<name>\w+)\s*\Z', re.I)
- end_re = re.compile(r'\s*end(\s*module(\s*(?P<name>\w+)|)|)\s*\Z', re.I)
- def __init__(self, parent, start_re_match, item):
- Block.__init__(self, parent)
- self.name = start_re_match.group('name')
- self.item = item
-
-class Interface(CodeBlock):
- classes = []
- start_re = re.compile(r'\s*interface(\s*(?P<name>\w+)|)', re.I)
- end_re = re.compile(r'\s*end(\s*interface(\s*(?P<name>\w+)|)|)\s*\Z', re.I)
-
-class PythonModule(CodeBlock):
- classes = []
- start_re = re.compile(r'\s*python\s*module\s*(?P<name>\w+)', re.I)
- end_re = re.compile(r'\s*end(\s*python\s*module(\s*(?P<name>\w+)|)|)\s*\Z', re.I)
+class ProgramUnit(Block):
+ """
+ <main program>
+ <external subprogram (function | subroutine)>
+ <module>
+ <block data>
+ """
+
+class ProgramBlock(ProgramUnit):
+ """
+ program [name]
+ <specification part>
+ <execution part>
+ <internal subprogram part>
+ end [program [name]]
+ """
+ classes = {}
-class Subroutine(CodeBlock):
- classes = []
- start_re = re.compile(r'\s*subroutine\s*(?P<name>\w+)', re.I)
- end_re = re.compile(r'\s*end(\s*subroutine(\s*(?P<name>\w+)|)|)\s*\Z', re.I)
-
-class Function(CodeBlock):
- classes = []
- start_re = re.compile(r'\s*(?P<prefix>[\w,\s=()]*)\s*function\s*(?P<name>\w+)', re.I)
- end_re = re.compile(r'\s*end(\s*function(\s*(?P<name>\w+)|)|)\s*\Z')
-
-class Type(CodeBlock):
- classes = []
- start_re = re.compile(r'\s*type(?!\s*\()(.*::|)\s*(?P<name>\w+)\s*\Z', re.I)
- end_re = re.compile(r'\s*end(\s*type(\s*(?P<name>\w+)|)|)\s*\Z', re.I)
+class ModuleBlock(ProgramUnit):
+ """
+ module <name>
+ <specification part>
+ <module subprogram part>
+ end [module [name]]
+ """
+ classes = {}
+
+class BlockDataBlock(ProgramUnit):
+ """
+ block data [name]
+ end [block data [name]]
+ """
+ classes = {}
+
+class InterfaceBlock(ProgramUnit):
+ """
+ abstract interface | interface [<generic-spec>]
+ <interface specification>
+ end interface [<generic spec>]
+ """
+ classes = {}
+
+class PythonModuleBlock(ProgramUnit):
+ """
+ python module <name>
+ ..
+ end [python module [<name>]]
+ """
+
+class SubroutineBlock(ProgramUnit):
+ """
+ [prefix] subroutine <name> [ ( [<dummy-arg-list>] ) [<proc-language-binding-spec>]]
+ <specification-part>
+ <execution-part>
+ <internal-subprogram part>
+ end [subroutine [name]]
+ """
+ classes = {}
+
+class FunctionBlock(ProgramUnit):
+ classes = {}
+
+class TypeBlock(Block):
+ """
+ type [[type-attr-spec-list] ::] <name> [(type-param-name-list)]
+ <type-param-def-stmt>
+ <private-or-sequence>
+ <component-part>
+ <type-bound-procedure-part>
+ end type [name]
+ """
+ classes = {}
class StatementBlock(Block):
- classes = []
-
- def __init__(self, parent, start_re_match, item):
- Block.__init__(self, parent)
- self.item = item
-
- def isenditem(self, item):
- line,sline = split2(item.get_line())
- if sline: return False # end statement never contains strings
- m = self.end_re.match(line)
- if not m: return False
- # check if the block start name matches with the block end name
- if m.groupdict().has_key('name'):
- end_name = m.group('name')
- if end_name: end_name = end_name.strip()
- name = self.get_name()
- if end_name and name != end_name:
- message = self.reader.format_message(\
- 'WARNING',
- 'expected the end of %r block but got end of %r'\
- % (name, end_name),
- item.span[0],item.span[1])
- print >> sys.stderr, message
- return True
-
- def fill(self):
- item = self.get_item()
- while item is not None:
- if isinstance(item, Line):
- # handle end of a block
- flag = self.isenditem(item)
- if flag: # end of block
- break
- # handle subblocks
- if self.isblock(item):
- item = self.get_item()
- continue
-
- # line contains something else
- self.content.append(item)
- item = self.get_item()
- if item is None:
- message = self.reader.format_message(\
- 'WARNING',
- 'failed to find the end of block',
- self.item.span[0],self.item.span[1])
- print >> sys.stderr, message
- sys.stderr.flush()
- return
-
+ """
+ <start stmt-block>
+ <statements>
+ <end stmt-block>
+ """
+ classes = {}
+
class DoBlock(StatementBlock):
- start_re = re.compile(r'\s*do\b\s*(?P<label>\d*)', re.I)
- end_re = re.compile(r'\s*end\s*do(\s*(?P<name>.*)|)\s*\Z', re.I)
- def __init__(self, parent, start_re_match, item):
- StatementBlock.__init__(self, parent, start_re_match, item)
- label = start_re_match.group('label').strip()
- if label.endswith(':'): label = label[:-1].strip()
+ begin_re = re.compile(r'do\b\s*(?P<label>\d*)', re.I).match
+
+ def __init__(self, parent, item):
+ label = self.begin_re(item.get_line()).group('label').strip()
self.endlabel = label
- self.name = item.label
+ StatementBlock.__init__(self, parent, item)
- def isenditem(self, item):
+ def isendblock(self, item):
if self.endlabel:
+ # Handle:
+ # do 1, i=1,n
+ # ..
+ # 1 continue
if item.label==self.endlabel:
# item may contain computational statemets
self.content.append(item)
@@ -250,31 +253,14 @@ class DoBlock(StatementBlock):
self.put_item(item)
return True
else:
- return StatementBlock.isenditem(self, item)
+ return StatementBlock.isendblock(self, item)
return False
class IfThenBlock(StatementBlock):
- start_re = re.compile(r'\s*if\b.*?\bthen\s*\Z', re.I)
- #start_re = re.compile(r'\s*if\b', re.I)
- end_re = re.compile(r'\s*end\s*if(\s*(?P<name>.*)|)\s*\Z', re.I)
+ pass
- def __init__(self, parent, start_re_match, item):
- StatementBlock.__init__(self, parent, start_re_match, item)
- self.name = item.label
-
-
-# Initialize classes lists
-
-basic_blocks = [Program,PythonModule,Module,Interface,Subroutine,Function,Type]
-stmt_blocks = [DoBlock,IfThenBlock]
+class SelectBlock(StatementBlock):
-Block.classes.extend(basic_blocks + stmt_blocks)
-Module.classes.extend(Block.classes[1:])
-PythonModule.classes.extend(Module.classes)
-Interface.classes.extend(Block.classes[1:])
-Subroutine.classes.extend(Block.classes[1:])
-Function.classes.extend(Subroutine.classes)
-Type.classes.extend(Block.classes[3:])
+ pass
-StatementBlock.classes.extend(stmt_blocks)