summaryrefslogtreecommitdiff
path: root/numpy/f2py/lib
diff options
context:
space:
mode:
authorPearu Peterson <pearu.peterson@gmail.com>2006-06-05 20:58:13 +0000
committerPearu Peterson <pearu.peterson@gmail.com>2006-06-05 20:58:13 +0000
commit858fdcea384a8b7c2460ec00501a26d8caa6995c (patch)
treeb94caf2bd61b31dc1773de0196049f42aa5e1e53 /numpy/f2py/lib
parentd3d8f52c27e035bcdfd52344a03c370299a75196 (diff)
downloadnumpy-858fdcea384a8b7c2460ec00501a26d8caa6995c.tar.gz
Impl. Fortran parser cont.
Diffstat (limited to 'numpy/f2py/lib')
-rw-r--r--numpy/f2py/lib/block.py368
-rw-r--r--numpy/f2py/lib/init.py85
-rw-r--r--numpy/f2py/lib/parsefortran.py69
-rw-r--r--numpy/f2py/lib/readfortran.py32
-rw-r--r--numpy/f2py/lib/splitline.py267
-rw-r--r--numpy/f2py/lib/stmt.py578
6 files changed, 1167 insertions, 232 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)
diff --git a/numpy/f2py/lib/init.py b/numpy/f2py/lib/init.py
new file mode 100644
index 000000000..a803a9580
--- /dev/null
+++ b/numpy/f2py/lib/init.py
@@ -0,0 +1,85 @@
+
+from block import *
+from stmt import *
+
+basic_blocks = [ProgramBlock,PythonModuleBlock,ModuleBlock,BlockDataBlock,
+ SubroutineBlock,FunctionBlock,InterfaceBlock,TypeBlock]
+stmt_blocks = [DoBlock,IfThenBlock,SelectBlock]
+
+Block.classes['free90'] = [ProgramBlock,ModuleBlock,BlockDataBlock,
+ SubroutineBlock,FunctionBlock,InterfaceBlock,TypeBlock] + stmt_blocks
+Block.classes['fix90'] = Block.classes['free90']
+Block.classes['fix77'] = [ProgramBlock,BlockDataBlock,SubroutineBlock,FunctionBlock] + stmt_blocks
+Block.classes['pyf'] = [PythonModuleBlock] + Block.classes['free90']
+
+ProgramBlock.classes['free90'] = [ModuleBlock,SubroutineBlock,FunctionBlock,InterfaceBlock,TypeBlock] + stmt_blocks
+ProgramBlock.classes['fix90'] = ProgramBlock.classes['free90']
+ProgramBlock.classes['fix77'] = [SubroutineBlock,FunctionBlock] + stmt_blocks
+ProgramBlock.classes['pyf'] = ProgramBlock.classes['free90']
+
+ModuleBlock.classes['free90'] = [ModuleBlock,SubroutineBlock,FunctionBlock,InterfaceBlock,TypeBlock]
+ModuleBlock.classes['fix90'] = ModuleBlock.classes['free90']
+ModuleBlock.classes['fix77'] = []
+ModuleBlock.classes['pyf'] = ModuleBlock.classes['free90']
+
+BlockDataBlock.classes['free90'] = [TypeBlock]
+BlockDataBlock.classes['fix90'] = BlockDataBlock.classes['free90']
+BlockDataBlock.classes['fix77'] = []
+BlockDataBlock.classes['pyf'] = BlockDataBlock.classes['free90']
+
+
+PythonModuleBlock.classes['free90'] = [ModuleBlock,SubroutineBlock,FunctionBlock,InterfaceBlock,TypeBlock]
+PythonModuleBlock.classes['fix90'] = PythonModuleBlock.classes['free90']
+PythonModuleBlock.classes['fix77'] = []
+PythonModuleBlock.classes['pyf'] = PythonModuleBlock.classes['free90']
+
+InterfaceBlock.classes['free90'] = [ModuleBlock,SubroutineBlock,FunctionBlock,InterfaceBlock,TypeBlock] + stmt_blocks
+InterfaceBlock.classes['fix90'] = InterfaceBlock.classes['free90']
+InterfaceBlock.classes['fix77'] = []
+InterfaceBlock.classes['pyf'] = InterfaceBlock.classes['free90']
+
+SubroutineBlock.classes['free90'] = [InterfaceBlock,TypeBlock] + stmt_blocks
+SubroutineBlock.classes['fix90'] = SubroutineBlock.classes['free90']
+SubroutineBlock.classes['fix77'] = stmt_blocks
+SubroutineBlock.classes['pyf'] = SubroutineBlock.classes['free90']
+
+FunctionBlock.classes = SubroutineBlock.classes
+
+TypeBlock.classes['free90'] = [ModuleBlock, SubroutineBlock, FunctionBlock, InterfaceBlock, TypeBlock] + stmt_blocks
+TypeBlock.classes['fix90'] = TypeBlock.classes['free90']
+TypeBlock.classes['fix77'] = []
+TypeBlock.classes['pyf'] = TypeBlock.classes['free90']
+
+StatementBlock.classes['free90'] = stmt_blocks
+StatementBlock.classes['fix90'] = StatementBlock.classes['free90']
+StatementBlock.classes['fix77'] = stmt_blocks
+StatementBlock.classes['pyf'] = StatementBlock.classes['free90']
+
+
+# Initialize stmt_cls attributes
+
+ProgramBlock.stmt_cls = Program
+ModuleBlock.stmt_cls = Module
+PythonModuleBlock.stmt_cls = PythonModule
+BlockDataBlock.stmt_cls = BlockData
+InterfaceBlock.stmt_cls = Interface
+SubroutineBlock.stmt_cls = Subroutine
+FunctionBlock.stmt_cls = Function
+TypeBlock.stmt_cls = Type
+
+IfThenBlock.stmt_cls = IfThen
+DoBlock.stmt_cls = Do
+SelectBlock.stmt_cls = Select
+
+ProgramBlock.end_stmt_cls = EndProgram
+ModuleBlock.end_stmt_cls = EndModule
+PythonModuleBlock.end_stmt_cls = EndPythonModule
+BlockDataBlock.end_stmt_cls = EndBlockData
+InterfaceBlock.end_stmt_cls = EndInterface
+SubroutineBlock.end_stmt_cls = EndSubroutine
+FunctionBlock.end_stmt_cls = EndFunction
+TypeBlock.end_stmt_cls = EndType
+
+IfThenBlock.end_stmt_cls = EndIfThen
+DoBlock.end_stmt_cls = EndDo
+SelectBlock.end_stmt_cls = EndSelect
diff --git a/numpy/f2py/lib/parsefortran.py b/numpy/f2py/lib/parsefortran.py
index 89d793a52..380c10ffd 100644
--- a/numpy/f2py/lib/parsefortran.py
+++ b/numpy/f2py/lib/parsefortran.py
@@ -11,8 +11,9 @@ Created: May 2006
"""
import re
-
-from numpy.distutils.misc_util import yellow_text
+import sys
+import traceback
+from numpy.distutils.misc_util import yellow_text, red_text
from readfortran import FortranFileReader, FortranStringReader
from block import Block
@@ -25,7 +26,8 @@ class FortranParser:
def get_item(self):
try:
- return self.reader.next(ignore_comments = True)
+ item = self.reader.next(ignore_comments = True)
+ return item
except StopIteration:
pass
@@ -33,9 +35,20 @@ class FortranParser:
self.reader.fifo_item.insert(0, item)
def parse(self):
- main = Block(self)
- main.fill()
- return main
+ import init
+ try:
+ main = Block(self)
+ main.fill()
+ return main
+ except KeyboardInterrupt:
+ raise
+ except:
+ message = self.reader.format_message('FATAL ERROR',
+ 'while processing line',
+ self.reader.linecount, self.reader.linecount)
+ self.reader.show_message(message, sys.stdout)
+ traceback.print_exc(file=sys.stdout)
+ self.reader.show_message(red_text('STOPPED PARSING'), sys.stdout)
def test_pyf():
string = """
@@ -45,13 +58,36 @@ python module foo
real r
end subroutine bar
end interface
-end python module
+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
+ end subroutine bar
+
+end module foo
+"""
+ reader = FortranStringReader(string, True, False)
+ parser = FortranParser(reader)
+ block = parser.parse()
+ print block
+
def test_f77():
string = """\
c program foo
@@ -68,13 +104,26 @@ c program foo
def simple_main():
import sys
for filename in sys.argv[1:]:
- print yellow_text('Processing '+filename)
reader = FortranFileReader(filename)
+ print yellow_text('Processing '+filename+' (mode=%r)' % (reader.mode))
+
parser = FortranParser(reader)
block = parser.parse()
- #print block
-
+ print 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)
+
if __name__ == "__main__":
#test_f77()
+ #test_free90()
#test_pyf()
simple_main()
+ #profile_main()
diff --git a/numpy/f2py/lib/readfortran.py b/numpy/f2py/lib/readfortran.py
index 658d69804..03a64534a 100644
--- a/numpy/f2py/lib/readfortran.py
+++ b/numpy/f2py/lib/readfortran.py
@@ -23,12 +23,12 @@ __all__ = ['FortranFileReader',
import re
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 LineSplitter, String, string_replace_map
+from splitline import String, string_replace_map, splitquote
_spacedigits=' 0123456789'
_cf2py_re = re.compile(r'(?P<indent>\s*)!f2py(?P<rest>.*)',re.I)
@@ -46,7 +46,7 @@ class Line:
""" Holds a Fortran source line.
"""
def __init__(self, line, linenospan, label, reader):
- self.line = line
+ self.line = line.strip()
self.span = linenospan
self.label = label
self.reader = reader
@@ -186,12 +186,13 @@ class FortranReaderBase:
return self._next(ignore_comments)
except StopIteration:
raise
- except Exception, msg:
+ except:
message = self.format_message('FATAL ERROR',
- 'while processing got exception: %s'\
- '\nSTOP READING' % msg,
+ '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):
@@ -257,6 +258,8 @@ class FortranReaderBase:
for i in range(max(1,startlineno-3),startlineno):
r.append('%5d:%s' % (i,self.source_lines[i-1]))
for i in range(startlineno,min(endlineno+3,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]
@@ -317,9 +320,11 @@ class FortranReaderBase:
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
+ #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)
@@ -606,6 +611,11 @@ python module foo
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
"""
@@ -653,7 +663,7 @@ def profile_main():
stats.print_stats(30)
if __name__ == "__main__":
- #test_pyf()
+ test_pyf()
#test_fix90()
#profile_main()
- simple_main()
+ #simple_main()
diff --git a/numpy/f2py/lib/splitline.py b/numpy/f2py/lib/splitline.py
index f5be43e9b..be45ced2c 100644
--- a/numpy/f2py/lib/splitline.py
+++ b/numpy/f2py/lib/splitline.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
-Defines LineSplitter.
+Defines LineSplitter and helper functions.
Copyright 2006 Pearu Peterson all rights reserved,
Pearu Peterson <pearu@cens.ioc.ee>
@@ -13,9 +13,10 @@ $Date: 2000/07/31 07:04:03 $
Pearu Peterson
"""
-__all__ = ['LineSplitter','String','split2','string_replace_map']
+__all__ = ['String','string_replace_map','splitquote','splitparen']
class String(str): pass
+class ParenString(str): pass
def split2(line, lower=False):
"""
@@ -25,39 +26,110 @@ def split2(line, lower=False):
"""
return LineSplitter(line,lower=lower).split2()
-def string_replace_map(line, lower=False, _cache={'index':0}):
+def string_replace_map(line, lower=False,
+ _cache={'index':0,'pindex':0}):
"""
- Replaces string constants with name _F2PY_STRING_CONSTANT_<index>
- and returns a new line and a map
- {_F2PY_STRING_CONSTANT_<index>: <original string constant>}
+ 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 LineSplitter(line, lower=lower):
+ for item in splitquote(line, lower=lower)[0]:
if isinstance(item, String):
key = rev_string_map.get(item)
if key is None:
_cache['index'] += 1
index = _cache['index']
- key = '_F2PY_STRING_CONSTANT_%s' % (index)
+ key = ' _F2PY_STRING_CONSTANT_%s_ ' % (index)
string_map[key] = item
rev_string_map[item] = key
items.append(key)
else:
items.append(item)
- return ''.join(items),string_map
+ newline = ''.join(items)
+ items = []
+ for item in splitparen(newline):
+ if isinstance(item,ParenString):
+ key = rev_string_map.get(item)
+ if key is None:
+ _cache['pindex'] += 1
+ index = _cache['pindex']
+ key = '(F2PY_EXPR_TUPLE_%s)' % (index)
+ string_map[key] = item
+ rev_string_map[item] = key
+ items.append(key)
+ else:
+ items.append(item)
+ return ''.join(items), string_map
-class LineSplitter:
- """ Splits a line into non strings and strings. E.g.
- abc=\"123\" -> ['abc=','\"123\"']
- Handles splitting lines with incomplete string blocks.
+def splitquote(line, stopchar=None, lower=False, quotechars = '"\''):
"""
- 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
+ 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
@@ -68,6 +140,20 @@ class LineSplitter:
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.
@@ -137,23 +223,155 @@ class LineSplitter:
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')
@@ -162,6 +380,15 @@ def test():
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()
diff --git a/numpy/f2py/lib/stmt.py b/numpy/f2py/lib/stmt.py
new file mode 100644
index 000000000..285423511
--- /dev/null
+++ b/numpy/f2py/lib/stmt.py
@@ -0,0 +1,578 @@
+"""Single line Fortran statements.
+
+"""
+
+__all__ = ['statements', 'end_stmts', 'block_stmts',
+ 'IfThen', 'Program', 'Module', 'PythonModule',
+ 'BlockData','Interface', 'Subroutine','Function',
+ 'Type','Do','Select',
+ 'EndProgram','EndModule','EndPythonModule','EndInterface',
+ 'EndBlockData','EndSubroutine','EndFunction','EndType','EndIfThen',
+ 'EndDo','EndSelect'
+ ]
+
+import re
+import sys
+class Statement:
+
+ def __init__(self, parent, item, name=None):
+ self.parent = parent
+ self.reader = parent.reader
+ self.item = item
+ if name is None:
+ name = item.label
+ self.name = name
+
+ # If statement instance is constructed by error, set isvalid to False
+ self.isvalid = True
+
+ def get_intent_tab(self,colon='',deintent=False):
+ from block import Block
+ tab = ''
+ p = self.parent
+ while isinstance(p, Block):
+ tab += ' '
+ p = p.parent
+ if deintent:
+ tab = tab[:-2]
+ s = self.item.label
+ if s:
+ tab = tab[len(s)+len(colon):]
+ if not tab: tab = ' '
+ tab = s + colon + tab
+ return tab
+
+# End statements
+
+class EndStatement(Statement):
+ """
+ END [<blocktype> [<name>]]
+
+ EndStatement instances have attributes:
+ name
+ isvalid
+ """
+
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line().replace(' ','')[3:]
+ if line.startswith(self.blocktype):
+ line = line[len(self.blocktype):].strip()
+ else:
+ if line:
+ # not the end of expected block
+ line = ''
+ self.isvalid = False
+ if line:
+ if not line==parent.name:
+ message = self.reader.format_message(\
+ 'WARNING',
+ 'expected the end of %r block but got end of %r, skipping.'\
+ % (parent.name, line),
+ item.span[0],item.span[1])
+ print >> sys.stderr, message
+ self.isvalid = False
+ self.name = parent.name
+
+ def __str__(self):
+ return self.get_intent_tab()[:-2] + 'END %s %s'\
+ % (self.blocktype.upper(),self.name or '')
+
+class EndProgram(EndStatement):
+ """
+ END [PROGRAM [name]]
+ """
+ start_re = re.compile(r'end(\s*program\s*\w*|)\Z', re.I).match
+ blocktype = 'program'
+
+class EndModule(EndStatement):
+ """
+ END [MODULE [name]]
+ """
+ start_re = re.compile(r'end(\s*module\s*\w*|)\Z', re.I).match
+ blocktype = 'module'
+
+class EndBlockData(EndStatement):
+ """
+ END [BLOCK DATA [name]]
+ """
+ start_re = re.compile(r'end(\s*block\s*data\s*\w*|)\Z', re.I).match
+ blocktype = 'blockdata'
+
+
+class EndPythonModule(EndStatement):
+ """
+ END PYTHON MODULE name
+ """
+ start_re = re.compile(r'end\s*python\s*module\s*\w+\Z', re.I).match
+ blocktype = 'pythonmodule'
+
+class EndType(EndStatement):
+ """
+ END TYPE [name]
+ """
+ start_re = re.compile(r'end\s*type\s*\w*', re.I).match
+ blocktype = 'type'
+
+class EndInterface(EndStatement):
+ """
+ END INTERFACE [name]
+ """
+ start_re = re.compile(r'end\s*interface\s*\w*', re.I).match
+ blocktype = 'interface'
+
+class EndSubroutine(EndStatement):
+ """
+ END [SUBROUTINE [name]]
+ """
+ start_re = re.compile(r'end\s*(subroutine\s*\w*|)', re.I).match
+ blocktype = 'subroutine'
+
+class EndFunction(EndStatement):
+ """
+ END [FUNCTION [name]]
+ """
+ start_re = re.compile(r'end\s*(function\s*\w*|)', re.I).match
+ blocktype = 'function'
+
+class EndIfThen(EndStatement):
+ """
+ END IF [name]
+ """
+ start_re = re.compile(r'end\s*if\s*\w*', re.I).match
+ blocktype = 'if'
+
+class EndSelect(EndStatement):
+ """
+ END SELECT [name]
+ """
+ start_re = re.compile(r'end\s*select\s*\w*', re.I).match
+ blocktype = 'select'
+
+class EndDo(EndStatement):
+ """
+ END DO [name]
+ """
+ start_re = re.compile(r'end\s*do\s*\w*', re.I).match
+ blocktype = 'do'
+
+# Begin statements
+
+class BeginStatement(Statement):
+ """ <blocktype> <name>
+
+ BeginStatement instances have the following attributes:
+ name
+ isvalid
+ """
+ def __init__(self, parent, item):
+ name = item.get_line().replace(' ','')[len(self.blocktype):].strip()
+ if not name:
+ name = '__'+self.blocktype.upper()+'__'
+ Statement.__init__(self, parent, item, name)
+
+class Program(BeginStatement):
+ """ PROGRAM [name]
+ """
+ blocktype = 'program'
+ start_re = re.compile(r'program\s*\w*\Z', re.I).match
+
+class Module(BeginStatement):
+ """
+ MODULE <name>
+ """
+ blocktype = 'module'
+ start_re = re.compile(r'module\s*\w+\Z', re.I).match
+
+ def __str__(self):
+ s = self.get_intent_tab(deintent=True)
+ s += 'MODULE '+ self.name
+ return s
+
+class PythonModule(BeginStatement):
+ """
+ PYTHON MODULE <name>
+ """
+ blocktype = 'pythonmodule'
+ start_re = re.compile(r'python\s*module\s*\w+\Z', re.I).match
+
+class BlockData(BeginStatement):
+ """
+ BLOCK DATA [name]
+ """
+ blocktype = 'blockdata'
+ start_re = re.compile(r'block\s*data\s*\w*\Z', re.I).match
+
+class Interface(BeginStatement):
+ """
+ INTERFACE [<generic-spec>]
+ """
+ blocktype = 'interface'
+ start_re = re.compile(r'interface\s*\w*\Z', re.I).match
+
+class Subroutine(BeginStatement):
+ """
+ [prefix] SUBROUTINE <name> [ ( [<dummy-arg-list>] ) [<proc-language-binding-spec>]]
+
+ Subroutine instance has the following attributes:
+ name
+ args
+ """
+ blocktype = 'subroutine'
+ start_re = re.compile(r'[\w\s]*subroutine\s*\w+', re.I).match
+
+ begin_re = re.compile(r'(?P<prefix>[\w\s]*)\s*subroutine\s*(?P<name>\w+)', re.I).match
+ def __init__(self, parent, item):
+ BeginStatement.__init__(self, parent, item)
+ line = item.get_line()
+ m = self.begin_re(line)
+ self.name = m.group('name')
+ line = line[m.end():].strip()
+ args = []
+ if line.startswith('('):
+ assert line.endswith(')'),`line`
+ for a in line.split(','):
+ args.append(a.strip())
+ self.args = args
+
+
+ def __str__(self):
+ s = self.get_intent_tab(deintent=True)
+ s += 'SUBROUTINE %s (%s)' % (self.name, ', '.join(self.args))
+ return s
+
+class Function(BeginStatement):
+ """
+ """
+ blocktype = 'function'
+ start_re = re.compile(r'([\w\s]+(\(\s*\w+\s*\)|)|)\s*function\s*\w+', re.I).match
+ begin_re = re.compile(r'(?P<prefix>([\w\s](\(\s*\w+\s*\)|))*)\s*function\s*(?P<name>\w+)', re.I).match
+
+ def __init__(self, parent, item):
+ m = self.begin_re(item.get_line())
+ name = m.group('name')
+ BeginStatement.__init__(self, parent, item, name)
+
+class Type(BeginStatement):
+ """
+ TYPE [[type-attr-spec-list] ::] <name> [(type-param-name-list)]
+ """
+
+ blocktype = 'type'
+ start_re = re.compile(r'type(?!\s*\()(.*::|)\s*\w+\Z', re.I).match
+ begin_re = re.compile(r'type(?!\s*\()(.*::|)\s*(?P<name>\w+)\Z', re.I).match
+
+ def __init__(self, parent, item):
+ BeginStatement.__init__(self, parent, item)
+ m = self.begin_re(item.get_line())
+ self.name = m.group('name')
+
+
+
+class IfThen(BeginStatement):
+ """
+ IF ( <scalar-logical-expr> ) THEN
+
+ IfThen instance has the following attributes:
+ expr
+ """
+
+ blocktype = 'ifthen'
+ start_re = re.compile(r'if\s*\(.*\)\s*then\Z', re.I).match
+
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line()[2:-4].strip()
+ assert line[0]=='(' and line[-1]==')',`line`
+ self.expr = line[1:-1].strip()
+
+ def __str__(self):
+ s = self.get_intent_tab(colon=':',deintent=True)
+ s += 'IF (%s) THEN' % (self.expr)
+ return s
+
+class Do(BeginStatement):
+ """
+ """
+ blocktype = 'do'
+ start_re = re.compile(r'do\b\s*\d*', re.I).match
+ 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
+ BeginStatement.__init__(self, parent, item)
+ self.name = item.label
+
+class Select(BeginStatement):
+
+ blocktype = 'select'
+ start_re = re.compile(r'select\s*case\s*\(', re.I).match
+
+# Other statements
+
+class Use(Statement):
+ """ Use statement class.
+
+ use [ [, <module-nature>] ::] <name> [, <rename-list> ]
+ use [ [, <module-nature>] ::] <name> ONLY : [ <only-list> ]
+
+ Use instance has attributes:
+ isuseonly - boolean
+ modulename - name
+ modulenature - list of names
+ use_list - list of 3-tuples (<name|operator>, <local>, <use>)
+ """
+ start_re = re.compile(r'use\b').match
+ stmt_re = re.compile(r'use\b((?P<modulenature>[\w,\s]*)\s*::|)\s*(?P<name>\w+)',re.I).match
+ only_re = re.compile(r'only\s*:',re.I).match
+ op_rename_re = re.compile(r'operator\s*\(\s*(?P<localop>[^)]+)\s*\)\s*=\s*\>'\
+ r'\s*operator\s*\(\s*(?P<useop>[^)]+)\s*\)', re.I).match
+ rename_re = re.compile(r'(?P<localname>\w+)\s*=\s*\>\s*(?P<usename>\w+)',re.I).match
+
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ self.isuseonly = False
+
+ line = item.get_line()
+ m = self.stmt_re(line)
+ self.modulename = m.group('name')
+
+ # init modulenature
+ self.modulenature = []
+ mn = m.group('modulenature') or ''
+ for n in mn.split(','):
+ n = n.strip()
+ if not n: continue
+ self.modulenature.append(n)
+
+ # process the rest of the line
+ self.use_list = []
+ rest = line[m.end():].strip()
+ only_m = self.only_re(rest)
+ if only_m:
+ self.isuseonly = True
+ rest = rest[only_m.end():].strip()
+ for n in rest.split(','):
+ n = n.strip()
+ if not n: continue
+ m1 = self.op_rename_re(n)
+ if m1:
+ localop, useop = m1.group('localop'),m1.group('useop')
+ self.use_list.append(('operator',localop,useop))
+ continue
+ m1 = self.rename_re(n)
+ if m1:
+ localname, usename = m1.group('localname'),m1.group('usename')
+ self.use_list.append(('name',localname,usename))
+ continue
+ self.use_list.append(('name',n,n))
+
+ def __str__(self):
+ s = self.get_intent_tab()
+ l = ['USE'] + self.modulenature
+ s += ', '.join(l) + ' :: ' + self.modulename
+ l = []
+ for type,local,use in self.use_list:
+ if type=='name':
+ if local==name: l.append(local)
+ else: l.append('%s => %s' % (local, use))
+ else:
+ assert type=='operator',`type`
+ l.append('OPERATOR(%s) => OPERATOR(%s)' % (local, use))
+ if self.isuseonly:
+ s += ', ONLY: ' + ', '.join(l)
+ else:
+ if l: s+= ', ' + ', '.join(l)
+ return s
+
+class Import(Statement):
+ """Import statement class
+
+ import [[::] <import-name-list>]
+
+ Import instance has attributes:
+ import_list - list of names
+ """
+ start_re = re.compile(r'import\b').match
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line()[6:].lstrip()
+ if line.startswith('::'): line = line[2:]
+ self.import_list = []
+ for n in line.split(','):
+ n = n.strip()
+ if not n: continue
+ self.import_list.append(n)
+
+ def __str__(self):
+ s = self.get_intent_tab() + 'IMPORT'
+ if self.import_list:
+ s += ' :: ' + ','.join(self.import_list)
+ return s
+
+class Assignment(Statement):
+ """Assignment statement class
+
+ <variable> = <expr>
+ <pointer variable> => <expr>
+
+ Assignment instance has attributes:
+ variable
+ sign
+ expr
+ """
+ start_re = re.compile(r'\w[\w%]*(\s*\(\s*[^)]*\)|)\s*=\>?',re.I).match
+ stmt_re = re.compile(r'(?P<variable>\w[\w%]*(\s*\(\s*[^)]*\)|))\s*(?P<sign>=\>?)\s*(?P<expr>.*)\Z',re.I).match
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line()
+ m = self.stmt_re(line)
+ self.variable = m.group('variable')
+ self.sign = m.group('sign')
+ self.expr = m.group('expr')
+ def __str__(self):
+ return self.get_intent_tab() + '%s %s %s' \
+ % (self.variable, self.sign, self.expr)
+
+class If(Statement):
+ """If statement class
+ IF (<scalar-logical-expr>) <action-stmt>
+
+ If instance has attributes:
+ expr
+ stmt
+ """
+ start_re = re.compile(r'if\b',re.I).match
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line()[2:].strip()
+ i = line.find(')')
+ self.expr = line[1:i].strip()
+ self.stmt = line[i+1:].strip()
+ def __str__(self):
+ return self.get_intent_tab()+ 'IF (%s) %s' % (self.expr, self.stmt)
+
+class Call(Statement):
+ """Call statement class
+ CALL <proc-designator> [([arg-spec-list])]
+
+ Call instance has attributes:
+ designator
+ arg_list
+ """
+ start_re = re.compile(r'call\b', re.I).match
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line()[4:].strip()
+ i = line.find('(')
+ self.arg_list = []
+ if i==-1:
+ self.designator = line.strip()
+ else:
+ self.designator = line[:i].strip()
+ for n in line[i+1:-1].split(','):
+ n = n.strip()
+ if not n: continue
+ self.arg_list.append(n)
+ def __str__(self):
+ s = self.get_intent_tab() + 'CALL '+str(self.designator)
+ if self.arg_list:
+ s += '('+', '.join(map(str,self.arg_list))+ ')'
+ return s
+
+class Contains(Statement):
+ """
+ CONTAINS
+ """
+ start_re = re.compile(r'contains\Z',re.I).match
+
+ def __str__(self): return self.get_intent_tab() + 'CONTAINS'
+
+class Continue(Statement):
+ """
+ CONTINUE
+ """
+ start_re = re.compile(r'continue\Z',re.I).match
+
+ def __str__(self): return self.get_intent_tab() + 'CONTINUE'
+
+class Return(Statement):
+ """
+ RETURN [<int-expr>]
+
+ Return instance has attributes:
+ expr
+ """
+ start_re = re.compile(r'return\b',re.I).match
+
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line()[6:].strip()
+ self.expr = ''
+ if line:
+ self.expr = line
+ def __str__(self):
+ s = self.get_intent_tab() + 'RETURN'
+ if self.expr:
+ s += ' ' + str(self.expr)
+ return s
+
+class Stop(Statement):
+ """
+ STOP [<stop-code>]
+
+ Return instance has attributes:
+ code
+ """
+ start_re = re.compile(r'stop\b',re.I).match
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line()[4:].strip()
+ self.code = ''
+ if line:
+ self.code = line
+ def __str__(self):
+ s = self.get_intent_tab() + 'STOP'
+ if self.code:
+ s += ' ' + str(self.code)
+ return s
+
+class Format(Statement):
+ """
+ FORMAT ( [<format-item-list>] )
+
+ Return instance has attributes:
+ spec
+ """
+ start_re = re.compile(r'format\s*\([^)]*\)\Z',re.I).match
+ def __init__(self, parent, item):
+ Statement.__init__(self, parent, item)
+ line = item.get_line()[6:].strip()
+ assert line[0]=='(' and line[-1]==')',`line`
+ self.spec = line[1:-1].strip()
+ def __str__(self):
+ return self.get_intent_tab() + 'FORMAT (%s)' % (self.spec)
+
+end_stmts = {'ModuleBlock':EndModule, 'PythonModuleBlock':EndPythonModule,
+ 'TypeBlock':EndType,
+ 'SubroutineBlock':EndSubroutine,'FunctionBlock':EndFunction,
+ 'IfThenBlock':EndIfThen,'DoBlock':EndDo,'InterfaceBlock':EndInterface,
+ 'SelectBlock':EndSelect}
+
+block_stmts = {'IfThenBlock':IfThen}
+
+exec_stmts = [Assignment, If, Call, Stop, Continue]
+statements = {}
+statements['Block'] = []
+statements['ProgramBlock'] = [Use, Contains] + exec_stmts
+# Format, misc_decl, Data, derived_type_defs, Interface_block, exec_stmt, Contains, StmtFunc_stmt
+statements['ModuleBlock'] = [Use, Contains]
+statements['BlockDataBlock'] = [Use]
+statements['SubroutineBlock'] = [Use, Contains, Return, Format] + exec_stmts
+statements['FunctionBlock'] = statements['SubroutineBlock']
+statements['InterfaceBlock'] = [Use, Import]
+statements['PythonModuleBlock'] = [Use]
+statements['TypeBlock'] = [Contains]
+for n in ['IfThenBlock','DoBlock','SelectBlock']:
+ statements[n] = exec_stmts