"""
Fortran single line statements.
-----
Permission to use, modify, and distribute this software is given under the
terms of the NumPy License. See http://scipy.org.
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
Author: Pearu Peterson <pearu@cens.ioc.ee>
Created: May 2006
-----
"""
__all__ = ['GeneralAssignment',
'Assignment','PointerAssignment','Assign','Call','Goto','ComputedGoto','AssignedGoto',
'Continue','Return','Stop','Print','Read','Read0','Read1','Write','Flush','Wait',
'Contains','Allocate','Deallocate','ModuleProcedure','Access','Public','Private',
'Close','Cycle','Backspace','Endfile','Rewind','Open','Format','Save',
'Data','Nullify','Use','Exit','Parameter','Equivalence','Dimension','Target',
'Pointer','Protected','Volatile','Value','ArithmeticIf','Intrinsic',
'Inquire','Sequence','External','Namelist','Common','Optional','Intent',
'Entry','Import','ForallStmt','SpecificBinding','GenericBinding',
'FinalBinding','Allocatable','Asynchronous','Bind','Else','ElseIf',
'Case','WhereStmt','ElseWhere','Enumerator','FortranName','Threadsafe',
'Depend','Check','CallStatement','CallProtoArgument','Pause']
import re
import sys
from base_classes import Statement,Variable
# Auxiliary tools
from utils import split_comma,specs_split_comma,AnalyzeError,ParseError,\
get_module_file, parse_bind, parse_result, is_name
class StatementWithNamelist(Statement):
"""
<statement> [ :: ] <name-list>
"""
def process_item(self):
if self.item.has_map():
self.isvalid = False
return
if hasattr(self,'stmtname'):
clsname = self.stmtname
else:
clsname = self.__class__.__name__
line = self.item.get_line()[len(clsname):].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = items = []
for item in split_comma(line):
if not is_name(item):
self.isvalid = False
return
items.append(item)
return
def tofortran(self,isfix=None):
if hasattr(self,'stmtname'):
clsname = self.stmtname.upper()
else:
clsname = self.__class__.__name__.upper()
s = ', '.join(self.items)
if s:
s = ' ' + s
return self.get_indent_tab(isfix=isfix) + clsname + s
# Execution statements
class GeneralAssignment(Statement):
"""
<variable> = <expr>
<pointer variable> => <expr>
"""
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
_repr_attr_names = ['variable','sign','expr'] + Statement._repr_attr_names
def process_item(self):
m = self.item_re(self.item.get_line())
if not m:
self.isvalid = False
return
self.sign = sign = m.group('sign')
if isinstance(self, Assignment) and sign != '=':
self.isvalid = False
return
elif isinstance(self, PointerAssignment) and sign != '=>':
self.isvalid = False
return
else:
if sign=='=>':
self.__class__ = PointerAssignment
else:
self.__class__ = Assignment
apply_map = self.item.apply_map
self.variable = apply_map(m.group('variable').replace(' ',''))
self.expr = apply_map(m.group('expr'))
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + '%s %s %s' \
% (self.variable, self.sign, self.expr)
def analyze(self): return
class Assignment(GeneralAssignment):
pass
class PointerAssignment(GeneralAssignment):
pass
class Assign(Statement):
"""
ASSIGN <label> TO <int-variable-name>
"""
modes = ['fix77']
match = re.compile(r'assign\s*\d+\s*to\s*\w+\s*\Z',re.I).match
def process_item(self):
line = self.item.get_line()[6:].lstrip()
i = line.lower().find('to')
assert not self.item.has_map()
self.items = [line[:i].rstrip(),line[i+2:].lstrip()]
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'ASSIGN %s TO %s' \
% (self.items[0], self.items[1])
def analyze(self): return
class Call(Statement):
"""Call statement class
CALL <procedure-designator> [ ( [ <actual-arg-spec-list> ] ) ]
<procedure-designator> = <procedure-name>
| <proc-component-ref>
| <data-ref> % <binding-name>
<actual-arg-spec> = [ <keyword> = ] <actual-arg>
<actual-arg> = <expr>
| <variable>
| <procedure-name>
| <proc-component-ref>
| <alt-return-spec>
<alt-return-spec> = * <label>
<proc-component-ref> = <variable> % <procedure-component-name>
<variable> = <designator>
Call instance has attributes:
designator
arg_list
"""
match = re.compile(r'call\b', re.I).match
def process_item(self):
item = self.item
apply_map = item.apply_map
line = item.get_line()[4:].strip()
i = line.find('(')
items = []
if i==-1:
self.designator = apply_map(line).strip()
else:
j = line.find(')')
if j == -1 or len(line)-1 != j:
self.isvalid = False
return
self.designator = apply_map(line[:i]).strip()
items = split_comma(line[i+1:-1], item)
self.items = items
return
def tofortran(self, isfix=None):
s = self.get_indent_tab(isfix=isfix) + 'CALL '+str(self.designator)
if self.items:
s += '('+', '.join(map(str,self.items))+ ')'
return s
def analyze(self):
a = self.programblock.a
variables = a.variables
if hasattr(a, 'external'):
external = a.external
if self.designator in external:
print >> sys.stderr, 'Need to analyze:',self
return
class Goto(Statement):
"""
GO TO <label>
"""
match = re.compile(r'go\s*to\s*\d+\s*\Z', re.I).match
def process_item(self):
assert not self.item.has_map()
self.label = self.item.get_line()[2:].lstrip()[2:].lstrip()
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'GO TO %s' % (self.label)
def analyze(self): return
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):
apply_map = self.item.apply_map
line = self.item.get_line()[2:].lstrip()[2:].lstrip()
i = line.index(')')
self.items = split_comma(line[1:i], self.item)
line = line[i+1:].lstrip()
if line.startswith(','):
line = line[1:].lstrip()
self.expr = apply_map(line)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'GO TO (%s) %s' \
% (', '.join(self.items), self.expr)
def analyze(self): return
class AssignedGoto(Statement):
"""
GO TO <int-variable-name> [ ( <label> [ , <label> ]... ) ]
"""
modes = ['fix77']
match = re.compile(r'go\s*to\s*\w+\s*\(?',re.I).match
def process_item(self):
line = self.item.get_line()[2:].lstrip()[2:].lstrip()
i = line.find('(')
if i==-1:
self.varname = line
self.items = []
return
self.varname = line[:i].rstrip()
assert line[-1]==')',`line`
self
self.items = split_comma(line[i+1:-1], self.item)
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
if self.items:
return tab + 'GO TO %s (%s)' \
% (self.varname, ', '.join(self.items))
return tab + 'GO TO %s' % (self.varname)
def analyze(self): return
class Continue(Statement):
"""
CONTINUE
"""
match = re.compile(r'continue\Z',re.I).match
def process_item(self):
self.label = self.item.label
return
def tofortran(self, isfix=None):
return self.get_indent_tab(deindent=True) + 'CONTINUE'
def analyze(self): return
class Return(Statement):
"""
RETURN [ <scalar-int-expr> ]
"""
match = re.compile(r'return\b',re.I).match
def process_item(self):
self.expr = self.item.apply_map(self.item.get_line()[6:].lstrip())
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
if self.expr:
return tab + 'RETURN %s' % (self.expr)
return tab + 'RETURN'
def analyze(self): return
class Stop(Statement):
"""
STOP [ <stop-code> ]
<stop-code> = <scalar-char-constant> | <1-5-digit>
"""
match = re.compile(r'stop\s*(\'\w*\'|"\w*"|\d+|)\Z',re.I).match
def process_item(self):
self.code = self.item.apply_map(self.item.get_line()[4:].lstrip())
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
if self.code:
return tab + 'STOP %s' % (self.code)
return tab + 'STOP'
def analyze(self): return
class Print(Statement):
"""
PRINT <format> [, <output-item-list>]
<format> = <default-char-expr> | <label> | *
<output-item> = <expr> | <io-implied-do>
<io-implied-do> = ( <io-implied-do-object-list> , <implied-do-control> )
<io-implied-do-object> = <input-item> | <output-item>
<implied-do-control> = <do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ]
<input-item> = <variable> | <io-implied-do>
"""
match = re.compile(r'print\s*(\'\w*\'|\"\w*\"|\d+|[*]|\b\w)', re.I).match
def process_item(self):
item = self.item
apply_map = item.apply_map
line = item.get_line()[5:].lstrip()
items = split_comma(line, item)
self.format = items[0]
self.items = items[1:]
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'PRINT %s' \
% (', '.join([self.format]+self.items))
def analyze(self): return
class Read(Statement):
"""
Read0: READ ( <io-control-spec-list> ) [ <input-item-list> ]
<io-control-spec-list> = [ UNIT = ] <io-unit>
| [ FORMAT = ] <format>
| [ NML = ] <namelist-group-name>
| ADVANCE = <scalar-default-char-expr>
...
Read1: READ <format> [, <input-item-list>]
<format> == <default-char-expr> | <label> | *
"""
match = re.compile(r'read\b\s*[\w(*\'"]', re.I).match
def process_item(self):
item = self.item
line = item.get_line()[4:].lstrip()
if line.startswith('('):
self.__class__ = Read0
else:
self.__class__ = Read1
self.process_item()
return
def analyze(self): return
class Read0(Read):
def process_item(self):
item = self.item
line = item.get_line()[4:].lstrip()
i = line.find(')')
self.specs = specs_split_comma(line[1:i], item)
self.items = split_comma(line[i+1:], item)
return
def tofortran(self, isfix=None):
s = self.get_indent_tab(isfix=isfix) + 'READ (%s)' % (', '.join(self.specs))
if self.items:
return s + ' ' + ', '.join(self.items)
return s
class Read1(Read):
def process_item(self):
item = self.item
line = item.get_line()[4:].lstrip()
items = split_comma(line, item)
self.format = items[0]
self.items = items[1:]
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'READ ' \
+ ', '.join([self.format]+self.items)
class Write(Statement):
"""
WRITE ( io-control-spec-list ) [<output-item-list>]
"""
match = re.compile(r'write\s*\(', re.I).match
def process_item(self):
item = self.item
line = item.get_line()[5:].lstrip()
i = line.find(')')
assert i != -1, `line`
self.specs = specs_split_comma(line[1:i], item)
self.items = split_comma(line[i+1:], item)
return
def tofortran(self, isfix=None):
s = self.get_indent_tab(isfix=isfix) + 'WRITE (%s)' % ', '.join(self.specs)
if self.items:
s += ' ' + ', '.join(self.items)
return s
def analyze(self): return
class Flush(Statement):
"""
FLUSH <file-unit-number>
FLUSH ( <flush-spec-list> )
<flush-spec> = [ UNIT = ] <file-unit-number>
| IOSTAT = <scalar-int-variable>
| IOMSG = <iomsg-variable>
| ERR = <label>
"""
match = re.compile(r'flush\b',re.I).match
def process_item(self):
line = self.item.get_line()[5:].lstrip()
if not line:
self.isvalid = False
return
if line.startswith('('):
assert line[-1] == ')', `line`
self.specs = specs_split_comma(line[1:-1],self.item)
else:
self.specs = specs_split_comma(line,self.item)
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
return tab + 'FLUSH (%s)' % (', '.join(self.specs))
def analyze(self): return
class Wait(Statement):
"""
WAIT ( <wait-spec-list> )
<wait-spec> = [ UNIT = ] <file-unit-number>
| END = <label>
| EOR = <label>
| ERR = <label>
| ID = <scalar-int-expr>
| IOMSG = <iomsg-variable>
| IOSTAT = <scalar-int-variable>
"""
match = re.compile(r'wait\s*\(.*\)\Z',re.I).match
def process_item(self):
self.specs = specs_split_comma(\
self.item.get_line()[4:].lstrip()[1:-1], self.item)
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
return tab + 'WAIT (%s)' % (', '.join(self.specs))
def analyze(self): return
class Contains(Statement):
"""
CONTAINS
"""
match = re.compile(r'contains\Z',re.I).match
def process_item(self): return
def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) + 'CONTAINS'
class Allocate(Statement):
"""
ALLOCATE ( [ <type-spec> :: ] <allocation-list> [ , <alloc-opt-list> ] )
<alloc-opt> = STAT = <stat-variable>
| ERRMSG = <errmsg-variable>
| SOURCE = <source-expr>
<allocation> = <allocate-object> [ ( <allocate-shape-spec-list> ) ]
"""
match = re.compile(r'allocate\s*\(.*\)\Z',re.I).match
def process_item(self):
line = self.item.get_line()[8:].lstrip()[1:-1].strip()
item2 = self.item.copy(line, True)
line2 = item2.get_line()
i = line2.find('::')
if i != -1:
spec = item2.apply_map(line2[:i].rstrip())
from block_statements import type_spec
stmt = None
for cls in type_spec:
if cls.match(spec):
stmt = cls(self, item2.copy(spec))
if stmt.isvalid:
break
if stmt is not None and stmt.isvalid:
spec = stmt
else:
self.warning('TODO: unparsed type-spec' + `spec`)
line2 = line2[i+2:].lstrip()
else:
spec = None
self.spec = spec
self.items = specs_split_comma(line2, item2)
return
def tofortran(self, isfix=None):
t = ''
if self.spec:
t = self.spec.tostr() + ' :: '
return self.get_indent_tab(isfix=isfix) \
+ 'ALLOCATE (%s%s)' % (t,', '.join(self.items))
def analyze(self): return
class Deallocate(Statement):
"""
DEALLOCATE ( <allocate-object-list> [ , <dealloc-opt-list> ] )
<allocate-object> = <variable-name>
| <structure-component>
<structure-component> = <data-ref>
<dealloc-opt> = STAT = <stat-variable>
| ERRMSG = <errmsg-variable>
"""
match = re.compile(r'deallocate\s*\(.*\)\Z',re.I).match
def process_item(self):
line = self.item.get_line()[10:].lstrip()[1:-1].strip()
self.items = specs_split_comma(line, self.item)
return
def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) \
+ 'DEALLOCATE (%s)' % (', '.join(self.items))
def analyze(self): return
class ModuleProcedure(Statement):
"""
[ MODULE ] PROCEDURE <procedure-name-list>
"""
match = re.compile(r'(module\s*|)procedure\b',re.I).match
def process_item(self):
line = self.item.get_line()
m = self.match(line)
assert m,`line`
items = split_comma(line[m.end():].strip(), self.item)
for n in items:
if not is_name(n):
self.isvalid = False
return
self.items = items
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
return tab + 'MODULE PROCEDURE %s' % (', '.join(self.items))
def analyze(self):
module_procedures = self.parent.a.module_procedures
module_procedures.extend(self.items)
# XXX: add names to parent_provides
return
class Access(Statement):
"""
<access-spec> [ [::] <access-id-list>]
<access-spec> = PUBLIC | PRIVATE
<access-id> = <use-name> | <generic-spec>
"""
match = re.compile(r'(public|private)\b',re.I).match
def process_item(self):
clsname = self.__class__.__name__.lower()
line = self.item.get_line()
if not line.lower().startswith(clsname):
self.isvalid = False
return
line = line[len(clsname):].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
clsname = self.__class__.__name__.upper()
tab = self.get_indent_tab(isfix=isfix)
if self.items:
return tab + clsname + ' ' + ', '.join(self.items)
return tab + clsname
def analyze(self):
clsname = self.__class__.__name__
l = getattr(self.parent.a, clsname.lower() + '_id_list')
if self.items:
for name in self.items:
if name not in l: l.append(name)
else:
if '' not in l:
l.append('')
return
class Public(Access):
is_public = True
class Private(Access):
is_public = False
class Close(Statement):
"""
CLOSE ( <close-spec-list> )
<close-spec> = [ UNIT = ] <file-unit-number>
| IOSTAT = <scalar-int-variable>
| IOMSG = <iomsg-variable>
| ERR = <label>
| STATUS = <scalar-default-char-expr>
"""
match = re.compile(r'close\s*\(.*\)\Z',re.I).match
def process_item(self):
line = self.item.get_line()[5:].lstrip()[1:-1].strip()
self.specs = specs_split_comma(line, self.item)
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
return tab + 'CLOSE (%s)' % (', '.join(self.specs))
def analyze(self): return
class Cycle(Statement):
"""
CYCLE [ <do-construct-name> ]
"""
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
def tofortran(self, isfix=None):
if self.name:
return self.get_indent_tab(isfix=isfix) + 'CYCLE ' + self.name
return self.get_indent_tab(isfix=isfix) + 'CYCLE'
def analyze(self): return
class FilePositioningStatement(Statement):
"""
REWIND <file-unit-number>
REWIND ( <position-spec-list> )
<position-spec-list> = [ UNIT = ] <file-unit-number>
| IOMSG = <iomsg-variable>
| IOSTAT = <scalar-int-variable>
| ERR = <label>
The same for BACKSPACE, ENDFILE.
"""
match = re.compile(r'(rewind|backspace|endfile)\b',re.I).match
def process_item(self):
clsname = self.__class__.__name__.lower()
line = self.item.get_line()
if not line.lower().startswith(clsname):
self.isvalid = False
return
line = line[len(clsname):].lstrip()
if line.startswith('('):
assert line[-1]==')',`line`
spec = line[1:-1].strip()
else:
spec = line
self.specs = specs_split_comma(spec, self.item)
return
def tofortran(self, isfix=None):
clsname = self.__class__.__name__.upper()
return self.get_indent_tab(isfix=isfix) + clsname + ' (%s)' % (', '.join(self.specs))
def analyze(self): return
class Backspace(FilePositioningStatement): pass
class Endfile(FilePositioningStatement): pass
class Rewind(FilePositioningStatement): pass
class Open(Statement):
"""
OPEN ( <connect-spec-list> )
<connect-spec> = [ UNIT = ] <file-unit-number>
| ACCESS = <scalar-default-char-expr>
| ..
"""
match = re.compile(r'open\s*\(.*\)\Z',re.I).match
def process_item(self):
line = self.item.get_line()[4:].lstrip()[1:-1].strip()
self.specs = specs_split_comma(line, self.item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'OPEN (%s)' % (', '.join(self.specs))
def analyze(self): return
class Format(Statement):
"""
FORMAT <format-specification>
<format-specification> = ( [ <format-item-list> ] )
<format-item> = [ <r> ] <data-edit-descr>
| <control-edit-descr>
| <char-string-edit-descr>
| [ <r> ] ( <format-item-list> )
<data-edit-descr> = I <w> [ . <m> ]
| B <w> [ . <m> ]
...
<r|w|m|d|e> = <int-literal-constant>
<v> = <signed-int-literal-constant>
<control-edit-descr> = <position-edit-descr>
| [ <r> ] /
| :
...
<position-edit-descr> = T <n>
| TL <n>
...
<sign-edit-descr> = SS | SP | S
...
"""
match = re.compile(r'format\s*\(.*\)\Z', re.I).match
def process_item(self):
item = self.item
if not item.label:
# R1001:
self.warning('R1001: FORMAT statement must be labeled but got %r.' \
% (item.label))
line = item.get_line()[6:].lstrip()
assert line[0]+line[-1]=='()',`line`
self.specs = split_comma(line[1:-1], item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'FORMAT (%s)' % (', '.join(self.specs))
def analyze(self): return
class Save(Statement):
"""
SAVE [ [ :: ] <saved-entity-list> ]
<saved-entity> = <object-name>
| <proc-pointer-name>
| / <common-block-name> /
<proc-pointer-name> = <name>
<object-name> = <name>
"""
match = re.compile(r'save\b',re.I).match
def process_item(self):
assert not self.item.has_map()
line = self.item.get_line()[4:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
items = []
for s in line.split(','):
s = s.strip()
if not s: continue
if s.startswith('/'):
assert s.endswith('/'),`s`
n = s[1:-1].strip()
assert is_name(n),`n`
items.append('/%s/' % (n))
elif is_name(s):
items.append(s)
else:
self.isvalid = False
return
self.items = items
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
if not self.items:
return tab + 'SAVE'
return tab + 'SAVE %s' % (', '.join(self.items))
def analyze(self): return
class Data(Statement):
"""
DATA <data-stmt-set> [ [ , ] <data-stmt-set> ]...
<data-stmt-set> = <data-stmt-object-list> / <data-stmt-value-list> /
<data-stmt-object> = <variable> | <data-implied-do>
<data-implied-do> = ( <data-i-do-object-list> , <data-i-do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ] )
<data-i-do-object> = <array-element> | <scalar-structure-component> | <data-implied-do>
<data-i-do-variable> = <scalar-int-variable>
<variable> = <designator>
<designator> = <object-name>
| <array-element>
| <array-section>
| <structure-component>
| <substring>
<array-element> = <data-ref>
<array-section> = <data-ref> [ ( <substring-range> ) ]
"""
match = re.compile(r'data\b',re.I).match
def process_item(self):
line = self.item.get_line()[4:].lstrip()
stmts = []
self.isvalid = False
while line:
i = line.find('/')
if i==-1: return
j = line.find('/',i+1)
if j==-1: return
l1, l2 = line[:i].rstrip(),line[i+1:j].strip()
l1 = split_comma(l1, self.item)
l2 = split_comma(l2, self.item)
stmts.append((l1,l2))
line = line[j+1:].lstrip()
if line.startswith(','):
line = line[1:].lstrip()
self.stmts = stmts
self.isvalid = True
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
l = []
for o,v in self.stmts:
l.append('%s / %s /' %(', '.join(o),', '.join(v)))
return tab + 'DATA ' + ' '.join(l)
def analyze(self): return
class Nullify(Statement):
"""
NULLIFY ( <pointer-object-list> )
<pointer-object> = <variable-name>
"""
match = re.compile(r'nullify\s*\(.*\)\Z',re.I).match
def process_item(self):
line = self.item.get_line()[7:].lstrip()[1:-1].strip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'NULLIFY (%s)' % (', '.join(self.items))
def analyze(self): return
class Use(Statement):
"""
USE [ [ , <module-nature> ] :: ] <module-name> [ , <rename-list> ]
USE [ [ , <module-nature> ] :: ] <module-name> , ONLY : [ <only-list> ]
<module-nature> = INTRINSIC | NON_INTRINSIC
<rename> = <local-name> => <use-name>
| OPERATOR ( <local-defined-operator> ) => OPERATOR ( <use-defined-operator> )
<only> = <generic-spec> | <only-use-name> | <rename>
<only-use-name> = <use-name>
"""
match = re.compile(r'use\b',re.I).match
def process_item(self):
line = self.item.get_line()[3:].lstrip()
nature = ''
if line.startswith(','):
i = line.find('::')
nature = line[1:i].strip().upper()
line = line[i+2:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
if nature and not is_name(nature):
self.isvalid = False
return
self.nature = nature
i = line.find(',')
self.isonly = False
if i==-1:
self.name = line
self.items = []
else:
self.name = line[:i].rstrip()
line = line[i+1:].lstrip()
if line.lower().startswith('only') and line[4:].lstrip().startswith(':'):
self.isonly = True
line = line[4:].lstrip()[1:].lstrip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
s = 'USE'
if self.nature:
s += ' ' + self.nature + ' ::'
s += ' ' + self.name
if self.isonly:
s += ', ONLY:'
elif self.items:
s += ','
if self.items:
s += ' ' + ', '.join(self.items)
return tab + s
def analyze(self):
use = self.parent.a.use
if self.name in use:
return
modules = self.top.a.module
if self.name not in modules:
fn = None
for d in self.reader.include_dirs:
fn = get_module_file(self.name, d)
if fn is not None:
break
if fn is not None:
from readfortran import FortranFileReader
from parsefortran import FortranParser
self.info('looking module information from %r' % (fn))
reader = FortranFileReader(fn)
parser = FortranParser(reader)
parser.parse()
parser.block.a.module.update(modules)
parser.analyze()
modules.update(parser.block.a.module)
if self.name not in modules:
self.warning('no information about the module %r in use statement' % (self.name))
return
module = modules[self.name]
use_provides = self.parent.a.use_provides
print use
return
class Exit(Statement):
"""
EXIT [ <do-construct-name> ]
"""
match = re.compile(r'exit\b\s*\w*\s*\Z',re.I).match
def process_item(self):
self.name = self.item.get_line()[4:].lstrip()
return
def tofortran(self, isfix=None):
if self.name:
return self.get_indent_tab(isfix=isfix) + 'EXIT ' + self.name
return self.get_indent_tab(isfix=isfix) + 'EXIT'
def analyze(self): return
class Parameter(Statement):
"""
PARAMETER ( <named-constant-def-list> )
<named-constant-def> = <named-constant> = <initialization-expr>
"""
match = re.compile(r'parameter\s*\(.*\)\Z', re.I).match
def process_item(self):
line = self.item.get_line()[9:].lstrip()[1:-1].strip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'PARAMETER (%s)' % (', '.join(self.items))
def analyze(self):
for item in self.items:
i = item.find('=')
assert i!=-1,`item`
name = item[:i].rstrip()
value = item[i+1:].lstrip()
var = self.get_variable(name)
var.update('parameter')
var.set_init(value)
return
class Equivalence(Statement):
"""
EQUIVALENCE <equivalence-set-list>
<equivalence-set> = ( <equivalence-object> , <equivalence-object-list> )
<equivalence-object> = <variable-name> | <array-element> | <substring>
"""
match = re.compile(r'equivalence\s*\(.*\)\Z', re.I).match
def process_item(self):
items = []
for s in self.item.get_line()[11:].lstrip().split(','):
s = s.strip()
assert s[0]+s[-1]=='()',`s,self.item.get_line()`
s = ', '.join(split_comma(s[1:-1], self.item))
items.append('('+s+')')
self.items = items
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'EQUIVALENCE %s' % (', '.join(self.items))
def analyze(self): return
class Dimension(Statement):
"""
DIMENSION [ :: ] <array-name> ( <array-spec> ) [ , <array-name> ( <array-spec> ) ]...
"""
match = re.compile(r'dimension\b', re.I).match
def process_item(self):
line = self.item.get_line()[9:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'DIMENSION %s' % (', '.join(self.items))
def analyze(self):
for line in self.items:
i = line.find('(')
assert i!=-1 and line.endswith(')'),`line`
name = line[:i].rstrip()
array_spec = split_comma(line[i+1:-1].strip(), self.item)
var = self.get_variable(name)
var.set_bounds(array_spec)
return
class Target(Statement):
"""
TARGET [ :: ] <object-name> ( <array-spec> ) [ , <object-name> ( <array-spec> ) ]...
"""
match = re.compile(r'target\b', re.I).match
def process_item(self):
line = self.item.get_line()[6:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'TARGET %s' % (', '.join(self.items))
def analyze(self):
for line in self.items:
i = line.find('(')
assert i!=-1 and line.endswith(')'),`line`
name = line[:i].rstrip()
array_spec = split_comma(line[i+1:-1].strip(), self.item)
var = self.get_variable(name)
var.set_bounds(array_spec)
var.update('target')
return
class Pointer(Statement):
"""
POINTER [ :: ] <pointer-decl-list>
<pointer-decl> = <object-name> [ ( <deferred-shape-spec-list> ) ]
| <proc-entity-name>
"""
match = re.compile(r'pointer\b',re.I).match
def process_item(self):
line = self.item.get_line()[7:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'POINTER %s' % (', '.join(self.items))
def analyze(self):
for line in self.items:
i = line.find('(')
if i==-1:
name = line
array_spec = None
else:
assert line.endswith(')'),`line`
name = line[:i].rstrip()
array_spec = split_comma(line[i+1:-1].strip(), self.item)
var = self.get_variable(name)
var.set_bounds(array_spec)
var.update('pointer')
return
class Protected(StatementWithNamelist):
"""
PROTECTED [ :: ] <entity-name-list>
"""
match = re.compile(r'protected\b',re.I).match
def analyze(self):
for name in self.items:
var = self.get_variable(name)
var.update('protected')
return
class Volatile(StatementWithNamelist):
"""
VOLATILE [ :: ] <object-name-list>
"""
match = re.compile(r'volatile\b',re.I).match
def analyze(self):
for name in self.items:
var = self.get_variable(name)
var.update('volatile')
return
class Value(StatementWithNamelist):
"""
VALUE [ :: ] <dummy-arg-name-list>
"""
match = re.compile(r'value\b',re.I).match
def analyze(self):
for name in self.items:
var = self.get_variable(name)
var.update('value')
return
class ArithmeticIf(Statement):
"""
IF ( <scalar-numeric-expr> ) <label> , <label> , <label>
"""
match = re.compile(r'if\s*\(.*\)\s*\d+\s*,\s*\d+\s*,\s*\d+\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 = self.item.apply_map(line[1:i]).strip()
self.labels = [l1.strip(),l2.strip(),l3.strip()]
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'IF (%s) %s' \
% (self.expr,', '.join(self.labels))
def analyze(self): return
class Intrinsic(StatementWithNamelist):
"""
INTRINSIC [ :: ] <intrinsic-procedure-name-list>
"""
match = re.compile(r'intrinsic\b',re.I).match
def analyze(self):
for name in self.items:
var = self.get_variable(name)
var.update('intrinsic')
return
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 = specs_split_comma(line[1:i].strip(), self.item)
self.items = split_comma(line[i+1:].lstrip(), self.item)
return
def tofortran(self, isfix=None):
if self.items:
return self.get_indent_tab(isfix=isfix) + 'INQUIRE (%s) %s' \
% (', '.join(self.specs), ', '.join(self.items))
return self.get_indent_tab(isfix=isfix) + 'INQUIRE (%s)' \
% (', '.join(self.specs))
def analyze(self): return
class Sequence(Statement):
"""
SEQUENCE
"""
match = re.compile(r'sequence\Z',re.I).match
def process_item(self):
return
def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) + 'SEQUENCE'
def analyze(self):
self.parent.update_attributes('SEQUENCE')
return
class External(StatementWithNamelist):
"""
EXTERNAL [ :: ] <external-name-list>
"""
match = re.compile(r'external\b', re.I).match
def analyze(self):
for name in self.items:
var = self.get_variable(name)
var.update('external')
return
class Namelist(Statement):
"""
NAMELIST / <namelist-group-name> / <namelist-group-object-list> [ [ , ] / <namelist-group-name> / <namelist-group-object-list> ]...
<namelist-group-object> = <variable-name>
"""
match = re.compile(r'namelist\b',re.I).match
def process_item(self):
line = self.item.get_line()[8:].lstrip()
items = []
while line:
assert line.startswith('/'),`line`
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 tofortran(self, isfix=None):
l = []
for name,s in self.items:
l.append('%s %s' % (name,s))
tab = self.get_indent_tab(isfix=isfix)
return tab + 'NAMELIST ' + ', '.join(l)
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):
item = self.item
line = 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[1:i].strip()
line = line[i+1:].lstrip()
i = line.find('/')
if i==-1:
items.append((name,split_comma(line, item)))
line = ''
continue
s = line[:i].rstrip()
if s.endswith(','):
s = s[:-1].rstrip()
items.append((name,split_comma(s,item)))
line = line[i:].lstrip()
self.items = items
return
def tofortran(self, isfix=None):
l = []
for name,s in self.items:
s = ', '.join(s)
if name:
l.append('/ %s / %s' % (name,s))
else:
l.append(s)
tab = self.get_indent_tab(isfix=isfix)
return tab + 'COMMON ' + ' '.join(l)
def analyze(self):
for cname, items in self.items:
for item in items:
i = item.find('(')
if i!=-1:
assert item.endswith(')'),`item`
name = item[:i].rstrip()
shape = split_comma(item[i+1:-1].strip(), self.item)
else:
name = item
shape = None
var = self.get_variable(name)
if shape is not None:
var.set_bounds(shape)
# XXX: add name,var to parent_provides
return
class Optional(StatementWithNamelist):
"""
OPTIONAL [ :: ] <dummy-arg-name-list>
<dummy-arg-name> = <name>
"""
match = re.compile(r'optional\b',re.I).match
def analyze(self):
for name in self.items:
var = self.get_variable(name)
var.update('optional')
return
class Intent(Statement):
"""
INTENT ( <intent-spec> ) [ :: ] <dummy-arg-name-list>
<intent-spec> = IN | OUT | INOUT
generalization for pyf-files:
INTENT ( <intent-spec-list> ) [ :: ] <dummy-arg-name-list>
<intent-spec> = IN | OUT | INOUT | CACHE | HIDE | OUT = <name>
"""
match = re.compile(r'intent\s*\(',re.I).match
def process_item(self):
line = self.item.get_line()[6:].lstrip()
i = line.find(')')
self.specs = specs_split_comma(line[1:i], self.item, upper=True)
line = line[i+1:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = [s.strip() for s in line.split(',')]
for n in self.items:
if not is_name(n):
self.isvalid = False
return
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'INTENT (%s) %s' \
% (', '.join(self.specs), ', '.join(self.items))
def analyze(self):
for name in self.items:
var = self.get_variable(name)
var.set_intent(self.specs)
return
class Entry(Statement):
"""
ENTRY <entry-name> [ ( [ <dummy-arg-list> ] ) [ <suffix> ] ]
<suffix> = <proc-language-binding-spec> [ RESULT ( <result-name> ) ]
| RESULT ( <result-name> ) [ <proc-language-binding-spec> ]
<proc-language-binding-spec> = <language-binding-spec>
<language-binding-spec> = BIND ( C [ , NAME = <scalar-char-initialization-expr> ] )
<dummy-arg> = <dummy-arg-name> | *
"""
match = re.compile(r'entry\b', re.I).match
def process_item(self):
line = self.item.get_line()[5:].lstrip()
m = re.match(r'\w+', line)
name = line[:m.end()]
line = line[m.end():].lstrip()
if line.startswith('('):
i = line.find(')')
assert i!=-1,`line`
items = split_comma(line[1:i], self.item)
line = line[i+1:].lstrip()
else:
items = []
self.bind, line = parse_bind(line, self.item)
self.result, line = parse_result(line, self.item)
if line:
assert self.bind is None,`self.bind`
self.bind, line = parse_bind(line, self.item)
assert not line,`line`
self.name = name
self.items = items
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
s = tab + 'ENTRY '+self.name
if self.items:
s += ' (%s)' % (', '.join(self.items))
if self.result:
s += ' RESULT (%s)' % (self.result)
if self.bind:
s += ' BIND (%s)' % (', '.join(self.bind))
return s
class Import(StatementWithNamelist):
"""
IMPORT [ [ :: ] <import-name-list> ]
"""
match = re.compile(r'import(\b|\Z)',re.I).match
class Forall(Statement):
"""
FORALL <forall-header> <forall-assignment-stmt>
<forall-header> = ( <forall-triplet-spec-list> [ , <scalar-mask-expr> ] )
<forall-triplet-spec> = <index-name> = <subscript> : <subscript> [ : <stride> ]
<subscript|stride> = <scalar-int-expr>
<forall-assignment-stmt> = <assignment-stmt> | <pointer-assignment-stmt>
"""
match = re.compile(r'forall\s*\(.*\).*=', re.I).match
def process_item(self):
line = self.item.get_line()[6:].lstrip()
i = line.index(')')
line0 = line[1:i]
line = line[i+1:].lstrip()
stmt = GeneralAssignment(self, self.item.copy(line, True))
if stmt.isvalid:
self.content = [stmt]
else:
self.isvalid = False
return
specs = []
mask = ''
for l in split_comma(line0,self.item):
j = l.find('=')
if j==-1:
assert not mask,`mask,l`
mask = l
continue
assert j!=-1,`l`
index = l[:j].rstrip()
it = self.item.copy(l[j+1:].lstrip())
l = it.get_line()
k = l.split(':')
if len(k)==3:
s1, s2, s3 = map(it.apply_map,
[k[0].strip(),k[1].strip(),k[2].strip()])
else:
assert len(k)==2,`k`
s1, s2 = map(it.apply_map,
[k[0].strip(),k[1].strip()])
s3 = '1'
specs.append((index,s1,s2,s3))
self.specs = specs
self.mask = mask
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
l = []
for index,s1,s2,s3 in self.specs:
s = '%s = %s : %s' % (index,s1,s2)
if s3!='1':
s += ' : %s' % (s3)
l.append(s)
s = ', '.join(l)
if self.mask:
s += ', ' + self.mask
return tab + 'FORALL (%s) %s' % \
(s, str(self.content[0]).lstrip())
def analyze(self): return
ForallStmt = Forall
class SpecificBinding(Statement):
"""
PROCEDURE [ ( <interface-name> ) ] [ [ , <binding-attr-list> ] :: ] <binding-name> [ => <procedure-name> ]
<binding-attr> = PASS [ ( <arg-name> ) ]
| NOPASS
| NON_OVERRIDABLE
| DEFERRED
| <access-spec>
<access-spec> = PUBLIC | PRIVATE
"""
match = re.compile(r'procedure\b',re.I).match
def process_item(self):
line = self.item.get_line()[9:].lstrip()
if line.startswith('('):
i = line.index(')')
name = line[1:i].strip()
line = line[i+1:].lstrip()
else:
name = ''
self.iname = name
if line.startswith(','):
line = line[1:].lstrip()
i = line.find('::')
if i != -1:
attrs = split_comma(line[:i], self.item)
line = line[i+2:].lstrip()
else:
attrs = []
attrs1 = []
for attr in attrs:
if is_name(attr):
attr = attr.upper()
else:
i = attr.find('(')
assert i!=-1 and attr.endswith(')'),`attr`
attr = '%s (%s)' % (attr[:i].rstrip().upper(), attr[i+1:-1].strip())
attrs1.append(attr)
self.attrs = attrs1
i = line.find('=')
if i==-1:
self.name = line
self.bname = ''
else:
self.name = line[:i].rstrip()
self.bname = line[i+1:].lstrip()[1:].lstrip()
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
s = 'PROCEDURE '
if self.iname:
s += '(' + self.iname + ') '
if self.attrs:
s += ', ' + ', '.join(self.attrs) + ' :: '
if self.bname:
s += '%s => %s' % (self.name, self.bname)
else:
s += self.name
return tab + s
class GenericBinding(Statement):
"""
GENERIC [ , <access-spec> ] :: <generic-spec> => <binding-name-list>
"""
match = re.compile(r'generic\b.*::.*=\>.*\Z', re.I).match
def process_item(self):
line = self.item.get_line()[7:].lstrip()
if line.startswith(','):
line = line[1:].lstrip()
i = line.index('::')
self.aspec = line[:i].rstrip().upper()
line = line[i+2:].lstrip()
i = line.index('=>')
self.spec = self.item.apply_map(line[:i].rstrip())
self.items = split_comma(line[i+2:].lstrip())
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
s = 'GENERIC'
if self.aspec:
s += ', '+self.aspec
s += ' :: ' + self.spec + ' => ' + ', '.join(self.items)
return tab + s
class FinalBinding(StatementWithNamelist):
"""
FINAL [ :: ] <final-subroutine-name-list>
"""
stmtname = 'final'
match = re.compile(r'final\b', re.I).match
class Allocatable(Statement):
"""
ALLOCATABLE [ :: ] <object-name> [ ( <deferred-shape-spec-list> ) ] [ , <object-name> [ ( <deferred-shape-spec-list> ) ] ]...
"""
match = re.compile(r'allocatable\b',re.I).match
def process_item(self):
line = self.item.get_line()[11:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'ALLOCATABLE ' + ', '.join(self.items)
def analyze(self):
for line in self.items:
i = line.find('(')
if i==-1:
name = line
array_spec = None
else:
assert line.endswith(')')
name = line[:i].rstrip()
array_spec = split_comma(line[i+1:-1], self.item)
var = self.get_variable(name)
var.update('allocatable')
if array_spec is not None:
var.set_bounds(array_spec)
return
class Asynchronous(StatementWithNamelist):
"""
ASYNCHRONOUS [ :: ] <object-name-list>
"""
match = re.compile(r'asynchronous\b',re.I).match
def analyze(self):
for name in self.items:
var = self.get_variable(name)
var.update('asynchronous')
return
class Bind(Statement):
"""
<language-binding-spec> [ :: ] <bind-entity-list>
<language-binding-spec> = BIND ( C [ , NAME = <scalar-char-initialization-expr> ] )
<bind-entity> = <entity-name> | / <common-block-name> /
"""
match = re.compile(r'bind\s*\(.*\)',re.I).match
def process_item(self):
line = self.item.line
self.specs, line = parse_bind(line, self.item)
if line.startswith('::'):
line = line[2:].lstrip()
items = []
for item in split_comma(line, self.item):
if item.startswith('/'):
assert item.endswith('/'),`item`
item = '/ ' + item[1:-1].strip() + ' /'
items.append(item)
self.items = items
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'BIND (%s) %s' %\
(', '.join(self.specs), ', '.join(self.items))
# IF construct statements
class Else(Statement):
"""
ELSE [<if-construct-name>]
"""
match = re.compile(r'else\b\s*\w*\s*\Z',re.I).match
def process_item(self):
item = self.item
self.name = item.get_line()[4:].strip()
parent_name = getattr(self.parent,'name','')
if self.name and self.name!=parent_name:
self.warning('expected if-construct-name %r but got %r, skipping.'\
% (parent_name, self.name))
self.isvalid = False
return
def tofortran(self, isfix=None):
if self.name:
return self.get_indent_tab(deindent=True) + 'ELSE ' + self.name
return self.get_indent_tab(deindent=True) + 'ELSE'
def analyze(self): return
class ElseIf(Statement):
"""
ELSE IF ( <scalar-logical-expr> ) THEN [ <if-construct-name> ]
"""
match = re.compile(r'else\s*if\s*\(.*\)\s*then\s*\w*\s*\Z',re.I).match
def process_item(self):
item = self.item
line = item.get_line()[4:].lstrip()[2:].lstrip()
i = line.find(')')
assert line[0]=='('
self.expr = item.apply_map(line[1:i])
self.name = line[i+1:].lstrip()[4:].strip()
parent_name = getattr(self.parent,'name','')
if self.name and self.name!=parent_name:
self.warning('expected if-construct-name %r but got %r, skipping.'\
% (parent_name, self.name))
self.isvalid = False
return
def tofortran(self, isfix=None):
s = ''
if self.name:
s = ' ' + self.name
return self.get_indent_tab(deindent=True) + 'ELSE IF (%s) THEN%s' \
% (self.expr, s)
def analyze(self): return
# SelectCase construct statements
class Case(Statement):
"""
CASE <case-selector> [ <case-constract-name> ]
<case-selector> = ( <case-value-range-list> ) | DEFAULT
<case-value-range> = <case-value>
| <case-value> :
| : <case-value>
| <case-value> : <case-value>
<case-value> = <scalar-(int|char|logical)-initialization-expr>
"""
match = re.compile(r'case\b\s*(\(.*\)|DEFAULT)\s*\w*\Z',re.I).match
def process_item(self):
#assert self.parent.__class__.__name__=='Select',`self.parent.__class__`
line = self.item.get_line()[4:].lstrip()
if line.startswith('('):
i = line.find(')')
items = split_comma(line[1:i].strip(), self.item)
line = line[i+1:].lstrip()
else:
assert line.lower().startswith('default'),`line`
items = []
line = line[7:].lstrip()
for i in range(len(items)):
it = self.item.copy(items[i])
rl = []
for r in it.get_line().split(':'):
rl.append(it.apply_map(r.strip()))
items[i] = rl
self.items = items
self.name = line
parent_name = getattr(self.parent, 'name', '')
if self.name and self.name!=parent_name:
self.warning('expected case-construct-name %r but got %r, skipping.'\
% (parent_name, self.name))
self.isvalid = False
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
s = 'CASE'
if self.items:
l = []
for item in self.items:
l.append((' : '.join(item)).strip())
s += ' ( %s )' % (', '.join(l))
else:
s += ' DEFAULT'
if self.name:
s += ' ' + self.name
return s
def analyze(self): 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 = self.item.apply_map(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 tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
return tab + 'WHERE ( %s ) %s' % (self.expr, str(self.content[0]).lstrip())
def analyze(self): return
WhereStmt = Where
class ElseWhere(Statement):
"""
ELSE WHERE ( <mask-expr> ) [ <where-construct-name> ]
ELSE WHERE [ <where-construct-name> ]
"""
match = re.compile(r'else\s*where\b',re.I).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 = self.item.apply_map(line[1:i].strip())
line = line[i+1:].lstrip()
self.name = line
parent_name = getattr(self.parent,'name','')
if self.name and not self.name==parent_name:
self.warning('expected where-construct-name %r but got %r, skipping.'\
% (parent_name, self.name))
self.isvalid = False
return
def tofortran(self, isfix=None):
tab = self.get_indent_tab(isfix=isfix)
s = 'ELSE WHERE'
if self.expr is not None:
s += ' ( %s )' % (self.expr)
if self.name:
s += ' ' + self.name
return tab + s
def analyze(self): return
# Enum construct statements
class Enumerator(Statement):
"""
ENUMERATOR [ :: ] <enumerator-list>
<enumerator> = <named-constant> [ = <scalar-int-initialization-expr> ]
"""
match = re.compile(r'enumerator\b',re.I).match
def process_item(self):
line = self.item.get_line()[10:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = split_comma(line, self.item)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'ENUMERATOR ' + ', '.join(self.items)
# F2PY specific statements
class FortranName(Statement):
"""
FORTRANNAME <name>
"""
match = re.compile(r'fortranname\s*\w+\Z',re.I).match
def process_item(self):
self.value = self.item.get_line()[11:].lstrip()
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'FORTRANNAME ' + self.value
class Threadsafe(Statement):
"""
THREADSAFE
"""
match = re.compile(r'threadsafe\Z',re.I).match
def process_item(self):
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'THREADSAFE'
class Depend(Statement):
"""
DEPEND ( <name-list> ) [ :: ] <dummy-arg-name-list>
"""
match = re.compile(r'depend\s*\(',re.I).match
def process_item(self):
line = self.item.get_line()[6:].lstrip()
i = line.find(')')
self.depends = split_comma(line[1:i].strip(), self.item)
line = line[i+1:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.items = split_comma(line)
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'DEPEND ( %s ) %s' \
% (', '.join(self.depends), ', '.join(self.items))
class Check(Statement):
"""
CHECK ( <c-int-scalar-expr> ) [ :: ] <name>
"""
match = re.compile(r'check\s*\(',re.I).match
def process_item(self):
line = self.item.get_line()[5:].lstrip()
i = line.find(')')
assert i!=-1,`line`
self.expr = self.item.apply_map(line[1:i].strip())
line = line[i+1:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
self.value = line
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'CHECK ( %s ) %s' \
% (self.expr, self.value)
class CallStatement(Statement):
"""
CALLSTATEMENT <c-expr>
"""
match = re.compile(r'callstatement\b', re.I).match
def process_item(self):
self.expr = self.item.apply_map(self.item.get_line()[13:].lstrip())
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'CALLSTATEMENT ' + self.expr
class CallProtoArgument(Statement):
"""
CALLPROTOARGUMENT <c-type-spec-list>
"""
match = re.compile(r'callprotoargument\b', re.I).match
def process_item(self):
self.specs = self.item.apply_map(self.item.get_line()[17:].lstrip())
return
def tofortran(self, isfix=None):
return self.get_indent_tab(isfix=isfix) + 'CALLPROTOARGUMENT ' + self.specs
# Non-standard statements
class Pause(Statement):
"""
PAUSE [ <char-literal-constant|int-literal-constant> ]
"""
match = re.compile(r'pause\s*(\d+|\'\w*\'|"\w*"|)\Z', re.I).match
def process_item(self):
self.value = self.item.apply_map(self.item.get_line()[5:].lstrip())
return
def tofortran(self, isfix=None):
if self.value:
return self.get_indent_tab(isfix=isfix) + 'PAUSE ' + self.value
return self.get_indent_tab(isfix=isfix) + 'PAUSE'
def analyze(self): return
|