[Numpy-svn] r2711 - trunk/numpy/f2py/lib
numpy-svn at scipy.org
numpy-svn at scipy.org
Fri Jun 30 09:36:23 EDT 2006
Author: pearu
Date: 2006-06-30 08:36:13 -0500 (Fri, 30 Jun 2006)
New Revision: 2711
Added:
trunk/numpy/f2py/lib/test_parser.py
Modified:
trunk/numpy/f2py/lib/base_classes.py
trunk/numpy/f2py/lib/block_statements.py
trunk/numpy/f2py/lib/parsefortran.py
trunk/numpy/f2py/lib/readfortran.py
trunk/numpy/f2py/lib/splitline.py
trunk/numpy/f2py/lib/statements.py
trunk/numpy/f2py/lib/typedecl_statements.py
Log:
Writting parser unittests, fixed bugs.
Modified: trunk/numpy/f2py/lib/base_classes.py
===================================================================
--- trunk/numpy/f2py/lib/base_classes.py 2006-06-30 13:28:59 UTC (rev 2710)
+++ trunk/numpy/f2py/lib/base_classes.py 2006-06-30 13:36:13 UTC (rev 2711)
@@ -27,7 +27,7 @@
self.process_item()
- def get_indent_tab(self,colon='',deindent=False):
+ def get_indent_tab(self,colon=None,deindent=False):
if self.reader.isfix:
tab = ' '*6
else:
@@ -41,6 +41,11 @@
if self.item is None:
return tab
s = self.item.label
+ if colon is None:
+ if self.reader.isfix:
+ colon = ''
+ else:
+ colon = ':'
if s:
c = ''
if self.reader.isfix:
Modified: trunk/numpy/f2py/lib/block_statements.py
===================================================================
--- trunk/numpy/f2py/lib/block_statements.py 2006-06-30 13:28:59 UTC (rev 2710)
+++ trunk/numpy/f2py/lib/block_statements.py 2006-06-30 13:36:13 UTC (rev 2711)
@@ -22,6 +22,9 @@
end_stmt_cls = EndSource
+ def tostr(self):
+ return '!' + self.blocktype.upper() + ' '+ self.name
+
def process_item(self):
self.name = self.reader.name
self.fill(end_flag = True)
@@ -383,7 +386,8 @@
def tostr(self):
return 'FORALL (%s)' % (self.specs)
def get_classes(self):
- return [Assignment, WhereStmt, WhereConstruct, ForallConstruct, ForallStmt]
+ return [GeneralAssignment, WhereStmt, WhereConstruct,
+ ForallConstruct, ForallStmt]
ForallConstruct = Forall
@@ -569,14 +573,14 @@
if line.startswith('('):
self.isvalid = False
return
- attr_specs = []
+ specs = []
i = line.find('::')
if i!=-1:
for s in line[:i].split(','):
s = s.strip()
- if s: attr_specs.append(s)
+ if s: specs.append(s)
line = line[i+2:].lstrip()
- self.attr_specs = attr_specs
+ self.specs = specs
i = line.find('(')
if i!=-1:
self.name = line[:i].rstrip()
@@ -592,15 +596,16 @@
def tostr(self):
s = 'TYPE'
- if self.attr_specs:
- s += ', '.join(['']+self.attr_specs) + ' ::'
+ if self.specs:
+ s += ', '.join(['']+self.specs) + ' ::'
s += ' ' + self.name
if self.params:
s += ' ('+self.params+')'
return s
def get_classes(self):
- return [Integer] + private_or_sequence + component_part + type_bound_procedure_part
+ return [Integer] + private_or_sequence + component_part +\
+ type_bound_procedure_part
TypeDecl = Type
@@ -652,6 +657,8 @@
DoublePrecision, Complex, DoubleComplex, Character, Logical, Byte
]
+derived_type_spec = [ ]
+type_spec = intrinsic_type_spec + derived_type_spec
declaration_type_spec = intrinsic_type_spec + [ TypeStmt, Class ]
type_declaration_stmt = declaration_type_spec
@@ -665,12 +672,13 @@
type_bound_procedure_part = [Contains, Private] + proc_binding_stmt
#R214
-action_stmt = [ Allocate, Assignment, Assign, Backspace, Call, Close,
+action_stmt = [ Allocate, GeneralAssignment, Assign, Backspace, Call, Close,
Continue, Cycle, Deallocate, Endfile, Exit, Flush, ForallStmt,
Goto, If, Inquire, Nullify, Open, Print, Read, Return, Rewind,
Stop, Wait, WhereStmt, Write, ArithmeticIf, ComputedGoto,
AssignedGoto, Pause ]
-#PointerAssignment,EndFunction, EndProgram, EndSubroutine,
+# GeneralAssignment = Assignment + PointerAssignment
+# EndFunction, EndProgram, EndSubroutine - part of the corresponding blocks
executable_construct = [ Associate, Do, ForallConstruct, IfThen,
Select, WhereConstruct ] + action_stmt
Modified: trunk/numpy/f2py/lib/parsefortran.py
===================================================================
--- trunk/numpy/f2py/lib/parsefortran.py 2006-06-30 13:28:59 UTC (rev 2710)
+++ trunk/numpy/f2py/lib/parsefortran.py 2006-06-30 13:36:13 UTC (rev 2711)
@@ -22,22 +22,22 @@
def __init__(self, reader):
self.reader = reader
- self.isfix77 = reader.isfix77
+ return
def get_item(self):
try:
- item = self.reader.next(ignore_comments = True)
- return item
+ return self.reader.next(ignore_comments = True)
except StopIteration:
pass
+ return
def put_item(self, item):
self.reader.fifo_item.insert(0, item)
+ return
def parse(self):
try:
- main = BeginSource(self)
- return main
+ return BeginSource(self)
except KeyboardInterrupt:
raise
except:
@@ -50,6 +50,7 @@
reader = reader.reader
traceback.print_exc(file=sys.stdout)
self.reader.show_message(red_text('STOPPED PARSING'), sys.stdout)
+ return
def test_pyf():
string = """
@@ -121,7 +122,6 @@
for filename in sys.argv[1:]:
reader = FortranFileReader(filename)
print yellow_text('Processing '+filename+' (mode=%r)' % (reader.mode))
-
parser = FortranParser(reader)
block = parser.parse()
#print block
@@ -137,13 +137,13 @@
stats.print_stats(30)
def parse_all_f():
- for filename in open('opt_all_f90.txt'):
+ for filename in open('opt_all_f.txt'):
filename = filename.strip()
reader = FortranFileReader(filename)
- #print yellow_text('Processing '+filename+' (mode=%r)' % (reader.mode))
-
+ print yellow_text('Processing '+filename+' (mode=%r)' % (reader.mode))
parser = FortranParser(reader)
block = parser.parse()
+ print block
if __name__ == "__main__":
#test_f77()
Modified: trunk/numpy/f2py/lib/readfortran.py
===================================================================
--- trunk/numpy/f2py/lib/readfortran.py 2006-06-30 13:28:59 UTC (rev 2710)
+++ trunk/numpy/f2py/lib/readfortran.py 2006-06-30 13:36:13 UTC (rev 2711)
@@ -51,7 +51,7 @@
""" Holds a Fortran source line.
"""
- f2py_strmap_findall = re.compile(r'( _F2PY_STRING_CONSTANT_\d+_ |\(F2PY_EXPR_TUPLE_\d+\))').findall
+ f2py_strmap_findall = re.compile(r'(_F2PY_STRING_CONSTANT_\d+_|F2PY_EXPR_TUPLE_\d+)').findall
def __init__(self, line, linenospan, label, reader):
self.line = line.strip()
@@ -61,8 +61,12 @@
self.strline = None
self.is_f2py_directive = linenospan[0] in reader.f2py_comment_lines
+ def has_map(self):
+ return not not (hasattr(self,'strlinemap') and self.strlinemap)
+
def apply_map(self, line):
- if not hasattr(self,'strlinemap'): return line
+ if not hasattr(self,'strlinemap') or not self.strlinemap:
+ return line
findall = self.f2py_strmap_findall
str_map = self.strlinemap
keys = findall(line)
Modified: trunk/numpy/f2py/lib/splitline.py
===================================================================
--- trunk/numpy/f2py/lib/splitline.py 2006-06-30 13:28:59 UTC (rev 2710)
+++ trunk/numpy/f2py/lib/splitline.py 2006-06-30 13:36:13 UTC (rev 2711)
@@ -28,7 +28,9 @@
"""
return LineSplitter(line,lower=lower).split2()
-_f2py_str_findall = re.compile(r"'_F2PY_STRING_CONSTANT_\d+_'").findall
+_f2py_str_findall = re.compile(r"_F2PY_STRING_CONSTANT_\d+_").findall
+_is_name = re.compile(r'\w*\Z',re.I).match
+_is_simple_str = re.compile(r'\w*\Z',re.I).match
def string_replace_map(line, lower=False,
_cache={'index':0,'pindex':0}):
@@ -41,31 +43,33 @@
string_map = {}
rev_string_map = {}
for item in splitquote(line, lower=lower)[0]:
- if isinstance(item, String):
+ if isinstance(item, String) and not _is_simple_str(item[1:-1]):
key = rev_string_map.get(item)
if key is None:
_cache['index'] += 1
index = _cache['index']
- key = "'_F2PY_STRING_CONSTANT_%s_'" % (index)
- string_map[key] = item
- rev_string_map[item] = key
- items.append(key)
+ key = "_F2PY_STRING_CONSTANT_%s_" % (index)
+ it = item[1:-1]
+ string_map[key] = it
+ rev_string_map[it] = key
+ items.append(item[0]+key+item[-1])
else:
items.append(item)
newline = ''.join(items)
items = []
expr_keys = []
for item in splitparen(newline):
- if isinstance(item, ParenString):
+ if isinstance(item, ParenString) and not _is_name(item[1:-1]):
key = rev_string_map.get(item)
if key is None:
_cache['pindex'] += 1
index = _cache['pindex']
- key = '(F2PY_EXPR_TUPLE_%s)' % (index)
- string_map[key] = item
- rev_string_map[item] = key
+ key = 'F2PY_EXPR_TUPLE_%s' % (index)
+ it = item[1:-1]
+ string_map[key] = it
+ rev_string_map[it] = key
expr_keys.append(key)
- items.append(key)
+ items.append(item[0]+key+item[-1])
else:
items.append(item)
found_keys = set()
Modified: trunk/numpy/f2py/lib/statements.py
===================================================================
--- trunk/numpy/f2py/lib/statements.py 2006-06-30 13:28:59 UTC (rev 2710)
+++ trunk/numpy/f2py/lib/statements.py 2006-06-30 13:36:13 UTC (rev 2711)
@@ -4,11 +4,55 @@
from base_classes import Statement
+# Auxiliary tools
+
is_name = re.compile(r'\w+\Z').match
+def split_comma(line, item):
+ newitem = item.copy(line, True)
+ apply_map = newitem.apply_map
+ items = []
+ for s in newitem.get_line().split(','):
+ s = apply_map(s).strip()
+ if not s: continue
+ items.append(s)
+ return items
+
+def specs_split_comma(line, item):
+ specs0 = split_comma(line, item)
+ specs = []
+ for spec in specs0:
+ i = spec.find('=')
+ if i!=-1:
+ kw = spec[:i].strip().upper()
+ v = spec[i+1:].strip()
+ specs.append('%s = %s' % (kw, v))
+ else:
+ specs.append(spec)
+ return specs
+
+class StatementWithNamelist(Statement):
+ """
+ <statement> [ :: ] <name-list>
+ """
+ def process_item(self):
+ assert not self.item.has_map()
+ clsname = self.__class__.__name__.lower()
+ line = self.item.get_line()[len(clsname):].lstrip()
+ if line.startswith('::'):
+ line = line[2:].lstrip()
+ self.items = [s.strip() for s in line.split(',')]
+ return
+ def __str__(self):
+ clsname = self.__class__.__name__.upper()
+ s = ', '.join(self.items)
+ if s:
+ s = ' ' + s
+ return self.get_indent_tab() + clsname + s
+
# Execution statements
-class Assignment(Statement):
+class GeneralAssignment(Statement):
"""
<variable> = <expr>
<pointer variable> => <expr>
@@ -19,15 +63,36 @@
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')
+ 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)
+class Assignment(GeneralAssignment):
+ pass
+
+class PointerAssignment(GeneralAssignment):
+ pass
+
class Assign(Statement):
"""
ASSIGN <label> TO <int-variable-name>
@@ -37,6 +102,7 @@
def process_item(self):
line = self.item.get_line()[6:].lstrip()
i = line.find('to')
+ assert not self.item.has_map()
self.items = [line[:i].rstrip(),line[i+2:].lstrip()]
return
def __str__(self):
@@ -46,8 +112,24 @@
class Call(Statement):
"""Call statement class
- CALL <proc-designator> [([arg-spec-list])]
+ 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
@@ -56,42 +138,41 @@
def process_item(self):
item = self.item
+ apply_map = item.apply_map
line = item.get_line()[4:].strip()
i = line.find('(')
- self.arg_list = []
+ items = []
if i==-1:
- self.designator = line.strip()
+ self.designator = apply_map(line).strip()
else:
j = line.find(')')
if j == -1 or len(line)-1 != j:
self.isvalid = False
return
- 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)
+ 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.arg_list:
- s += '('+', '.join(map(str,self.arg_list))+ ')'
+ if self.items:
+ s += '('+', '.join(map(str,self.items))+ ')'
return s
class Goto(Statement):
"""
GO TO <label>
-
"""
- match = re.compile(r'go\s*to\b\s*\w*\s*\Z', re.I).match
+ match = re.compile(r'go\s*to\s*\d+\s*\Z', re.I).match
def process_item(self):
- self.gotolabel = self.item.get_line()[2:].lstrip()[2:].lstrip()
+ 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.gotolabel)
+ return self.get_indent_tab() + 'GO TO %s' % (self.label)
class ComputedGoto(Statement):
"""
@@ -99,10 +180,14 @@
"""
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 = [s.strip() for s in line[1:i].strip(',')]
- self.expr = line[i+1:].lstrip()
+ 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' \
@@ -113,20 +198,26 @@
GO TO <int-variable-name> [ ( <label> [ , <label> ]... ) ]
"""
modes = ['fix77']
- match = re.compile(r'go\s*to\s*\w+\s*,?\s*\(',re.I).match
+ 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`
- varname = line[:i].rstrip()
- if varname.endswith(','):
- varname = varname[:-1].rstrip()
- self.varname = varname
- self.items = [s.strip() for s in line[i+1:-1].split(',')]
+ self
+ self.items = split_comma(line[i+1:-1], self.item)
return
+
def __str__(self):
- return self.get_indent_tab() + 'GO TO %s (%s)' \
- % (self.varname, ', '.join(self.items))
+ 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)
class Continue(Statement):
"""
@@ -149,25 +240,31 @@
match = re.compile(r'return\b',re.I).match
def process_item(self):
- self.expr = self.item.get_line()[6:].lstrip()
+ self.expr = self.item.apply_map(self.item.get_line()[6:].lstrip())
return
def __str__(self):
- return self.get_indent_tab() + 'RETURN %s' % (self.expr)
+ tab = self.get_indent_tab()
+ if self.expr:
+ return tab + 'RETURN %s' % (self.expr)
+ return tab + 'RETURN'
class Stop(Statement):
"""
STOP [ <stop-code> ]
<stop-code> = <scalar-char-constant> | <1-5-digit>
"""
- match = re.compile(r'stop\s*(\'\w*\'|\d+|)\Z',re.I).match
+ match = re.compile(r'stop\s*(\'\w*\'|"\w*"|\d+|)\Z',re.I).match
def process_item(self):
- self.stopcode = self.item.get_line()[4:].lstrip()
+ self.code = self.item.apply_map(self.item.get_line()[4:].lstrip())
return
def __str__(self):
- return self.get_indent_tab() + 'STOP %s' % (self.stopcode)
+ tab = self.get_indent_tab()
+ if self.code:
+ return tab + 'STOP %s' % (self.code)
+ return tab + 'STOP'
class Print(Statement):
"""
@@ -180,27 +277,35 @@
<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*\'|\d+|[*]|\b\w)', re.I).match
+ 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 = line.split(',')
- self.format = items[0].strip()
- self.items = [s.strip() for s in items[1:]]
+ 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))
+ return self.get_indent_tab() + 'PRINT %s' \
+ % (', '.join([self.format]+self.items))
class Read(Statement):
"""
-Read0: READ ( io-control-spec-list ) [<input-item-list>]
+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
+ match = re.compile(r'read\b\s*[\w(*\'"]', re.I).match
def process_item(self):
item = self.item
@@ -210,6 +315,7 @@
else:
self.__class__ = Read1
self.process_item()
+ return
class Read0(Read):
@@ -217,25 +323,29 @@
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(',')]
+ self.specs = specs_split_comma(line[1:i], item)
+ self.items = split_comma(line[i+1:], item)
+ return
def __str__(self):
- return self.get_indent_tab() + 'READ (%s) %s' \
- % (self.io_control_specs, ', '.join(self.items))
+ 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 = line.split(',')
- self.format = items[0].strip()
- self.items = [s.strip() for s in items[1:]]
+ items = split_comma(line, item)
+ self.format = items[0]
+ self.items = items[1:]
return
def __str__(self):
- return self.get_indent_tab() + 'READ %s' % (', '.join([self.format]+self.items))
+ return self.get_indent_tab() + 'READ ' \
+ + ', '.join([self.format]+self.items)
class Write(Statement):
"""
@@ -246,13 +356,19 @@
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(',')]
+ 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):
- return self.get_indent_tab() + 'WRITE (%s) %s' \
- % (self.io_control_specs, ', '.join(self.items))
+ s = self.get_indent_tab() + 'WRITE (%s)' % ', '.join(self.specs)
+ if self.items:
+ s += ' ' + ', '.join(self.items)
+ return s
+
+
class Flush(Statement):
"""
FLUSH <file-unit-number>
@@ -263,22 +379,22 @@
| 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('('):
- if not line.endswith(')'):
- self.isvalid = False
- return
- self.specs = line[1:-1].strip()
+ assert line[-1] == ')', `line`
+ self.specs = specs_split_comma(line[1:-1],self.item)
else:
- self.specs = line
+ self.specs = specs_split_comma(line,self.item)
return
+
def __str__(self):
tab = self.get_indent_tab()
- return tab + 'FLUSH (%s)' % (self.specs)
+ return tab + 'FLUSH (%s)' % (', '.join(self.specs))
class Wait(Statement):
"""
@@ -294,11 +410,12 @@
"""
match = re.compile(r'wait\s*\(.*\)\Z',re.I).match
def process_item(self):
- self.specs = self.item.get_line()[4:].lstrip()[1:-1].strip()
+ 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)' % (self.specs)
+ return tab + 'WAIT (%s)' % (', '.join(self.specs))
class Contains(Statement):
"""
@@ -311,22 +428,60 @@
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):
- self.items = self.item.get_line()[8:].lstrip()[1:-1].strip()
- def __str__(self): return self.get_indent_tab() \
- + 'ALLOCATE ( %s )' % (self.items)
+ 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:
+ print '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))
+
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):
- self.items = self.item.get_line()[10:].lstrip()[1:-1].strip()
+ 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 )' % (self.items)
+ + 'DEALLOCATE (%s)' % (', '.join(self.items))
class ModuleProcedure(Statement):
"""
@@ -336,15 +491,24 @@
def process_item(self):
line = self.item.get_line()
m = self.match(line)
- self.names = [s.strip() for s in line[m.end():].split(',')]
+ 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.names))
+ return tab + 'MODULE PROCEDURE %s' % (', '.join(self.items))
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):
@@ -356,12 +520,14 @@
line = line[len(clsname):].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
+ 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 + ' ' + ', '.join(self.items)
return tab + clsname
class Public(Access): pass
@@ -378,11 +544,12 @@
"""
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()
+ 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)' % (self.close_specs)
+ return tab + 'CLOSE (%s)' % (', '.join(self.specs))
class Cycle(Statement):
"""
@@ -393,7 +560,9 @@
self.name = self.item.get_line()[5:].lstrip()
return
def __str__(self):
- return self.get_indent_tab() + 'CYCLE ' + self.name
+ if self.name:
+ return self.get_indent_tab() + 'CYCLE ' + self.name
+ return self.get_indent_tab() + 'CYCLE'
class FilePositioningStatement(Statement):
"""
@@ -416,18 +585,15 @@
line = line[len(clsname):].lstrip()
if line.startswith('('):
assert line[-1]==')',`line`
- self.fileunit = None
- self.position_specs = line[1:-1].strip()
+ spec = line[1:-1].strip()
else:
- self.fileunit = line
- self.position_specs = None
+ spec = line
+ self.specs = specs_split_comma(spec, self.item)
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)
+ return self.get_indent_tab() + clsname + ' (%s)' % (', '.join(self.specs))
class Backspace(FilePositioningStatement): pass
@@ -444,15 +610,34 @@
"""
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()
+ 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)' % (self.connect_specs)
+ return self.get_indent_tab() + 'OPEN (%s)' % (', '.join(self.specs))
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
@@ -465,13 +650,13 @@
'R1001: FORMAT statement must be labeled but got %r.' \
% (item.label),
item.span[0],item.span[1])
- print >> sys.stderr, message
+ self.show_message(message)
line = item.get_line()[6:].lstrip()
assert line[0]+line[-1]=='()',`line`
- self.specs = line[1:-1].strip()
+ self.specs = split_comma(line[1:-1], item)
return
def __str__(self):
- return self.get_indent_tab() + 'FORMAT (%s)' % (self.specs)
+ return self.get_indent_tab() + 'FORMAT (%s)' % (', '.join(self.specs))
class Save(Statement):
"""
@@ -484,6 +669,7 @@
"""
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()
@@ -507,7 +693,7 @@
tab = self.get_indent_tab()
if not self.items:
return tab + 'SAVE'
- return tab + 'SAVE :: %s' % (', '.join(self.items))
+ return tab + 'SAVE %s' % (', '.join(self.items))
class Data(Statement):
"""
@@ -538,7 +724,10 @@
if i==-1: return
j = line.find('/',i+1)
if j==-1: return
- stmts.append((line[:i].rstrip(),line[i+1:j].strip()))
+ 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()
@@ -550,7 +739,7 @@
tab = self.get_indent_tab()
l = []
for o,v in self.stmts:
- l.append('%s / %s /' %(o,v))
+ l.append('%s / %s /' %(', '.join(o),', '.join(v)))
return tab + 'DATA ' + ' '.join(l)
class Nullify(Statement):
@@ -560,10 +749,11 @@
"""
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()
+ 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)' % (self.item_list)
+ return self.get_indent_tab() + 'NULLIFY (%s)' % (', '.join(self.items))
class Use(Statement):
"""
@@ -581,32 +771,36 @@
nature = ''
if line.startswith(','):
i = line.find('::')
- nature = line[1:i].strip()
+ 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.module = line
+ self.name = line
self.items = []
else:
- self.module = line[:i].rstrip()
+ self.name = 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(',')]
+ 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.module
+ s += ' ' + self.name
if self.isonly:
- s += ' ONLY:'
+ s += ', ONLY:'
elif self.items:
s += ','
if self.items:
@@ -619,10 +813,12 @@
"""
match = re.compile(r'exit\b\s*\w*\s*\Z',re.I).match
def process_item(self):
- self.exitname = self.item.get_line()[4:].lstrip()
+ self.name = self.item.get_line()[4:].lstrip()
return
def __str__(self):
- return self.get_indent_tab() + 'EXIT ' + self.exitname
+ if self.name:
+ return self.get_indent_tab() + 'EXIT ' + self.name
+ return self.get_indent_tab() + 'EXIT'
class Parameter(Statement):
"""
@@ -631,10 +827,11 @@
"""
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()
+ 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)' % (self.params)
+ return self.get_indent_tab() + 'PARAMETER (%s)' % (', '.join(self.items))
class Equivalence(Statement):
"""
@@ -648,8 +845,10 @@
for s in self.item.get_line()[11:].lstrip().split(','):
s = s.strip()
assert s[0]+s[-1]=='()',`s,self.item.get_line()`
- items.append(s)
+ 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))
@@ -663,7 +862,7 @@
line = self.item.get_line()[9:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
+ self.items = split_comma(line, self.item)
return
def __str__(self):
return self.get_indent_tab() + 'DIMENSION %s' % (', '.join(self.items))
@@ -678,7 +877,7 @@
line = self.item.get_line()[6:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
+ self.items = split_comma(line, self.item)
return
def __str__(self):
return self.get_indent_tab() + 'TARGET %s' % (', '.join(self.items))
@@ -695,64 +894,41 @@
line = self.item.get_line()[7:].lstrip()
if line.startswith('::'):
line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
+ self.items = split_comma(line, self.item)
return
def __str__(self):
return self.get_indent_tab() + 'POINTER %s' % (', '.join(self.items))
-class Protected(Statement):
+class Protected(StatementWithNamelist):
"""
PROTECTED [ :: ] <entity-name-list>
"""
match = re.compile(r'protected\b',re.I).match
- def process_item(self):
- line = self.item.get_line()[9:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
- return
- def __str__(self):
- return self.get_indent_tab() + 'PROTECTED %s' % (', '.join(self.items))
-class Volatile(Statement):
+
+class Volatile(StatementWithNamelist):
"""
Volatile [ :: ] <object-name-list>
"""
match = re.compile(r'volatile\b',re.I).match
- def process_item(self):
- line = self.item.get_line()[8:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
- return
- def __str__(self):
- return self.get_indent_tab() + 'VOLATILE %s' % (', '.join(self.items))
-class Value(Statement):
+class Value(StatementWithNamelist):
"""
VALUE [ :: ] <dummy-arg-name-list>
"""
match = re.compile(r'value\b',re.I).match
- def process_item(self):
- line = self.item.get_line()[5:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
- return
- def __str__(self):
- return self.get_indent_tab() + 'VALUE %s' % (', '.join(self.items))
class ArithmeticIf(Statement):
"""
IF ( <scalar-numeric-expr> ) <label> , <label> , <label>
"""
- match = re.compile(r'if\s*\(.*\)\s*\w+\s*,\s*\w+\s*,\s*\w+\s*\Z', re.I).match
+ 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 = line[1:i].strip()
+ self.expr = self.item.apply_map(line[1:i]).strip()
self.labels = [l1.strip(),l2.strip(),l3.strip()]
return
@@ -760,19 +936,11 @@
return self.get_indent_tab() + 'IF (%s) %s' \
% (self.expr,', '.join(self.labels))
-class Intrinsic(Statement):
+class Intrinsic(StatementWithNamelist):
"""
INTRINSIC [ :: ] <intrinsic-procedure-name-list>
"""
match = re.compile(r'intrinsic\b',re.I).match
- def process_item(self):
- line = self.item.get_line()[10:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
- return
- def __str__(self):
- return self.get_indent_tab() + 'INTRINSIC ' + ', '.join(self.items)
class Inquire(Statement):
"""
@@ -789,11 +957,15 @@
def process_item(self):
line = self.item.get_line()[7:].lstrip()
i = line.index(')')
- self.specs = line[1:i].strip()
- self.items = line[i+1:].lstrip()
+ 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):
- return self.get_indent_tab() + 'INQUIRE (%s) %s' % (self.specs, self.items)
+ 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))
class Sequence(Statement):
"""
@@ -804,19 +976,11 @@
return
def __str__(self): return self.get_indent_tab() + 'SEQUENCE'
-class External(Statement):
+class External(StatementWithNamelist):
"""
EXTERNAL [ :: ] <external-name-list>
"""
match = re.compile(r'external\b').match
- def process_item(self):
- line = self.item.get_line()[8:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- self.items = [s.strip() for s in line.split(',')]
- return
- def __str__(self):
- return self.get_indent_tab() + 'EXTERNAL ' + ', '.join(self.items)
class Namelist(Statement):
"""
@@ -862,7 +1026,8 @@
"""
match = re.compile(r'common\b',re.I).match
def process_item(self):
- line = self.item.get_line()[6:].lstrip()
+ item = self.item
+ line = item.get_line()[6:].lstrip()
items = []
while line:
if not line.startswith('/'):
@@ -871,56 +1036,60 @@
else:
i = line.find('/',1)
assert i!=-1,`line`
- name = line[:i+1]
+ name = line[1:i].strip()
line = line[i+1:].lstrip()
i = line.find('/')
if i==-1:
- items.append((name,line))
+ items.append((name,split_comma(line, item)))
line = ''
continue
s = line[:i].rstrip()
if s.endswith(','):
s = s[:-1].rstrip()
- items.append((name,s))
- line = line[i+1:].lstrip()
+ 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:
- l.append('%s %s' % (name,s))
+ 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)
+ return tab + 'COMMON ' + ' '.join(l)
-class Optional(Statement):
+class Optional(StatementWithNamelist):
"""
OPTIONAL [ :: ] <dummy-arg-name-list>
<dummy-arg-name> = <name>
"""
match = re.compile(r'optional\b',re.I).match
- def process_item(self):
- line = self.item.get_line()[8:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- self.items = [s.split() for s in line.split(',')]
- return
- def __str__(self):
- return self.get_indent_tab() + 'OPTIONAL ' + ', '.join(self.items)
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 = [s.strip() for s in line[1:i].strip().split(',')]
+ self.specs = split_comma(line[1:i], self.item)
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' \
@@ -933,53 +1102,65 @@
| 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()
- i = line.find('(')
- if i==-1:
- self.entryname = line
- self.items = []
- self.suffix = ''
+ 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:
- self.entryname = line[:i].rstrip()
- line = line[i:]
+ items = []
+ binds = []
+ result = ''
+ if line.startswith('bind'):
+ line = line[4:].lstrip()
i = line.find(')')
- self.items = [s.split() for s in line[1:i].split(',')]
- self.suffix = line[i+1:].lstrip()
+ assert line.startswith('(') and i != -1,`line`
+ binds = split_comma(line[1:i], self.item)
+ line = line[i+1:].lstrip()
+ if line.startswith('result'):
+ line = line[6:].lstrip()
+ i = line.find(')')
+ assert line.startswith('(') and i != -1,`line`
+ result = line[1:i].strip()
+ assert is_name(result),`result,line`
+ line = line[i+1:].lstrip()
+ if line.startswith('bind'):
+ assert not binds
+ line = line[4:].lstrip()
+ i = line.find(')')
+ assert line.startswith('(') and i != -1,`line`
+ binds = split_comma(line[1:i], self.item)
+ line = line[i+1:].lstrip()
+ assert not line,`line`
+ self.name = name
+ self.items = items
+ self.result = result
+ self.binds = binds
return
def __str__(self):
tab = self.get_indent_tab()
- s = tab + 'ENTRY '+self.entryname
+ s = tab + 'ENTRY '+self.name
if self.items:
s += ' (%s)' % (', '.join(self.items))
- if self.suffix:
- if not self.items:
- s += ' ()'
- s += ' ' + self.suffix
+ if self.result:
+ s += ' RESULT (%s)' % (self.result)
+ if self.binds:
+ s += ' BIND (%s)' % (', '.join(self.binds))
return s
-class Import(Statement):
+class Import(StatementWithNamelist):
"""
IMPORT [ [ :: ] <import-name-list> ]
"""
- match = re.compile(r'import\b',re.I).match
- def process_item(self):
- line = self.item.get_line()[6:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- items = []
- for s in line.split(','):
- s = s.strip()
- if not is_name(s):
- self.isvalid = False
- return
- items.append(s)
- self.items = items
- return
- def __str__(self):
- return self.get_indent_tab() + 'IMPORT ' + ', '.join(self.items)
+ match = re.compile(r'import(\b|\Z)',re.I).match
class Forall(Statement):
"""
@@ -995,7 +1176,7 @@
i = line.index(')')
self.specs = line[1:i].strip()
line = line[i+1:].lstrip()
- stmt = Assignment(self, self.item.copy(line))
+ stmt = GeneralAssignment(self, self.item.copy(line))
if stmt.isvalid:
self.content = [stmt]
else:
@@ -1068,26 +1249,11 @@
return tab + s
-class FinalBinding(Statement):
+class FinalBinding(StatementWithNamelist):
"""
FINAL [ :: ] <final-subroutine-name-list>
"""
match = re.compile(r'final\b', re.I).match
- def process_item(self):
- line = self.item.get_line()[5:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- items = []
- for s in line.split(','):
- s = s.strip()
- if not is_name(s):
- self.isvalid = False
- return
- items.append(s)
- self.items = items
- return
- def __str__(self):
- return self.get_indent_tab() + 'FINAL ' + ', '.join(self.items)
class Allocatable(Statement):
"""
@@ -1107,29 +1273,12 @@
def __str__(self):
return self.get_tab_indent() + 'ALLOCATABLE ' + ', '.join(self.items)
-class Asynchronous(Statement):
+class Asynchronous(StatementWithNamelist):
"""
ASYNCHRONOUS [ :: ] <object-name-list>
"""
match = re.compile(r'asynchronous\b',re.I).match
- def process_item(self):
- line = self.item.get_line()[12:].lstrip()
- if line.startswith('::'):
- line = line[2:].lstrip()
- items = []
- for s in line.split(','):
- s = s.strip()
- if not is_name(s):
- self.isvalid = False
- return
- items.append(s)
- self.items = items
- return
-
- def __str__(self):
- return self.get_indent_tab() + 'ASYNCHRONOUS ' + ', '.join(self.items)
-
class Bind(Statement):
"""
<language-binding-spec> [ :: ] <bind-entity-list>
Added: trunk/numpy/f2py/lib/test_parser.py
===================================================================
--- trunk/numpy/f2py/lib/test_parser.py 2006-06-30 13:28:59 UTC (rev 2710)
+++ trunk/numpy/f2py/lib/test_parser.py 2006-06-30 13:36:13 UTC (rev 2711)
@@ -0,0 +1,310 @@
+
+from numpy.testing import *
+from block_statements import *
+from readfortran import Line, FortranStringReader
+
+def toLine(line, label=''):
+ if label:
+ line = label + ' : ' + line
+ reader = FortranStringReader(line, True, False)
+ return reader.next()
+
+def parse(cls, line, label=''):
+ item = toLine(line, label=label)
+ if not cls.match(item.get_line()):
+ raise ValueError, '%r does not match %s pattern' % (line, cls.__name__)
+ stmt = cls(item, item)
+
+ if stmt.isvalid:
+ return str(stmt)
+ raise ValueError, 'parsing %r with %s pattern failed' % (line, cls.__name__)
+
+class test_Statements(NumpyTestCase):
+
+ def check_assignment(self):
+ assert_equal(parse(Assignment,'a=b'), 'a = b')
+ assert_equal(parse(PointerAssignment,'a=>b'), 'a => b')
+ assert_equal(parse(Assignment,'a (2)=b(n,m)'), 'a(2) = b(n,m)')
+ assert_equal(parse(Assignment,'a % 2(2,4)=b(a(i))'), 'a%2(2,4) = b(a(i))')
+
+ def check_assign(self):
+ assert_equal(parse(Assign,'assign 10 to a'),'ASSIGN 10 TO a')
+
+ def check_call(self):
+ assert_equal(parse(Call,'call a'),'CALL a')
+ assert_equal(parse(Call,'call a()'),'CALL a')
+ assert_equal(parse(Call,'call a(1)'),'CALL a(1)')
+ assert_equal(parse(Call,'call a(1,2)'),'CALL a(1, 2)')
+ assert_equal(parse(Call,'call a % 2 ( n , a+1 )'),'CALL a % 2(n, a+1)')
+
+ def check_goto(self):
+ assert_equal(parse(Goto,'go to 19'),'GO TO 19')
+ assert_equal(parse(Goto,'goto 19'),'GO TO 19')
+ assert_equal(parse(ComputedGoto,'goto (1, 2 ,3) a+b(2)'),
+ 'GO TO (1, 2, 3) a+b(2)')
+ assert_equal(parse(ComputedGoto,'goto (1, 2 ,3) , a+b(2)'),
+ 'GO TO (1, 2, 3) a+b(2)')
+ assert_equal(parse(AssignedGoto,'goto a'),'GO TO a')
+ assert_equal(parse(AssignedGoto,'goto a ( 1 )'),'GO TO a (1)')
+ assert_equal(parse(AssignedGoto,'goto a ( 1 ,2)'),'GO TO a (1, 2)')
+
+ def check_continue(self):
+ assert_equal(parse(Continue,'continue'),'CONTINUE')
+
+ def check_return(self):
+ assert_equal(parse(Return,'return'),'RETURN')
+ assert_equal(parse(Return,'return a'),'RETURN a')
+ assert_equal(parse(Return,'return a+1'),'RETURN a+1')
+ assert_equal(parse(Return,'return a(c, a)'),'RETURN a(c, a)')
+
+ def check_stop(self):
+ assert_equal(parse(Stop,'stop'),'STOP')
+ assert_equal(parse(Stop,'stop 1'),'STOP 1')
+ assert_equal(parse(Stop,'stop "a"'),'STOP "a"')
+ assert_equal(parse(Stop,'stop "a b"'),'STOP "a b"')
+
+ def check_print(self):
+ assert_equal(parse(Print, 'print*'),'PRINT *')
+ assert_equal(parse(Print, 'print "a b( c )"'),'PRINT "a b( c )"')
+ assert_equal(parse(Print, 'print 12, a'),'PRINT 12, a')
+ assert_equal(parse(Print, 'print 12, a , b'),'PRINT 12, a, b')
+ assert_equal(parse(Print, 'print 12, a(c,1) , b'),'PRINT 12, a(c,1), b')
+
+ def check_read(self):
+ assert_equal(parse(Read, 'read ( 10 )'),'READ (10)')
+ assert_equal(parse(Read, 'read ( 10 ) a '),'READ (10) a')
+ assert_equal(parse(Read, 'read ( 10 ) a , b'),'READ (10) a, b')
+ assert_equal(parse(Read, 'read *'),'READ *')
+ assert_equal(parse(Read, 'read 12'),'READ 12')
+ assert_equal(parse(Read, 'read "a b"'),'READ "a b"')
+ assert_equal(parse(Read, 'read "a b",a'),'READ "a b", a')
+ assert_equal(parse(Read, 'read * , a'),'READ *, a')
+ assert_equal(parse(Read, 'read "hey a" , a'),'READ "hey a", a')
+ assert_equal(parse(Read, 'read * , a , b'),'READ *, a, b')
+ assert_equal(parse(Read, 'read ( unit =10 )'),'READ (UNIT = 10)')
+
+ def check_write(self):
+ assert_equal(parse(Write, 'write ( 10 )'),'WRITE (10)')
+ assert_equal(parse(Write, 'write ( 10 , a )'),'WRITE (10, a)')
+ assert_equal(parse(Write, 'write ( 10 ) b'),'WRITE (10) b')
+ assert_equal(parse(Write, 'write ( 10 ) a(1) , b+2'),'WRITE (10) a(1), b+2')
+ assert_equal(parse(Write, 'write ( unit=10 )'),'WRITE (UNIT = 10)')
+
+ def check_flush(self):
+ assert_equal(parse(Flush, 'flush 10'),'FLUSH (10)')
+ assert_equal(parse(Flush, 'flush (10)'),'FLUSH (10)')
+ assert_equal(parse(Flush, 'flush (UNIT = 10)'),'FLUSH (UNIT = 10)')
+ assert_equal(parse(Flush, 'flush (10, err= 23)'),'FLUSH (10, ERR = 23)')
+
+ def check_wait(self):
+ assert_equal(parse(Wait, 'wait(10)'),'WAIT (10)')
+ assert_equal(parse(Wait, 'wait(10,err=129)'),'WAIT (10, ERR = 129)')
+
+ def check_contains(self):
+ assert_equal(parse(Contains, 'contains'),'CONTAINS')
+
+ def check_allocate(self):
+ assert_equal(parse(Allocate, 'allocate (a)'), 'ALLOCATE (a)')
+ assert_equal(parse(Allocate, \
+ 'allocate (a, stat=b)'), 'ALLOCATE (a, STAT = b)')
+ assert_equal(parse(Allocate, 'allocate (a,b(:1))'), 'ALLOCATE (a, b(:1))')
+ assert_equal(parse(Allocate, \
+ 'allocate (real(8)::a)'), 'ALLOCATE (REAL(8) :: a)')
+ def check_deallocate(self):
+ assert_equal(parse(Deallocate, 'deallocate (a)'), 'DEALLOCATE (a)')
+ assert_equal(parse(Deallocate, 'deallocate (a, stat=b)'), 'DEALLOCATE (a, STAT = b)')
+
+ def check_moduleprocedure(self):
+ assert_equal(parse(ModuleProcedure,\
+ 'ModuleProcedure a'), 'MODULE PROCEDURE a')
+ assert_equal(parse(ModuleProcedure,\
+ 'module procedure a , b'), 'MODULE PROCEDURE a, b')
+
+ def check_access(self):
+ assert_equal(parse(Public,'Public'),'PUBLIC')
+ assert_equal(parse(Public,'public a'),'PUBLIC a')
+ assert_equal(parse(Public,'public :: a'),'PUBLIC a')
+ assert_equal(parse(Public,'public a,b,c'),'PUBLIC a, b, c')
+ assert_equal(parse(Public,'public :: a(:,:)'),'PUBLIC a(:,:)')
+ assert_equal(parse(Private,'private'),'PRIVATE')
+ assert_equal(parse(Private,'private :: a'),'PRIVATE a')
+
+ def check_close(self):
+ assert_equal(parse(Close,'close (12)'),'CLOSE (12)')
+ assert_equal(parse(Close,'close (12, err=99)'),'CLOSE (12, ERR = 99)')
+ assert_equal(parse(Close,'close (12, status = a(1,2))'),'CLOSE (12, STATUS = a(1,2))')
+
+ def check_cycle(self):
+ assert_equal(parse(Cycle,'cycle'),'CYCLE')
+ assert_equal(parse(Cycle,'cycle ab'),'CYCLE ab')
+
+ def check_rewind(self):
+ assert_equal(parse(Rewind,'rewind 1'),'REWIND (1)')
+ assert_equal(parse(Rewind,'rewind (1)'),'REWIND (1)')
+ assert_equal(parse(Rewind,'rewind (1, err = 123)'),'REWIND (1, ERR = 123)')
+
+ def check_backspace(self):
+ assert_equal(parse(Backspace,'backspace 1'),'BACKSPACE (1)')
+ assert_equal(parse(Backspace,'backspace (1)'),'BACKSPACE (1)')
+ assert_equal(parse(Backspace,'backspace (1, err = 123)'),'BACKSPACE (1, ERR = 123)')
+
+ def check_endfile(self):
+ assert_equal(parse(Endfile,'endfile 1'),'ENDFILE (1)')
+ assert_equal(parse(Endfile,'endfile (1)'),'ENDFILE (1)')
+ assert_equal(parse(Endfile,'endfile (1, err = 123)'),'ENDFILE (1, ERR = 123)')
+
+ def check_open(self):
+ assert_equal(parse(Open,'open (1)'),'OPEN (1)')
+ assert_equal(parse(Open,'open (1, err = 123)'),'OPEN (1, ERR = 123)')
+
+ def check_format(self):
+ assert_equal(parse(Format,'1: format ()'),'1: FORMAT ()')
+ assert_equal(parse(Format,'199 format (1)'),'199: FORMAT (1)')
+ assert_equal(parse(Format,'2 format (1 , SS)'),'2: FORMAT (1, ss)')
+
+ def check_save(self):
+ assert_equal(parse(Save,'save'), 'SAVE')
+ assert_equal(parse(Save,'save :: a'), 'SAVE a')
+ assert_equal(parse(Save,'save a,b'), 'SAVE a, b')
+
+ def check_data(self):
+ assert_equal(parse(Data,'data a /b/'), 'DATA a / b /')
+ assert_equal(parse(Data,'data a , c /b/'), 'DATA a, c / b /')
+ assert_equal(parse(Data,'data a /b ,c/'), 'DATA a / b, c /')
+ assert_equal(parse(Data,'data a /b/ c,e /d/'), 'DATA a / b / c, e / d /')
+ assert_equal(parse(Data,'data a(1,2) /b/'), 'DATA a(1,2) / b /')
+ assert_equal(parse(Data,'data a /b, c(1)/'), 'DATA a / b, c(1) /')
+
+ def check_nullify(self):
+ assert_equal(parse(Nullify,'nullify(a)'),'NULLIFY (a)')
+ assert_equal(parse(Nullify,'nullify(a ,b)'),'NULLIFY (a, b)')
+
+ def check_use(self):
+ assert_equal(parse(Use, 'use a'), 'USE a')
+ assert_equal(parse(Use, 'use :: a'), 'USE a')
+ assert_equal(parse(Use, 'use, intrinsic:: a'), 'USE INTRINSIC :: a')
+ assert_equal(parse(Use, 'use :: a ,only: b'), 'USE a, ONLY: b')
+ assert_equal(parse(Use, 'use :: a , only: b=>c'), 'USE a, ONLY: b=>c')
+ assert_equal(parse(Use, 'use :: a , b=>c'), 'USE a, b=>c')
+ assert_equal(parse(Use,\
+ 'use :: a , only: operator(+) , b'),\
+ 'USE a, ONLY: operator(+), b')
+
+ def check_exit(self):
+ assert_equal(parse(Exit,'exit'),'EXIT')
+ assert_equal(parse(Exit,'exit ab'),'EXIT ab')
+
+ def check_parameter(self):
+ assert_equal(parse(Parameter,'parameter (a = b(1,2))'),
+ 'PARAMETER (a = b(1,2))')
+ assert_equal(parse(Parameter,'parameter (a = b(1,2) , b=1)'),
+ 'PARAMETER (a = b(1,2), b=1)')
+
+ def check_equivalence(self):
+ assert_equal(parse(Equivalence,'equivalence (a , b)'),'EQUIVALENCE (a, b)')
+ assert_equal(parse(Equivalence,'equivalence (a , b) , ( c, d(1) , g )'),
+ 'EQUIVALENCE (a, b), (c, d(1), g)')
+
+ def check_dimension(self):
+ assert_equal(parse(Dimension,'dimension a(b)'),'DIMENSION a(b)')
+ assert_equal(parse(Dimension,'dimension::a(b)'),'DIMENSION a(b)')
+ assert_equal(parse(Dimension,'dimension a(b) , c(d)'),'DIMENSION a(b), c(d)')
+ assert_equal(parse(Dimension,'dimension a(b,c)'),'DIMENSION a(b,c)')
+
+ def check_target(self):
+ assert_equal(parse(Target,'target a(b)'),'TARGET a(b)')
+ assert_equal(parse(Target,'target::a(b)'),'TARGET a(b)')
+ assert_equal(parse(Target,'target a(b) , c(d)'),'TARGET a(b), c(d)')
+ assert_equal(parse(Target,'target a(b,c)'),'TARGET a(b,c)')
+
+ def check_pointer(self):
+ assert_equal(parse(Pointer,'pointer a=b'),'POINTER a=b')
+ assert_equal(parse(Pointer,'pointer :: a=b'),'POINTER a=b')
+ assert_equal(parse(Pointer,'pointer a=b, c=d(1,2)'),'POINTER a=b, c=d(1,2)')
+
+ def check_protected(self):
+ assert_equal(parse(Protected,'protected a'),'PROTECTED a')
+ assert_equal(parse(Protected,'protected::a'),'PROTECTED a')
+ assert_equal(parse(Protected,'protected a , b'),'PROTECTED a, b')
+
+ def check_volatile(self):
+ assert_equal(parse(Volatile,'volatile a'),'VOLATILE a')
+ assert_equal(parse(Volatile,'volatile::a'),'VOLATILE a')
+ assert_equal(parse(Volatile,'volatile a , b'),'VOLATILE a, b')
+
+ def check_value(self):
+ assert_equal(parse(Value,'value a'),'VALUE a')
+ assert_equal(parse(Value,'value::a'),'VALUE a')
+ assert_equal(parse(Value,'value a , b'),'VALUE a, b')
+
+ def check_arithmeticif(self):
+ assert_equal(parse(ArithmeticIf,'if (a) 1,2,3'),'IF (a) 1, 2, 3')
+ assert_equal(parse(ArithmeticIf,'if (a(1)) 1,2,3'),'IF (a(1)) 1, 2, 3')
+ assert_equal(parse(ArithmeticIf,'if (a(1,2)) 1,2,3'),'IF (a(1,2)) 1, 2, 3')
+
+ def check_intrinsic(self):
+ assert_equal(parse(Intrinsic,'intrinsic a'),'INTRINSIC a')
+ assert_equal(parse(Intrinsic,'intrinsic::a'),'INTRINSIC a')
+ assert_equal(parse(Intrinsic,'intrinsic a , b'),'INTRINSIC a, b')
+
+ def check_inquire(self):
+ assert_equal(parse(Inquire, 'inquire (1)'),'INQUIRE (1)')
+ assert_equal(parse(Inquire, 'inquire (1, err=123)'),'INQUIRE (1, ERR = 123)')
+ assert_equal(parse(Inquire, 'inquire (iolength=a) b'),'INQUIRE (IOLENGTH = a) b')
+ assert_equal(parse(Inquire, 'inquire (iolength=a) b ,c(1,2)'),
+ 'INQUIRE (IOLENGTH = a) b, c(1,2)')
+
+ def check_sequence(self):
+ assert_equal(parse(Sequence, 'sequence'),'SEQUENCE')
+
+ def check_external(self):
+ assert_equal(parse(External,'external a'),'EXTERNAL a')
+ assert_equal(parse(External,'external::a'),'EXTERNAL a')
+ assert_equal(parse(External,'external a , b'),'EXTERNAL a, b')
+
+ def check_common(self):
+ assert_equal(parse(Common, 'common a'),'COMMON a')
+ assert_equal(parse(Common, 'common a , b'),'COMMON a, b')
+ assert_equal(parse(Common, 'common a , b(1,2)'),'COMMON a, b(1,2)')
+ assert_equal(parse(Common, 'common // a'),'COMMON a')
+ assert_equal(parse(Common, 'common / name/ a'),'COMMON / name / a')
+ assert_equal(parse(Common, 'common / name/ a , c'),'COMMON / name / a, c')
+ assert_equal(parse(Common, 'common / name/ a /foo/ c(1) ,d'),
+ 'COMMON / name / a / foo / c(1), d')
+ assert_equal(parse(Common, 'common / name/ a, /foo/ c(1) ,d'),
+ 'COMMON / name / a / foo / c(1), d')
+
+ def check_optional(self):
+ assert_equal(parse(Optional,'optional a'),'OPTIONAL a')
+ assert_equal(parse(Optional,'optional::a'),'OPTIONAL a')
+ assert_equal(parse(Optional,'optional a , b'),'OPTIONAL a, b')
+
+ def check_intent(self):
+ assert_equal(parse(Intent,'intent (in) a'),'INTENT (in) a')
+ assert_equal(parse(Intent,'intent(in)::a'),'INTENT (in) a')
+ assert_equal(parse(Intent,'intent(in) a , b'),'INTENT (in) a, b')
+ assert_equal(parse(Intent,'intent (in, out) a'),'INTENT (in, out) a')
+
+ def check_entry(self):
+ assert_equal(parse(Entry,'entry a'), 'ENTRY a')
+ assert_equal(parse(Entry,'entry a()'), 'ENTRY a')
+ assert_equal(parse(Entry,'entry a(b)'), 'ENTRY a (b)')
+ assert_equal(parse(Entry,'entry a(b,*)'), 'ENTRY a (b, *)')
+ assert_equal(parse(Entry,'entry a bind(c , name="a b")'),
+ 'ENTRY a BIND (c, name="a b")')
+ assert_equal(parse(Entry,'entry a result (b)'), 'ENTRY a RESULT (b)')
+ assert_equal(parse(Entry,'entry a bind(d) result (b)'),
+ 'ENTRY a RESULT (b) BIND (d)')
+ assert_equal(parse(Entry,'entry a result (b) bind(c)'),
+ 'ENTRY a RESULT (b) BIND (c)')
+ assert_equal(parse(Entry,'entry a(b,*) result (g)'),
+ 'ENTRY a (b, *) RESULT (g)')
+
+ def check_import(self):
+ assert_equal(parse(Import,'import'),'IMPORT')
+ assert_equal(parse(Import,'import a'),'IMPORT a')
+ assert_equal(parse(Import,'import::a'),'IMPORT a')
+ assert_equal(parse(Import,'import a , b'),'IMPORT a, b')
+
+if __name__ == "__main__":
+ NumpyTest().run()
Modified: trunk/numpy/f2py/lib/typedecl_statements.py
===================================================================
--- trunk/numpy/f2py/lib/typedecl_statements.py 2006-06-30 13:28:59 UTC (rev 2710)
+++ trunk/numpy/f2py/lib/typedecl_statements.py 2006-06-30 13:36:13 UTC (rev 2711)
@@ -61,6 +61,7 @@
def process_item(self):
item = self.item
+ apply_map = item.apply_map
clsname = self.__class__.__name__.lower()
line = item.get_line()
from block_statements import Function
@@ -81,14 +82,14 @@
if line.startswith('('):
i = line.find(')')
- selector = line[:i+1].strip()
+ selector = apply_map(line[:i+1].strip())
line = line[i+1:].lstrip()
elif line.startswith('*'):
selector = '*'
line = line[1:].lstrip()
if line.startswith('('):
i = line.find(')')
- selector += line[:i+1].rstrip()
+ selector += apply_map(line[:i+1].rstrip())
line = line[i+1:].lstrip()
else:
m = re.match(r'\d+(_\w+|)|[*]',line)
More information about the Numpy-svn
mailing list