diff options
author | Pearu Peterson <pearu.peterson@gmail.com> | 2006-06-26 05:54:44 +0000 |
---|---|---|
committer | Pearu Peterson <pearu.peterson@gmail.com> | 2006-06-26 05:54:44 +0000 |
commit | ff660cb1a45a60128b6d934bc6977773b3ca7e34 (patch) | |
tree | baf63ccb3f12bee380bf723d6eb8b49703e50666 /numpy/f2py | |
parent | ecd8d3e9db972b5d1f3633266004942004052354 (diff) | |
download | numpy-ff660cb1a45a60128b6d934bc6977773b3ca7e34.tar.gz |
Cont. impl. Fortran parser.
Diffstat (limited to 'numpy/f2py')
-rw-r--r-- | numpy/f2py/lib/base_classes.py | 12 | ||||
-rw-r--r-- | numpy/f2py/lib/block_statements.py | 79 | ||||
-rw-r--r-- | numpy/f2py/lib/parsefortran.py | 11 | ||||
-rw-r--r-- | numpy/f2py/lib/readfortran.py | 70 | ||||
-rw-r--r-- | numpy/f2py/lib/splitline.py | 19 | ||||
-rw-r--r-- | numpy/f2py/lib/statements.py | 233 | ||||
-rw-r--r-- | numpy/f2py/lib/typedecl_statements.py | 24 |
7 files changed, 388 insertions, 60 deletions
diff --git a/numpy/f2py/lib/base_classes.py b/numpy/f2py/lib/base_classes.py index 24a86ebf6..4f588ff32 100644 --- a/numpy/f2py/lib/base_classes.py +++ b/numpy/f2py/lib/base_classes.py @@ -126,7 +126,13 @@ class BeginStatement(Statement): return False def handle_unknown_item(self, item): - print self.__class__.__name__,item,item.get_line() + message = item.reader.format_message(\ + 'WARNING', + 'no parse pattern found for "%s" in %r block.'\ + % (item.get_line(),self.__class__.__name__), + item.span[0], item.span[1]) + print >> sys.stderr, message + sys.stderr.flush() self.content.append(item) return @@ -148,7 +154,7 @@ class BeginStatement(Statement): item = self.get_item() if not end_flag: - message = self.reader.format_message(\ + message = self.item.reader.format_message(\ 'WARNING', 'failed to find the end of block for %s'\ % (self.__class__.__name__), @@ -184,7 +190,7 @@ class EndStatement(Statement): self.isvalid = False if line: if not line==self.parent.name: - message = self.reader.format_message(\ + message = item.reader.format_message(\ 'WARNING', 'expected the end of %r block but got end of %r, skipping.'\ % (self.parent.name, line), diff --git a/numpy/f2py/lib/block_statements.py b/numpy/f2py/lib/block_statements.py index e78ebe355..92a7f1493 100644 --- a/numpy/f2py/lib/block_statements.py +++ b/numpy/f2py/lib/block_statements.py @@ -38,7 +38,7 @@ class BeginSource(BeginStatement): if self.reader.isfix77: line = item.get_line() if line=='end': - message = self.reader.format_message(\ + message = item.reader.format_message(\ 'WARNING', 'assuming the end of undefined PROGRAM statement', item.span[0],item.span[1]) @@ -131,11 +131,21 @@ class EndInterface(EndStatement): class Interface(BeginStatement): """ - INTERFACE [generic-spec] | ABSTRACT INTERFACE - END INTERFACE [generic-spec] + INTERFACE [<generic-spec>] | ABSTRACT INTERFACE + END INTERFACE [<generic-spec>] + + <generic-spec> = <generic-name> + | OPERATOR ( <defined-operator> ) + | ASSIGNMENT ( = ) + | <dtio-generic-spec> + <dtio-generic-spec> = READ ( FORMATTED ) + | READ ( UNFORMATTED ) + | WRITE ( FORMATTED ) + | WRITE ( UNFORMATTED ) + """ modes = ['free90', 'fix90', 'pyf'] - match = re.compile(r'(interface\s*\w*|abstract\s*interface)\Z',re.I).match + match = re.compile(r'(interface\s*(\w+\s*\(.*\)|\w*)|abstract\s*interface)\Z',re.I).match end_stmt_cls = EndInterface blocktype = 'interface' @@ -252,6 +262,34 @@ class Select(BeginStatement): def get_classes(self): return [Case] + execution_part_construct +# Where + +class EndWhere(EndStatement): + match = re.compile(r'end\s*\w*\Z',re.I).match + + +class Where(BeginStatement): + """ + [ <where-construct-name> : ] WHERE ( <mask-expr> ) + <mask-expr> = <logical-expr> + """ + match = re.compile(r'where\s*\([^)]*\)\Z',re.I).match + end_stmt_cls = EndWhere + name = '' + def tostr(self): + return 'WHERE ( %s )' % (self.expr) + def process_item(self): + self.expr = self.item.get_line()[5:].lstrip()[1:-1].strip() + self.name = self.item.label + return BeginStatement.process_item(self) + + def get_classes(self): + return [Assignment, WhereStmt, + WhereConstruct, ElseWhere + ] + +WhereConstruct = Where + # IfThen class EndIfThen(EndStatement): @@ -313,7 +351,7 @@ class If(BeginStatement): if stmt.isvalid: self.content.append(stmt) return - self.handle_unknown_item(newitem) + self.isvalid = False return def tostr(self): @@ -387,6 +425,7 @@ class Type(BeginStatement): """ match = re.compile(r'type\b\s*').match end_stmt_cls = EndType + is_name = re.compile(r'\w+\Z').match def process_item(self): line = self.item.get_line()[4:].lstrip() @@ -409,6 +448,9 @@ class Type(BeginStatement): else: self.name = line self.params = '' + if not self.is_name(self.name): + self.isvalid = False + return return BeginStatement.process_item(self) def tostr(self): @@ -443,14 +485,17 @@ module_subprogram_part = [ ] specification_stmt = [ - # Access, Allocatable, Asynchronous, Bind, Common, + # Access, Allocatable, Asynchronous, Bind, + Common, Data, Dimension, - Equivalence, #External, Intent - # Intrinsic, Namelist, Optional, Pointer, Protected, + Equivalence, External, #Intent + Intrinsic, + #Namelist, + Optional, #Pointer, Protected, Save, #Target, Volatile, Value ] intrinsic_type_spec = [ - Integer , Real, DoublePrecision, Complex, Character, Logical + Integer , Real, DoublePrecision, Complex, DoubleComplex, Character, Logical ] declaration_type_spec = intrinsic_type_spec + [ TypeStmt, @@ -459,7 +504,7 @@ declaration_type_spec = intrinsic_type_spec + [ type_declaration_stmt = declaration_type_spec private_or_sequence = [ - Private, #Sequence + Private, Sequence ] component_part = declaration_type_spec + [ @@ -483,24 +528,26 @@ action_stmt = [ Endfile, #EndFunction, EndProgram, EndSubroutine, Exit, # Flush, Forall, - Goto, If, #Inquire, + Goto, If, Inquire, Nullify, Open, Print, Read, Return, Rewind, - Stop, #Wait, Where, + Stop, #Wait, + WhereStmt, Write, - # arithmetic-if-stmt, computed-goto-stmt + ArithmeticIf, + ComputedGoto ] -executable_construct = action_stmt + [ +executable_construct = [ # Associate, Case, Do, # Forall, IfThen, - Select, #Where - ] + Select, WhereConstruct + ] + action_stmt execution_part_construct = executable_construct + [ Format, #Entry, Data ] diff --git a/numpy/f2py/lib/parsefortran.py b/numpy/f2py/lib/parsefortran.py index 71355a9ad..21eec49fe 100644 --- a/numpy/f2py/lib/parsefortran.py +++ b/numpy/f2py/lib/parsefortran.py @@ -42,10 +42,13 @@ class FortranParser: 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) + reader = self.reader + while reader is not None: + message = reader.format_message('FATAL ERROR', + 'while processing line', + reader.linecount, reader.linecount) + reader.show_message(message, sys.stdout) + reader = reader.reader traceback.print_exc(file=sys.stdout) self.reader.show_message(red_text('STOPPED PARSING'), sys.stdout) diff --git a/numpy/f2py/lib/readfortran.py b/numpy/f2py/lib/readfortran.py index 1d6335865..26bfa1b0b 100644 --- a/numpy/f2py/lib/readfortran.py +++ b/numpy/f2py/lib/readfortran.py @@ -21,6 +21,7 @@ __all__ = ['FortranFileReader', ] import re +import os import sys import tempfile import traceback @@ -35,6 +36,7 @@ _cf2py_re = re.compile(r'(?P<indent>\s*)!f2py(?P<rest>.*)',re.I) _is_fix_cont = lambda line: line and len(line)>5 and line[5]!=' ' and line[:5]==5*' ' _is_f90_cont = lambda line: line and '&' in line and line.rstrip()[-1]=='&' _f90label_re = re.compile(r'\s*(?P<label>(\w+\s*:|\d+))\s*(\b|(?=&)|\Z)',re.I) +_is_include_line = re.compile(r'\s*include\s*"[^"]+"\s*\Z',re.I).match class FortranReaderError: # TODO: may be derive it from Exception def __init__(self, message): @@ -45,6 +47,9 @@ class FortranReaderError: # TODO: may be derive it from Exception class Line: """ Holds a Fortran source line. """ + + f2py_strmap_findall = re.compile(r'( _F2PY_STRING_CONSTANT_\d+_ |\(F2PY_EXPR_TUPLE_\d+\))').findall + def __init__(self, line, linenospan, label, reader): self.line = line.strip() self.span = linenospan @@ -55,16 +60,11 @@ class Line: if line is None: line = self.line if apply_map and hasattr(self,'strlinemap'): + findall = self.f2py_strmap_findall str_map = self.strlinemap - keys = str_map.keys() - flag = True - while flag: - flag = False - for k in keys: - if k in line: - flag = True - line = line.replace(k, str_map[k]) - assert k not in line, `k,line` + keys = findall(line) + for k in keys: + line = line.replace(k, str_map[k]) return Line(line, self.span, self.label, self.reader) def __repr__(self): return self.__class__.__name__+'(%r,%s,%r)' \ @@ -139,6 +139,7 @@ class FortranReaderBase: self.ispyf = isfree and isstrict self.isfree = isfree self.isfix = not isfree + self.isstrict = isstrict if self.isfree90: mode = 'free90' elif self.isfix90: mode = 'fix90' @@ -156,6 +157,10 @@ class FortranReaderBase: self.name = '%s mode=%s' % (source, mode) + self.reader = None + self.include_dirs = ['.'] + return + def close_source(self): # called when self.source.next() raises StopIteration. pass @@ -184,7 +189,9 @@ class FortranReaderBase: self.linecount += 1 # expand tabs, replace special symbols, get rid of nl characters line = line.expandtabs().replace('\xa0',' ').rstrip('\n\r\f') - self.source_lines.append(line) + self.source_lines.append(line) + if not line: + return self.get_single_line() return line def get_next_line(self): @@ -199,8 +206,36 @@ class FortranReaderBase: return self def next(self, ignore_comments = False): + try: - return self._next(ignore_comments) + if self.reader is not None: + try: + return self.reader.next() + except StopIteration: + self.reader = None + item = self._next(ignore_comments) + if isinstance(item, Line) and _is_include_line(item.line): + filename = item.line.strip()[7:].lstrip()[1:-1] + include_dirs = self.include_dirs[:] + path = filename + for incl_dir in include_dirs: + path = os.path.join(incl_dir, filename) + if os.path.exists(path): + break + if not os.path.isfile(path): + dirs = os.pathsep.join(include_dirs) + message = self.format_message('WARNING', + 'include file not found in %s, ignoring.' % (dirs), + self.linecount, self.linecount) + self.show_message(message, sys.stdout) + return item + message = self.format_message('INFORMATION', + 'found file %r' % (path), + self.linecount, self.linecount) + self.show_message(message, sys.stdout) + self.reader = FortranFileReader(path, include_dirs = include_dirs) + return self.reader.next() + return item except StopIteration: raise except: @@ -577,10 +612,16 @@ class FortranReaderBase: class FortranFileReader(FortranReaderBase): - def __init__(self, filename): + def __init__(self, filename, + include_dirs = None): isfree, isstrict = get_source_info(filename) self.file = open(filename,'r') FortranReaderBase.__init__(self, self.file, isfree, isstrict) + if include_dirs is None: + self.include_dirs.insert(0, os.path.dirname(filename)) + else: + self.include_dirs = include_dirs[:] + return def close_source(self): self.file.close() @@ -638,6 +679,7 @@ python module foo endif end interface if ( pc_get_lun() .ne. 6) & + write ( pc_get_lun(), '( & & /, a, /, " p=", i4, " stopping c_flag=", a, & & /, " print unit=", i8)') & @@ -689,7 +731,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 be45ced2c..c5d6869b0 100644 --- a/numpy/f2py/lib/splitline.py +++ b/numpy/f2py/lib/splitline.py @@ -15,6 +15,8 @@ Pearu Peterson __all__ = ['String','string_replace_map','splitquote','splitparen'] +import re + class String(str): pass class ParenString(str): pass @@ -26,6 +28,8 @@ def split2(line, lower=False): """ return LineSplitter(line,lower=lower).split2() +_f2py_str_findall = re.compile(r' _F2PY_STRING_CONSTANT_\d+_ ').findall + def string_replace_map(line, lower=False, _cache={'index':0,'pindex':0}): """ @@ -50,8 +54,9 @@ def string_replace_map(line, lower=False, items.append(item) newline = ''.join(items) items = [] + expr_keys = [] for item in splitparen(newline): - if isinstance(item,ParenString): + if isinstance(item, ParenString): key = rev_string_map.get(item) if key is None: _cache['pindex'] += 1 @@ -59,9 +64,21 @@ def string_replace_map(line, lower=False, key = '(F2PY_EXPR_TUPLE_%s)' % (index) string_map[key] = item rev_string_map[item] = key + expr_keys.append(key) items.append(key) else: items.append(item) + found_keys = set() + for k in expr_keys: + v = string_map[k] + l = _f2py_str_findall(v) + if l: + found_keys = found_keys.union(l) + for k1 in l: + v = v.replace(k1, string_map[k1]) + string_map[k] = v + for k in found_keys: + del string_map[k] return ''.join(items), string_map def splitquote(line, stopchar=None, lower=False, quotechars = '"\''): diff --git a/numpy/f2py/lib/statements.py b/numpy/f2py/lib/statements.py index 09b60d328..803493aed 100644 --- a/numpy/f2py/lib/statements.py +++ b/numpy/f2py/lib/statements.py @@ -12,8 +12,10 @@ class Assignment(Statement): <pointer variable> => <expr> """ - match = re.compile(r'\w(\s*\(\s*[^)]*\)|[\w%]*)*\s*=\>?',re.I).match - item_re = re.compile(r'(?P<variable>\w(\s*\(\s*[^)]*\)|[\w%]*)*)\s*(?P<sign>=\>?)\s*(?P<expr>.*)\Z',re.I).match + #match = re.compile(r'\w(\s*\(\s*[^)]*\)|[\w%]*)*\s*=\>?',re.I).match + #item_re = re.compile(r'(?P<variable>\w(\s*\(\s*[^)]*\)|[\w%]*)*)\s*(?P<sign>=\>?)\s*(?P<expr>.*)\Z',re.I).match + match = re.compile(r'\w[^=]*\s*=\>?').match + item_re = re.compile(r'(?P<variable>\w[^=]*)\s*(?P<sign>=\>?)\s*(?P<expr>.*)\Z',re.I).match def process_item(self): m = self.item_re(self.item.get_line()) @@ -62,15 +64,32 @@ class Goto(Statement): GO TO <label> """ - match = re.compile(r'go\s*to\b\s*\w*\Z', re.I).match + match = re.compile(r'go\s*to\b\s*\w*\s*\Z', re.I).match def process_item(self): - self.gotolabel = self.item.get_line()[2:].strip()[2:].strip() + self.gotolabel = self.item.get_line()[2:].lstrip()[2:].lstrip() return def __str__(self): return self.get_indent_tab() + 'GO TO %s' % (self.gotolabel) - + +class ComputedGoto(Statement): + """ + GO TO ( <label-list> ) [ , ] <scalar-int-expr> + """ + match = re.compile(r'go\s*to\s*\(',re.I).match + def process_item(self): + line = self.item.get_line()[2:].lstrip()[2:].lstrip() + i = line.index(')') + self.items = [s.strip() for s in line[1:i].strip(',')] + self.expr = line[i+1:].lstrip() + return + def __str__(self): + return self.get_indent_tab() + 'GO TO (%s) %s' \ + % (', '.join(self.items), self.expr) + + + class Continue(Statement): """ CONTINUE @@ -103,7 +122,7 @@ class Stop(Statement): """ STOP [stop-code] """ - match = re.compile(r'stop\b\s*\w*\Z',re.I).match + match = re.compile(r'stop\b\s*\w*\s*\Z',re.I).match def process_item(self): self.stopcode = self.item.get_line()[4:].lstrip() @@ -279,7 +298,7 @@ class Cycle(Statement): """ CYCLE [ <do-construct-name> ] """ - match = re.compile(r'cycle\b\s*\w*\Z',re.I).match + match = re.compile(r'cycle\b\s*\w*\s*\Z',re.I).match def process_item(self): self.name = self.item.get_line()[5:].lstrip() return @@ -424,16 +443,18 @@ class Data(Statement): def process_item(self): line = self.item.get_line()[4:].lstrip() stmts = [] + self.isvalid = False while line: i = line.find('/') - assert i!=-1,`line` + if i==-1: return j = line.find('/',i+1) - assert j!=-1,`line` + if j==-1: return stmts.append((line[:i].rstrip(),line[i+1:j].strip())) line = line[j+1:].lstrip() if line.startswith(','): line = line[1:].lstrip() self.stmts = stmts + self.isvalid = True return def __str__(self): @@ -507,7 +528,7 @@ class Exit(Statement): """ EXIT [ <do-construct-name> ] """ - match = re.compile(r'exit\b\s*\w*\Z',re.I).match + match = re.compile(r'exit\b\s*\w*\s*\Z',re.I).match def process_item(self): self.exitname = self.item.get_line()[4:].lstrip() return @@ -558,13 +579,143 @@ class Dimension(Statement): def __str__(self): return self.get_indent_tab() + 'DIMENSION %s' % (', '.join(self.items)) +class ArithmeticIf(Statement): + """ + IF ( <scalar-numeric-expr> ) <label> , <label> , <label> + """ + match = re.compile(r'if\s*\(.*\)\s*\w+\s*,\s*\w+\s*,\s*\w+\s*\Z', re.I).match + def process_item(self): + line = self.item.get_line()[2:].lstrip() + line,l2,l3 = line.rsplit(',',2) + i = line.rindex(')') + l1 = line[i+1:] + self.expr = line[1:i].strip() + self.labels = [l1.strip(),l2.strip(),l3.strip()] + return + + def __str__(self): + return self.get_indent_tab() + 'IF (%s) %s' \ + % (self.expr,', '.join(self.labels)) + +class Intrinsic(Statement): + """ + INTRINSIC [ :: ] <intrinsic-procedure-name-list> + """ + match = re.compile(r'intrinsic\b',re.I).match + def process_item(self): + line = self.item.get_line()[10:].lstrip() + if line.startswith('::'): + line = line[2:].lstrip() + self.items = [s.strip() for s in line.split(',')] + return + def __str__(self): + return self.get_indent_tab() + 'INTRINSIC ' + ', '.join(self.items) + +class Inquire(Statement): + """ + INQUIRE ( <inquire-spec-list> ) + INQUIRE ( IOLENGTH = <scalar-int-variable> ) <output-item-list> + + <inquire-spec> = [ UNIT = ] <file-unit-number> + | FILE = <file-name-expr> + ... + <output-item> = <expr> + | <io-implied-do> + """ + match = re.compile(r'inquire\s*\(',re.I).match + def process_item(self): + line = self.item.get_line()[7:].lstrip() + i = line.index(')') + self.specs = line[1:i].strip() + self.items = line[i+1:].lstrip() + return + def __str__(self): + return self.get_indent_tab() + 'INQUIRE (%s) %s' % (self.specs, self.items) + +class Sequence(Statement): + """ + SEQUENCE + """ + match = re.compile(r'sequence\Z',re.I).match + def process_item(self): + return + def __str__(self): return self.get_indent_tab() + 'SEQUENCE' + +class External(Statement): + """ + EXTERNAL [ :: ] <external-name-list> + """ + match = re.compile(r'external\b').match + def process_item(self): + line = self.item.get_line()[8:].lstrip() + if line.startswith('::'): + line = line[2:].lstrip() + self.items = [s.strip() for s in line.split(',')] + return + def __str__(self): + return self.get_indent_tab() + 'EXTERNAL ' + ', '.join(self.items) + +class Common(Statement): + """ + COMMON [ / [ <common-block-name> ] / ] <common-block-object-list> \ + [ [ , ] / [ <common-block-name> ] / <common-block-object-list> ]... + <common-block-object> = <variable-name> [ ( <explicit-shape-spec-list> ) ] + | <proc-pointer-name> + """ + match = re.compile(r'common\b',re.I).match + def process_item(self): + line = self.item.get_line()[6:].lstrip() + items = [] + while line: + if not line.startswith('/'): + name = '' + assert not items,`line` + else: + i = line.find('/',1) + assert i!=-1,`line` + name = line[:i+1] + line = line[i+1:].lstrip() + i = line.find('/') + if i==-1: + items.append((name,line)) + line = '' + continue + s = line[:i].rstrip() + if s.endswith(','): + s = s[:-1].rstrip() + items.append((name,s)) + line = line[i+1:].lstrip() + self.items = items + return + def __str__(self): + l = [] + for name,s in self.items: + l.append('%s %s' % (name,s)) + tab = self.get_indent_tab() + return tab + 'COMMON ' + ', '.join(l) + +class Optional(Statement): + """ + OPTIONAL [ :: ] <dummy-arg-name-list> + <dummy-arg-name> = <name> + """ + match = re.compile(r'optional\b',re.I).match + def process_item(self): + line = self.item.get_line()[8:].lstrip() + if line.startswith('::'): + line = line[2:].lstrip() + self.items = [s.split() for s in line.split(',')] + return + def __str__(self): + return self.get_indent_tab() + 'OPTIONAL ' + ', '.join(self.items) + # IF construct statements class Else(Statement): """ ELSE [<if-construct-name>] """ - match = re.compile(r'else\s*\w*\Z',re.I).match + match = re.compile(r'else\b\s*\w*\s*\Z',re.I).match def process_item(self): item = self.item @@ -586,7 +737,7 @@ class ElseIf(Statement): """ ELSE IF ( <scalar-logical-expr> ) THEN [<if-construct-name>] """ - match = re.compile(r'else\s*if\s*\(.*\)\s*then\s*\w*\Z',re.I).match + match = re.compile(r'else\s*if\s*\(.*\)\s*then\s*\w*\s*\Z',re.I).match def process_item(self): item = self.item @@ -643,3 +794,61 @@ class Case(Statement): print >> sys.stderr, message self.isvalid = False return + +# Where construct statements + +class Where(Statement): + """ + WHERE ( <mask-expr> ) <where-assignment-stmt> + """ + match = re.compile(r'where\s*\(.*\)\s*\w.*\Z',re.I).match + def process_item(self): + line = self.item.get_line()[5:].lstrip() + i = line.index(')') + self.expr = line[1:i].strip() + line = line[i+1:].lstrip() + newitem = self.item.copy(line) + cls = Assignment + if cls.match(line): + stmt = cls(self, newitem) + if stmt.isvalid: + self.content = [stmt] + return + self.isvalid = False + return + def __str__(self): + tab = self.get_indent_tab() + return tab + 'WHERE (%s) %s' % (self.expr, self.content[0]) + +WhereStmt = Where + +class ElseWhere(Statement): + """ + ELSEWHERE ( <mask-expr> ) [ <where-construct-name> ] + ELSEWHERE [ <where-construct-name> ] + """ + match = re.compile(r'else\s*where\b').match + def process_item(self): + line = self.item.get_line()[4:].lstrip()[5:].lstrip() + self.expr = None + if line.startswith('('): + i = line.index(')') + assert i != -1,`line` + self.expr = line[1:i].strip() + line = line[i+1:].lstrip() + self.name = line + if self.name and not self.name==self.parent.name: + message = self.reader.format_message(\ + 'WARNING', + 'expected where-construct-name %r but got %r, skipping.'\ + % (self.parent.name, self.name), + self.item.span[0],self.item.span[1]) + print >> sys.stderr, message + self.isvalid = False + return + + def __str__(self): + tab = self.get_indent_tab() + if self.expr is None: + return tab + 'ELSEWHERE ' + self.name + return tab + 'ELSEWHERE (%s) ' % (self.expr) + self.name diff --git a/numpy/f2py/lib/typedecl_statements.py b/numpy/f2py/lib/typedecl_statements.py index 66e162100..ee9d96b98 100644 --- a/numpy/f2py/lib/typedecl_statements.py +++ b/numpy/f2py/lib/typedecl_statements.py @@ -82,15 +82,16 @@ class TypeDeclarationStatement(Statement): selector += line[:i+1].rstrip() line = line[i+1:].lstrip() else: - i = line.find(',') - if i!=-1: - selector += line[:i].rstrip() - line = line[i+1:].lstrip() - else: - i = line.find('::') - assert i!=-1,`line` - selector += line[:i].rstrip() - line = line[i+2:].lstrip() + i = len(line) + ci = '' + for c in [',','::',' ']: + j = line.find(c) + if j!=-1 and j<i: + i = j + ci = c + assert i!=len(line),`i,line` + selector += line[:i].rstrip() + line = line[i+len(ci):].lstrip() else: selector = '' if line.startswith(','): @@ -98,7 +99,6 @@ class TypeDeclarationStatement(Statement): self.raw_selector = selector i = line.find('::') - if i==-1: self.attrspec = '' self.entity_decls = line @@ -125,6 +125,10 @@ class DoublePrecision(TypeDeclarationStatement): class Complex(TypeDeclarationStatement): match = re.compile(r'complex\b',re.I).match +class DoubleComplex(TypeDeclarationStatement): + match = re.compile(r'double\s*complex\b',re.I).match + modes = ['pyf','fix77'] + class Logical(TypeDeclarationStatement): match = re.compile(r'logical\b',re.I).match |