diff options
author | Pearu Peterson <pearu.peterson@gmail.com> | 2006-06-22 10:25:57 +0000 |
---|---|---|
committer | Pearu Peterson <pearu.peterson@gmail.com> | 2006-06-22 10:25:57 +0000 |
commit | d5a5da520b1eddd10a7dde79b0e7df281ee1abaa (patch) | |
tree | f19a3ce2d0e327bc02771dee39a4b0ccea7aeccf /numpy/f2py/lib/statements.py | |
parent | 1fe0237f46025a44779ad98974b9a587b6aa6ac8 (diff) | |
download | numpy-d5a5da520b1eddd10a7dde79b0e7df281ee1abaa.tar.gz |
Cont. impl. Fortran parser.
Diffstat (limited to 'numpy/f2py/lib/statements.py')
-rw-r--r-- | numpy/f2py/lib/statements.py | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/numpy/f2py/lib/statements.py b/numpy/f2py/lib/statements.py new file mode 100644 index 000000000..09b60d328 --- /dev/null +++ b/numpy/f2py/lib/statements.py @@ -0,0 +1,645 @@ + +import re +import sys + +from base_classes import Statement + +# Execution statements + +class Assignment(Statement): + """ + <variable> = <expr> + <pointer variable> => <expr> + """ + + match = re.compile(r'\w(\s*\(\s*[^)]*\)|[\w%]*)*\s*=\>?',re.I).match + item_re = re.compile(r'(?P<variable>\w(\s*\(\s*[^)]*\)|[\w%]*)*)\s*(?P<sign>=\>?)\s*(?P<expr>.*)\Z',re.I).match + + def process_item(self): + m = self.item_re(self.item.get_line()) + self.variable = m.group('variable').replace(' ','') + self.sign = m.group('sign') + self.expr = m.group('expr') + return + + def __str__(self): + return self.get_indent_tab() + '%s %s %s' \ + % (self.variable, self.sign, self.expr) + +class Call(Statement): + """Call statement class + CALL <proc-designator> [([arg-spec-list])] + + Call instance has attributes: + designator + arg_list + """ + match = re.compile(r'call\b', re.I).match + + def process_item(self): + item = self.item + line = item.get_line()[4:].strip() + i = line.find('(') + self.arg_list = [] + if i==-1: + self.designator = line.strip() + else: + self.designator = line[:i].strip() + for n in line[i+1:-1].split(','): + n = n.strip() + if not n: continue + self.arg_list.append(n) + return + + def __str__(self): + s = self.get_indent_tab() + 'CALL '+str(self.designator) + if self.arg_list: + s += '('+', '.join(map(str,self.arg_list))+ ')' + return s + +class Goto(Statement): + """ + GO TO <label> + + """ + match = re.compile(r'go\s*to\b\s*\w*\Z', re.I).match + + def process_item(self): + self.gotolabel = self.item.get_line()[2:].strip()[2:].strip() + return + + def __str__(self): + return self.get_indent_tab() + 'GO TO %s' % (self.gotolabel) + +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' + + +class Return(Statement): + """ + RETURN [scalar-int-expr] + """ + match = re.compile(r'return\b',re.I).match + + def process_item(self): + line = self.item.get_line()[6:].lstrip() + self.expr = line + return + + def __str__(self): + return self.get_indent_tab() + 'RETURN %s' % (self.expr) + +class Stop(Statement): + """ + STOP [stop-code] + """ + match = re.compile(r'stop\b\s*\w*\Z',re.I).match + + def process_item(self): + self.stopcode = self.item.get_line()[4:].lstrip() + return + + def __str__(self): + return self.get_indent_tab() + 'STOP %s' % (self.stopcode) + +class Print(Statement): + """ + PRINT <format> [, <output-item-list>] + <format> == <default-char-expr> | <label> | * + """ + match = re.compile(r'print\b\s*[\w*]', re.I).match + + def process_item(self): + item = self.item + line = item.get_line()[5:].lstrip() + items = line.split(',') + self.format = items[0].strip() + self.items = [s.strip() for s in items[1:]] + return + + def __str__(self): + return self.get_indent_tab() + 'PRINT %s' % (', '.join([self.format]+self.items)) + +class Read(Statement): + """ +Read0: READ ( io-control-spec-list ) [<input-item-list>] + +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() + +class Read0(Read): + + def process_item(self): + item = self.item + line = item.get_line()[4:].lstrip() + i = line.find(')') + self.io_control_specs = line[1:i].strip() + self.items = [s.strip() for s in line[i+1:].split(',')] + + def __str__(self): + return self.get_indent_tab() + 'READ (%s) %s' \ + % (self.io_control_specs, ', '.join(self.items)) + +class Read1(Read): + + def process_item(self): + item = self.item + line = item.get_line()[4:].lstrip() + items = line.split(',') + self.format = items[0].strip() + self.items = [s.strip() for s in items[1:]] + return + + def __str__(self): + return self.get_indent_tab() + 'READ %s' % (', '.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(')') + self.io_control_specs = line[1:i].strip() + self.items = [s.strip() for s in line[i+1:].split(',')] + + def __str__(self): + return self.get_indent_tab() + 'WRITE (%s) %s' \ + % (self.io_control_specs, ', '.join(self.items)) + +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> ] ) + """ + match = re.compile(r'allocate\s*\(.*\)\Z',re.I).match + def process_item(self): + self.items = self.item.get_line()[8:].lstrip()[1:-1].strip() + def __str__(self): return self.get_indent_tab() \ + + 'ALLOCATE ( %s )' % (self.items) + +class Deallocate(Statement): + """ + DEALLOCATE ( <allocate-object-list> [ , <dealloc-opt-list> ] ) + """ + match = re.compile(r'deallocate\s*\(.*\)\Z',re.I).match + def process_item(self): + self.items = self.item.get_line()[10:].lstrip()[1:-1].strip() + def __str__(self): return self.get_indent_tab() \ + + 'DEALLOCATE ( %s )' % (self.items) + +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) + self.names = [s.strip() for s in line[m.end():].split(',')] + def __str__(self): + tab = self.get_indent_tab() + return tab + 'MODULE PROCEDURE %s' % (', '.join(self.names)) + +class Access(Statement): + """ + <access-spec> [ [::] <access-id-list>] + <access-spec> = PUBLIC | PRIVATE + """ + 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.startswith(clsname): + self.isvalid = False + return + line = line[len(clsname):].lstrip() + if line.startswith('::'): + line = line[2:].lstrip() + self.items = [s.strip() for s in line.split(',')] + 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 + +class Public(Access): pass +class Private(Access): pass + +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): + self.close_specs = self.item.get_line()[5:].lstrip()[1:-1].strip() + return + def __str__(self): + tab = self.get_indent_tab() + return tab + 'CLOSE (%s)' % (self.close_specs) + +class Cycle(Statement): + """ + CYCLE [ <do-construct-name> ] + """ + match = re.compile(r'cycle\b\s*\w*\Z',re.I).match + def process_item(self): + self.name = self.item.get_line()[5:].lstrip() + return + def __str__(self): + return self.get_indent_tab() + 'CYCLE ' + self.name + +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.startswith(clsname): + self.isvalid = False + return + line = line[len(clsname):].lstrip() + if line.startswith('('): + assert line[-1]==')',`line` + self.fileunit = None + self.position_specs = line[1:-1].strip() + else: + self.fileunit = line + self.position_specs = None + return + + def __str__(self): + clsname = self.__class__.__name__.upper() + if self.fileunit is None: + return self.get_indent_tab() + clsname + ' (%s)' % (self.position_specs) + return self.get_indent_tab() + clsname + ' %s' % (self.fileunit) + +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): + self.connect_specs = self.item.get_line()[4:].lstrip()[1:-1].strip() + return + def __str__(self): + return self.get_indent_tab() + 'OPEN (%s)' % (self.connect_specs) + +class Format(Statement): + """ + FORMAT <format-specification> + <format-specification> = ( [ <format-item-list> ] ) + + """ + match = re.compile(r'format\s*\(.*\)\Z', re.I).match + def process_item(self): + item = self.item + if not item.label: + # R1001: + message = self.reader.format_message(\ + 'WARNING', + 'R1001: FORMAT statement must be labeled but got %r.' \ + % (item.label), + item.span[0],item.span[1]) + print >> sys.stderr, message + line = item.get_line()[6:].lstrip() + assert line[0]+line[-1]=='()',`line` + self.specs = line[1:-1].strip() + return + def __str__(self): + return self.get_indent_tab() + 'FORMAT (%s)' % (self.specs) + +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 + is_name = re.compile(r'\w+\Z').match + def process_item(self): + 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 self.is_name(n) + items.append('/%s/' % ()) + elif self.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)) + +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 = [] + while line: + i = line.find('/') + assert i!=-1,`line` + j = line.find('/',i+1) + assert j!=-1,`line` + stmts.append((line[:i].rstrip(),line[i+1:j].strip())) + line = line[j+1:].lstrip() + if line.startswith(','): + line = line[1:].lstrip() + self.stmts = stmts + return + + def __str__(self): + tab = self.get_indent_tab() + l = [] + for o,v in self.stmts: + l.append('%s / %s /' %(o,v)) + return tab + 'DATA ' + ' '.join(l) + +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): + self.item_list = self.item.get_line()[7:].lstrip()[1:-1].strip() + return + def __str__(self): + return self.get_indent_tab() + 'NULLIFY (%s)' % (self.item_list) + +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() + line = line[i+2:].lstrip() + if line.startswith('::'): + line = line[2:].lstrip() + self.nature = nature + i = line.find(',') + self.isonly = False + if i==-1: + self.module = line + self.items = [] + else: + self.module = line[:i].rstrip() + line = line[i+1:].lstrip() + if line.startswith('only') and line[4:].lstrip().startswith(':'): + self.isonly = True + line = line[4:].lstrip()[1:].lstrip() + self.items = [s.strip() for s in line.split(',')] + + def __str__(self): + tab = self.get_indent_tab() + s = 'USE' + if self.nature: + s += ' ' + self.nature + ' ::' + s += ' ' + self.module + if self.isonly: + s += ' ONLY:' + elif self.items: + s += ',' + if self.items: + s += ' ' + ', '.join(self.items) + return s + +class Exit(Statement): + """ + EXIT [ <do-construct-name> ] + """ + match = re.compile(r'exit\b\s*\w*\Z',re.I).match + def process_item(self): + self.exitname = self.item.get_line()[4:].lstrip() + return + def __str__(self): + return self.get_indent_tab() + 'EXIT ' + self.exitname + +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): + self.params = self.item.get_line()[9:].lstrip()[1:-1].strip() + return + def __str__(self): + return self.get_indent_tab() + 'PARAMETER (%s)' % (self.params) + +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()[12:].lstrip().split(','): + s = s.strip() + assert s[0]+s[-1]=='()',`s` + items.append(s) + self.items = items + def __str__(self): + return self.get_indent_tab() + 'EQUIVALENCE %s' % (', '.join(self.items)) + +class Dimension(Statement): + """ + DIMENSION [ :: ] <array-name> ( <array-spec> ) [ , <array-name> ( <array-spec> ) ]... + + """ + match = re.compile(r'dimension\b').match + def process_item(self): + line = self.item.get_line()[9:].lstrip() + if line.startswith('::'): + line = line[2:].lstrip() + self.items = [s.split() for s in line.split(',')] + return + def __str__(self): + return self.get_indent_tab() + 'DIMENSION %s' % (', '.join(self.items)) + +# IF construct statements + +class Else(Statement): + """ + ELSE [<if-construct-name>] + """ + match = re.compile(r'else\s*\w*\Z',re.I).match + + def process_item(self): + item = self.item + self.name = item.get_line()[4:].strip() + if self.name and not self.name==self.parent.name: + message = self.reader.format_message(\ + 'WARNING', + 'expected if-construct-name %r but got %r, skipping.'\ + % (self.parent.name, self.name), + item.span[0],item.span[1]) + print >> sys.stderr, message + self.isvalid = False + return + + def __str__(self): + return self.get_indent_tab(deindent=True) + 'ELSE ' + self.name + +class ElseIf(Statement): + """ + ELSE IF ( <scalar-logical-expr> ) THEN [<if-construct-name>] + """ + match = re.compile(r'else\s*if\s*\(.*\)\s*then\s*\w*\Z',re.I).match + + def process_item(self): + item = self.item + line = item.get_line()[4:].lstrip()[2:].lstrip() + i = line.find(')') + assert line[0]=='(' + self.expr = line[1:i] + self.name = line[i+1:].lstrip()[4:].strip() + if self.name and not self.name==self.parent.name: + message = self.reader.format_message(\ + 'WARNING', + 'expected if-construct-name %r but got %r, skipping.'\ + % (self.parent.name, self.name), + item.span[0],item.span[1]) + print >> sys.stderr, message + self.isvalid = False + return + + def __str__(self): + return self.get_indent_tab(deindent=True) + 'ELSE IF (%s) THEN %s' \ + % (self.expr, self.name) + +# 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(')') + self.ranges = line[1:i].strip() + line = line[i+1:].lstrip() + else: + assert line.startswith('default'),`line` + self.ranges = '' + line = line[7:].lstrip() + self.name = line + if self.name and not self.name==self.parent.name: + message = self.reader.format_message(\ + 'WARNING', + 'expected case-construct-name %r but got %r, skipping.'\ + % (self.parent.name, self.name), + self.item.span[0],self.item.span[1]) + print >> sys.stderr, message + self.isvalid = False + return |