diff options
Diffstat (limited to 'numpy/f2py/lib/parser/statements.py')
-rw-r--r-- | numpy/f2py/lib/parser/statements.py | 1856 |
1 files changed, 1856 insertions, 0 deletions
diff --git a/numpy/f2py/lib/parser/statements.py b/numpy/f2py/lib/parser/statements.py new file mode 100644 index 000000000..5c982ea8b --- /dev/null +++ b/numpy/f2py/lib/parser/statements.py @@ -0,0 +1,1856 @@ +""" +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 __str__(self): + 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() + 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 __str__(self): + return self.get_indent_tab() + '%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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + s = self.get_indent_tab() + '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 'Need to analyze:',self + print 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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + s = self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + s = self.get_indent_tab() + '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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): return self.get_indent_tab() + '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 __str__(self): + t = '' + if self.spec: + t = self.spec.tostr() + ' :: ' + return self.get_indent_tab() \ + + '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 __str__(self): return self.get_indent_tab() \ + + '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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + clsname = self.__class__.__name__.upper() + tab = self.get_indent_tab() + if self.items: + return tab + clsname + ' ' + ', '.join(self.items) + return tab + clsname + + def analyze(self): + clsname = self.__class__.__name__.upper() + if self.items: + for name in self.items: + var = self.get_variable(name) + var.update(clsname) + else: + self.parent.update_attributes(clsname) + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + if self.name: + return self.get_indent_tab() + 'CYCLE ' + self.name + return self.get_indent_tab() + '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 __str__(self): + clsname = self.__class__.__name__.upper() + return self.get_indent_tab() + 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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + tab = self.get_indent_tab() + 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 use.has_key(self.name): + return + + modules = self.top.a.module + if not modules.has_key(self.name): + 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 not modules.has_key(self.name): + 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 + + + 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 __str__(self): + if self.name: + return self.get_indent_tab() + 'EXIT ' + self.name + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + if self.items: + return self.get_indent_tab() + 'INQUIRE (%s) %s' \ + % (', '.join(self.specs), ', '.join(self.items)) + return self.get_indent_tab() + '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 __str__(self): return self.get_indent_tab() + '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 __str__(self): + l = [] + for name,s in self.items: + l.append('%s %s' % (name,s)) + tab = self.get_indent_tab() + 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 __str__(self): + 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() + 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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + 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 __str__(self): + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + tab = self.get_indent_tab() + 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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + 'FORTRANNAME ' + self.value + +class Threadsafe(Statement): + """ + THREADSAFE + """ + match = re.compile(r'threadsafe\Z',re.I).match + def process_item(self): + return + def __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + return self.get_indent_tab() + '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 __str__(self): + if self.value: + return self.get_indent_tab() + 'PAUSE ' + self.value + return self.get_indent_tab() + 'PAUSE' + def analyze(self): return + |