PageRenderTime 59ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/statements.py

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

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