diff options
Diffstat (limited to 'numpy/f2py/lib/base_classes.py')
-rw-r--r-- | numpy/f2py/lib/base_classes.py | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/numpy/f2py/lib/base_classes.py b/numpy/f2py/lib/base_classes.py new file mode 100644 index 000000000..24a86ebf6 --- /dev/null +++ b/numpy/f2py/lib/base_classes.py @@ -0,0 +1,199 @@ + +__all__ = ['Statement','BeginStatement','EndStatement'] + +import re +import sys +from readfortran import Line + + +class Statement: + """ + Statement instance has attributes: + parent - Parent BeginStatement or FortranParser instance + item - Line instance containing the statement line + isvalid - boolean, when False, the Statement instance will be ignored + """ + modes = ['free90','fix90','fix77','pyf'] + + def __init__(self, parent, item): + self.parent = parent + self.reader = parent.reader + self.item = item + + # If statement instance is constructed by error, set isvalid to False + self.isvalid = True + + self.process_item() + + def get_indent_tab(self,colon='',deindent=False): + if self.reader.isfix: + tab = ' '*6 + else: + tab = '' + p = self.parent + while isinstance(p, Statement): + tab += ' ' + p = p.parent + if deindent: + tab = tab[:-2] + if self.item is None: + return tab + s = self.item.label + if s: + c = '' + if self.reader.isfix: + c = ' ' + tab = tab[len(c+s)+len(colon):] + if not tab: tab = ' ' + tab = c + s + colon + tab + return tab + +class BeginStatement(Statement): + """ <blocktype> <name> + + BeginStatement instances have additional attributes: + name + blocktype + + Block instance has attributes: + content - list of Line or Statement instances + name - name of the block, unnamed blocks are named + with the line label + parent - Block or FortranParser instance + item - Line instance containing the block start statement + get_item, put_item - methods to retrive/submit Line instaces + from/to Fortran reader. + isvalid - boolean, when False, the Block instance will be ignored. + + stmt_cls, end_stmt_cls + + """ + def __init__(self, parent, item=None): + + self.content = [] + self.get_item = parent.get_item # get line function + self.put_item = parent.put_item # put line function + if not hasattr(self, 'blocktype'): + self.blocktype = self.__class__.__name__.lower() + if not hasattr(self, 'name'): + # process_item may change this + self.name = '__'+self.blocktype.upper()+'__' + + Statement.__init__(self, parent, item) + return + + def process_item(self): + """ Process the line + """ + item = self.item + if item is None: return + self.fill() + return + + def tostr(self): + return self.blocktype.upper() + ' '+ self.name + + def __str__(self): + l=[self.get_indent_tab(colon=':') + self.tostr()] + for c in self.content: + l.append(str(c)) + return '\n'.join(l) + + def process_subitem(self, item): + """ + Check is item is blocks start statement, if it is, read the block. + + Return True to stop adding items to given block. + """ + line = item.get_line() + + # First check for the end of block + cls = self.end_stmt_cls + if cls.match(line): + stmt = cls(self, item) + if stmt.isvalid: + self.content.append(stmt) + return True + + # Look for statement match + for cls in self.classes: + if cls.match(line): + stmt = cls(self, item) + if stmt.isvalid: + self.content.append(stmt) + return False + self.handle_unknown_item(item) + return False + + def handle_unknown_item(self, item): + print self.__class__.__name__,item,item.get_line() + self.content.append(item) + return + + def fill(self, end_flag = False): + """ + Fills blocks content until the end of block statement. + """ + + mode = self.reader.mode + classes = self.get_classes() + self.classes = [cls for cls in classes if mode in cls.modes] + + item = self.get_item() + while item is not None: + if isinstance(item, Line): + if self.process_subitem(item): + end_flag = True + break + item = self.get_item() + + if not end_flag: + message = self.reader.format_message(\ + 'WARNING', + '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 EndStatement(Statement): + """ + END [<blocktype> [<name>]] + + EndStatement instances have additional attributes: + name + blocktype + """ + + def __init__(self, parent, item): + if not hasattr(self, 'blocktype'): + self.blocktype = self.__class__.__name__.lower()[3:] + Statement.__init__(self, parent, item) + + def process_item(self): + item = self.item + line = item.get_line().replace(' ','')[3:] + blocktype = self.blocktype + if line.startswith(blocktype): + line = line[len(blocktype):].strip() + else: + if line: + # not the end of expected block + line = '' + self.isvalid = False + if line: + if not line==self.parent.name: + message = self.reader.format_message(\ + 'WARNING', + 'expected the end of %r block but got end of %r, skipping.'\ + % (self.parent.name, line), + item.span[0],item.span[1]) + print >> sys.stderr, message + self.isvalid = False + self.name = self.parent.name + + def __str__(self): + return self.get_indent_tab()[:-2] + 'END %s %s'\ + % (self.blocktype.upper(),self.name or '') + |