Skip to content

Commit

Permalink
ENH: add support for operator() in crackfortran.
Browse files Browse the repository at this point in the history
Some interface name may contains parenthesis when used
with operator, like:
 interface operator(==)
   module procedure my_type_equals
 end interface operator(==)

Make the end part properly detected, and store also
the operator ('==' in that case) in the name.

Also implement support to list the implemented by in
any interface declaration.
  • Loading branch information
dcaliste committed Nov 29, 2019
1 parent 3fcf144 commit a1cbd29
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions numpy/f2py/crackfortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,12 +560,14 @@ def readfortrancode(ffile, dowithline=show, istop=1):
beforethisafter % ('', groupbegins90, groupbegins90, '.*'), re.I), 'begin'
groupends = r'end|endprogram|endblockdata|endmodule|endpythonmodule|endinterface'
endpattern = re.compile(
beforethisafter % ('', groupends, groupends, r'[\w\s]*'), re.I), 'end'
# endifs='end\s*(if|do|where|select|while|forall)'
endifs = r'(end\s*(if|do|where|select|while|forall))|(module\s*procedure)'
beforethisafter % ('', groupends, groupends, '.*'), re.I), 'end'
endifs = r'end\s*(if|do|where|select|while|forall)'
endifpattern = re.compile(
beforethisafter % (r'[\w]*?', endifs, endifs, r'[\w\s]*'), re.I), 'endif'
#
moduleprocedures = r'module\s*procedure'
moduleprocedurepattern = re.compile(
beforethisafter % ('', moduleprocedures, moduleprocedures, r'.*'), re.I), 'moduleprocedure'
implicitpattern = re.compile(
beforethisafter % ('', 'implicit', 'implicit', '.*'), re.I), 'implicit'
dimensionpattern = re.compile(beforethisafter % (
Expand Down Expand Up @@ -714,7 +716,8 @@ def crackline(line, reset=0):
callpattern, usepattern, containspattern,
entrypattern,
f2pyenhancementspattern,
multilinepattern
multilinepattern,
moduleprocedurepattern
]:
m = pat[0].match(line)
if m:
Expand Down Expand Up @@ -784,6 +787,8 @@ def crackline(line, reset=0):
expectbegin = 0
elif pat[1] == 'endif':
pass
elif pat[1] == 'moduleprocedure':
analyzeline(m, pat[1], line)
elif pat[1] == 'contains':
if ignorecontains:
return
Expand Down Expand Up @@ -872,6 +877,8 @@ def appenddecl(decl, decl2, force=1):
r'\s*(?P<this>(@\(@.*?@\)@|[*][\d*]+|[*]\s*@\(@.*?@\)@|))(?P<after>.*)\Z', re.I)
nameargspattern = re.compile(
r'\s*(?P<name>\b[\w$]+\b)\s*(@\(@\s*(?P<args>[\w\s,]*)\s*@\)@|)\s*((result(\s*@\(@\s*(?P<result>\b[\w$]+\b)\s*@\)@|))|(bind\s*@\(@\s*(?P<bind>.*)\s*@\)@))*\s*\Z', re.I)
operatorpattern = re.compile(
r'\s*operator@\(@\s*(?P<name>[^)]+)\s*@\)@\s*\Z', re.I)
callnameargspattern = re.compile(
r'\s*(?P<name>\b[\w$]+\b)\s*@\(@\s*(?P<args>.*)\s*@\)@\s*\Z', re.I)
real16pattern = re.compile(
Expand All @@ -894,6 +901,9 @@ def _resolvenameargspattern(line):
m1 = nameargspattern.match(line)
if m1:
return m1.group('name'), m1.group('args'), m1.group('result'), m1.group('bind')
m1 = operatorpattern.match(line)
if m1:
return 'operator(' + m1.group('name') + ')', [], None, None
m1 = callnameargspattern.match(line)
if m1:
return m1.group('name'), m1.group('args'), None, None
Expand Down Expand Up @@ -1135,6 +1145,8 @@ def analyzeline(m, case, line):
continue
else:
k = rmbadname1(m1.group('name'))
if case in ['public', 'private'] and k == 'operator':
k = 'operator' + m1.group('after')
if k not in edecl:
edecl[k] = {}
if case == 'dimension':
Expand Down Expand Up @@ -1177,6 +1189,8 @@ def analyzeline(m, case, line):
groupcache[groupcounter]['vars'] = edecl
if last_name is not None:
previous_context = ('variable', last_name, groupcounter)
elif case == 'moduleprocedure':
groupcache[groupcounter]['implementedby'] = [x.strip() for x in m.group('after').split(',')]
elif case == 'parameter':
edecl = groupcache[groupcounter]['vars']
ll = m.group('after').strip()[1:-1]
Expand Down Expand Up @@ -2070,7 +2084,7 @@ def analyzebody(block, args, tab=''):
else:
as_ = args
b = postcrack(b, as_, tab=tab + '\t')
if b['block'] == 'interface' and not b['body']:
if b['block'] == 'interface' and not b['body'] and not b['implementedby']:
if 'f2pyenhancements' not in b:
continue
if b['block'].replace(' ', '') == 'pythonmodule':
Expand Down

0 comments on commit a1cbd29

Please sign in to comment.