/TOOLS/FparserTools/fparser/statements.py
Python | 1928 lines | 1896 code | 11 blank | 21 comment | 18 complexity | 2484bbb0efbbd9812a07e6922aabe951 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- """
- 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',
- 'Comment']
- 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
- from utils import classes
- 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('')
- if not isinstance(self.parent, classes.Module):
- parentclsname = self.parent.__class__.__name__
- message = 'C548 violation: %s statement only allowed in the'\
- ' specification-part of a module, not in a %s.'\
- % (clsname.upper(), parentclsname.lower())
- self.warning(message)
- access_id_list = self.parent.a.private_id_list + self.parent.a.public_id_list
- if access_id_list.count('')>1:
- message = 'C548 violation: only one access-stmt with omitted'\
- ' access-id-list is permitted in'\
- ' the module-specification-part.'
- self.warning(message)
- # todo: check for conflicting access statement usages (e.g. private foo; public foo)
- # todo: check for conflicting generic-spec id-s.
- 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 item.label is None:
- # R1001:
- self.warning('FORMAT statement must be labeled (F2008:C1001).' \
- % (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 = self.reader.find_module_source_file(self.name)
- if fn is not None:
- from readfortran import FortranFileReader
- from parsefortran import FortranParser
- self.info('looking module information from %r' % (fn))
- reader = FortranFileReader(fn, include_dirs=self.reader.include_dirs, source_only=self.reader.source_only)
- 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[self.name] = module
- use_provides = self.parent.a.use_provides
- renames = [split_comma(item, comma='=>') for item in self.items if '=>' in item]
- norenames = [item for item in self.items if '=>' not in item]
- all_mod_provides = dict(module.a.module_provides)
- all_mod_provides.update(module.a.use_provides)
- if self.isonly:
- # populate use_provides with items/renames only.
- for rename, orig in renames:
- self.populate_use_provides(all_mod_provides, use_provides, orig, rename)
- for name in norenames:
- self.populate_use_provides(all_mod_provides, use_provides, name)
- else:
- # norenames should be empty
- if norenames:
- self.warning("'use' without 'only' clause does not rename the variables '%s'" % ', '.join(norenames))
- # populate use_provides with renamed vars from module.
- for rename, orig in renames:
- self.populate_use_provides(all_mod_provides, use_provides, orig, rename)
- # get all the rest
- unrenamed = set(all_mod_provides) - set([b for (a,b) in renames])
- for name in unrenamed:
- self.populate_use_provides(all_mod_provides, use_provides, name)
- return
- def populate_use_provides(self, all_mod_provides, use_provides, name, rename=None):
- ovar = all_mod_provides.get(name, None)
- if ovar is None:
- raise AnalyzeError("entity name '%s' is not in module '%s'" % (name, self.name))
- if rename:
- name_idx = rename #XXX: rename != ovar.name -- should mark this somehow?
- else:
- name_idx = name
- if name_idx in use_provides:
- self.warning("entity name '%s' is already declared in module '%s', overriding." % (name, self.name))
- use_provides[name_idx] = ovar
- 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()
- …
Large files files are truncated, but you can click here to view the full file