diff options
author | Pearu Peterson <pearu.peterson@gmail.com> | 2006-06-05 20:58:13 +0000 |
---|---|---|
committer | Pearu Peterson <pearu.peterson@gmail.com> | 2006-06-05 20:58:13 +0000 |
commit | 858fdcea384a8b7c2460ec00501a26d8caa6995c (patch) | |
tree | b94caf2bd61b31dc1773de0196049f42aa5e1e53 /numpy | |
parent | d3d8f52c27e035bcdfd52344a03c370299a75196 (diff) | |
download | numpy-858fdcea384a8b7c2460ec00501a26d8caa6995c.tar.gz |
Impl. Fortran parser cont.
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/f2py/lib/block.py | 368 | ||||
-rw-r--r-- | numpy/f2py/lib/init.py | 85 | ||||
-rw-r--r-- | numpy/f2py/lib/parsefortran.py | 69 | ||||
-rw-r--r-- | numpy/f2py/lib/readfortran.py | 32 | ||||
-rw-r--r-- | numpy/f2py/lib/splitline.py | 267 | ||||
-rw-r--r-- | numpy/f2py/lib/stmt.py | 578 |
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 |