PageRenderTime 61ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/TOOLS/FparserTools/fparser/statements.py

http://github.com/tkotani/ecalj
Python | 1928 lines | 1896 code | 11 blank | 21 comment | 18 complexity | 2484bbb0efbbd9812a07e6922aabe951 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. """
  2. Fortran single line statements.
  3. -----
  4. Permission to use, modify, and distribute this software is given under the
  5. terms of the NumPy License. See http://scipy.org.
  6. NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
  7. Author: Pearu Peterson <pearu@cens.ioc.ee>
  8. Created: May 2006
  9. -----
  10. """
  11. __all__ = ['GeneralAssignment',
  12. 'Assignment','PointerAssignment','Assign','Call','Goto','ComputedGoto','AssignedGoto',
  13. 'Continue','Return','Stop','Print','Read','Read0','Read1','Write','Flush','Wait',
  14. 'Contains','Allocate','Deallocate','ModuleProcedure','Access','Public','Private',
  15. 'Close','Cycle','Backspace','Endfile','Rewind','Open','Format','Save',
  16. 'Data','Nullify','Use','Exit','Parameter','Equivalence','Dimension','Target',
  17. 'Pointer','Protected','Volatile','Value','ArithmeticIf','Intrinsic',
  18. 'Inquire','Sequence','External','Namelist','Common','Optional','Intent',
  19. 'Entry','Import','ForallStmt','SpecificBinding','GenericBinding',
  20. 'FinalBinding','Allocatable','Asynchronous','Bind','Else','ElseIf',
  21. 'Case','WhereStmt','ElseWhere','Enumerator','FortranName','Threadsafe',
  22. 'Depend','Check','CallStatement','CallProtoArgument','Pause',
  23. 'Comment']
  24. import re
  25. import sys
  26. from base_classes import Statement, Variable
  27. # Auxiliary tools
  28. from utils import split_comma, specs_split_comma, AnalyzeError, ParseError,\
  29. get_module_file, parse_bind, parse_result, is_name
  30. from utils import classes
  31. class StatementWithNamelist(Statement):
  32. """
  33. <statement> [ :: ] <name-list>
  34. """
  35. def process_item(self):
  36. if self.item.has_map():
  37. self.isvalid = False
  38. return
  39. if hasattr(self,'stmtname'):
  40. clsname = self.stmtname
  41. else:
  42. clsname = self.__class__.__name__
  43. line = self.item.get_line()[len(clsname):].lstrip()
  44. if line.startswith('::'):
  45. line = line[2:].lstrip()
  46. self.items = items = []
  47. for item in split_comma(line):
  48. if not is_name(item):
  49. self.isvalid = False
  50. return
  51. items.append(item)
  52. return
  53. def tofortran(self,isfix=None):
  54. if hasattr(self,'stmtname'):
  55. clsname = self.stmtname.upper()
  56. else:
  57. clsname = self.__class__.__name__.upper()
  58. s = ', '.join(self.items)
  59. if s:
  60. s = ' ' + s
  61. return self.get_indent_tab(isfix=isfix) + clsname + s
  62. # Execution statements
  63. class GeneralAssignment(Statement):
  64. """
  65. <variable> = <expr>
  66. <pointer variable> => <expr>
  67. """
  68. match = re.compile(r'\w[^=]*\s*=\>?').match
  69. item_re = re.compile(r'(?P<variable>\w[^=]*)\s*(?P<sign>=\>?)\s*(?P<expr>.*)\Z',re.I).match
  70. _repr_attr_names = ['variable','sign','expr'] + Statement._repr_attr_names
  71. def process_item(self):
  72. m = self.item_re(self.item.get_line())
  73. if not m:
  74. self.isvalid = False
  75. return
  76. self.sign = sign = m.group('sign')
  77. if isinstance(self, Assignment) and sign != '=':
  78. self.isvalid = False
  79. return
  80. elif isinstance(self, PointerAssignment) and sign != '=>':
  81. self.isvalid = False
  82. return
  83. else:
  84. if sign=='=>':
  85. self.__class__ = PointerAssignment
  86. else:
  87. self.__class__ = Assignment
  88. apply_map = self.item.apply_map
  89. self.variable = apply_map(m.group('variable').replace(' ',''))
  90. self.expr = apply_map(m.group('expr'))
  91. return
  92. def tofortran(self, isfix=None):
  93. return self.get_indent_tab(isfix=isfix) + '%s %s %s' \
  94. % (self.variable, self.sign, self.expr)
  95. def analyze(self): return
  96. class Assignment(GeneralAssignment):
  97. pass
  98. class PointerAssignment(GeneralAssignment):
  99. pass
  100. class Assign(Statement):
  101. """
  102. ASSIGN <label> TO <int-variable-name>
  103. """
  104. modes = ['fix77']
  105. match = re.compile(r'assign\s*\d+\s*to\s*\w+\s*\Z',re.I).match
  106. def process_item(self):
  107. line = self.item.get_line()[6:].lstrip()
  108. i = line.lower().find('to')
  109. assert not self.item.has_map()
  110. self.items = [line[:i].rstrip(),line[i+2:].lstrip()]
  111. return
  112. def tofortran(self, isfix=None):
  113. return self.get_indent_tab(isfix=isfix) + 'ASSIGN %s TO %s' \
  114. % (self.items[0], self.items[1])
  115. def analyze(self): return
  116. class Call(Statement):
  117. """Call statement class
  118. CALL <procedure-designator> [ ( [ <actual-arg-spec-list> ] ) ]
  119. <procedure-designator> = <procedure-name>
  120. | <proc-component-ref>
  121. | <data-ref> % <binding-name>
  122. <actual-arg-spec> = [ <keyword> = ] <actual-arg>
  123. <actual-arg> = <expr>
  124. | <variable>
  125. | <procedure-name>
  126. | <proc-component-ref>
  127. | <alt-return-spec>
  128. <alt-return-spec> = * <label>
  129. <proc-component-ref> = <variable> % <procedure-component-name>
  130. <variable> = <designator>
  131. Call instance has attributes:
  132. designator
  133. arg_list
  134. """
  135. match = re.compile(r'call\b', re.I).match
  136. def process_item(self):
  137. item = self.item
  138. apply_map = item.apply_map
  139. line = item.get_line()[4:].strip()
  140. i = line.find('(')
  141. items = []
  142. if i==-1:
  143. self.designator = apply_map(line).strip()
  144. else:
  145. j = line.find(')')
  146. if j == -1 or len(line)-1 != j:
  147. self.isvalid = False
  148. return
  149. self.designator = apply_map(line[:i]).strip()
  150. items = split_comma(line[i+1:-1], item)
  151. self.items = items
  152. return
  153. def tofortran(self, isfix=None):
  154. s = self.get_indent_tab(isfix=isfix) + 'CALL '+str(self.designator)
  155. if self.items:
  156. s += '('+', '.join(map(str,self.items))+ ')'
  157. return s
  158. def analyze(self):
  159. a = self.programblock.a
  160. variables = a.variables
  161. if hasattr(a, 'external'):
  162. external = a.external
  163. if self.designator in external:
  164. print >> sys.stderr, 'Need to analyze:',self
  165. return
  166. class Goto(Statement):
  167. """
  168. GO TO <label>
  169. """
  170. match = re.compile(r'go\s*to\s*\d+\s*\Z', re.I).match
  171. def process_item(self):
  172. assert not self.item.has_map()
  173. self.label = self.item.get_line()[2:].lstrip()[2:].lstrip()
  174. return
  175. def tofortran(self, isfix=None):
  176. return self.get_indent_tab(isfix=isfix) + 'GO TO %s' % (self.label)
  177. def analyze(self): return
  178. class ComputedGoto(Statement):
  179. """
  180. GO TO ( <label-list> ) [ , ] <scalar-int-expr>
  181. """
  182. match = re.compile(r'go\s*to\s*\(',re.I).match
  183. def process_item(self):
  184. apply_map = self.item.apply_map
  185. line = self.item.get_line()[2:].lstrip()[2:].lstrip()
  186. i = line.index(')')
  187. self.items = split_comma(line[1:i], self.item)
  188. line = line[i+1:].lstrip()
  189. if line.startswith(','):
  190. line = line[1:].lstrip()
  191. self.expr = apply_map(line)
  192. return
  193. def tofortran(self, isfix=None):
  194. return self.get_indent_tab(isfix=isfix) + 'GO TO (%s) %s' \
  195. % (', '.join(self.items), self.expr)
  196. def analyze(self): return
  197. class AssignedGoto(Statement):
  198. """
  199. GO TO <int-variable-name> [ ( <label> [ , <label> ]... ) ]
  200. """
  201. modes = ['fix77']
  202. match = re.compile(r'go\s*to\s*\w+\s*\(?',re.I).match
  203. def process_item(self):
  204. line = self.item.get_line()[2:].lstrip()[2:].lstrip()
  205. i = line.find('(')
  206. if i==-1:
  207. self.varname = line
  208. self.items = []
  209. return
  210. self.varname = line[:i].rstrip()
  211. assert line[-1]==')',`line`
  212. self
  213. self.items = split_comma(line[i+1:-1], self.item)
  214. return
  215. def tofortran(self, isfix=None):
  216. tab = self.get_indent_tab(isfix=isfix)
  217. if self.items:
  218. return tab + 'GO TO %s (%s)' \
  219. % (self.varname, ', '.join(self.items))
  220. return tab + 'GO TO %s' % (self.varname)
  221. def analyze(self): return
  222. class Continue(Statement):
  223. """
  224. CONTINUE
  225. """
  226. match = re.compile(r'continue\Z',re.I).match
  227. def process_item(self):
  228. self.label = self.item.label
  229. return
  230. def tofortran(self, isfix=None):
  231. return self.get_indent_tab(deindent=True) + 'CONTINUE'
  232. def analyze(self): return
  233. class Return(Statement):
  234. """
  235. RETURN [ <scalar-int-expr> ]
  236. """
  237. match = re.compile(r'return\b',re.I).match
  238. def process_item(self):
  239. self.expr = self.item.apply_map(self.item.get_line()[6:].lstrip())
  240. return
  241. def tofortran(self, isfix=None):
  242. tab = self.get_indent_tab(isfix=isfix)
  243. if self.expr:
  244. return tab + 'RETURN %s' % (self.expr)
  245. return tab + 'RETURN'
  246. def analyze(self): return
  247. class Stop(Statement):
  248. """
  249. STOP [ <stop-code> ]
  250. <stop-code> = <scalar-char-constant> | <1-5-digit>
  251. """
  252. match = re.compile(r'stop\s*((\'\w*\'|"\w*")+|\d+|)\Z',re.I).match
  253. def process_item(self):
  254. self.code = self.item.apply_map(self.item.get_line()[4:].lstrip())
  255. return
  256. def tofortran(self, isfix=None):
  257. tab = self.get_indent_tab(isfix=isfix)
  258. if self.code:
  259. return tab + 'STOP %s' % (self.code)
  260. return tab + 'STOP'
  261. def analyze(self): return
  262. class Print(Statement):
  263. """
  264. PRINT <format> [, <output-item-list>]
  265. <format> = <default-char-expr> | <label> | *
  266. <output-item> = <expr> | <io-implied-do>
  267. <io-implied-do> = ( <io-implied-do-object-list> , <implied-do-control> )
  268. <io-implied-do-object> = <input-item> | <output-item>
  269. <implied-do-control> = <do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ]
  270. <input-item> = <variable> | <io-implied-do>
  271. """
  272. match = re.compile(r'print\s*(\'\w*\'|\"\w*\"|\d+|[*]|\b\w)', re.I).match
  273. def process_item(self):
  274. item = self.item
  275. apply_map = item.apply_map
  276. line = item.get_line()[5:].lstrip()
  277. items = split_comma(line, item)
  278. self.format = items[0]
  279. self.items = items[1:]
  280. return
  281. def tofortran(self, isfix=None):
  282. return self.get_indent_tab(isfix=isfix) + 'PRINT %s' \
  283. % (', '.join([self.format]+self.items))
  284. def analyze(self): return
  285. class Read(Statement):
  286. """
  287. Read0: READ ( <io-control-spec-list> ) [ <input-item-list> ]
  288. <io-control-spec-list> = [ UNIT = ] <io-unit>
  289. | [ FORMAT = ] <format>
  290. | [ NML = ] <namelist-group-name>
  291. | ADVANCE = <scalar-default-char-expr>
  292. ...
  293. Read1: READ <format> [, <input-item-list>]
  294. <format> == <default-char-expr> | <label> | *
  295. """
  296. match = re.compile(r'read\b\s*[\w(*\'"]', re.I).match
  297. def process_item(self):
  298. item = self.item
  299. line = item.get_line()[4:].lstrip()
  300. if line.startswith('('):
  301. self.__class__ = Read0
  302. else:
  303. self.__class__ = Read1
  304. self.process_item()
  305. return
  306. def analyze(self): return
  307. class Read0(Read):
  308. def process_item(self):
  309. item = self.item
  310. line = item.get_line()[4:].lstrip()
  311. i = line.find(')')
  312. self.specs = specs_split_comma(line[1:i], item)
  313. self.items = split_comma(line[i+1:], item)
  314. return
  315. def tofortran(self, isfix=None):
  316. s = self.get_indent_tab(isfix=isfix) + 'READ (%s)' % (', '.join(self.specs))
  317. if self.items:
  318. return s + ' ' + ', '.join(self.items)
  319. return s
  320. class Read1(Read):
  321. def process_item(self):
  322. item = self.item
  323. line = item.get_line()[4:].lstrip()
  324. items = split_comma(line, item)
  325. self.format = items[0]
  326. self.items = items[1:]
  327. return
  328. def tofortran(self, isfix=None):
  329. return self.get_indent_tab(isfix=isfix) + 'READ ' \
  330. + ', '.join([self.format]+self.items)
  331. class Write(Statement):
  332. """
  333. WRITE ( io-control-spec-list ) [<output-item-list>]
  334. """
  335. match = re.compile(r'write\s*\(', re.I).match
  336. def process_item(self):
  337. item = self.item
  338. line = item.get_line()[5:].lstrip()
  339. i = line.find(')')
  340. assert i != -1, `line`
  341. self.specs = specs_split_comma(line[1:i], item)
  342. self.items = split_comma(line[i+1:], item)
  343. return
  344. def tofortran(self, isfix=None):
  345. s = self.get_indent_tab(isfix=isfix) + 'WRITE (%s)' % ', '.join(self.specs)
  346. if self.items:
  347. s += ' ' + ', '.join(self.items)
  348. return s
  349. def analyze(self): return
  350. class Flush(Statement):
  351. """
  352. FLUSH <file-unit-number>
  353. FLUSH ( <flush-spec-list> )
  354. <flush-spec> = [ UNIT = ] <file-unit-number>
  355. | IOSTAT = <scalar-int-variable>
  356. | IOMSG = <iomsg-variable>
  357. | ERR = <label>
  358. """
  359. match = re.compile(r'flush\b',re.I).match
  360. def process_item(self):
  361. line = self.item.get_line()[5:].lstrip()
  362. if not line:
  363. self.isvalid = False
  364. return
  365. if line.startswith('('):
  366. assert line[-1] == ')', `line`
  367. self.specs = specs_split_comma(line[1:-1],self.item)
  368. else:
  369. self.specs = specs_split_comma(line,self.item)
  370. return
  371. def tofortran(self, isfix=None):
  372. tab = self.get_indent_tab(isfix=isfix)
  373. return tab + 'FLUSH (%s)' % (', '.join(self.specs))
  374. def analyze(self): return
  375. class Wait(Statement):
  376. """
  377. WAIT ( <wait-spec-list> )
  378. <wait-spec> = [ UNIT = ] <file-unit-number>
  379. | END = <label>
  380. | EOR = <label>
  381. | ERR = <label>
  382. | ID = <scalar-int-expr>
  383. | IOMSG = <iomsg-variable>
  384. | IOSTAT = <scalar-int-variable>
  385. """
  386. match = re.compile(r'wait\s*\(.*\)\Z',re.I).match
  387. def process_item(self):
  388. self.specs = specs_split_comma(\
  389. self.item.get_line()[4:].lstrip()[1:-1], self.item)
  390. return
  391. def tofortran(self, isfix=None):
  392. tab = self.get_indent_tab(isfix=isfix)
  393. return tab + 'WAIT (%s)' % (', '.join(self.specs))
  394. def analyze(self): return
  395. class Contains(Statement):
  396. """
  397. CONTAINS
  398. """
  399. match = re.compile(r'contains\Z',re.I).match
  400. def process_item(self): return
  401. def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) + 'CONTAINS'
  402. class Allocate(Statement):
  403. """
  404. ALLOCATE ( [ <type-spec> :: ] <allocation-list> [ , <alloc-opt-list> ] )
  405. <alloc-opt> = STAT = <stat-variable>
  406. | ERRMSG = <errmsg-variable>
  407. | SOURCE = <source-expr>
  408. <allocation> = <allocate-object> [ ( <allocate-shape-spec-list> ) ]
  409. """
  410. match = re.compile(r'allocate\s*\(.*\)\Z',re.I).match
  411. def process_item(self):
  412. line = self.item.get_line()[8:].lstrip()[1:-1].strip()
  413. item2 = self.item.copy(line, True)
  414. line2 = item2.get_line()
  415. i = line2.find('::')
  416. if i != -1:
  417. spec = item2.apply_map(line2[:i].rstrip())
  418. from block_statements import type_spec
  419. stmt = None
  420. for cls in type_spec:
  421. if cls.match(spec):
  422. stmt = cls(self, item2.copy(spec))
  423. if stmt.isvalid:
  424. break
  425. if stmt is not None and stmt.isvalid:
  426. spec = stmt
  427. else:
  428. self.warning('TODO: unparsed type-spec' + `spec`)
  429. line2 = line2[i+2:].lstrip()
  430. else:
  431. spec = None
  432. self.spec = spec
  433. self.items = specs_split_comma(line2, item2)
  434. return
  435. def tofortran(self, isfix=None):
  436. t = ''
  437. if self.spec:
  438. t = self.spec.tostr() + ' :: '
  439. return self.get_indent_tab(isfix=isfix) \
  440. + 'ALLOCATE (%s%s)' % (t,', '.join(self.items))
  441. def analyze(self): return
  442. class Deallocate(Statement):
  443. """
  444. DEALLOCATE ( <allocate-object-list> [ , <dealloc-opt-list> ] )
  445. <allocate-object> = <variable-name>
  446. | <structure-component>
  447. <structure-component> = <data-ref>
  448. <dealloc-opt> = STAT = <stat-variable>
  449. | ERRMSG = <errmsg-variable>
  450. """
  451. match = re.compile(r'deallocate\s*\(.*\)\Z',re.I).match
  452. def process_item(self):
  453. line = self.item.get_line()[10:].lstrip()[1:-1].strip()
  454. self.items = specs_split_comma(line, self.item)
  455. return
  456. def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) \
  457. + 'DEALLOCATE (%s)' % (', '.join(self.items))
  458. def analyze(self): return
  459. class ModuleProcedure(Statement):
  460. """
  461. [ MODULE ] PROCEDURE <procedure-name-list>
  462. """
  463. match = re.compile(r'(module\s*|)procedure\b',re.I).match
  464. def process_item(self):
  465. line = self.item.get_line()
  466. m = self.match(line)
  467. assert m,`line`
  468. items = split_comma(line[m.end():].strip(), self.item)
  469. for n in items:
  470. if not is_name(n):
  471. self.isvalid = False
  472. return
  473. self.items = items
  474. return
  475. def tofortran(self, isfix=None):
  476. tab = self.get_indent_tab(isfix=isfix)
  477. return tab + 'MODULE PROCEDURE %s' % (', '.join(self.items))
  478. def analyze(self):
  479. module_procedures = self.parent.a.module_procedures
  480. module_procedures.extend(self.items)
  481. # XXX: add names to parent_provides
  482. return
  483. class Access(Statement):
  484. """
  485. <access-spec> [ [::] <access-id-list>]
  486. <access-spec> = PUBLIC | PRIVATE
  487. <access-id> = <use-name> | <generic-spec>
  488. """
  489. match = re.compile(r'(public|private)\b',re.I).match
  490. def process_item(self):
  491. clsname = self.__class__.__name__.lower()
  492. line = self.item.get_line()
  493. if not line.lower().startswith(clsname):
  494. self.isvalid = False
  495. return
  496. line = line[len(clsname):].lstrip()
  497. if line.startswith('::'):
  498. line = line[2:].lstrip()
  499. self.items = split_comma(line, self.item)
  500. return
  501. def tofortran(self, isfix=None):
  502. clsname = self.__class__.__name__.upper()
  503. tab = self.get_indent_tab(isfix=isfix)
  504. if self.items:
  505. return tab + clsname + ' ' + ', '.join(self.items)
  506. return tab + clsname
  507. def analyze(self):
  508. clsname = self.__class__.__name__
  509. l = getattr(self.parent.a, clsname.lower() + '_id_list')
  510. if self.items:
  511. for name in self.items:
  512. if name not in l: l.append(name)
  513. else:
  514. if '' not in l:
  515. l.append('')
  516. if not isinstance(self.parent, classes.Module):
  517. parentclsname = self.parent.__class__.__name__
  518. message = 'C548 violation: %s statement only allowed in the'\
  519. ' specification-part of a module, not in a %s.'\
  520. % (clsname.upper(), parentclsname.lower())
  521. self.warning(message)
  522. access_id_list = self.parent.a.private_id_list + self.parent.a.public_id_list
  523. if access_id_list.count('')>1:
  524. message = 'C548 violation: only one access-stmt with omitted'\
  525. ' access-id-list is permitted in'\
  526. ' the module-specification-part.'
  527. self.warning(message)
  528. # todo: check for conflicting access statement usages (e.g. private foo; public foo)
  529. # todo: check for conflicting generic-spec id-s.
  530. return
  531. class Public(Access):
  532. is_public = True
  533. class Private(Access):
  534. is_public = False
  535. class Close(Statement):
  536. """
  537. CLOSE ( <close-spec-list> )
  538. <close-spec> = [ UNIT = ] <file-unit-number>
  539. | IOSTAT = <scalar-int-variable>
  540. | IOMSG = <iomsg-variable>
  541. | ERR = <label>
  542. | STATUS = <scalar-default-char-expr>
  543. """
  544. match = re.compile(r'close\s*\(.*\)\Z',re.I).match
  545. def process_item(self):
  546. line = self.item.get_line()[5:].lstrip()[1:-1].strip()
  547. self.specs = specs_split_comma(line, self.item)
  548. return
  549. def tofortran(self, isfix=None):
  550. tab = self.get_indent_tab(isfix=isfix)
  551. return tab + 'CLOSE (%s)' % (', '.join(self.specs))
  552. def analyze(self): return
  553. class Cycle(Statement):
  554. """
  555. CYCLE [ <do-construct-name> ]
  556. """
  557. match = re.compile(r'cycle\b\s*\w*\s*\Z',re.I).match
  558. def process_item(self):
  559. self.name = self.item.get_line()[5:].lstrip()
  560. return
  561. def tofortran(self, isfix=None):
  562. if self.name:
  563. return self.get_indent_tab(isfix=isfix) + 'CYCLE ' + self.name
  564. return self.get_indent_tab(isfix=isfix) + 'CYCLE'
  565. def analyze(self): return
  566. class FilePositioningStatement(Statement):
  567. """
  568. REWIND <file-unit-number>
  569. REWIND ( <position-spec-list> )
  570. <position-spec-list> = [ UNIT = ] <file-unit-number>
  571. | IOMSG = <iomsg-variable>
  572. | IOSTAT = <scalar-int-variable>
  573. | ERR = <label>
  574. The same for BACKSPACE, ENDFILE.
  575. """
  576. match = re.compile(r'(rewind|backspace|endfile)\b',re.I).match
  577. def process_item(self):
  578. clsname = self.__class__.__name__.lower()
  579. line = self.item.get_line()
  580. if not line.lower().startswith(clsname):
  581. self.isvalid = False
  582. return
  583. line = line[len(clsname):].lstrip()
  584. if line.startswith('('):
  585. assert line[-1]==')',`line`
  586. spec = line[1:-1].strip()
  587. else:
  588. spec = line
  589. self.specs = specs_split_comma(spec, self.item)
  590. return
  591. def tofortran(self, isfix=None):
  592. clsname = self.__class__.__name__.upper()
  593. return self.get_indent_tab(isfix=isfix) + clsname + ' (%s)' % (', '.join(self.specs))
  594. def analyze(self): return
  595. class Backspace(FilePositioningStatement): pass
  596. class Endfile(FilePositioningStatement): pass
  597. class Rewind(FilePositioningStatement): pass
  598. class Open(Statement):
  599. """
  600. OPEN ( <connect-spec-list> )
  601. <connect-spec> = [ UNIT = ] <file-unit-number>
  602. | ACCESS = <scalar-default-char-expr>
  603. | ..
  604. """
  605. match = re.compile(r'open\s*\(.*\)\Z',re.I).match
  606. def process_item(self):
  607. line = self.item.get_line()[4:].lstrip()[1:-1].strip()
  608. self.specs = specs_split_comma(line, self.item)
  609. return
  610. def tofortran(self, isfix=None):
  611. return self.get_indent_tab(isfix=isfix) + 'OPEN (%s)' % (', '.join(self.specs))
  612. def analyze(self): return
  613. class Format(Statement):
  614. """
  615. FORMAT <format-specification>
  616. <format-specification> = ( [ <format-item-list> ] )
  617. <format-item> = [ <r> ] <data-edit-descr>
  618. | <control-edit-descr>
  619. | <char-string-edit-descr>
  620. | [ <r> ] ( <format-item-list> )
  621. <data-edit-descr> = I <w> [ . <m> ]
  622. | B <w> [ . <m> ]
  623. ...
  624. <r|w|m|d|e> = <int-literal-constant>
  625. <v> = <signed-int-literal-constant>
  626. <control-edit-descr> = <position-edit-descr>
  627. | [ <r> ] /
  628. | :
  629. ...
  630. <position-edit-descr> = T <n>
  631. | TL <n>
  632. ...
  633. <sign-edit-descr> = SS | SP | S
  634. ...
  635. """
  636. match = re.compile(r'format\s*\(.*\)\Z', re.I).match
  637. def process_item(self):
  638. item = self.item
  639. if item.label is None:
  640. # R1001:
  641. self.warning('FORMAT statement must be labeled (F2008:C1001).' \
  642. % (item.label))
  643. line = item.get_line()[6:].lstrip()
  644. assert line[0]+line[-1]=='()',`line`
  645. self.specs = split_comma(line[1:-1], item)
  646. return
  647. def tofortran(self, isfix=None):
  648. return self.get_indent_tab(isfix=isfix) + 'FORMAT (%s)' % (', '.join(self.specs))
  649. def analyze(self): return
  650. class Save(Statement):
  651. """
  652. SAVE [ [ :: ] <saved-entity-list> ]
  653. <saved-entity> = <object-name>
  654. | <proc-pointer-name>
  655. | / <common-block-name> /
  656. <proc-pointer-name> = <name>
  657. <object-name> = <name>
  658. """
  659. match = re.compile(r'save\b',re.I).match
  660. def process_item(self):
  661. assert not self.item.has_map()
  662. line = self.item.get_line()[4:].lstrip()
  663. if line.startswith('::'):
  664. line = line[2:].lstrip()
  665. items = []
  666. for s in line.split(','):
  667. s = s.strip()
  668. if not s: continue
  669. if s.startswith('/'):
  670. assert s.endswith('/'),`s`
  671. n = s[1:-1].strip()
  672. assert is_name(n),`n`
  673. items.append('/%s/' % (n))
  674. elif is_name(s):
  675. items.append(s)
  676. else:
  677. self.isvalid = False
  678. return
  679. self.items = items
  680. return
  681. def tofortran(self, isfix=None):
  682. tab = self.get_indent_tab(isfix=isfix)
  683. if not self.items:
  684. return tab + 'SAVE'
  685. return tab + 'SAVE %s' % (', '.join(self.items))
  686. def analyze(self): return
  687. class Data(Statement):
  688. """
  689. DATA <data-stmt-set> [ [ , ] <data-stmt-set> ]...
  690. <data-stmt-set> = <data-stmt-object-list> / <data-stmt-value-list> /
  691. <data-stmt-object> = <variable> | <data-implied-do>
  692. <data-implied-do> = ( <data-i-do-object-list> , <data-i-do-variable> = <scalar-int-expr> , <scalar-int-expr> [ , <scalar-int-expr> ] )
  693. <data-i-do-object> = <array-element> | <scalar-structure-component> | <data-implied-do>
  694. <data-i-do-variable> = <scalar-int-variable>
  695. <variable> = <designator>
  696. <designator> = <object-name>
  697. | <array-element>
  698. | <array-section>
  699. | <structure-component>
  700. | <substring>
  701. <array-element> = <data-ref>
  702. <array-section> = <data-ref> [ ( <substring-range> ) ]
  703. """
  704. match = re.compile(r'data\b',re.I).match
  705. def process_item(self):
  706. line = self.item.get_line()[4:].lstrip()
  707. stmts = []
  708. self.isvalid = False
  709. while line:
  710. i = line.find('/')
  711. if i==-1: return
  712. j = line.find('/',i+1)
  713. if j==-1: return
  714. l1, l2 = line[:i].rstrip(),line[i+1:j].strip()
  715. l1 = split_comma(l1, self.item)
  716. l2 = split_comma(l2, self.item)
  717. stmts.append((l1,l2))
  718. line = line[j+1:].lstrip()
  719. if line.startswith(','):
  720. line = line[1:].lstrip()
  721. self.stmts = stmts
  722. self.isvalid = True
  723. return
  724. def tofortran(self, isfix=None):
  725. tab = self.get_indent_tab(isfix=isfix)
  726. l = []
  727. for o,v in self.stmts:
  728. l.append('%s / %s /' %(', '.join(o),', '.join(v)))
  729. return tab + 'DATA ' + ' '.join(l)
  730. def analyze(self): return
  731. class Nullify(Statement):
  732. """
  733. NULLIFY ( <pointer-object-list> )
  734. <pointer-object> = <variable-name>
  735. """
  736. match = re.compile(r'nullify\s*\(.*\)\Z',re.I).match
  737. def process_item(self):
  738. line = self.item.get_line()[7:].lstrip()[1:-1].strip()
  739. self.items = split_comma(line, self.item)
  740. return
  741. def tofortran(self, isfix=None):
  742. return self.get_indent_tab(isfix=isfix) + 'NULLIFY (%s)' % (', '.join(self.items))
  743. def analyze(self): return
  744. class Use(Statement):
  745. """
  746. USE [ [ , <module-nature> ] :: ] <module-name> [ , <rename-list> ]
  747. USE [ [ , <module-nature> ] :: ] <module-name> , ONLY : [ <only-list> ]
  748. <module-nature> = INTRINSIC | NON_INTRINSIC
  749. <rename> = <local-name> => <use-name>
  750. | OPERATOR ( <local-defined-operator> ) => OPERATOR ( <use-defined-operator> )
  751. <only> = <generic-spec> | <only-use-name> | <rename>
  752. <only-use-name> = <use-name>
  753. """
  754. match = re.compile(r'use\b',re.I).match
  755. def process_item(self):
  756. line = self.item.get_line()[3:].lstrip()
  757. nature = ''
  758. if line.startswith(','):
  759. i = line.find('::')
  760. nature = line[1:i].strip().upper()
  761. line = line[i+2:].lstrip()
  762. if line.startswith('::'):
  763. line = line[2:].lstrip()
  764. if nature and not is_name(nature):
  765. self.isvalid = False
  766. return
  767. self.nature = nature
  768. i = line.find(',')
  769. self.isonly = False
  770. if i==-1:
  771. self.name = line
  772. self.items = []
  773. else:
  774. self.name = line[:i].rstrip()
  775. line = line[i+1:].lstrip()
  776. if line.lower().startswith('only') and line[4:].lstrip().startswith(':'):
  777. self.isonly = True
  778. line = line[4:].lstrip()[1:].lstrip()
  779. self.items = split_comma(line, self.item)
  780. return
  781. def tofortran(self, isfix=None):
  782. tab = self.get_indent_tab(isfix=isfix)
  783. s = 'USE'
  784. if self.nature:
  785. s += ' ' + self.nature + ' ::'
  786. s += ' ' + self.name
  787. if self.isonly:
  788. s += ', ONLY:'
  789. elif self.items:
  790. s += ','
  791. if self.items:
  792. s += ' ' + ', '.join(self.items)
  793. return tab + s
  794. def analyze(self):
  795. use = self.parent.a.use
  796. if self.name in use:
  797. return
  798. modules = self.top.a.module
  799. if self.name not in modules:
  800. fn = self.reader.find_module_source_file(self.name)
  801. if fn is not None:
  802. from readfortran import FortranFileReader
  803. from parsefortran import FortranParser
  804. self.info('looking module information from %r' % (fn))
  805. reader = FortranFileReader(fn, include_dirs=self.reader.include_dirs, source_only=self.reader.source_only)
  806. parser = FortranParser(reader)
  807. parser.parse()
  808. parser.block.a.module.update(modules)
  809. parser.analyze()
  810. modules.update(parser.block.a.module)
  811. if self.name not in modules:
  812. self.warning('no information about the module %r in use statement' % (self.name))
  813. return
  814. module = modules[self.name]
  815. use[self.name] = module
  816. use_provides = self.parent.a.use_provides
  817. renames = [split_comma(item, comma='=>') for item in self.items if '=>' in item]
  818. norenames = [item for item in self.items if '=>' not in item]
  819. all_mod_provides = dict(module.a.module_provides)
  820. all_mod_provides.update(module.a.use_provides)
  821. if self.isonly:
  822. # populate use_provides with items/renames only.
  823. for rename, orig in renames:
  824. self.populate_use_provides(all_mod_provides, use_provides, orig, rename)
  825. for name in norenames:
  826. self.populate_use_provides(all_mod_provides, use_provides, name)
  827. else:
  828. # norenames should be empty
  829. if norenames:
  830. self.warning("'use' without 'only' clause does not rename the variables '%s'" % ', '.join(norenames))
  831. # populate use_provides with renamed vars from module.
  832. for rename, orig in renames:
  833. self.populate_use_provides(all_mod_provides, use_provides, orig, rename)
  834. # get all the rest
  835. unrenamed = set(all_mod_provides) - set([b for (a,b) in renames])
  836. for name in unrenamed:
  837. self.populate_use_provides(all_mod_provides, use_provides, name)
  838. return
  839. def populate_use_provides(self, all_mod_provides, use_provides, name, rename=None):
  840. ovar = all_mod_provides.get(name, None)
  841. if ovar is None:
  842. raise AnalyzeError("entity name '%s' is not in module '%s'" % (name, self.name))
  843. if rename:
  844. name_idx = rename #XXX: rename != ovar.name -- should mark this somehow?
  845. else:
  846. name_idx = name
  847. if name_idx in use_provides:
  848. self.warning("entity name '%s' is already declared in module '%s', overriding." % (name, self.name))
  849. use_provides[name_idx] = ovar
  850. class Exit(Statement):
  851. """
  852. EXIT [ <do-construct-name> ]
  853. """
  854. match = re.compile(r'exit\b\s*\w*\s*\Z',re.I).match
  855. def process_item(self):
  856. self.name = self.item.get_line()[4:].lstrip()
  857. return
  858. def tofortran(self, isfix=None):
  859. if self.name:
  860. return self.get_indent_tab(isfix=isfix) + 'EXIT ' + self.name
  861. return self.get_indent_tab(isfix=isfix) + 'EXIT'
  862. def analyze(self): return
  863. class Parameter(Statement):
  864. """
  865. PARAMETER ( <named-constant-def-list> )
  866. <named-constant-def> = <named-constant> = <initialization-expr>
  867. """
  868. match = re.compile(r'parameter\s*\(.*\)\Z', re.I).match
  869. def process_item(self):
  870. line = self.item.get_line()[9:].lstrip()[1:-1].strip()
  871. self.items = split_comma(line, self.item)
  872. return
  873. def tofortran(self, isfix=None):
  874. return self.get_indent_tab(isfix=isfix) + 'PARAMETER (%s)' % (', '.join(self.items))
  875. def analyze(self):
  876. for item in self.items:
  877. i = item.find('=')
  878. assert i!=-1,`item`
  879. name = item[:i].rstrip()
  880. value = item[i+1:].lstrip()
  881. var = self.get_variable(name)
  882. var.update('parameter')
  883. var.set_init(value)
  884. return
  885. class Equivalence(Statement):
  886. """
  887. EQUIVALENCE <equivalence-set-list>
  888. <equivalence-set> = ( <equivalence-object> , <equivalence-object-list> )
  889. <equivalence-object> = <variable-name> | <array-element> | <substring>
  890. """
  891. match = re.compile(r'equivalence\s*\(.*\)\Z', re.I).match
  892. def process_item(self):
  893. items = []
  894. for s in self.item.get_line()[11:].lstrip().split(','):
  895. s = s.strip()
  896. assert s[0]+s[-1]=='()',`s,self.item.get_line()`
  897. s = ', '.join(split_comma(s[1:-1], self.item))
  898. items.append('('+s+')')
  899. self.items = items
  900. return
  901. def tofortran(self, isfix=None):
  902. return self.get_indent_tab(isfix=isfix) + 'EQUIVALENCE %s' % (', '.join(self.items))
  903. def analyze(self): return
  904. class Dimension(Statement):
  905. """
  906. DIMENSION [ :: ] <array-name> ( <array-spec> ) [ , <array-name> ( <array-spec> ) ]...
  907. """
  908. match = re.compile(r'dimension\b', re.I).match
  909. def process_item(self):
  910. line = self.item.get_line()[9:].lstrip()
  911. if line.startswith('::'):
  912. line = line[2:].lstrip()
  913. self.items = split_comma(line, self.item)
  914. return
  915. def tofortran(self, isfix=None):
  916. return self.get_indent_tab(isfix=isfix) + 'DIMENSION %s' % (', '.join(self.items))
  917. def analyze(self):
  918. for line in self.items:
  919. i = line.find('(')
  920. assert i!=-1 and line.endswith(')'),`line`
  921. name = line[:i].rstrip()
  922. array_spec = split_comma(line[i+1:-1].strip(), self.item)
  923. var = self.get_variable(name)
  924. var.set_bounds(array_spec)
  925. return
  926. class Target(Statement):
  927. """
  928. TARGET [ :: ] <object-name> ( <array-spec> ) [ , <object-name> ( <array-spec> ) ]...
  929. """
  930. match = re.compile(r'target\b', re.I).match
  931. def process_item(self):
  932. line = self.item.get_line()[6:].lstrip()
  933. if line.startswith('::'):
  934. line = line[2:].lstrip()
  935. self.items = split_comma(line, self.item)
  936. return
  937. def tofortran(self, isfix=None):
  938. return self.get_indent_tab(isfix=isfix) + 'TARGET %s' % (', '.join(self.items))
  939. def analyze(self):
  940. for line in self.items:
  941. i = line.find('(')
  942. assert i!=-1 and line.endswith(')'),`line`
  943. name = line[:i].rstrip()
  944. array_spec = split_comma(line[i+1:-1].strip(), self.item)
  945. var = self.get_variable(name)
  946. var.set_bounds(array_spec)
  947. var.update('target')
  948. return
  949. class Pointer(Statement):
  950. """
  951. POINTER [ :: ] <pointer-decl-list>
  952. <pointer-decl> = <object-name> [ ( <deferred-shape-spec-list> ) ]
  953. | <proc-entity-name>
  954. """
  955. match = re.compile(r'pointer\b',re.I).match
  956. def process_item(self):
  957. line = self.item.get_line()[7:].lstrip()
  958. if line.startswith('::'):
  959. line = line[2:].lstrip()
  960. self.items = split_comma(line, self.item)
  961. return
  962. def tofortran(self, isfix=None):
  963. return self.get_indent_tab(isfix=isfix) + 'POINTER %s' % (', '.join(self.items))
  964. def analyze(self):
  965. for line in self.items:
  966. i = line.find('(')
  967. if i==-1:
  968. name = line
  969. array_spec = None
  970. else:
  971. assert line.endswith(')'),`line`
  972. name = line[:i].rstrip()
  973. array_spec = split_comma(line[i+1:-1].strip(), self.item)
  974. var = self.get_variable(name)
  975. var.set_bounds(array_spec)
  976. var.update('pointer')
  977. return
  978. class Protected(StatementWithNamelist):
  979. """
  980. PROTECTED [ :: ] <entity-name-list>
  981. """
  982. match = re.compile(r'protected\b',re.I).match
  983. def analyze(self):
  984. for name in self.items:
  985. var = self.get_variable(name)
  986. var.update('protected')
  987. return
  988. class Volatile(StatementWithNamelist):
  989. """
  990. VOLATILE [ :: ] <object-name-list>
  991. """
  992. match = re.compile(r'volatile\b',re.I).match
  993. def analyze(self):
  994. for name in self.items:
  995. var = self.get_variable(name)
  996. var.update('volatile')
  997. return
  998. class Value(StatementWithNamelist):
  999. """
  1000. VALUE [ :: ] <dummy-arg-name-list>
  1001. """
  1002. match = re.compile(r'value\b',re.I).match
  1003. def analyze(self):
  1004. for name in self.items:
  1005. var = self.get_variable(name)
  1006. var.update('value')
  1007. return
  1008. class ArithmeticIf(Statement):
  1009. """
  1010. IF ( <scalar-numeric-expr> ) <label> , <label> , <label>
  1011. """
  1012. match = re.compile(r'if\s*\(.*\)\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\Z', re.I).match
  1013. def process_item(self):
  1014. line = self.item.get_line()[2:].lstrip()
  1015. line,l2,l3 = line.rsplit(',',2)
  1016. i = line.rindex(')')
  1017. l1 = line[i+1:]
  1018. self.expr = self.item.apply_map(line[1:i]).strip()
  1019. self.labels = [l1.strip(),l2.strip(),l3.strip()]
  1020. return
  1021. def tofortran(self, isfix=None):
  1022. return self.get_indent_tab(isfix=isfix) + 'IF (%s) %s' \
  1023. % (self.expr,', '.join(self.labels))
  1024. def analyze(self): return
  1025. class Intrinsic(StatementWithNamelist):
  1026. """
  1027. INTRINSIC [ :: ] <intrinsic-procedure-name-list>
  1028. """
  1029. match = re.compile(r'intrinsic\b',re.I).match
  1030. def analyze(self):
  1031. for name in self.items:
  1032. var = self.get_variable(name)
  1033. var.update('intrinsic')
  1034. return
  1035. class Inquire(Statement):
  1036. """
  1037. INQUIRE ( <inquire-spec-list> )
  1038. INQUIRE ( IOLENGTH = <scalar-int-variable> ) <output-item-list>
  1039. <inquire-spec> = [ UNIT = ] <file-unit-number>
  1040. | FILE = <file-name-expr>
  1041. ...
  1042. <output-item> = <expr>
  1043. | <io-implied-do>
  1044. """
  1045. match = re.compile(r'inquire\s*\(',re.I).match
  1046. def process_item(self):
  1047. line = self.item.get_line()[7:].lstrip()
  1048. i = line.index(')')
  1049. self.specs = specs_split_comma(line[1:i].strip(), self.item)
  1050. self.items = split_comma(line[i+1:].lstrip(), self.item)
  1051. return
  1052. def tofortran(self, isfix=None):
  1053. if self.items:
  1054. return self.get_indent_tab(isfix=isfix) + 'INQUIRE (%s) %s' \
  1055. % (', '.join(self.specs), ', '.join(self.items))
  1056. return self.get_indent_tab(isfix=isfix) + 'INQUIRE (%s)' \
  1057. % (', '.join(self.specs))
  1058. def analyze(self): return
  1059. class Sequence(Statement):
  1060. """
  1061. SEQUENCE
  1062. """
  1063. match = re.compile(r'sequence\Z',re.I).match
  1064. def process_item(self):
  1065. return
  1066. def tofortran(self, isfix=None): return self.get_indent_tab(isfix=isfix) + 'SEQUENCE'
  1067. def analyze(self):
  1068. self.parent.update_attributes('SEQUENCE')
  1069. return
  1070. class External(StatementWithNamelist):
  1071. """
  1072. EXTERNAL [ :: ] <external-name-list>
  1073. """
  1074. match = re.compile(r'external\b', re.I).match
  1075. def analyze(self):
  1076. for name in self.items:
  1077. var = self.get_variable(name)
  1078. var.update('external')
  1079. return
  1080. class Namelist(Statement):
  1081. """
  1082. NAMELIST / <namelist-group-name> / <namelist-group-object-list> [ [ , ] / <namelist-group-name> / <namelist-group-object-list> ]...
  1083. <namelist-group-object> = <variable-name>
  1084. """
  1085. match = re.compile(r'namelist\b',re.I).match
  1086. def process_item(self):
  1087. line = self.item.get_line()[8:].lstrip()
  1088. items = []
  1089. while line:
  1090. assert line.startswith('/'),`line`
  1091. i = line.find('/',1)
  1092. assert i!=-1,`line`
  1093. name = line[:i+1]
  1094. line = line[i+1:].lstrip()
  1095. i = line.find('/')
  1096. if i==-1:
  1097. items.append((name,line))
  1098. line = ''
  1099. continue
  1100. s = line[:i].rstrip()
  1101. if s.endswith(','):
  1102. s = s[:-1].rstrip()
  1103. items.append((name,s))
  1104. line = line[i+1:].lstrip()
  1105. self.items = items
  1106. return
  1107. def tofortran(self, isfix=None):
  1108. l = []
  1109. for name,s in self.items:
  1110. l.append('%s %s' % (name,s))
  1111. tab = self.get_indent_tab(isfix=isfix)
  1112. return tab + 'NAMELIST ' + ', '.join(l)
  1113. class Common(Statement):
  1114. """
  1115. COMMON [ / [ <common-block-name> ] / ] <common-block-object-list> \
  1116. [ [ , ] / [ <common-block-name> ] / <common-block-object-list> ]...
  1117. <common-block-object> = <variable-name> [ ( <explicit-shape-spec-list> ) ]
  1118. | <proc-pointer-name>
  1119. """
  1120. match = re.compile(r'common\b',re.I).match
  1121. def process_item(self):
  1122. item = self.item
  1123. line = item.get_line()[6:].lstrip()
  1124. items = []
  1125. while line:
  1126. if not line.startswith('/'):
  1127. name = ''
  1128. assert not items,`line`
  1129. else:
  1130. i = line.find('/',1)
  1131. assert i!=-1,`line`
  1132. name = line[1:i].strip()
  1133. line = line[i+1:].lstrip()
  1134. i = line.find('/')
  1135. if i==-1:
  1136. items.append((name,split_comma(line, item)))
  1137. line = ''
  1138. continue
  1139. s = line[:i].rstrip()
  1140. if s.endswith(','):
  1141. s = s[:-1].rstrip()
  1142. items.append((name,split_comma(s,item)))
  1143. line = line[i:].lstrip()
  1144. self.items = items
  1145. return
  1146. def tofortran(self, isfix=None):
  1147. l = []
  1148. for name,s in self.items:
  1149. s = ', '.join(s)
  1150. if name:
  1151. l.append('/ %s / %s' % (name,s))
  1152. else:
  1153. l.append(s)
  1154. tab = self.get_indent_tab(isfix=isfix)
  1155. return tab + 'COMMON ' + ' '.join(l)
  1156. def analyze(self):
  1157. for cname, items in self.items:
  1158. for item in items:
  1159. i = item.find('(')
  1160. if i!=-1:
  1161. assert item.endswith(')'),`item`
  1162. name = item[:i].rstrip()
  1163. shape = split_comma(item[i+1:-1].strip(), self.item)
  1164. else:
  1165. name = item
  1166. shape = None
  1167. var = self.get_variable(name)
  1168. if shape is not None:
  1169. var.set_bounds(shape)
  1170. # XXX: add name,var to parent_provides
  1171. return
  1172. class Optional(StatementWithNamelist):
  1173. """
  1174. OPTIONAL [ :: ] <dummy-arg-name-list>
  1175. <dummy-arg-name> = <name>
  1176. """
  1177. match = re.compile(r'optional\b',re.I).match
  1178. def analyze(self):
  1179. for name in self.items:
  1180. var = self.get_variable(name)
  1181. var.update('optional')
  1182. return
  1183. class Intent(Statement):
  1184. """
  1185. INTENT ( <intent-spec> ) [ :: ] <dummy-arg-name-list>
  1186. <intent-spec> = IN | OUT | INOUT
  1187. generalization for pyf-files:
  1188. INTENT ( <intent-spec-list> ) [ :: ] <dummy-arg-name-list>
  1189. <intent-spec> = IN | OUT | INOUT | CACHE | HIDE | OUT = <name>
  1190. """
  1191. match = re.compile(r'intent\s*\(',re.I).match
  1192. def process_item(self):
  1193. line = self.item.get_line()[6:].lstrip()
  1194. i = line.find(')')
  1195. self.specs = specs_split_comma(line[1:i], self.item, upper=True)
  1196. line = line[i+1:].lstrip()
  1197. if line.startswith('::'):
  1198. line = line[2:].lstrip()
  1199. self.items = [s.strip() for s in line.split(',')]
  1200. for n in self.items:
  1201. if not is_name(n):
  1202. self.isvalid = False
  1203. return
  1204. return
  1205. def tofortran(self, isfix=None):
  1206. return self.get_indent_tab(isfix=isfix) + 'INTENT (%s) %s' \
  1207. % (', '.join(self.specs), ', '.join(self.items))
  1208. def analyze(self):
  1209. for name in self.items:
  1210. var = self.get_variable(name)
  1211. var.set_intent(self.specs)
  1212. return
  1213. class Entry(Statement):
  1214. """
  1215. ENTRY <entry-name> [ ( [ <dummy-arg-list> ] ) [ <suffix> ] ]
  1216. <suffix> = <proc-language-binding-spec> [ RESULT ( <result-name> ) ]
  1217. | RESULT ( <result-name> ) [ <proc-language-binding-spec> ]
  1218. <proc-language-binding-spec> = <language-binding-spec>
  1219. <language-binding-spec> = BIND ( C [ , NAME = <scalar-char-initialization-expr> ] )
  1220. <dummy-arg> = <dummy-arg-name> | *
  1221. """
  1222. match = re.compile(r'entry\b', re.I).match
  1223. def process_item(self):
  1224. line = self.item.get_line()[5:].lstrip()
  1225. m = re.match(r'\w+', line)
  1226. name = line[:m.end()]
  1227. line = line[m.end():].lstrip()
  1228. if line.startswith('('):
  1229. i = line.find(')')
  1230. assert i!=-1,`line`
  1231. items = split_comma(line[1:i], self.item)
  1232. line = line[i+1:].lstrip()
  1233. else:
  1234. items = []
  1235. self.bind, line = parse_bind(line, self.item)
  1236. self.result, line = parse_result(line, self.item)
  1237. if line:
  1238. assert self.bind is None,`self.bind`
  1239. self.bind, line = parse_bind(line, self.item)
  1240. assert not line,`line`
  1241. self.name = name
  1242. self.items = items
  1243. return
  1244. def tofortran(self, isfix=None):
  1245. tab = self.get_indent_tab(isfix=isfix)
  1246. s = tab + 'ENTRY '+self.name
  1247. if self.items:
  1248. s += ' (%s)' % (', '.join(self.items))
  1249. if self.result:
  1250. s += ' RESULT (%s)' % (self.result)
  1251. if self.bind:
  1252. s += ' BIND (%s)' % (', '.join(self.bind))
  1253. return s
  1254. class Import(StatementWithNamelist):
  1255. """
  1256. IMPORT [ [ :: ] <import-name-list> ]
  1257. """
  1258. match = re.compile(r'import(\b|\Z)',re.I).match
  1259. class Forall(Statement):
  1260. """
  1261. FORALL <forall-header> <forall-assignment-stmt>
  1262. <forall-header> = ( <forall-triplet-spec-list> [ , <scalar-mask-expr> ] )
  1263. <forall-triplet-spec> = <index-name> = <subscript> : <subscript> [ : <stride> ]
  1264. <subscript|stride> = <scalar-int-expr>
  1265. <forall-assignment-stmt> = <assignment-stmt> | <pointer-assignment-stmt>
  1266. """
  1267. match = re.compile(r'forall\s*\(.*\).*=', re.I).match
  1268. def process_item(self):
  1269. line = self.item.get_line()[6:].lstrip()
  1270. i = line.index(')')
  1271. line0 = line[1:i]
  1272. line = line[i+1:].lstrip()
  1273. stmt = GeneralAssignment(self, self.item.copy(line, True))
  1274. if stmt.isvalid:
  1275. self.content = [stmt]
  1276. else:
  1277. self.isvalid = False
  1278. return
  1279. specs = []
  1280. mask = ''
  1281. for l in split_comma(line0,self.item):
  1282. j = l.find('=')
  1283. if j==-1:
  1284. assert not mask,`mask,l`
  1285. mask = l
  1286. continue
  1287. assert j!=-1,`l`
  1288. index = l[:j].rstrip()
  1289. it = self.item.copy(l[j+1:].lstrip())
  1290. l = it.get_line()
  1291. k = l.split(':')
  1292. if len(k)==3:
  1293. s1, s2, s3 = map(it.apply_map,
  1294. [k[0].strip(),k[1].strip(),k[2].strip()])
  1295. else:
  1296. assert len(k)==2,`k`
  1297. s1, s2 = map(it.apply_map,
  1298. [k[0].strip(),k[1].strip()])
  1299. s3 = '1'
  1300. specs.append((index,s1,s2,s3))
  1301. self.specs = specs
  1302. self.mask = mask
  1303. return
  1304. def tofortran(self, isfix=None):
  1305. tab = self.get_indent_tab(isfix=isfix)
  1306. l = []
  1307. for index,s1,s2,s3 in self.specs:
  1308. s = '%s = %s : %s' % (index,s1,s2)
  1309. if s3!='1':
  1310. s += ' : %s' % (s3)
  1311. l.append(s)
  1312. s = ', '.join(l)
  1313. if self.mask:
  1314. s += ', ' + self.mask
  1315. return tab + 'FORALL (%s) %s' % \
  1316. (s, str(self.content[0]).lstrip())
  1317. def analyze(self): return
  1318. ForallStmt = Forall
  1319. class SpecificBinding(Statement):
  1320. """
  1321. PROCEDURE [ ( <interface-name> ) ] [ [ , <binding-attr-list> ] :: ] <binding-name> [ => <procedure-name> ]
  1322. <binding-attr> = PASS [ ( <arg-name> ) ]
  1323. | NOPASS
  1324. | NON_OVERRIDABLE
  1325. | DEFERRED
  1326. | <access-spec>
  1327. <access-spec> = PUBLIC | PRIVATE
  1328. """
  1329. match = re.compile(r'procedure\b',re.I).match
  1330. def process_item(self):
  1331. line = self.item.get_line()[9:].lstrip()

Large files files are truncated, but you can click here to view the full file