fparser Reference Guide  0.0.14
Fortran2003.py
1 #!/usr/bin/env python
2 
3 # Modified work Copyright (c) 2017-2022 Science and Technology
4 # Facilities Council.
5 # Original work Copyright (c) 1999-2008 Pearu Peterson
6 
7 # All rights reserved.
8 
9 # Modifications made as part of the fparser project are distributed
10 # under the following license:
11 
12 # Redistribution and use in source and binary forms, with or without
13 # modification, are permitted provided that the following conditions are
14 # met:
15 
16 # 1. Redistributions of source code must retain the above copyright
17 # notice, this list of conditions and the following disclaimer.
18 
19 # 2. Redistributions in binary form must reproduce the above copyright
20 # notice, this list of conditions and the following disclaimer in the
21 # documentation and/or other materials provided with the distribution.
22 
23 # 3. Neither the name of the copyright holder nor the names of its
24 # contributors may be used to endorse or promote products derived from
25 # this software without specific prior written permission.
26 
27 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 
39 # --------------------------------------------------------------------
40 
41 # The original software (in the f2py project) was distributed under
42 # the following license:
43 
44 # Redistribution and use in source and binary forms, with or without
45 # modification, are permitted provided that the following conditions are met:
46 
47 # a. Redistributions of source code must retain the above copyright notice,
48 # this list of conditions and the following disclaimer.
49 # b. Redistributions in binary form must reproduce the above copyright
50 # notice, this list of conditions and the following disclaimer in the
51 # documentation and/or other materials provided with the distribution.
52 # c. Neither the name of the F2PY project nor the names of its
53 # contributors may be used to endorse or promote products derived from
54 # this software without specific prior written permission.
55 
56 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
57 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
60 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
62 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
63 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
66 # DAMAGE.
67 
68 """Fortran 2003 Syntax Rules.
69 """
70 # Original author: Pearu Peterson <pearu@cens.ioc.ee>
71 # First version created: Oct 2006
72 
73 import re
74 from fparser.common.splitline import string_replace_map
75 from fparser.two import pattern_tools as pattern
76 from fparser.common.readfortran import FortranReaderBase
77 from fparser.two.symbol_table import SYMBOL_TABLES
78 from fparser.two.utils import (
79  Base,
80  BlockBase,
81  StringBase,
82  WORDClsBase,
83  NumberBase,
84  STRINGBase,
85  BracketBase,
86  StmtBase,
87  EndStmtBase,
88  BinaryOpBase,
89  Type_Declaration_StmtBase,
90  CALLBase,
91  CallBase,
92  KeywordValueBase,
93  SeparatorBase,
94  SequenceBase,
95  UnaryOpBase,
96  walk,
97  DynamicImport,
98 )
99 from fparser.two.utils import (
100  NoMatchError,
101  FortranSyntaxError,
102  InternalSyntaxError,
103  InternalError,
104  show_result,
105 )
106 
107 #
108 # SECTION 1
109 #
110 
111 # R101: <xyz-list> = <xyz> [ , <xyz> ]...
112 # R102: <xyz-name> = <name>
113 # R103: <scalar-xyz> = <xyz>
114 
115 #
116 # SECTION 2
117 #
118 
119 
120 class Comment(Base):
121  """
122  Represents a Fortran Comment.
123  """
124 
125  subclass_names = []
126 
127  @show_result
128  def __new__(cls, string, parent_cls=None):
129  """
130  Create a new Comment instance.
131 
132  :param type cls: the class of object to create.
133  :param string: (source of) Fortran string to parse.
134  :type string: str or :py:class:`FortranReaderBase`
135  :param parent_cls: the parent class of this object.
136  :type parent_cls: :py:type:`type`
137 
138  """
139  from fparser.common import readfortran
140 
141  if isinstance(string, readfortran.Comment):
142  # We were after a comment and we got a comment. Construct
143  # one manually to avoid recursively calling this __new__
144  # method again...
145  obj = object.__new__(cls)
146  obj.init(string)
147  return obj
148  elif isinstance(string, FortranReaderBase):
149  reader = string
150  item = reader.get_item()
151  if item is None:
152  return
153  if isinstance(item, readfortran.Comment):
154  # This effectively recursively calls this routine
155  return Comment(item)
156  else:
157  # We didn't get a comment so put the item back in the FIFO
158  reader.put_item(item)
159  return
160  else:
161  # We didn't get a comment
162  return
163 
164  def init(self, comment):
165  """
166  Initialise this Comment
167 
168  :param comment: The comment object produced by the reader
169  :type comment: :py:class:`readfortran.Comment`
170  """
171  self.items = [comment.comment]
172  self.item = comment
173 
174  def tostr(self):
175  """
176  :returns: this comment as a string.
177  :rtype: :py:class:`str`
178  """
179  return str(self.items[0])
180 
181  def restore_reader(self, reader):
182  """
183  Undo the read of this comment by putting its content back
184  into the reader (which has a FIFO buffer)
185 
186  :param reader: the reader instance to return the comment to
187  :type reader: :py:class:`fparser.readfortran.FortranReaderBase`
188  """
189  reader.put_item(self.item)
190 
191 
192 def match_comment_or_include(reader):
193  """Creates a comment or include object from the current line.
194 
195  :param reader: the fortran file reader containing the line \
196  of code that we are trying to match
197  :type reader: :py:class:`fparser.common.readfortran.FortranFileReader` \
198  or \
199  :py:class:`fparser.common.readfortran.FortranStringReader`
200 
201  :return: a comment or include object if found, otherwise `None`.
202  :rtype: :py:class:`fparser.two.Fortran2003.Comment` or \
203  :py:class:`fparser.two.Fortran2003.Include_Stmt`
204 
205  """
206  obj = Comment(reader)
207  obj = Include_Stmt(reader) if not obj else obj
208  return obj
209 
210 
211 def add_comments_includes_directives(content, reader):
212  """Creates comment, include, and/or cpp directive objects and adds them to
213  the content list. Comment, include, and/or directive objects are added
214  until a line that is not a comment, include, or directive is found.
215 
216  :param content: a `list` of matched objects. Any matched comments, \
217  includes, or directives in this routine are added to \
218  this list.
219  :type content: :obj:`list`
220  :param reader: the fortran file reader containing the line(s) \
221  of code that we are trying to match
222  :type reader: :py:class:`fparser.common.readfortran.FortranFileReader` \
223  or \
224  :py:class:`fparser.common.readfortran.FortranStringReader`
225 
226  """
227  from fparser.two.C99Preprocessor import match_cpp_directive
228 
229  obj = match_comment_or_include(reader)
230  obj = match_cpp_directive(reader) if not obj else obj
231  while obj:
232  content.append(obj)
233  obj = match_comment_or_include(reader)
234  obj = match_cpp_directive(reader) if not obj else obj
235 
236 
237 class Program(BlockBase): # R201
238  """
239  Fortran 2003 rule R201
240  program is program-unit
241  [ program-unit ] ...
242 
243  """
244 
245  subclass_names = []
246  use_names = ["Program_Unit"]
247 
248  @show_result
249  def __new__(cls, string):
250  """Wrapper around base class __new__ to catch an internal NoMatchError
251  exception and raise it as an external FortranSyntaxError exception.
252 
253  :param type cls: the class of object to create
254  :param string: (source of) Fortran string to parse
255  :type string: :py:class:`FortranReaderBase`
256  :raises FortranSyntaxError: if the code is not valid Fortran
257 
258  """
259  # pylint: disable=unused-argument
260  try:
261  return Base.__new__(cls, string)
262  except NoMatchError:
263  # At the moment there is no useful information provided by
264  # NoMatchError so we pass on an empty string.
265  raise FortranSyntaxError(string, "")
266  except InternalSyntaxError as excinfo:
267  # InternalSyntaxError is used when a syntax error has been
268  # found in a rule that does not have access to the reader
269  # object. This is then re-raised here as a
270  # FortranSyntaxError, adding the reader object (which
271  # provides line number information).
272  raise FortranSyntaxError(string, excinfo)
273 
274  @staticmethod
275  def match(reader):
276  """Implements the matching for a Program. Whilst the rule looks like
277  it could make use of BlockBase, the parser must not match if an
278  optional program_unit has a syntax error, which the BlockBase
279  match implementation does not do.
280 
281  :param reader: the fortran file reader containing the line(s)
282  of code that we are trying to match
283  :type reader: :py:class:`fparser.common.readfortran.FortranFileReader`
284  or
285  :py:class:`fparser.common.readfortran.FortranStringReader`
286  :return: `tuple` containing a single `list` which contains
287  instance of the classes that have matched if there is
288  a match or `None` if there is no match
289 
290  """
291  content = []
292  add_comments_includes_directives(content, reader)
293  comments = content != []
294  try:
295  while True:
296  obj = Program_Unit(reader)
297  content.append(obj)
298  add_comments_includes_directives(content, reader)
299  # cause a StopIteration exception if there are no more lines
300  next_line = reader.next()
301  # put the line back in the case where there are more lines
302  reader.put_item(next_line)
303  except NoMatchError:
304  # Found a syntax error for this rule. Now look to match
305  # (via Main_Program0) with a program containing no program
306  # statement as this is optional in Fortran.
307  #
308  result = BlockBase.match(Main_Program0, [], None, reader)
309  if not result and comments:
310  # This program only contains comments.
311  return (content,)
312  else:
313  return result
314  except StopIteration:
315  # Reader has no more lines.
316  pass
317  return (content,)
318 
319 
320 class Include_Filename(StringBase): # pylint: disable=invalid-name
321 
322  """Implements the matching of a filename from an include statement."""
323 
324  # There are no other classes. This is a simple string match.
325  subclass_names = []
326 
327  @staticmethod
328  def match(string):
329  """Match the string with the regular expression file_name in the
330  pattern_tools file. The only content that is not accepted is
331  an empty string or white space at the start or end of the
332  string.
333 
334  :param str string: the string to match with the pattern rule.
335  :return: a tuple of size 1 containing a string with the \
336  matched name if there is a match, or None if there is not.
337  :rtype: (str) or NoneType
338 
339  """
340  return StringBase.match(pattern.file_name, string)
341 
342 
343 class Include_Stmt(Base): # pylint: disable=invalid-name
344 
345  """Implements the matching of a Fortran include statement. There is no
346  rule for this as the compiler is expected to inline any content
347  from an include statement when one is found. However, for a parser
348  it can make sense to represent an include statement in a parse
349  tree.
350 
351  include-stmt is INCLUDE ['filename' or "filename"]
352 
353  """
354 
355  use_names = ["Include_Filename"]
356 
357  @staticmethod
358  def match(string):
359  """Implements the matching for an include statement.
360 
361  :param str string: the string to match with as an include statement.
362  :returns: a tuple of size 1 containing an Include_Filename \
363  object with the matched filename if there is a match, or None \
364  if there is not.
365  :rtype: (:py:class:`fparser.two.Fortran2003.Include_Filename`) \
366  or NoneType
367 
368  """
369  if not string:
370  return None
371 
372  line = string.strip()
373  if line[:7].upper() != "INCLUDE":
374  # The line does not start with the include token and/or the line
375  # is too short.
376  return None
377  rhs = line[7:].strip()
378  if rhs is None or len(rhs) < 3:
379  # Either we didn't find any includes or the content after
380  # the include token is too short to be valid (it must at
381  # least contain quotes and one character.
382  return None
383  if not (
384  (rhs[0] == "'" and rhs[-1] == "'") or (rhs[0] == '"' and rhs[-1] == '"')
385  ):
386  # The filename should be surrounded by single or double
387  # quotes but this is not the case.
388  return None
389  # Remove the quotes.
390  file_name = rhs[1:-1]
391  # Pass the potential filename to the relevant class.
392  name = Include_Filename(file_name)
393  if not name:
394  raise InternalError(
395  "Fortran2003.py:Include_Stmt:match Include_Filename should "
396  "never return None or an empty name"
397  )
398  return (name,)
399 
400  def tostr(self):
401  """
402  :return: this include_stmt as a string
403  :rtype: str
404  """
405 
406  return "INCLUDE '{0}'".format(self.items[0])
407 
408 
409 class Program_Unit(Base): # R202
410  """
411  :F03R:`202`::
412  <program-unit> = <main-program>
413  | <external-subprogram>
414  | <module>
415  | <block-data>
416  """
417 
418  subclass_names = [
419  "Comment",
420  "Main_Program",
421  "External_Subprogram",
422  "Module",
423  "Block_Data",
424  ]
425 
426 
427 class External_Subprogram(Base): # R203
428  """
429  :F03R:`203`::
430  <external-subprogram> = <function-subprogram>
431  | <subroutine-subprogram>
432  """
433 
434  subclass_names = ["Comment", "Function_Subprogram", "Subroutine_Subprogram"]
435 
436 
437 class Specification_Part(BlockBase): # R204
438  """
439  :F03R:`204`::
440  <specification-part> = [ <use-stmt> ]...
441  [ <import-stmt> ]...
442  [ <implicit-part> ]
443  [ <declaration-construct> ]...
444  """
445 
446  subclass_names = []
447  use_names = ["Use_Stmt", "Import_Stmt", "Implicit_Part", "Declaration_Construct"]
448 
449  @staticmethod
450  def match(reader):
451  return BlockBase.match(
452  None,
453  [Use_Stmt, Import_Stmt, Implicit_Part, Declaration_Construct],
454  None,
455  reader,
456  )
457 
458 
459 class Implicit_Part(BlockBase): # R205
460  """
461  :F03R:`205`::
462  <implicit-part> = [ <implicit-part-stmt> ]...
463  <implicit-stmt>
464  """
465 
466  subclass_names = []
467  use_names = ["Implicit_Part_Stmt", "Implicit_Stmt"]
468 
469  @staticmethod
470  def match(reader):
471  return BlockBase.match(None, [Implicit_Part_Stmt], None, reader)
472 
473 
474 class Implicit_Part_Stmt(Base): # R206
475  """
476  :F03R:`206`::
477  <implicit-part-stmt> = <implicit-stmt>
478  | <parameter-stmt>
479  | <format-stmt>
480  | <entry-stmt>
481  """
482 
483  subclass_names = [
484  "Comment",
485  "Implicit_Stmt",
486  "Parameter_Stmt",
487  "Format_Stmt",
488  "Entry_Stmt",
489  ]
490 
491 
492 class Declaration_Construct(Base): # R207
493  """Fortran 2003 rule R207
494 
495  declaration-construct is derived-type-def
496  or entry-stmt
497  or enum-def
498  or format-stmt
499  or interface-block
500  or parameter-stmt
501  or procedure-declaration-stmt
502  or specification-stmt
503  or type-declaration-stmt
504  or stmt-function-stmt
505 
506  Note, stmt-function-stmt is not currently matched.
507 
508  """
509 
510  # Commented out Stmt_Function_Stmt as it can falsely match an
511  # access to an array or function. Reintroducing statement
512  # functions is captured in issue #202.
513 
514  # 'Type_Declaration_Stmt', 'Stmt_Function_Stmt']
515  subclass_names = [
516  "Derived_Type_Def",
517  "Entry_Stmt",
518  "Enum_Def",
519  "Format_Stmt",
520  "Interface_Block",
521  "Parameter_Stmt",
522  "Procedure_Declaration_Stmt",
523  "Specification_Stmt",
524  "Type_Declaration_Stmt",
525  ]
526 
527 
528 class Execution_Part(BlockBase): # R208
529  """:F03R:`208`::
530  <execution-part> = <executable-construct>
531  | [ <execution-part-construct> ]...
532 
533  <execution-part> shall not contain <end-function-stmt>,
534  <end-program-stmt>, <end-subroutine-stmt>
535 
536  """
537 
538  subclass_names = []
539  use_names = ["Executable_Construct_C201", "Execution_Part_Construct_C201"]
540 
541  @staticmethod
542  def match(string):
543  return BlockBase.match(
544  Executable_Construct_C201, [Execution_Part_Construct_C201], None, string
545  )
546 
547 
548 class Execution_Part_Construct(Base): # R209
549  """
550  <execution-part-construct> = <executable-construct>
551  | <format-stmt>
552  | <entry-stmt>
553  | <data-stmt>
554  """
555 
556  subclass_names = [
557  "Comment",
558  "Executable_Construct",
559  "Format_Stmt",
560  "Entry_Stmt",
561  "Data_Stmt",
562  ]
563 
564 
566  subclass_names = [
567  "Comment",
568  "Executable_Construct_C201",
569  "Format_Stmt",
570  "Entry_Stmt",
571  "Data_Stmt",
572  ]
573 
574 
575 class Internal_Subprogram_Part(BlockBase): # R210
576  """
577  <internal-subprogram-part> = <contains-stmt>
578  <internal-subprogram>
579  [ <internal-subprogram> ]...
580  """
581 
582  subclass_names = []
583  use_names = ["Contains_Stmt", "Internal_Subprogram"]
584 
585  @staticmethod
586  def match(reader):
587  return BlockBase.match(Contains_Stmt, [Internal_Subprogram], None, reader)
588 
589 
590 class Internal_Subprogram(Base): # R211
591  """
592  <internal-subprogram> = <function-subprogram>
593  | <subroutine-subprogram>
594  """
595 
596  subclass_names = ["Function_Subprogram", "Subroutine_Subprogram"]
597 
598 
599 class Specification_Stmt(Base): # R212
600  """
601  <specification-stmt> = <access-stmt>
602  | <allocatable-stmt>
603  | <asynchronous-stmt>
604  | <bind-stmt>
605  | <common-stmt>
606  | <data-stmt>
607  | <dimension-stmt>
608  | <equivalence-stmt>
609  | <external-stmt>
610  | <intent-stmt>
611  | <intrinsic-stmt>
612  | <namelist-stmt>
613  | <optional-stmt>
614  | <pointer-stmt>
615  | <protected-stmt>
616  | <save-stmt>
617  | <target-stmt>
618  | <volatile-stmt>
619  | <value-stmt>
620  """
621 
622  subclass_names = [
623  "Access_Stmt",
624  "Allocatable_Stmt",
625  "Asynchronous_Stmt",
626  "Bind_Stmt",
627  "Comment",
628  "Common_Stmt",
629  "Data_Stmt",
630  "Dimension_Stmt",
631  "Equivalence_Stmt",
632  "External_Stmt",
633  "Intent_Stmt",
634  "Intrinsic_Stmt",
635  "Namelist_Stmt",
636  "Optional_Stmt",
637  "Pointer_Stmt",
638  "Cray_Pointer_Stmt",
639  "Protected_Stmt",
640  "Save_Stmt",
641  "Target_Stmt",
642  "Volatile_Stmt",
643  "Value_Stmt",
644  ]
645 
646 
647 class Executable_Construct(Base): # R213
648  # pylint: disable=invalid-name
649  """
650  Fortran 2003 rule R213
651  executable-construct is action-stmt
652  or associate-construct
653  or case-construct
654  or do-construct
655  or forall-construct
656  or if-construct
657  or select-type-construct
658  or where-construct
659 
660  """
661  subclass_names = [
662  "Action_Stmt",
663  "Associate_Construct",
664  "Case_Construct",
665  "Do_Construct",
666  "Forall_Construct",
667  "If_Construct",
668  "Select_Type_Construct",
669  "Where_Construct",
670  ]
671 
672 
674  subclass_names = Executable_Construct.subclass_names[:]
675  subclass_names[subclass_names.index("Action_Stmt")] = "Action_Stmt_C201"
676 
677 
678 class Action_Stmt(Base): # R214
679  """
680  <action-stmt> = <allocate-stmt>
681  | <assignment-stmt>
682  | <backspace-stmt>
683  | <call-stmt>
684  | <close-stmt>
685  | <continue-stmt>
686  | <cycle-stmt>
687  | <deallocate-stmt>
688  | <endfile-stmt>
689  | <end-function-stmt>
690  | <end-program-stmt>
691  | <end-subroutine-stmt>
692  | <exit-stmt>
693  | <flush-stmt>
694  | <forall-stmt>
695  | <goto-stmt>
696  | <if-stmt>
697  | <inquire-stmt>
698  | <nullify-stmt>
699  | <open-stmt>
700  | <pointer-assignment-stmt>
701  | <print-stmt>
702  | <read-stmt>
703  | <return-stmt>
704  | <rewind-stmt>
705  | <stop-stmt>
706  | <wait-stmt>
707  | <where-stmt>
708  | <write-stmt>
709  | <arithmetic-if-stmt>
710  | <computed-goto-stmt>
711  """
712 
713  subclass_names = [
714  "Allocate_Stmt",
715  "Assignment_Stmt",
716  "Backspace_Stmt",
717  "Call_Stmt",
718  "Close_Stmt",
719  "Comment",
720  "Continue_Stmt",
721  "Cycle_Stmt",
722  "Deallocate_Stmt",
723  "Endfile_Stmt",
724  "End_Function_Stmt",
725  "End_Subroutine_Stmt",
726  "Exit_Stmt",
727  "Flush_Stmt",
728  "Forall_Stmt",
729  "Goto_Stmt",
730  "If_Stmt",
731  "Inquire_Stmt",
732  "Nullify_Stmt",
733  "Open_Stmt",
734  "Pointer_Assignment_Stmt",
735  "Print_Stmt",
736  "Read_Stmt",
737  "Return_Stmt",
738  "Rewind_Stmt",
739  "Stop_Stmt",
740  "Wait_Stmt",
741  "Where_Stmt",
742  "Write_Stmt",
743  "Arithmetic_If_Stmt",
744  "Computed_Goto_Stmt",
745  ]
746 
747 
748 class Action_Stmt_C201(Base):
749  """
750  <action-stmt-c201> = <action-stmt>
751  C201 is applied.
752  """
753 
754  subclass_names = Action_Stmt.subclass_names[:]
755  subclass_names.remove("End_Function_Stmt")
756  subclass_names.remove("End_Subroutine_Stmt")
757  # subclass_names.remove('End_Program_Stmt')
758 
759 
760 class Action_Stmt_C802(Base):
761  """
762  <action-stmt-c802> = <action-stmt>
763  C802 is applied.
764  """
765 
766  subclass_names = Action_Stmt.subclass_names[:]
767  subclass_names.remove("End_Function_Stmt")
768  subclass_names.remove("End_Subroutine_Stmt")
769  subclass_names.remove("If_Stmt")
770 
771 
772 class Action_Stmt_C824(Base):
773  """
774  <action-stmt-c824> = <action-stmt>
775  C824 is applied.
776  """
777 
778  subclass_names = Action_Stmt.subclass_names[:]
779  subclass_names.remove("End_Function_Stmt")
780  subclass_names.remove("End_Subroutine_Stmt")
781  subclass_names.remove("Continue_Stmt")
782  subclass_names.remove("Goto_Stmt")
783  subclass_names.remove("Return_Stmt")
784  subclass_names.remove("Stop_Stmt")
785  subclass_names.remove("Exit_Stmt")
786  subclass_names.remove("Cycle_Stmt")
787  subclass_names.remove("Arithmetic_If_Stmt")
788 
789 
790 class Keyword(Base): # R215
791  """
792  <keyword> = <name>
793  """
794 
795  subclass_names = ["Name"]
796 
797 
798 #
799 # SECTION 3
800 #
801 
802 # R301: <character> = <alphanumeric-character> | <special-character>
803 # R302: <alphanumeric-character> = <letter> | <digit> | <underscore>
804 # R303: <underscore> = _
805 
806 
807 class Name(StringBase): # R304
808  """
809  Fortran 2003 rule R304
810  name is letter [ alphanumeric_character ]...
811 
812  """
813 
814  # There are no other classes. This is a simple string match.
815  subclass_names = []
816 
817  @staticmethod
818  def match(string):
819  """Match the string with the regular expression abs_name in the
820  pattern_tools file.
821 
822  :param str string: the string to match with the pattern rule.
823  :return: a tuple of size 1 containing a string with the \
824  matched name if there is a match, or None if there is not.
825  :rtype: (str) or None
826 
827  """
828  return StringBase.match(pattern.abs_name, string.strip())
829 
830 
831 class Constant(Base): # R305
832  """
833  <constant> = <literal-constant>
834  | <named-constant>
835  """
836 
837  subclass_names = ["Literal_Constant", "Named_Constant"]
838 
839 
840 class Literal_Constant(Base): # R306
841  """
842  <literal-constant> = <int-literal-constant>
843  | <real-literal-constant>
844  | <complex-literal-constant>
845  | <logical-literal-constant>
846  | <char-literal-constant>
847  | <boz-literal-constant>
848  """
849 
850  subclass_names = [
851  "Int_Literal_Constant",
852  "Real_Literal_Constant",
853  "Complex_Literal_Constant",
854  "Logical_Literal_Constant",
855  "Char_Literal_Constant",
856  "Boz_Literal_Constant",
857  ]
858 
859 
860 class Named_Constant(Base): # R307
861  """
862  <named-constant> = <name>
863  """
864 
865  subclass_names = ["Name"]
866 
867 
868 class Int_Constant(Base): # R308
869  """
870  <int-constant> = <constant>
871  """
872 
873  subclass_names = ["Constant"]
874 
875 
876 class Char_Constant(Base): # R309
877  """
878  <char-constant> = <constant>
879  """
880 
881  subclass_names = ["Constant"]
882 
883 
884 # R310: <intrinsic-operator> = <power-op> | <mult-op> | <add-op> |
885 # <concat-op> | <rel-op> | <not-op> | <and-op> | <or-op> | <equiv-op>
886 # Rule 310 is defined in pattern_tools.py. As it is only used by Rule
887 # 312 it does not need to be defined explicitly as a class. Note, it
888 # could be created as a class if it were useful for code
889 # manipulation. We could additionally create each of the operators
890 # themselves as classes.
891 
892 
893 class Defined_Operator(Base): # pylint: disable=invalid-name
894  """Fortran 2003 rule R311
895  R311 defined-operator is defined-unary-op
896  or defined-binary-op
897  or extended-intrinsic-op
898 
899  Note, defined-operator is defined in pattern_tools.py so could be
900  called directly via a stringbase match. However, the defined unary
901  and binary op rules have constraints which would not be checked if
902  we did this.
903 
904  Note, whilst we subclass for both Defined Unary and Binary ops,
905  the match is the same so we will only ever match with the first
906  (so the second is not really necessary here). This is OK from a
907  parsing point of view as they both return a Defined_Op class, so
908  are identical from the parsers point of view.
909 
910  """
911 
912  subclass_names = ["Defined_Unary_Op", "Defined_Binary_Op", "Extended_Intrinsic_Op"]
913 
914 
915 class Extended_Intrinsic_Op(StringBase): # pylint: disable=invalid-name
916  """Fortran 2003 rule R312
917  R312 extended-intrinsic-op is intrinsic-operator
918 
919  Note, extended-intrinsic-op is only ever used by R311 and is
920  defined in pattern_tools.py so could be matched directly in the
921  Defined_Operator class (by changing it to STRINGBase and moving
922  the match in this class into the Defined_Operator class). This
923  would mean that this class would not be required. However, the
924  parse tree would then not have the concept of an
925  Extended_Intrinsic_Op which might be useful for code manipulation
926  tools.
927 
928  """
929 
930  @staticmethod
931  def match(string):
932  """Implements the matching for the extended-intrinsic-op
933  rule. Matches the string with the regular expression
934  extended_intrinsic_operator in the pattern_tools file.
935 
936  :param str string: the string to match with the pattern rule.
937  :return: a tuple of size 1 containing a string with the \
938  matched name if there is a match, or None if there is not.
939  :rtype: (str) or None
940 
941  """
942  return StringBase.match(pattern.extended_intrinsic_operator, string)
943 
944 
945 class Label(StringBase): # R313
946  """
947  ::
948  <label> = <digit> [ <digit> [ <digit> [ <digit> [ <digit> ] ] ] ]
949 
950  Attributes
951  ----------
952  string : str
953  """
954 
955  subclass_names = []
956 
957  @staticmethod
958  def match(string):
959  return StringBase.match(pattern.abs_label, string)
960 
961  def __int__(self):
962  return int(self.string)
963 
964 
965 #
966 # SECTION 4
967 #
968 
969 
970 class Type_Spec(Base): # R401
971  """
972  <type-spec> = <intrinsic-type-spec>
973  | <derived-type-spec>
974  """
975 
976  subclass_names = ["Intrinsic_Type_Spec", "Derived_Type_Spec"]
977 
978 
979 class Type_Param_Value(StringBase): # R402
980  """
981  <type-param-value> = <scalar-int-expr>
982  | *
983  | :
984  """
985 
986  subclass_names = ["Scalar_Int_Expr"]
987  use_names = []
988 
989  @staticmethod
990  def match(string):
991  return StringBase.match(["*", ":"], string)
992 
993 
994 class Intrinsic_Type_Spec(WORDClsBase): # R403
995  """
996  <intrinsic-type-spec> = INTEGER [ <kind-selector> ]
997  | REAL [ <kind-selector> ]
998  | DOUBLE COMPLEX
999  | COMPLEX [ <kind-selector> ]
1000  | CHARACTER [ <char-selector> ]
1001  | LOGICAL [ <kind-selector> ]
1002  Extensions:
1003  | DOUBLE PRECISION
1004  | BYTE
1005  """
1006 
1007  subclass_names = []
1008  use_names = ["Kind_Selector", "Char_Selector"]
1009 
1010  @staticmethod
1011  def match(string):
1012  for w, cls in [
1013  ("INTEGER", Kind_Selector),
1014  ("REAL", Kind_Selector),
1015  ("COMPLEX", Kind_Selector),
1016  ("LOGICAL", Kind_Selector),
1017  ("CHARACTER", Char_Selector),
1018  (pattern.abs_double_complex_name, None),
1019  (pattern.abs_double_precision_name, None),
1020  ("BYTE", None),
1021  ]:
1022  try:
1023  obj = WORDClsBase.match(w, cls, string)
1024  except NoMatchError:
1025  obj = None
1026  if obj is not None:
1027  return obj
1028  return None
1029 
1030 
1031 class Kind_Selector(Base): # R404
1032  """
1033  Fortran 2003 rule R404
1034  kind-selector is ( [ KIND = ] scalar-int-initialization-expr )
1035  A non-standard extension is also supported here:
1036  | * char-length
1037 
1038  There is an associated constraint that we can't enforce in fparser:
1039 
1040  'C404 (R404) The value of scalar-int-initialization-expr shall be
1041  nonnegative and shall specify a representation method that
1042  exists on the processor.'
1043 
1044  """
1045 
1046  subclass_names = []
1047  use_names = ["Char_Length", "Scalar_Int_Initialization_Expr"]
1048 
1049  @staticmethod
1050  def match(string):
1051  """Implements the matching for a Kind_Selector.
1052 
1053  :param str string: a string containing the code to match
1054  :return: `None` if there is no match, otherwise a `tuple` of \
1055  size 3 containing a '(', a single `list` which contains an \
1056  instance of classes that have matched and a ')', or a `tuple` \
1057  of size 2 containing a '*' and an instance of classes that \
1058  have matched.
1059  :rtype: `NoneType` or ( str, [ MatchedClasses ], str) or ( \
1060  str, :py:class:`fparser.two.Fortran2003.Char_Length`)
1061 
1062  :raises InternalError: if None is passed instead of a \
1063  string. The parent rule should not pass None and the logic in \
1064  this routine relies on a valid string.
1065 
1066  :raises InternalError: if the string passed is <=1 characters \
1067  long. The parent rule passing this string should ensure the \
1068  string is at least 2 characters long and the logic in this \
1069  routine relies on this. The reason there is a minimum of two \
1070  is that the pattern '*n' where 'n' is a number is the smallest \
1071  valid pattern. The other valid pattern must have at least a \
1072  name with one character surrounded by brackets e.g. '(x)' so \
1073  should be at least 3 characters long.
1074 
1075  """
1076  if string is None:
1077  raise InternalError(
1078  "String argument in class Kind_Selector method match() " "is None."
1079  )
1080  if len(string) <= 1:
1081  raise InternalError(
1082  "String argument '{0}' in class Kind_Selector method "
1083  "match() is too short to be valid.".format(string)
1084  )
1085 
1086  # remove any leading or trailing white space
1087  string = string.strip()
1088 
1089  if string[0] + string[-1] != "()":
1090  # must be the '*n' extension
1091  if not string.startswith("*"):
1092  return None
1093  return "*", Char_Length(string[1:].lstrip())
1094  # remove left and right brackets and subsequently any leading
1095  # or trailing spaces
1096  string = string[1:-1].strip()
1097  # check for optional 'kind='
1098  if len(string) > 5:
1099  # string is long enough to potentially contain 'kind=...'
1100  if string[:4].upper() == "KIND" and string[4:].lstrip()[0] == "=":
1101  # found 'kind=' so strip it out, including any leading spaces
1102  string = string[4:].lstrip()[1:].lstrip()
1103  return "(", Scalar_Int_Initialization_Expr(string), ")"
1104 
1105  def tostr(self):
1106  """
1107  :return: this kind_selector as a string
1108  :rtype: str
1109  """
1110  if len(self.items) == 2:
1111  result = "{0[0]}{0[1]}".format(self.items)
1112  elif len(self.items) == 3:
1113  result = "{0[0]}KIND = {0[1]}{0[2]}".format(self.items)
1114  else:
1115  raise InternalError(
1116  "Class Kind_Selector method tostr() has '{0}' items, "
1117  "but expecting 2 or 3.".format(len(self.items))
1118  )
1119  return result
1120 
1121 
1122 class Signed_Int_Literal_Constant(NumberBase): # R405
1123  """
1124  <signed-int-literal-constant> = [ <sign> ] <int-literal-constant>
1125  """
1126 
1127  # never used because sign is included in pattern
1128  subclass_names = ["Int_Literal_Constant"]
1129 
1130  @staticmethod
1131  def match(string):
1132  return NumberBase.match(pattern.abs_signed_int_literal_constant_named, string)
1133 
1134 
1135 class Int_Literal_Constant(NumberBase): # R406
1136  """
1137  <int-literal-constant> = <digit-string> [ _ <kind-param> ]
1138  """
1139 
1140  subclass_names = []
1141 
1142  @staticmethod
1143  def match(string):
1144  return NumberBase.match(pattern.abs_int_literal_constant_named, string)
1145 
1146 
1147 class Digit_String(NumberBase):
1148  """
1149  <digit-string> = <digit> [ <digit> ]...
1150  """
1151 
1152  subclass_names = []
1153 
1154  @staticmethod
1155  def match(string):
1156  return NumberBase.match(pattern.abs_digit_string_named, string)
1157 
1158 
1159 # R407: <kind-param> = <digit-string> | <scalar-int-constant-name>
1160 # R408: <signed-digit-string> = [ <sign> ] <digit-string>
1161 # R409: <digit-string> = <digit> [ <digit> ]...
1162 # R410: <sign> = + | -
1163 
1164 
1165 class Boz_Literal_Constant(Base): # R411
1166  """
1167  <boz-literal-constant> = <binary-constant>
1168  | <octal-constant>
1169  | <hex-constant>
1170  """
1171 
1172  subclass_names = ["Binary_Constant", "Octal_Constant", "Hex_Constant"]
1173 
1174 
1175 class Binary_Constant(STRINGBase): # R412
1176  """
1177  <binary-constant> = B ' <digit> [ <digit> ]... '
1178  | B \" <digit> [ <digit> ]... \"
1179  """
1180 
1181  subclass_names = []
1182 
1183  @staticmethod
1184  def match(string):
1185  return STRINGBase.match(pattern.abs_binary_constant, string)
1186 
1187 
1188 class Octal_Constant(STRINGBase): # R413
1189  """
1190  <octal-constant> = O ' <digit> [ <digit> ]... '
1191  | O \" <digit> [ <digit> ]... \"
1192  """
1193 
1194  subclass_names = []
1195 
1196  @staticmethod
1197  def match(string):
1198  return STRINGBase.match(pattern.abs_octal_constant, string)
1199 
1200 
1201 class Hex_Constant(STRINGBase): # R414
1202  """
1203  <hex-constant> = Z ' <digit> [ <digit> ]... '
1204  | Z \" <digit> [ <digit> ]... \"
1205  """
1206 
1207  subclass_names = []
1208 
1209  @staticmethod
1210  def match(string):
1211  return STRINGBase.match(pattern.abs_hex_constant, string)
1212 
1213 
1214 # R415: <hex-digit> = <digit> | A | B | C | D | E | F
1215 
1216 
1217 class Signed_Real_Literal_Constant(NumberBase): # R416
1218  """
1219  <signed-real-literal-constant> = [ <sign> ] <real-literal-constant>
1220  """
1221 
1222  subclass_names = ["Real_Literal_Constant"] # never used
1223 
1224  @staticmethod
1225  def match(string):
1226  return NumberBase.match(pattern.abs_signed_real_literal_constant_named, string)
1227 
1228 
1229 class Real_Literal_Constant(NumberBase): # R417
1230  """ """
1231 
1232  subclass_names = []
1233 
1234  @staticmethod
1235  def match(string):
1236  return NumberBase.match(pattern.abs_real_literal_constant_named, string)
1237 
1238 
1239 # R418: <significand> = <digit-string> . [ <digit-string> ] | . <digit-string>
1240 # R419: <exponent-letter> = E | D
1241 # R420: <exponent> = <signed-digit-string>
1242 
1243 
1244 class Complex_Literal_Constant(Base): # R421
1245  """
1246  <complex-literal-constant> = ( <real-part>, <imag-part> )
1247  """
1248 
1249  subclass_names = []
1250  use_names = ["Real_Part", "Imag_Part"]
1251 
1252  @staticmethod
1253  def match(string):
1254  if not string or string[0] + string[-1] != "()":
1255  return
1256  if not pattern.abs_complex_literal_constant.match(string):
1257  return
1258  r, i = string[1:-1].split(",")
1259  return Real_Part(r.strip()), Imag_Part(i.strip())
1260 
1261  def tostr(self):
1262  return "(%s, %s)" % tuple(self.items)
1263 
1264 
1265 class Real_Part(Base): # R422
1266  """
1267  <real-part> = <signed-int-literal-constant>
1268  | <signed-real-literal-constant>
1269  | <named-constant>
1270  """
1271 
1272  subclass_names = [
1273  "Signed_Int_Literal_Constant",
1274  "Signed_Real_Literal_Constant",
1275  "Named_Constant",
1276  ]
1277 
1278 
1279 class Imag_Part(Base): # R423
1280  """
1281  <imag-part> = <real-part>
1282  """
1283 
1284  subclass_names = [
1285  "Signed_Int_Literal_Constant",
1286  "Signed_Real_Literal_Constant",
1287  "Named_Constant",
1288  ]
1289 
1290 
1291 class Char_Selector(Base): # R424
1292  """
1293  <char-selector> = <length-selector>
1294  | ( LEN = <type-param-value> ,
1295  KIND = <scalar-int-initialization-expr> )
1296  | ( <type-param-value> ,
1297  [ KIND = ] <scalar-int-initialization-expr> )
1298  | ( KIND = <scalar-int-initialization-expr>
1299  [ , LEN = <type-param-value> ] )
1300  """
1301 
1302  subclass_names = ["Length_Selector"]
1303  use_names = ["Type_Param_Value", "Scalar_Int_Initialization_Expr"]
1304 
1305  @staticmethod
1306  def match(string):
1307  if string[0] + string[-1] != "()":
1308  return
1309  line, repmap = string_replace_map(string[1:-1].strip())
1310  if line[:3].upper() == "LEN" and line[3:].lstrip().startswith("="):
1311  line = line[3:].lstrip()
1312  line = line[1:].lstrip()
1313  i = line.find(",")
1314  if i == -1:
1315  return
1316  v = line[:i].rstrip()
1317  line = line[i + 1 :].lstrip()
1318  if line[:4].upper() != "KIND":
1319  return
1320  line = line[4:].lstrip()
1321  if not line.startswith("="):
1322  return
1323  line = line[1:].lstrip()
1324  v = repmap(v)
1325  line = repmap(line)
1326  return Type_Param_Value(v), Scalar_Int_Initialization_Expr(line)
1327  elif line[:4].upper() == "KIND" and line[4:].lstrip().startswith("="):
1328  line = line[4:].lstrip()
1329  line = line[1:].lstrip()
1330  i = line.find(",")
1331  if i == -1:
1332  return None, Scalar_Int_Initialization_Expr(line)
1333  v = line[i + 1 :].lstrip()
1334  line = line[:i].rstrip()
1335  if v[:3].upper() != "LEN":
1336  return
1337  v = v[3:].lstrip()
1338  if not v.startswith("="):
1339  return
1340  v = v[1:].lstrip()
1341  return Type_Param_Value(v), Scalar_Int_Initialization_Expr(line)
1342  else:
1343  i = line.find(",")
1344  if i == -1:
1345  return
1346  v = line[:i].rstrip()
1347  line = line[i + 1 :].lstrip()
1348  if line[:4].upper() == "KIND" and line[4:].lstrip().startswith("="):
1349  line = line[4:].lstrip()
1350  line = line[1:].lstrip()
1351  return Type_Param_Value(v), Scalar_Int_Initialization_Expr(line)
1352  return None
1353 
1354  def tostr(self):
1355  if self.items[0] is None:
1356  return "(KIND = %s)" % (self.items[1])
1357  return "(LEN = %s, KIND = %s)" % (self.items[0], self.items[1])
1358 
1359 
1360 class Length_Selector(Base): # R425
1361  """
1362  <length -selector> = ( [ LEN = ] <type-param-value> )
1363  | * <char-length> [ , ]
1364  """
1365 
1366  subclass_names = []
1367  use_names = ["Type_Param_Value", "Char_Length"]
1368 
1369  @staticmethod
1370  def match(string):
1371  if string[0] + string[-1] == "()":
1372  line = string[1:-1].strip()
1373  if line[:3].upper() == "LEN" and line[3:].lstrip().startswith("="):
1374  line = line[3:].lstrip()
1375  line = line[1:].lstrip()
1376  return "(", Type_Param_Value(line), ")"
1377  if not string.startswith("*"):
1378  return
1379  line = string[1:].lstrip()
1380  if string[-1] == ",":
1381  line = line[:-1].rstrip()
1382  return "*", Char_Length(line)
1383 
1384  def tostr(self):
1385  if len(self.items) == 2:
1386  return "%s%s" % tuple(self.items)
1387  return "%sLEN = %s%s" % tuple(self.items)
1388 
1389 
1390 class Char_Length(BracketBase): # R426
1391  """
1392  <char-length> = ( <type-param-value> )
1393  | <scalar-int-literal-constant>
1394  """
1395 
1396  subclass_names = ["Scalar_Int_Literal_Constant"]
1397  use_names = ["Type_Param_Value"]
1398 
1399  @staticmethod
1400  def match(string):
1401  return BracketBase.match("()", Type_Param_Value, string)
1402 
1403 
1404 class Char_Literal_Constant(Base): # pylint: disable=invalid-name
1405  """
1406  Fortran 2003 rule R427
1407 
1408  char-literal-constant is [ kind-param _ ] ' rep-char '
1409  or [ kind-param _ ] " rep-char "
1410  """
1411 
1412  subclass_names = []
1413  rep = pattern.char_literal_constant
1414 
1415  @staticmethod
1416  def match(string):
1417  """Implements the matching for a Char_Literal_Constant. For example
1418 
1419  "hello"
1420  'hello'
1421  nondefaultcharset_"nondefaultchars"
1422 
1423  There is an associated constraint C422: "The value of
1424  kind-param shall specify a representation method that exists
1425  on the processor." However, this cannot be validated by
1426  fparser so no checks are performed.
1427 
1428  :param str string: a string containing the code to match.
1429  :return: `None` if there is no match, otherwise a `tuple` of
1430  size 2 containing the character constant and the kind
1431  value as strings.
1432  :rtype: `NoneType` or (`str`, `NoneType`) or (`str`, `str`)
1433 
1434  """
1435  if not string:
1436  return None
1437  strip_string = string.strip()
1438  if not strip_string:
1439  # the string is empty or only contains blank space
1440  return None
1441  if strip_string[-1] not in "\"'":
1442  return None
1443  if strip_string[-1] == '"':
1444  abs_a_n_char_literal_constant_named = (
1445  pattern.abs_a_n_char_literal_constant_named2
1446  )
1447  else:
1448  abs_a_n_char_literal_constant_named = (
1449  pattern.abs_a_n_char_literal_constant_named1
1450  )
1451  line, repmap = string_replace_map(strip_string)
1452  match = abs_a_n_char_literal_constant_named.match(line)
1453  if not match:
1454  return None
1455  kind_param = match.group("kind_param")
1456  line = match.group("value")
1457  line = repmap(line)
1458  return line, kind_param
1459 
1460  def tostr(self):
1461  """
1462  :return: this Char_Literal_Constant as a string.
1463  :rtype: str
1464 
1465  :raises InternalError: if the internal items list variable is \
1466  not the expected size.
1467  :raises InternalError: if the first element of the internal \
1468  items list is None or is an empty string.
1469  """
1470  if len(self.items) != 2:
1471  raise InternalError(
1472  "Class Char_Literal_Constant method tostr() has '{0}' items, "
1473  "but expecting 2.".format(len(self.items))
1474  )
1475  if not self.items[0]:
1476  # items[0] is the value of the constant so is required. It
1477  # also can't be empty as it needs to include the
1478  # surrounding quotes to be valid
1479  raise InternalError(
1480  "Class Char_Literal_Constant method tostr(). 'Items' entry 0 "
1481  "should not be empty"
1482  )
1483  char_str = str(self.items[0])
1484  if not self.items[1]:
1485  return char_str
1486  # The character constant has a kind specifier
1487  kind_str = str(self.items[1])
1488  return f"{kind_str}_{char_str}"
1489 
1490 
1491 class Logical_Literal_Constant(NumberBase): # R428
1492  """
1493  <logical-literal-constant> = .TRUE. [ _ <kind-param> ]
1494  | .FALSE. [ _ <kind-param> ]
1495  """
1496 
1497  subclass_names = []
1498 
1499  @staticmethod
1500  def match(string):
1501  return NumberBase.match(pattern.abs_logical_literal_constant_named, string)
1502 
1503 
1504 class Derived_Type_Def(BlockBase): # R429
1505  """
1506  <derived-type-def> = <derived-type-stmt>
1507  [ <type-param-def-stmt> ]...
1508  [ <private-or-sequence> ]...
1509  [ <component-part> ]
1510  [ <type-bound-procedure-part> ]
1511  <end-type-stmt>
1512  """
1513 
1514  subclass_names = []
1515  use_names = [
1516  "Derived_Type_Stmt",
1517  "Type_Param_Def_Stmt",
1518  "Private_Or_Sequence",
1519  "Component_Part",
1520  "Type_Bound_Procedure_Part",
1521  "End_Type_Stmt",
1522  ]
1523 
1524  @staticmethod
1525  def match(reader):
1526  return BlockBase.match(
1527  Derived_Type_Stmt,
1528  [
1529  Type_Param_Def_Stmt,
1530  Private_Or_Sequence,
1531  Component_Part,
1532  Type_Bound_Procedure_Part,
1533  ],
1534  End_Type_Stmt,
1535  reader,
1536  match_names=True, # C431
1537  )
1538 
1539 
1540 class Derived_Type_Stmt(StmtBase): # pylint: disable=invalid-name
1541  """
1542  Fortran 2003 rule R430
1543 
1544  derived-type-stmt is TYPE [ [ , type-attr-spec-list ] :: ]
1545  type-name [ ( type-param-name-list ) ]
1546 
1547  """
1548 
1549  subclass_names = []
1550  use_names = ["Type_Attr_Spec_List", "Type_Name", "Type_Param_Name_List"]
1551 
1552  @staticmethod
1553  def match(string):
1554  """Implements the matching for a Derived Type Statement.
1555 
1556  :param str string: a string containing the code to match
1557  :return: `None` if there is no match, otherwise a `tuple` of \
1558  size 3 containing an `Attribute_Spec_List` (or `None` if \
1559  there isn't one), the name of the type (in a `Name` \
1560  class) and a `Parameter_Name_List` (or `None` is there \
1561  isn't one).
1562  :rtype: ( `Type_Attr_Spec_List` or `None`, `Name`, \
1563  `Type_Param_Name_List` or `None` ) or `None`
1564 
1565  """
1566  string_strip = string.strip()
1567  if string_strip[:4].upper() != "TYPE":
1568  return None
1569  line = string_strip[4:].lstrip()
1570  position = line.find("::")
1571  attr_specs = None
1572  if position != -1:
1573  if line.startswith(","):
1574  lstrip = line[1:position].strip()
1575  if not lstrip:
1576  # There is no content after the "," and before the
1577  # "::"
1578  return None
1579  attr_specs = Type_Attr_Spec_List(lstrip)
1580  elif line[:position].strip():
1581  # There is invalid content between and 'TYPE' and '::'
1582  return None
1583  line = line[position + 2 :].lstrip()
1584  match = pattern.name.match(line)
1585  if not match:
1586  # There is no content after the "TYPE" or the "::"
1587  return None
1588  name = Type_Name(match.group())
1589  line = line[match.end() :].lstrip()
1590  if not line:
1591  return attr_specs, name, None
1592  if line[0] + line[-1] != "()":
1593  return None
1594  return attr_specs, name, Type_Param_Name_List(line[1:-1].strip())
1595 
1596  def tostr(self):
1597  """
1598  :return: this derived type statement as a string
1599  :rtype: str
1600  :raises InternalError: if items array is not the expected size
1601  :raises InternalError: if items array[1] has no content
1602 
1603  """
1604  if len(self.items) != 3:
1605  raise InternalError(
1606  "Derived_Type_Stmt.tostr(). 'items' should be of size 3 but "
1607  "found '{0}'.".format(len(self.items))
1608  )
1609  if not self.items[1]:
1610  raise InternalError(
1611  "Derived_Type_Stmt.tostr(). 'items[1]' should be a Name "
1612  "instance containing the derived type name but it is empty"
1613  )
1614  string = "TYPE"
1615  if self.items[0]:
1616  string += ", {0} :: {1}".format(self.items[0], self.items[1])
1617  else:
1618  string += " :: {0}".format(self.items[1])
1619  if self.items[2]:
1620  string += "({0})".format(self.items[2])
1621  return string
1622 
1623  def get_start_name(self):
1624  """
1625  :return: this derived type statement's name as a string
1626  :rtype: str
1627 
1628  """
1629  return self.items[1].string
1630 
1631 
1632 class Type_Name(Name): # C424
1633  """
1634  <type-name> = <name>
1635  <type-name> shall not be DOUBLEPRECISION or the name of intrinsic type
1636  """
1637 
1638  subclass_names = []
1639  use_names = []
1640 
1641  @staticmethod
1642  def match(string):
1643  if pattern.abs_intrinsic_type_name.match(string):
1644  return
1645  return Name.match(string)
1646 
1647 
1648 class Type_Attr_Spec(Base): # R431
1649  """
1650  <type-attr-spec> = <access-spec>
1651  | EXTENDS ( <parent-type-name> )
1652  | ABSTRACT
1653  | BIND (C)
1654  """
1655 
1656  subclass_names = ["Access_Spec", "Language_Binding_Spec"][:-1]
1657  use_names = ["Parent_Type_Name"]
1658 
1659  @staticmethod
1660  def match(string):
1661  if len(string) == 8 and string.upper() == "ABSTRACT":
1662  return "ABSTRACT", None
1663  if string[:4].upper() == "BIND":
1664  line = string[4:].lstrip()
1665  if not line or line[0] + line[-1] != "()":
1666  return
1667  line = line[1:-1].strip()
1668  if line.upper() == "C":
1669  return "BIND", "C"
1670  elif string[:7].upper() == "EXTENDS":
1671  line = string[7:].lstrip()
1672  if not line or line[0] + line[-1] != "()":
1673  return
1674  return "EXTENDS", Parent_Type_Name(line[1:-1].strip())
1675 
1676  def tostr(self):
1677  if self.items[1] is None:
1678  return "%s" % (self.items[0])
1679  return "%s(%s)" % (self.items)
1680 
1681 
1682 class Private_Or_Sequence(Base): # R432
1683  """
1684  <private-or-sequence> = <private-components-stmt>
1685  | <sequence-stmt>
1686  """
1687 
1688  subclass_names = ["Private_Components_Stmt", "Sequence_Stmt"]
1689 
1690 
1691 class End_Type_Stmt(EndStmtBase): # R433
1692  """
1693  <end-type-stmt> = END TYPE [ <type-name> ]
1694  """
1695 
1696  subclass_names = []
1697  use_names = ["Type_Name"]
1698 
1699  @staticmethod
1700  def match(string):
1701  return EndStmtBase.match("TYPE", Type_Name, string, require_stmt_type=True)
1702 
1703 
1704 class Sequence_Stmt(STRINGBase): # R434
1705  """
1706  <sequence-stmt> = SEQUENCE
1707  """
1708 
1709  subclass_names = []
1710 
1711  @staticmethod
1712  def match(string):
1713  return STRINGBase.match("SEQUENCE", string)
1714 
1715 
1716 class Type_Param_Def_Stmt(StmtBase): # R435
1717  """
1718  <type-param-def-stmt> = INTEGER [ <kind-selector> ] ,
1719  <type-param-attr-spec> :: <type-param-decl-list>
1720  """
1721 
1722  subclass_names = []
1723  use_names = ["Kind_Selector", "Type_Param_Attr_Spec", "Type_Param_Decl_List"]
1724 
1725  @staticmethod
1726  def match(string):
1727  if string[:7].upper() != "INTEGER":
1728  return
1729  line, repmap = string_replace_map(string[7:].lstrip())
1730  if not line:
1731  return
1732  i = line.find(",")
1733  if i == -1:
1734  return
1735  kind_selector = repmap(line[:i].rstrip()) or None
1736  line = repmap(line[i + 1 :].lstrip())
1737  i = line.find("::")
1738  if i == -1:
1739  return
1740  l1 = line[:i].rstrip()
1741  l2 = line[i + 2 :].lstrip()
1742  if not l1 or not l2:
1743  return
1744  if kind_selector:
1745  kind_selector = Kind_Selector(kind_selector)
1746  return kind_selector, Type_Param_Attr_Spec(l1), Type_Param_Decl_List(l2)
1747 
1748  def tostr(self):
1749  s = "INTEGER"
1750  if self.items[0] is not None:
1751  s += "%s, %s :: %s" % tuple(self.items)
1752  else:
1753  s += ", %s :: %s" % tuple(self.items[1:])
1754  return s
1755 
1756 
1757 class Type_Param_Decl(BinaryOpBase): # R436
1758  """
1759  <type-param-decl> = <type-param-name>
1760  [ = <scalar-int-initialization-expr> ]
1761  """
1762 
1763  subclass_names = ["Type_Param_Name"]
1764  use_names = ["Scalar_Int_Initialization_Expr"]
1765 
1766  @staticmethod
1767  def match(string):
1768  if "=" not in string:
1769  return
1770  lhs, rhs = string.split("=", 1)
1771  lhs = lhs.rstrip()
1772  rhs = rhs.lstrip()
1773  if not lhs or not rhs:
1774  return
1775  return Type_Param_Name(lhs), "=", Scalar_Int_Initialization_Expr(rhs)
1776 
1777 
1778 class Type_Param_Attr_Spec(STRINGBase): # R437
1779  """
1780  <type-param-attr-spec> = KIND
1781  | LEN
1782  """
1783 
1784  subclass_names = []
1785 
1786  @staticmethod
1787  def match(string):
1788  return STRINGBase.match(["KIND", "LEN"], string)
1789 
1790 
1791 class Component_Part(BlockBase): # R438
1792  """
1793  <component-part> is [ <component-def-stmt> ]...
1794  """
1795 
1796  subclass_names = []
1797  use_names = ["Component_Def_Stmt"]
1798 
1799  @staticmethod
1800  def match(reader):
1801  content = []
1802  while 1:
1803  try:
1804  obj = Component_Def_Stmt(reader)
1805  except NoMatchError:
1806  obj = None
1807  if obj is None:
1808  break
1809  content.append(obj)
1810  if content:
1811  return (content,)
1812  return None
1813 
1814  def tofortran(self, tab="", isfix=None):
1815  """
1816  Converts this node (and all children) into Fortran.
1817 
1818  :param str tab: white space to prefix to output.
1819  :param bool isfix: whether or not to generate fixed-format output.
1820 
1821  :returns: Fortran code.
1822  :rtype: str
1823 
1824  """
1825  mylist = []
1826  for item in self.content:
1827  mylist.append(item.tofortran(tab=tab, isfix=isfix))
1828  return "\n".join(mylist)
1829 
1830 
1831 class Component_Def_Stmt(Base): # R439
1832  """
1833  <component-def-stmt> is <data-component-def-stmt>
1834  or <proc-component-def-stmt>
1835  """
1836 
1837  subclass_names = ["Data_Component_Def_Stmt", "Proc_Component_Def_Stmt"]
1838 
1839 
1840 class Data_Component_Def_Stmt(Type_Declaration_StmtBase): # R440
1841  """
1842  Fortran 2003 rule 440
1843  <data-component-def-stmt> is <declaration-type-spec> [
1844  [ , <component-attr-spec-list> ] :: ] <component-decl-list>
1845 
1846  Associated constraints are:
1847 
1848  "C436 (R440) No component-attr-spec shall appear more than once in a given
1849  component-def-stmt."
1850  "C437 (R440) A component declared with the CLASS keyword shall have the
1851  ALLOCATABLE or POINTER attribute."
1852  "C438 (R440) If the POINTER attribute is not specified for a component,
1853  the declaration-type-spec in the component-def-stmt shall be CLASS(*)
1854  or shall specify an intrinsic type or a previously defined derived
1855  type."
1856  "C439 (R440) If the POINTER attribute is specified for a component, the
1857  declaration-type-spec in the component-def-stmt shall be CLASS(*) or
1858  shall specify an intrinsic type or any accessible derived type
1859  including the type being defined."
1860  "C440 (R440) If the POINTER or ALLOCATABLE attribute is specified, each
1861  component-array-spec shall be a deferred-shape-spec-list."
1862  "C441 (R440) If neither the POINTER attribute nor the ALLOCATABLE
1863  attribute is specified, each component-array-spec shall be an
1864  explicit-shape-spec-list."
1865  "C443 (R440) A component shall not have both the ALLOCATABLE and the
1866  POINTER attribute."
1867  "C446 (R440) If component-initialization appears, a double-colon separator
1868  shall appear before the component-decl-list."
1869  "C447 (R440) If => appears in component-initialization, POINTER shall
1870  appear in the component-attr-spec-list. If = appears in
1871  component-initialization, POINTER or ALLOCATABLE shall not appear in
1872  the component-attr-spec-list."
1873 
1874  C436-C441, C443, C446-C447 are currently not checked - issue #258.
1875 
1876  """
1877 
1878  subclass_names = []
1879  use_names = [
1880  "Declaration_Type_Spec",
1881  "Component_Attr_Spec_List",
1882  "Component_Decl_List",
1883  ]
1884 
1885  @staticmethod
1886  def match(string):
1887  return Type_Declaration_StmtBase.match(
1888  Declaration_Type_Spec, Component_Attr_Spec_List, Component_Decl_List, string
1889  )
1890 
1891 
1893  """
1894  <dimension-component-attr-spec> = DIMENSION ( <component-array-spec> )
1895  """
1896 
1897  subclass_names = []
1898  use_names = ["Component_Array_Spec"]
1899 
1900  @staticmethod
1901  def match(string):
1902  return CALLBase.match("DIMENSION", Component_Array_Spec, string)
1903 
1904 
1905 class Component_Attr_Spec(STRINGBase): # R441
1906  """
1907  <component-attr-spec> = POINTER
1908  | DIMENSION ( <component-array-spec> )
1909  | ALLOCATABLE
1910  | <access-spec>
1911  """
1912 
1913  subclass_names = ["Access_Spec", "Dimension_Component_Attr_Spec"]
1914  use_names = []
1915  attributes = ["POINTER", "ALLOCATABLE"]
1916 
1917  @classmethod
1918  def match(cls, string):
1919  """Implements the matching for component attribute specifications.
1920 
1921  Note that this is implemented as a `classmethod` (not a
1922  `staticmethod`), using attribute keywords from the list provided
1923  as a class property. This allows expanding this list for
1924  Fortran 2008 without having to reimplement the matching.
1925 
1926  :param str string: the string to match as an attribute.
1927 
1928  :return: None if there is no match, otherwise a 1-tuple \
1929  containing the matched attribute string.
1930  :rtype: NoneType or (str,)
1931 
1932  """
1933  return STRINGBase.match(cls.attributes, string)
1934 
1935 
1936 class Component_Decl(Base): # R442
1937  """
1938  <component-decl> = <component-name> [ ( <component-array-spec> ) ]
1939  [ * <char-length> ] [ <component-initialization> ]
1940  """
1941 
1942  subclass_names = []
1943  use_names = [
1944  "Component_Name",
1945  "Component_Array_Spec",
1946  "Char_Length",
1947  "Component_Initialization",
1948  ]
1949 
1950  @staticmethod
1951  def match(string):
1952  m = pattern.name.match(string)
1953  if m is None:
1954  return
1955  name = Component_Name(m.group())
1956  newline = string[m.end() :].lstrip()
1957  if not newline:
1958  return name, None, None, None
1959  array_spec = None
1960  char_length = None
1961  init = None
1962  if newline.startswith("("):
1963  line, repmap = string_replace_map(newline)
1964  i = line.find(")")
1965  if i == -1:
1966  return
1967  array_spec = Component_Array_Spec(repmap(line[1:i].strip()))
1968  newline = repmap(line[i + 1 :].lstrip())
1969  if newline.startswith("*"):
1970  line, repmap = string_replace_map(newline)
1971  i = line.find("=")
1972  if i != -1:
1973  char_length = repmap(line[1:i].strip())
1974  newline = repmap(newline[i:].lstrip())
1975  else:
1976  char_length = repmap(newline[1:].strip())
1977  newline = ""
1978  char_length = Char_Length(char_length)
1979  if newline.startswith("="):
1980  init = Component_Initialization(newline)
1981  else:
1982  assert newline == "", repr(newline)
1983  return name, array_spec, char_length, init
1984 
1985  def tostr(self):
1986  s = str(self.items[0])
1987  if self.items[1] is not None:
1988  s += "(" + str(self.items[1]) + ")"
1989  if self.items[2] is not None:
1990  s += "*" + str(self.items[2])
1991  if self.items[3] is not None:
1992  s += " " + str(self.items[3])
1993  return s
1994 
1995 
1996 class Component_Array_Spec(Base): # R443
1997  """
1998  <component-array-spec> = <explicit-shape-spec-list>
1999  | <deferred-shape-spec-list>
2000  """
2001 
2002  subclass_names = ["Explicit_Shape_Spec_List", "Deferred_Shape_Spec_List"]
2003 
2004 
2005 class Component_Initialization(Base): # R444
2006  """
2007  <component-initialization> = = <initialization-expr>
2008  | => <null-init>
2009  """
2010 
2011  subclass_names = []
2012  use_names = ["Initialization_Expr", "Null_Init"]
2013 
2014  @staticmethod
2015  def match(string):
2016  if string.startswith("=>"):
2017  return "=>", Null_Init(string[2:].lstrip())
2018  if string.startswith("="):
2019  return "=", Initialization_Expr(string[1:].lstrip())
2020  return None
2021 
2022  def tostr(self):
2023  return "%s %s" % tuple(self.items)
2024 
2025 
2026 class Proc_Component_Def_Stmt(StmtBase): # R445
2027  """
2028  <proc-component-def-stmt> is PROCEDURE ( [ <proc-interface> ] )
2029  , <proc-component-attr-spec-list> :: <proc-decl-list>
2030 
2031  where
2032 
2033  proc-component-attr-spec is POINTER
2034  or PASS [ (arg-name) ]
2035  or NOPASS
2036  or access-spec
2037 
2038  The standard specifies the following constraints:
2039 
2040  "C448 The same proc-component-attr-spec shall not appear more than once
2041  in a given proc-component-def-stmt." Not checked by fparser - #232.
2042 
2043  "C449 POINTER shall appear in each proc-component-attr-spec-list."
2044 
2045  "C450 If the procedure pointer component has an implicit interface or
2046  has no arguments, NOPASS shall be specified." Not checked by
2047  fparser - #232.
2048 
2049  "C451 If PASS (arg-name) appears, the interface shall have a dummy argument
2050  named arg-name." Not checked by fparser - #232.
2051 
2052  "C452 PASS and NOPASS shall not both appear in the same
2053  proc-component-attr-spec-list." Not checked by fparser - #232.
2054  """
2055 
2056  subclass_names = []
2057  use_names = ["Proc_Interface", "Proc_Component_Attr_Spec_List", "Proc_Decl_List"]
2058 
2059  @staticmethod
2060  def match(string):
2061  """
2062  Attempts to match the supplied string with the pattern for a
2063  declaration of a procedure part of a component.
2064 
2065  :param str string: the string to test for a match.
2066 
2067  :returns: None (if no match) or a tuple consisting of the procedure \
2068  interface, the list of attributes and a list of procedure \
2069  names or None.
2070  :rtype: NoneType or \
2071  (:py:class:`fparser.two.Fortran2003.Proc_Interface`, \
2072  :py:class:`fparser.two.Fortran2003.Proc_Component_Attr_Spec_List`,\
2073  :py:class:`fparser.two.Fortran2003.Proc_Decl_List`)
2074  """
2075  if string[:9].upper() != "PROCEDURE":
2076  return None
2077  line, repmap = string_replace_map(string[9:].lstrip())
2078  if not line.startswith("("):
2079  return None
2080  idx = line.find(")")
2081  if idx == -1:
2082  return None
2083  pinterface = repmap(line[: idx + 1])[1:-1].strip() or None
2084  if pinterface:
2085  pinterface = Proc_Interface(pinterface)
2086  line = line[idx + 1 :].lstrip()
2087  if not line.startswith(","):
2088  return None
2089  line = line[1:].strip()
2090  idx = line.find("::")
2091  if idx == -1:
2092  return None
2093  attr_spec_list = Proc_Component_Attr_Spec_List(repmap(line[:idx].rstrip()))
2094  # C449 POINTER must be present in the attribute list
2095  if Proc_Component_Attr_Spec("POINTER") not in attr_spec_list.items:
2096  return None
2097  return (
2098  pinterface,
2099  attr_spec_list,
2100  Proc_Decl_List(repmap(line[idx + 2 :].lstrip())),
2101  )
2102 
2103  def tostr(self):
2104  if self.items[0] is not None:
2105  return "PROCEDURE(%s), %s :: %s" % (self.items)
2106  return "PROCEDURE(), %s :: %s" % (self.items[1:])
2107 
2108 
2110  """
2111  <proc-component-PASS-arg-name> = PASS ( <arg-name> )
2112  """
2113 
2114  subclass_names = []
2115  use_names = ["Arg_Name"]
2116 
2117  @staticmethod
2118  def match(string):
2119  return CALLBase.match("PASS", Arg_Name, string)
2120 
2121 
2122 class Proc_Component_Attr_Spec(STRINGBase): # R446
2123  """
2124  <proc-component-attr-spec> = POINTER
2125  | PASS [ ( <arg-name> ) ]
2126  | NOPASS
2127  | <access-spec>
2128  """
2129 
2130  subclass_names = ["Access_Spec", "Proc_Component_PASS_Arg_Name"]
2131 
2132  @staticmethod
2133  def match(string):
2134  return STRINGBase.match(["POINTER", "PASS", "NOPASS"], string.upper())
2135 
2136 
2137 class Private_Components_Stmt(STRINGBase): # pylint: disable=invalid-name
2138  """
2139  :F03R:`447`::
2140 
2141  Fortran 2003 rule R447
2142  that specifies support for private components statement
2143  within a derived type.
2144 
2145  <private-components-stmt> = PRIVATE
2146  """
2147 
2148  subclass_names = []
2149 
2150  @staticmethod
2151  def match(string):
2152  """
2153  :param str string: Fortran code to check for a match
2154  :return: keyword "PRIVATE" or None if no match is found
2155  :rtype: str or None
2156  """
2157  return StringBase.match("PRIVATE", string.upper())
2158 
2159 
2160 class Type_Bound_Procedure_Part(BlockBase): # pylint: disable=invalid-name
2161  """
2162  :F03R:`448`::
2163 
2164  Fortran 2003 rule R448
2165  that specifies the type-bound procedure part of a derived type.
2166 
2167  <type-bound-procedure-part> = <contains-stmt>
2168  [ <binding-private-stmt> ]
2169  <proc-binding-stmt>
2170  [ <proc-binding-stmt> ]...
2171  """
2172 
2173  subclass_names = []
2174  use_names = ["Contains_Stmt", "Binding_Private_Stmt", "Proc_Binding_Stmt"]
2175 
2176  @staticmethod
2177  def match(reader):
2178  """
2179  :param reader: the Fortran reader containing the line(s) of code \
2180  that we are trying to match
2181  :type reader: :py:class:`fparser.common.readfortran.FortranReaderBase`
2182  :return: code block containing instances of the classes that match \
2183  the syntax of the type-bound procedure part of a derived type.
2184  :rtype: ([`Contains_Stmt`, `Specific_Binding`, `str`, `Name`, \
2185  `Name`]) or `None`
2186  """
2187  return BlockBase.match(
2188  Contains_Stmt, [Binding_Private_Stmt, Proc_Binding_Stmt], None, reader
2189  )
2190 
2191 
2192 class Binding_Private_Stmt(StmtBase, STRINGBase): # pylint: disable=invalid-name
2193  """
2194  :F03R:`449`::
2195 
2196  Fortran 2003 rule R449
2197  for binding private statement within the type-bound procedure
2198  part of a derived type.
2199 
2200  <binding-private-stmt> = PRIVATE
2201  """
2202 
2203  subclass_names = []
2204 
2205  @staticmethod
2206  def match(string):
2207  """
2208  :param str string: Fortran code to check for a match
2209  :return: keyword "PRIVATE" or None if no match is found
2210  :rtype: str or None
2211  """
2212  return StringBase.match("PRIVATE", string.upper())
2213 
2214 
2215 class Proc_Binding_Stmt(Base): # pylint: disable=invalid-name
2216  """
2217  :F03R:`450`::
2218 
2219  Fortran 2003 rule R450
2220  that specifies procedure binding for the type-bound procedures
2221  within a derived type.
2222 
2223  <proc-binding-stmt> = <specific-binding>
2224  | <generic-binding>
2225  | <final-binding>
2226  """
2227 
2228  subclass_names = ["Specific_Binding", "Generic_Binding", "Final_Binding"]
2229 
2230 
2231 class Specific_Binding(StmtBase): # pylint: disable=invalid-name
2232  """:F03R:`451`::
2233 
2234  Fortran 2003 rule R451
2235  that specifies syntax of specific binding for a type-bound
2236  procedure within a derived type.
2237 
2238  <specific-binding> = PROCEDURE [ ( <interface-name> ) ] [
2239  [ , <binding-attr-list> ] :: ] <binding-name> [ => <procedure-name> ]
2240 
2241  The following are associated constraints:
2242 
2243  "C456 (R451) If => procedure-name appears, the double-colon
2244  separator shall appear."
2245 
2246  "C457 (R451) If => procedure-name appears, interface-name shall not
2247  appear."
2248 
2249  "C458 (R451) The procedure-name shall be the name of an accessible
2250  module procedure or an external procedure that has an explicit
2251  interface." Note, this is not checked by fparser.
2252 
2253  """
2254 
2255  subclass_names = []
2256  use_names = [
2257  "Interface_Name",
2258  "Binding_Attr_List",
2259  "Binding_Name",
2260  "Procedure_Name",
2261  ]
2262 
2263  @staticmethod
2264  def match(string):
2265  """
2266  :param str string: Fortran code to check for a match
2267  :return: 5-tuple containing strings and instances of the classes
2268  describing a specific type-bound procedure (optional
2269  interface name, optional binding attribute list,
2270  optional double colon delimiter, mandatory binding
2271  name and optional procedure name)
2272  :rtype: 5-tuple of objects (1 mandatory and 4 optional)
2273  """
2274  # Remove any leading, trailing spaces.
2275  string_strip = string.strip()
2276  if string_strip[:9].upper() != "PROCEDURE":
2277  # There is no 'PROCEDURE' statement.
2278  return None
2279  if len(string_strip) < 11:
2280  # Line is too short to be valid
2281  return None
2282  # Remember whether there was a space after the keyword
2283  space_after = False
2284  if string_strip[9] == " ":
2285  space_after = True
2286  line = string_strip[9:].lstrip()
2287  # Find optional interface name if it exists.
2288  iname = None
2289  if line.startswith("("):
2290  index = line.find(")")
2291  if index == -1:
2292  # Left brace has no corresponding right brace
2293  return None
2294  iname = Interface_Name(line[1:index].strip())
2295  line = line[index + 1 :].lstrip()
2296  # Look for optional double colon and binding attribute list.
2297  dcolon = None
2298  mylist = None
2299  index = line.find("::")
2300  if index != -1:
2301  dcolon = "::"
2302  if line.startswith(","):
2303  mylist = Binding_Attr_List(line[1:index].strip())
2304  elif line[:index].strip():
2305  # There is content between procedure (with optional
2306  # interface) and :: that does not start with a ','
2307  # which is a syntax error.
2308  return None
2309  line = line[index + 2 :].lstrip()
2310  if not iname and not dcolon:
2311  # there is no interface name or double colon between the
2312  # keyword and the binding name. Therefore we expect a
2313  # space between the two.
2314  if not space_after:
2315  # No space was found so return to indicate an
2316  # error.
2317  return None
2318  # Find optional procedure name.
2319  index = line.find("=>")
2320  pname = None
2321  if index != -1:
2322  pname = Procedure_Name(line[index + 2 :].lstrip())
2323  line = line[:index].rstrip()
2324  if not dcolon:
2325  # Constraint C456 requires '::' if there is a
2326  # procedure-name.
2327  return None
2328  if iname and pname:
2329  # Constraint C457 disallows interface-name if there is a
2330  # procedure-name.
2331  return None
2332  # Return class arguments.
2333  return iname, mylist, dcolon, Binding_Name(line), pname
2334 
2335  def tostr(self):
2336  """
2337  :return: parsed representation of a specific type-bound procedure
2338  :rtype: `str`
2339 
2340  """
2341  if len(self.items) != 5:
2342  raise InternalError(
2343  "Class Specific_Binding method tostr() has '{0}' items, "
2344  "but expecting 5.".format(len(self.items))
2345  )
2346 
2347  stmt = "PROCEDURE"
2348  # Add optional interface name
2349  if self.items[0]:
2350  stmt += "({0})".format(self.items[0])
2351  # Add optional double colon and binding attribute list
2352  # (if the list is present)
2353  if self.items[1] and self.items[2]:
2354  stmt += ", {0} {1}".format(self.items[1], self.items[2])
2355  elif not self.items[1] and self.items[2]:
2356  stmt += " {0}".format(self.items[2])
2357  # Add mandatory Binding_Name
2358  stmt += " {0}".format(self.items[3])
2359  # Add optional procedure name
2360  if self.items[4]:
2361  stmt += " => {0}".format(self.items[4])
2362  return stmt
2363 
2364 
2365 class Binding_PASS_Arg_Name(CALLBase):
2366  # pylint: disable=invalid-name
2367  """
2368  :F03R:`453_help`::
2369 
2370  Fortran 2003 helper rule (for R453)
2371  that specifies syntax of passed-object dummy argument for a
2372  specific type-bound procedure.
2373 
2374  <binding-PASS-arg-name> = PASS ( <arg-name> )
2375  """
2376  subclass_names = []
2377  use_names = ["Arg_Name"]
2378 
2379  @staticmethod
2380  def match(string):
2381  """
2382  :param str string: Fortran code to check for a match
2383  :return: keyword "PASS" with the name of a passed-object
2384  dummy argument or nothing if no match is found
2385  :rtype: str
2386  """
2387  return CALLBase.match("PASS", Arg_Name, string)
2388 
2389 
2390 class Generic_Binding(StmtBase):
2391  # pylint: disable=invalid-name
2392  """
2393  :F03R:`452`::
2394 
2395  Fortran 2003 rule R452
2396  that specifies syntax of generic binding for a type-bound
2397  procedure within a derived type.
2398 
2399  <generic-binding> = GENERIC [ , <access-spec> ] ::
2400  <generic-spec> => <binding-name-list>
2401  """
2402  subclass_names = []
2403  use_names = ["Access_Spec", "Generic_Spec", "Binding_Name_List"]
2404 
2405  @staticmethod
2406  def match(string):
2407  """
2408  :param str string: Fortran code to check for a match
2409  :return: 3-tuple containing strings and instances of the
2410  classes describing a generic type-bound procedure
2411  (optional access specifier, mandatory generic
2412  identifier and mandatory binding name list)
2413  :rtype: 3-tuple of objects (2 mandatory and 1 optional)
2414  """
2415  # Incorrect 'GENERIC' statement
2416  if string[:7].upper() != "GENERIC":
2417  return
2418  line = string[7:].lstrip()
2419  i = line.find("::")
2420  # No mandatory double colon
2421  if i == -1:
2422  return
2423  aspec = None
2424  # Return optional access specifier (PRIVATE or PUBLIC)
2425  if line.startswith(","):
2426  aspec = Access_Spec(line[1:i].strip())
2427  line = line[i + 2 :].lstrip()
2428  i = line.find("=>")
2429  if i == -1:
2430  return
2431  # Return mandatory Generic_Spec and Binding_Name_List
2432  return (
2433  aspec,
2434  Generic_Spec(line[:i].rstrip()),
2435  Binding_Name_List(line[i + 3 :].lstrip()),
2436  )
2437 
2438  def tostr(self):
2439  """
2440  :return: parsed representation of a "GENERIC" type-bound procedure
2441  :rtype: str
2442  """
2443  if self.items[0] is None:
2444  return "GENERIC :: %s => %s" % (self.items[1:])
2445  return "GENERIC, %s :: %s => %s" % (self.items)
2446 
2447 
2448 class Binding_Attr(STRINGBase): # pylint: disable=invalid-name
2449 
2450  """
2451  :F03R:`453`::
2452 
2453  Fortran 2003 rule R453
2454  that specifies syntax of allowed binding attributes for a
2455  specific type-bound procedure binding.
2456 
2457  <binding-attr> = PASS [ ( <arg-name> ) ]
2458  | NOPASS
2459  | NON_OVERRIDABLE
2460  | DEFERRED
2461  | <access-spec>
2462  """
2463 
2464  subclass_names = ["Access_Spec", "Binding_PASS_Arg_Name"]
2465 
2466  @staticmethod
2467  def match(string):
2468  """
2469  :return: keywords for allowed binding attributes or
2470  nothing if no match is found
2471  :rtype: str
2472  """
2473  return STRINGBase.match(
2474  ["PASS", "NOPASS", "NON_OVERRIDABLE", "DEFERRED"], string
2475  )
2476 
2477 
2478 class Final_Binding(StmtBase, WORDClsBase): # pylint: disable=invalid-name
2479 
2480  """
2481  :F03R:`454`::
2482 
2483  Fortran 2003 rule R454
2484  that specifies syntax of final binding for a type-bound
2485  procedure within a derived type.
2486 
2487  <final-binding> = FINAL [ :: ] <final-subroutine-name-list>
2488  """
2489 
2490  subclass_names = []
2491  use_names = ["Final_Subroutine_Name_List"]
2492 
2493  @staticmethod
2494  def match(string):
2495  """
2496  :return: keyword "FINAL" with the list of "FINAL" type-bound
2497  procedures or nothing if no match is found
2498  :rtype: str
2499  """
2500  return WORDClsBase.match(
2501  "FINAL", Final_Subroutine_Name_List, string, colons=True, require_cls=True
2502  )
2503 
2504  # String representation with optional double colons included
2505  tostr = WORDClsBase.tostr_a
2506 
2507 
2508 class Derived_Type_Spec(CallBase): # R455
2509  """
2510  <derived-type-spec> = <type-name> [ ( <type-param-spec-list> ) ]
2511  """
2512 
2513  subclass_names = ["Type_Name"]
2514  use_names = ["Type_Param_Spec_List"]
2515 
2516  @staticmethod
2517  def match(string):
2518  return CallBase.match(Type_Name, Type_Param_Spec_List, string)
2519 
2520 
2521 class Type_Param_Spec(KeywordValueBase): # R456
2522  """
2523  <type-param-spec> = [ <keyword> = ] <type-param-value>
2524  """
2525 
2526  subclass_names = ["Type_Param_Value"]
2527  use_names = ["Keyword"]
2528 
2529  @staticmethod
2530  def match(string):
2531  return KeywordValueBase.match(Keyword, Type_Param_Value, string)
2532 
2533 
2534 class Structure_Constructor(CallBase): # R457
2535  """
2536  <structure-constructor> = <derived-type-spec> ( [ <component-spec-list> ] )
2537  """
2538 
2539  subclass_names = []
2540  use_names = ["Derived_Type_Spec", "Component_Spec_List"]
2541 
2542  @staticmethod
2543  def match(string):
2544  return CallBase.match(Derived_Type_Spec, Component_Spec_List, string)
2545 
2546 
2547 class Component_Spec(KeywordValueBase): # R458
2548  """
2549  <component-spec> = [ <keyword> = ] <component-data-source>
2550  """
2551 
2552  subclass_names = ["Component_Data_Source"]
2553  use_names = ["Keyword"]
2554 
2555  @staticmethod
2556  def match(string):
2557  return KeywordValueBase.match(Keyword, Component_Data_Source, string)
2558 
2559 
2560 class Component_Data_Source(Base): # R459
2561  """
2562  <component-data-source> = <expr>
2563  | <data-target>
2564  | <proc-target>
2565  """
2566 
2567  subclass_names = ["Proc_Target", "Data_Target", "Expr"]
2568 
2569 
2570 class Enum_Def(BlockBase): # R460
2571  """
2572  <enum-def> = <enum-def-stmt>
2573  <enumerator-def-stmt>
2574  [ <enumerator-def-stmt> ]...
2575  <end-enum-stmt>
2576  """
2577 
2578  subclass_names = []
2579  use_names = ["Enum_Def_Stmt", "Enumerator_Def_Stmt", "End_Enum_Stmt"]
2580 
2581  @staticmethod
2582  def match(reader):
2583  return BlockBase.match(
2584  Enum_Def_Stmt, [Enumerator_Def_Stmt], End_Enum_Stmt, reader
2585  )
2586 
2587 
2588 class Enum_Def_Stmt(StmtBase): # R461
2589  """
2590  <enum-def-stmt> = ENUM, BIND(C)
2591  """
2592 
2593  subclass_names = []
2594  use_names = []
2595 
2596  @staticmethod
2597  def match(string):
2598  if string.upper().replace(" ", "") != "ENUM,BIND(C)":
2599  return
2600  return ("ENUM, BIND(C)",)
2601 
2602  def tostr(self):
2603  return "%s" % (self.items[0])
2604 
2605 
2606 class Enumerator_Def_Stmt(StmtBase, WORDClsBase): # R462
2607  """
2608  <enumerator-def-stmt> = ENUMERATOR [ :: ] <enumerator-list>
2609  """
2610 
2611  subclass_names = []
2612  use_names = ["Enumerator_List"]
2613 
2614  @staticmethod
2615  def match(string):
2616  return WORDClsBase.match(
2617  "ENUMERATOR", Enumerator_List, string, colons=True, require_cls=True
2618  )
2619 
2620  tostr = WORDClsBase.tostr_a
2621 
2622 
2623 class Enumerator(BinaryOpBase): # R463
2624  """
2625  <enumerator> = <named-constant> [ = <scalar-int-initialization-expr> ]
2626  """
2627 
2628  subclass_names = ["Named_Constant"]
2629  use_names = ["Scalar_Int_Initialization_Expr"]
2630 
2631  @staticmethod
2632  def match(string):
2633  if "=" not in string:
2634  return
2635  lhs, rhs = string.split("=", 1)
2636  return (
2637  Named_Constant(lhs.rstrip()),
2638  "=",
2639  Scalar_Int_Initialization_Expr(rhs.lstrip()),
2640  )
2641 
2642 
2643 class End_Enum_Stmt(EndStmtBase): # R464
2644  """
2645  <end-enum-stmt> = END ENUM
2646  """
2647 
2648  subclass_names = []
2649 
2650  @staticmethod
2651  def match(string):
2652  return EndStmtBase.match("ENUM", None, string, require_stmt_type=True)
2653 
2654 
2655 class Array_Constructor(BracketBase): # R465
2656  """
2657  <array-constructor> = (/ <ac-spec> /)
2658  | <left-square-bracket> <ac-spec>
2659  <right-square-bracket>
2660 
2661  """
2662 
2663  subclass_names = []
2664  use_names = ["Ac_Spec"]
2665 
2666  @staticmethod
2667  def match(string):
2668  try:
2669  obj = BracketBase.match("(//)", Ac_Spec, string)
2670  except NoMatchError:
2671  obj = None
2672  if obj is None:
2673  obj = BracketBase.match("[]", Ac_Spec, string)
2674  return obj
2675 
2676 
2677 class Ac_Spec(Base): # R466
2678  """
2679  <ac-spec> = <type-spec> ::
2680  | [ <type-spec> :: ] <ac-value-list>
2681  """
2682 
2683  subclass_names = ["Ac_Value_List"]
2684  use_names = ["Type_Spec"]
2685 
2686  @staticmethod
2687  def match(string):
2688  if string.endswith("::"):
2689  return Type_Spec(string[:-2].rstrip()), None
2690  line, repmap = string_replace_map(string)
2691  i = line.find("::")
2692  if i == -1:
2693  return
2694  ts = line[:i].rstrip()
2695  line = line[i + 2 :].lstrip()
2696  ts = repmap(ts)
2697  line = repmap(line)
2698  return Type_Spec(ts), Ac_Value_List(line)
2699 
2700  def tostr(self):
2701  if self.items[0] is None:
2702  return str(self.items[1])
2703  if self.items[1] is None:
2704  return str(self.items[0]) + " ::"
2705  return "%s :: %s" % self.items
2706 
2707 
2708 # R467: <left-square-bracket> = [
2709 # R468: <right-square-bracket> = ]
2710 
2711 
2712 class Ac_Value(Base): # R469
2713  """
2714  <ac-value> = <expr>
2715  | <ac-implied-do>
2716  """
2717 
2718  subclass_names = ["Ac_Implied_Do", "Expr"]
2719 
2720 
2721 class Ac_Implied_Do(Base):
2722  """
2723  Fortran2003 rule R470.
2724  Describes the form of implicit do loop used within an array constructor.
2725 
2726  ac-implied-do is ( ac-value-list , ac-implied-do-control )
2727 
2728  Subject to the following constraint:
2729 
2730  "C497 (R470) The ac-do-variable of an ac-implied-do that is in another
2731  ac-implied-do shall not appear as the ac-do-variable of the
2732  containing ac-implied-do."
2733 
2734  C497 is currently not checked - issue #257.
2735 
2736  """
2737 
2738  subclass_names = []
2739  use_names = ["Ac_Value_List", "Ac_Implied_Do_Control"]
2740 
2741  @staticmethod
2742  def match(string):
2743  if string[0] + string[-1] != "()":
2744  return
2745  line, repmap = string_replace_map(string[1:-1].strip())
2746  i = line.rfind("=")
2747  if i == -1:
2748  return
2749  j = line[:i].rfind(",")
2750  assert j != -1
2751  s1 = repmap(line[:j].rstrip())
2752  s2 = repmap(line[j + 1 :].lstrip())
2753  return Ac_Value_List(s1), Ac_Implied_Do_Control(s2)
2754 
2755  def tostr(self):
2756  return "(%s, %s)" % tuple(self.items)
2757 
2758 
2760  """
2761  Fortran2003 rule R471.
2762  Specifies the syntax for the control of an implicit loop within an
2763  array constructor.
2764 
2765  ac-implied-do-control is ac-do-variable = scalar-int-expr,
2766  scalar-int-expr [ , scalar-int-expr ]
2767 
2768  where (R472) ac-do-variable is scalar-int-variable
2769 
2770  """
2771 
2772  subclass_names = []
2773  use_names = ["Ac_Do_Variable", "Scalar_Int_Expr"]
2774 
2775  @staticmethod
2776  def match(string):
2777  """ Attempts to match the supplied string with the pattern for
2778  implied-do control.
2779 
2780  :param str string: the string to test for a match.
2781 
2782  :returns: None if there is no match or a 2-tuple containing the \
2783  do-variable name and the list of integer expressions (for \
2784  start, stop [, step]).
2785  :rtype: NoneType or \
2786  (:py:class:`fparser.two.Fortran2003.Ac_Do_Variable`, list)
2787  """
2788  idx = string.find("=")
2789  if idx == -1:
2790  return None
2791  do_var = string[:idx].rstrip()
2792  line, repmap = string_replace_map(string[idx + 1 :].lstrip())
2793  int_exprns = line.split(",")
2794  if not (2 <= len(int_exprns) <= 3):
2795  return None
2796  exprn_list = [Scalar_Int_Expr(repmap(s.strip())) for s in int_exprns]
2797  return Ac_Do_Variable(do_var), exprn_list
2798 
2799  def tostr(self):
2800  return "%s = %s" % (self.items[0], ", ".join(map(str, self.items[1])))
2801 
2802 
2803 class Ac_Do_Variable(Base):
2804  """
2805  Fortran2003 rule R472.
2806  Specifies the permitted form of an implicit do-loop variable within an
2807  array constructor.
2808 
2809  ac-do-variable is scalar-int-variable
2810  ac-do-variable shall be a named variable
2811 
2812  Subject to the following constraint:
2813 
2814  "C493 (R472) ac-do-variable shall be a named variable."
2815 
2816  C493 is currently not checked - issue #257.
2817 
2818  """
2819 
2820  subclass_names = ["Scalar_Int_Variable"]
2821 
2822 
2823 #
2824 # SECTION 5
2825 #
2826 
2827 
2828 class Type_Declaration_Stmt(Type_Declaration_StmtBase): # R501
2829  """
2830  Fortran 2003 rule 501
2831  <type-declaration-stmt> = <declaration-type-spec> [
2832  [ , <attr-spec> ]... :: ] <entity-decl-list>
2833 
2834  Associated constraints are:
2835 
2836  "C507 (R501) The same attr-spec shall not appear more than once in a given
2837  type-declaration-stmt."
2838  "C509 (R501) An entity declared with the CLASS keyword shall be a dummy
2839  argument or have the ALLOCATABLE or POINTER attribute."
2840  "C510 (R501) An array that has the POINTER or ALLOCATABLE attribute shall
2841  be specified with an array-spec that is a deferred-shape-spec-list."
2842  "C511 (R501) An array-spec for an object-name that is a function result
2843  that does not have the ALLOCATABLE or POINTER attribute shall be an
2844  explicit-shape-spec-list."
2845  "C512 (R501) If the POINTER attribute is specified, the ALLOCATABLE,
2846  TARGET, EXTERNAL, or INTRINSIC attribute shall not be specified."
2847  "C513 (R501) If the TARGET attribute is specified, the POINTER, EXTERNAL,
2848  INTRINSIC, or PARAMETER attribute shall not be specified."
2849  "C514 (R501) The PARAMETER attribute shall not be specified for a dummy
2850  argument, a pointer, an allocatable entity, a function, or an object
2851  in a common block."
2852  "C515 (R501) The INTENT, VALUE, and OPTIONAL attributes may be specified
2853  only for dummy arguments."
2854  "C516 (R501) The INTENT attribute shall not be specified for a dummy
2855  procedure without the POINTER attribute."
2856  "C517 (R501) The SAVE attribute shall not be specified for an object that
2857  is in a common block, a dummy argument, a procedure, a function
2858  result, an automatic data object, or an object with the PARAMETER
2859  attribute."
2860  "C519 (R501) An entity in an entity-decl-list shall not have the EXTERNAL
2861  or INTRINSIC attribute specified unless it is a function."
2862  "C522 (R501) The initialization shall appear if the statement contains a
2863  PARAMETER attribute."
2864  "C523 (R501) If initialization appears, a double-colon separator shall
2865  appear before the entity-decl-list."
2866  "C526 (R501) If the VOLATILE attribute is specified, the PARAMETER,
2867  INTRINSIC, EXTERNAL, or INTENT(IN) attribute shall not be specified."
2868  "C527 (R501) If the VALUE attribute is specified, the PARAMETER, EXTERNAL,
2869  POINTER, ALLOCATABLE, DIMENSION, VOLATILE, INTENT(INOUT), or
2870  INTENT(OUT) attribute shall not be specified."
2871  "C528 (R501) If the VALUE attribute is specified, the length type
2872  parameter values shall be omitted or specified by initialization
2873  expressions."
2874  "C529 (R501) The VALUE attribute shall not be specified for a dummy
2875  procedure."
2876  "C530 (R501) The ALLOCATABLE, POINTER, or OPTIONAL attribute shall not be
2877  specified for adummy argument of a procedure that has
2878  aproc-language-binding-spec."
2879  "C532 (R501) If a language-binding-spec is specified, the entity declared
2880  shall be an interoperable variable."
2881  "C533 (R501) If a language-binding-spec with a NAME= specifier appears,
2882  the entity-decl-list shall consist of a single entity-decl."
2883  "C534 (R503) The PROTECTED attribute is permitted only in the
2884  specification part of a module."
2885  "C535 (R501) The PROTECTED attribute is permitted only for a procedure
2886  pointer or named variable that is not in a common block."
2887  "C536 (R501) If the PROTECTED attribute is specified, the EXTERNAL,
2888  INTRINSIC, or PARAMETER attribute shall not be specified."
2889 
2890  C507, C509-C517, C519, C522-C523, C526-C530, C532-C533, C535-C536 are
2891  currently not checked - issue #259.
2892 
2893  """
2894 
2895  subclass_names = []
2896  use_names = ["Declaration_Type_Spec", "Attr_Spec_List", "Entity_Decl_List"]
2897 
2898  @staticmethod
2899  def get_attr_spec_list_cls():
2900  """Return the type used to match the attr-spec-list
2901 
2902  This method allows to overwrite the type used in :py:meth:`match`
2903  in derived classes
2904  (e.g., :py:class:`fparser.two.Fortran2008.Type_Declaration_Stmt`).
2905 
2906  This cannot be implemented as an attribute because the relevant type
2907  :class:`Attr_Spec_List` is auto-generated at the end of the file
2908  using the :attr:`use_names` property of the class.
2909 
2910  """
2911  return Attr_Spec_List
2912 
2913  @staticmethod
2914  def add_to_symbol_table(result):
2915  """Capture the declared symbols in the symbol table of the current
2916  scoping region
2917 
2918  :param result: the declared type, attributes and entities or None
2919  :type result: `NoneType` or \
2920  (Declaration_Type_Spec, Attr_Spec_List or NoneType, \
2921  Entity_Decl_List)
2922  """
2923  if result:
2924  # We matched a declaration - capture the declared symbols in the
2925  # symbol table of the current scoping region.
2926  table = SYMBOL_TABLES.current_scope
2927 
2928  if table and isinstance(result[0], Intrinsic_Type_Spec):
2929  # We have a definition of symbol(s) of intrinsic type
2930  decl_list = walk(result, Entity_Decl)
2931  for decl in decl_list:
2932  # TODO #201 use an enumeration to specify the primitive
2933  # type rather than a string.
2934  table.add_data_symbol(decl.items[0].string, str(result[0]))
2935  # TODO #201 support symbols that are not of intrinsic type.
2936 
2937  @classmethod
2938  def match(cls, string):
2939  """
2940  Attempts to match the supplied string as a type declaration. If the
2941  match is successful the declared symbols are added to the symbol table
2942  of the current scope (if there is one).
2943 
2944  Note that this is implemented as a class method to allow parameterizing
2945  the type used to match attr-spec-list via :py:meth:`get_attr_spec_list_cls`.
2946 
2947  :param str string: the string to match.
2948 
2949  :returns: 3-tuple containing the matched declaration.
2950  :rtype: (Declaration_Type_Spec, Attr_Spec_List or NoneType, \
2951  Entity_Decl_List)
2952 
2953  """
2954  result = Type_Declaration_StmtBase.match(
2955  Declaration_Type_Spec,
2956  cls.get_attr_spec_list_cls(),
2957  Entity_Decl_List,
2958  string,
2959  )
2960  cls.add_to_symbol_table(result)
2961  return result
2962 
2963  @staticmethod
2964  def match2(string):
2965  line, repmap = string_replace_map(string)
2966  i = line.find("::")
2967  if i != -1:
2968  j = line[:i].find(",")
2969  if j != -1:
2970  i = j
2971  else:
2972  if line[:6].upper() == "DOUBLE":
2973  m = re.search(r"\s[a-z_]", line[6:].lstrip(), re.I)
2974  if m is None:
2975  return
2976  i = m.start() + len(line) - len(line[6:].lstrip())
2977  else:
2978  m = re.search(r"\s[a-z_]", line, re.I)
2979  if m is None:
2980  return
2981  i = m.start()
2982  type_spec = Declaration_Type_Spec(repmap(line[:i].rstrip()))
2983  if type_spec is None:
2984  return
2985  line = line[i:].lstrip()
2986  if line.startswith(","):
2987  i = line.find("::")
2988  if i == -1:
2989  return
2990  attr_specs = Attr_Spec_List(repmap(line[1:i].strip()))
2991  if attr_specs is None:
2992  return
2993  line = line[i:]
2994  else:
2995  attr_specs = None
2996  if line.startswith("::"):
2997  line = line[2:].lstrip()
2998  entity_decls = Entity_Decl_List(repmap(line))
2999  if entity_decls is None:
3000  return
3001  return type_spec, attr_specs, entity_decls
3002 
3003  def tostr(self):
3004  if self.items[1] is None:
3005  return "%s :: %s" % (self.items[0], self.items[2])
3006  else:
3007  return "%s, %s :: %s" % self.items
3008 
3009 
3010 class Declaration_Type_Spec(Base): # R502
3011  """
3012  <declaration-type-spec> = <intrinsic-type-spec>
3013  | TYPE ( <derived-type-spec> )
3014  | CLASS ( <derived-type-spec> )
3015  | CLASS ( * )
3016  """
3017 
3018  subclass_names = ["Intrinsic_Type_Spec"]
3019  use_names = ["Derived_Type_Spec"]
3020 
3021  @staticmethod
3022  def match(string):
3023  """Implements the matching of a declaration type specification.
3024 
3025  :param str string: the reader or string to match as a \
3026  declaration type specification.
3027 
3028  :return: A tuple of size 2 containing a string with the value \
3029  'TYPE' or 'CLASS' and a 'Derived_Type_Spec' instance if there \
3030  is a match or None if not.
3031  :rtype: (str, \
3032  py:class:`fparser.two.Fortran2003.Derived_Type_Spec`,) or \
3033  NoneType
3034 
3035  """
3036  if not string:
3037  return None
3038  if string[-1] != ")":
3039  return None
3040  start = string[:4].upper()
3041  if start == "TYPE":
3042  line = string[4:].lstrip()
3043  if not line.startswith("("):
3044  return None
3045  return "TYPE", Derived_Type_Spec(line[1:-1].strip())
3046  start = string[:5].upper()
3047  if start == "CLASS":
3048  line = string[5:].lstrip()
3049  if not line.startswith("("):
3050  return None
3051  line = line[1:-1].strip()
3052  if line == "*":
3053  return "CLASS", "*"
3054  return "CLASS", Derived_Type_Spec(line)
3055  return None
3056 
3057  def tostr(self):
3058  return "%s(%s)" % self.items
3059 
3060 
3061 class Dimension_Attr_Spec(CALLBase): # R503.d
3062  """
3063  <dimension-attr-spec> = DIMENSION ( <array-spec> )
3064  """
3065 
3066  subclass_names = []
3067  use_names = ["Array_Spec"]
3068 
3069  @staticmethod
3070  def match(string):
3071  return CALLBase.match("DIMENSION", Array_Spec, string)
3072 
3073 
3074 class Intent_Attr_Spec(CALLBase): # R503.f
3075  """
3076  <intent-attr-spec> = INTENT ( <intent-spec> )
3077  """
3078 
3079  subclass_names = []
3080  use_names = ["Intent_Spec"]
3081 
3082  @staticmethod
3083  def match(string):
3084  return CALLBase.match("INTENT", Intent_Spec, string)
3085 
3086 
3087 class Attr_Spec(STRINGBase): # R503
3088  """
3089  <attr-spec> = <access-spec>
3090  | ALLOCATABLE
3091  | ASYNCHRONOUS
3092  | DIMENSION ( <array-spec> )
3093  | EXTERNAL
3094  | INTENT ( <intent-spec> )
3095  | INTRINSIC
3096  | <language-binding-spec>
3097  | OPTIONAL
3098  | PARAMETER
3099  | POINTER
3100  | PROTECTED
3101  | SAVE
3102  | TARGET
3103  | VALUE
3104  | VOLATILE
3105  """
3106 
3107  subclass_names = [
3108  "Access_Spec",
3109  "Language_Binding_Spec",
3110  "Dimension_Attr_Spec",
3111  "Intent_Attr_Spec",
3112  ]
3113  use_names = []
3114 
3115  @staticmethod
3116  def match(string):
3117  return STRINGBase.match(pattern.abs_attr_spec, string)
3118 
3119 
3120 class Entity_Decl(Base): # R504
3121  """
3122  <entity-decl> = <object-name> [ ( <array-spec> ) ]
3123  [ * <char-length> ] [ <initialization> ]
3124  | <function-name> [ * <char-length> ]
3125  """
3126 
3127  subclass_names = []
3128  use_names = [
3129  "Object_Name",
3130  "Array_Spec",
3131  "Char_Length",
3132  "Initialization",
3133  "Function_Name",
3134  ]
3135 
3136  @staticmethod
3137  def match(string, target=False):
3138  m = pattern.name.match(string)
3139  if m is None:
3140  return
3141  name = Name(m.group())
3142  newline = string[m.end() :].lstrip()
3143  if not newline:
3144  return name, None, None, None
3145  array_spec = None
3146  char_length = None
3147  init = None
3148  if newline.startswith("("):
3149  line, repmap = string_replace_map(newline)
3150  i = line.find(")")
3151  if i == -1:
3152  return
3153  array_spec = Array_Spec(repmap(line[1:i].strip()))
3154  newline = repmap(line[i + 1 :].lstrip())
3155  if target:
3156  if newline:
3157  return
3158  return name, array_spec, None, None
3159  if newline.startswith("*"):
3160  line, repmap = string_replace_map(newline)
3161  i = line.find("=")
3162  if i != -1:
3163  char_length = repmap(line[1:i].strip())
3164  newline = repmap(newline[i:].lstrip())
3165  else:
3166  char_length = repmap(newline[1:].strip())
3167  newline = ""
3168  char_length = Char_Length(char_length)
3169  if newline.startswith("="):
3170  init = Initialization(newline)
3171  elif newline:
3172  return
3173  else:
3174  assert newline == "", repr((newline, string))
3175  return name, array_spec, char_length, init
3176 
3177  def tostr(self):
3178  s = str(self.items[0])
3179  if self.items[1] is not None:
3180  s += "(" + str(self.items[1]) + ")"
3181  if self.items[2] is not None:
3182  s += "*" + str(self.items[2])
3183  if self.items[3] is not None:
3184  s += " " + str(self.items[3])
3185  return s
3186 
3187  def get_name(self):
3188  """Provides the entity name as an instance of the :py:class:`Name` class.
3189 
3190  :rtype: :py:class:`Name`
3191  """
3192  return self.items[0]
3193 
3194 
3195 class Object_Name(Base): # R505
3196  """
3197  <object-name> = <name>
3198  """
3199 
3200  subclass_names = ["Name"]
3201 
3202 
3203 class Initialization(Base): # R506
3204  """
3205  <initialization> = = <initialization-expr>
3206  | => <null-init>
3207  """
3208 
3209  subclass_names = []
3210  use_names = ["Initialization_Expr", "Null_Init"]
3211 
3212  @staticmethod
3213  def match(string):
3214  if string.startswith("=>"):
3215  return "=>", Null_Init(string[2:].lstrip())
3216  if string.startswith("="):
3217  return "=", Initialization_Expr(string[1:].lstrip())
3218  return None
3219 
3220  def tostr(self):
3221  return "%s %s" % self.items
3222 
3223 
3224 class Null_Init(STRINGBase): # R507
3225  """
3226  <null-init> = <function-reference>
3227 
3228  <function-reference> shall be a reference to the NULL
3229  intrinsic function with no arguments.
3230  """
3231 
3232  subclass_names = ["Function_Reference"]
3233 
3234  @staticmethod
3235  def match(string):
3236  return STRINGBase.match("NULL", string)
3237 
3238 
3239 class Access_Spec(STRINGBase): # R508
3240  """
3241  :F03R:`508`::
3242  <access-spec> = PUBLIC
3243  | PRIVATE
3244  """
3245 
3246  subclass_names = []
3247 
3248  @staticmethod
3249  def match(string):
3250  return STRINGBase.match(["PUBLIC", "PRIVATE"], string)
3251 
3252 
3253 class Language_Binding_Spec(Base): # R509
3254  """
3255  :F03R:`509`::
3256  <language-binding-spec> = BIND ( C [ ,
3257  NAME = <scalar-char-initialization-expr> ] )
3258  """
3259 
3260  subclass_names = []
3261  use_names = ["Scalar_Char_Initialization_Expr"]
3262 
3263  @staticmethod
3264  def match(string):
3265  start = string[:4].upper()
3266  if start != "BIND":
3267  return
3268  line = string[4:].lstrip()
3269  if not line or line[0] + line[-1] != "()":
3270  return
3271  line = line[1:-1].strip()
3272  if not line:
3273  return
3274  start = line[0].upper()
3275  if start != "C":
3276  return
3277  line = line[1:].lstrip()
3278  if not line:
3279  return (None,)
3280  if not line.startswith(","):
3281  return
3282  line = line[1:].lstrip()
3283  start = line[:4].upper()
3284  if start != "NAME":
3285  return
3286  line = line[4:].lstrip()
3287  if not line.startswith("="):
3288  return
3289  return (Scalar_Char_Initialization_Expr(line[1:].lstrip()),)
3290 
3291  def tostr(self):
3292  if self.items[0] is None:
3293  return "BIND(C)"
3294  return "BIND(C, NAME = %s)" % (self.items[0])
3295 
3296 
3297 class Array_Spec(Base): # R510
3298  """
3299  :F03R:`510`::
3300  <array-spec> = <explicit-shape-spec-list>
3301  | <assumed-shape-spec-list>
3302  | <deferred-shape-spec-list>
3303  | <assumed-size-spec>
3304  """
3305 
3306  subclass_names = [
3307  "Assumed_Size_Spec",
3308  "Explicit_Shape_Spec_List",
3309  "Assumed_Shape_Spec_List",
3310  "Deferred_Shape_Spec_List",
3311  ]
3312 
3313 
3314 class Explicit_Shape_Spec(SeparatorBase): # R511
3315  """
3316  <explicit-shape-spec> = [ <lower-bound> : ] <upper-bound>
3317  """
3318 
3319  subclass_names = []
3320  use_names = ["Lower_Bound", "Upper_Bound"]
3321 
3322  @staticmethod
3323  def match(string):
3324  line, repmap = string_replace_map(string)
3325  if ":" not in line:
3326  return None, Upper_Bound(string)
3327  lower, upper = line.split(":", 1)
3328  lower = lower.rstrip()
3329  upper = upper.lstrip()
3330  if not upper:
3331  return
3332  if not lower:
3333  return
3334  return Lower_Bound(repmap(lower)), Upper_Bound(repmap(upper))
3335 
3336  def tostr(self):
3337  if self.items[0] is None:
3338  return str(self.items[1])
3339  return SeparatorBase.tostr(self)
3340 
3341 
3342 class Lower_Bound(Base): # R512
3343  """
3344  <lower-bound> = <specification-expr>
3345  """
3346 
3347  subclass_names = ["Specification_Expr"]
3348 
3349 
3350 class Upper_Bound(Base): # R513
3351  """
3352  <upper-bound> = <specification-expr>
3353  """
3354 
3355  subclass_names = ["Specification_Expr"]
3356 
3357 
3358 class Assumed_Shape_Spec(SeparatorBase): # R514
3359  """
3360  :F03R:`514`::
3361  <assumed-shape-spec> = [ <lower-bound> ] :
3362  """
3363 
3364  subclass_names = []
3365  use_names = ["Lower_Bound"]
3366 
3367  @staticmethod
3368  def match(string):
3369  return SeparatorBase.match(Lower_Bound, None, string)
3370 
3371 
3372 class Deferred_Shape_Spec(SeparatorBase): # R515
3373  """
3374  :F03R:`515`::
3375  <deferred_shape_spec> = :
3376  """
3377 
3378  subclass_names = []
3379 
3380  @staticmethod
3381  def match(string):
3382  if string == ":":
3383  return None, None
3384  return None
3385 
3386 
3387 class Assumed_Size_Spec(Base): # R516
3388  """
3389  :F03R:`516`::
3390  <assumed-size-spec> = [ <explicit-shape-spec-list> , ]
3391  [ <lower-bound> : ] *
3392  """
3393 
3394  subclass_names = []
3395  use_names = ["Explicit_Shape_Spec_List", "Lower_Bound"]
3396 
3397  @staticmethod
3398  def match(string):
3399  if not string.endswith("*"):
3400  return
3401  line = string[:-1].rstrip()
3402  if not line:
3403  return None, None
3404  if line.endswith(":"):
3405  line, repmap = string_replace_map(line[:-1].rstrip())
3406  i = line.rfind(",")
3407  if i == -1:
3408  return None, Lower_Bound(repmap(line))
3409  return (
3410  Explicit_Shape_Spec_List(repmap(line[:i].rstrip())),
3411  Lower_Bound(repmap(line[i + 1 :].lstrip())),
3412  )
3413  if not line.endswith(","):
3414  return
3415  line = line[:-1].rstrip()
3416  return Explicit_Shape_Spec_List(line), None
3417 
3418  def tostr(self):
3419  s = ""
3420  if self.items[0] is not None:
3421  s += str(self.items[0]) + ", "
3422  if self.items[1] is not None:
3423  s += str(self.items[1]) + " : "
3424  s += "*"
3425  return s
3426 
3427 
3428 class Intent_Spec(STRINGBase): # R517
3429  """
3430  <intent-spec> = IN
3431  | OUT
3432  | INOUT
3433  """
3434 
3435  subclass_names = []
3436 
3437  @staticmethod
3438  def match(string):
3439  return STRINGBase.match(pattern.abs_intent_spec, string)
3440 
3441 
3442 class Access_Stmt(StmtBase, WORDClsBase): # R518
3443  """
3444  :F03R:`518`::
3445  <access-stmt> = <access-spec> [ [ :: ] <access-id-list> ]
3446  """
3447 
3448  subclass_names = []
3449  use_names = ["Access_Spec", "Access_Id_List"]
3450 
3451  @staticmethod
3452  def match(string):
3453  return WORDClsBase.match(
3454  ["PUBLIC", "PRIVATE"],
3455  Access_Id_List,
3456  string,
3457  colons=True,
3458  require_cls=False,
3459  )
3460 
3461  tostr = WORDClsBase.tostr_a
3462 
3463 
3464 class Access_Id(Base): # R519
3465  """
3466  :F03R:`519`::
3467  <access-id> = <use-name>
3468  | <generic-spec>
3469  """
3470 
3471  subclass_names = ["Use_Name", "Generic_Spec"]
3472 
3473 
3475  """
3476  <..> = <object-name> [ ( <deferred-shape-spec-list> ) ]
3477  """
3478 
3479  subclass_names = ["Object_Name"]
3480  use_names = ["Deferred_Shape_Spec_List"]
3481 
3482  @staticmethod
3483  def match(string):
3484  return CallBase.match(
3485  Object_Name, Deferred_Shape_Spec_List, string, require_rhs=True
3486  )
3487 
3488 
3489 class Allocatable_Stmt(StmtBase, WORDClsBase): # R520
3490  """
3491  :F03R:`520`::
3492  <allocateble-stmt> = ALLOCATABLE [ :: ] <object-name> [
3493  ( <deferred-shape-spec-list> ) ] [ , <object-name>
3494  [ ( <deferred-shape-spec-list> ) ] ]...
3495  """
3496 
3497  subclass_names = []
3498  use_names = ["Object_Name_Deferred_Shape_Spec_List_Item_List"]
3499 
3500  @staticmethod
3501  def match(string):
3502  return WORDClsBase.match(
3503  "ALLOCATABLE",
3504  Object_Name_Deferred_Shape_Spec_List_Item_List,
3505  string,
3506  colons=True,
3507  require_cls=True,
3508  )
3509 
3510 
3511 class Asynchronous_Stmt(StmtBase, WORDClsBase): # R521
3512  """
3513  :F03R:`521`::
3514  <asynchronous-stmt> = ASYNCHRONOUS [ :: ] <object-name-list>
3515  """
3516 
3517  subclass_names = []
3518  use_names = ["Object_Name_List"]
3519 
3520  @staticmethod
3521  def match(string):
3522  return WORDClsBase.match(
3523  "ASYNCHRONOUS", Object_Name_List, string, colons=True, require_cls=True
3524  )
3525 
3526 
3527 class Bind_Stmt(StmtBase): # R522
3528  """
3529  :F03R:`522`::
3530  <bind-stmt> = <language-binding-spec> [ :: ] <bind-entity-list>
3531  """
3532 
3533  subclass_names = []
3534  use_names = ["Language_Binding_Spec", "Bind_Entity_List"]
3535 
3536  @staticmethod
3537  def match(string):
3538  i = string.find("::")
3539  if i == -1:
3540  i = string.find(")")
3541  if i == -1:
3542  return
3543  lhs, rhs = string[:i], string[i + 1 :]
3544  else:
3545  lhs, rhs = string.split("::", 1)
3546  lhs = lhs.rstrip()
3547  rhs = rhs.lstrip()
3548  if not lhs or not rhs:
3549  return
3550  return Language_Binding_Spec(lhs), Bind_Entity_List(rhs)
3551 
3552  def tostr(self):
3553  return "%s :: %s" % self.items
3554 
3555 
3556 class Bind_Entity(BracketBase): # R523
3557  """
3558  <bind-entity> = <entity-name>
3559  | / <common-block-name> /
3560  """
3561 
3562  subclass_names = ["Entity_Name"]
3563  use_names = ["Common_Block_Name"]
3564 
3565  @staticmethod
3566  def match(string):
3567  return BracketBase.match("//", Common_Block_Name, string)
3568 
3569 
3570 class Data_Stmt(StmtBase): # R524
3571  """
3572  :F03R:524::
3573  <data-stmt> = DATA <data-stmt-set> [ [ , ] <data-stmt-set> ]...
3574  """
3575 
3576  subclass_names = []
3577  use_names = ["Data_Stmt_Set"]
3578 
3579  @staticmethod
3580  def match(string):
3581  if string[:4].upper() != "DATA":
3582  return
3583  line, repmap = string_replace_map(string[4:].lstrip())
3584  i = line.find("/")
3585  if i == -1:
3586  return
3587  i = line.find("/", i + 1)
3588  if i == -1:
3589  return
3590  items = [Data_Stmt_Set(repmap(line[: i + 1]))]
3591  line = line[i + 1 :].lstrip()
3592  while line:
3593  if line.startswith(","):
3594  line = line[1:].lstrip()
3595  i = line.find("/")
3596  if i == -1:
3597  return
3598  i = line.find("/", i + 1)
3599  if i == -1:
3600  return
3601  items.append(Data_Stmt_Set(repmap(line[: i + 1])))
3602  line = line[i + 1 :].lstrip()
3603  return tuple(items)
3604 
3605  def tostr(self):
3606  return "DATA " + ", ".join(map(str, self.items))
3607 
3608 
3609 class Data_Stmt_Set(Base): # R525
3610  """
3611  :F03R:525::
3612  <data-stmt-set> = <data-stmt-object-list> / <data-stmt-value-list> /
3613  """
3614 
3615  subclass_names = []
3616  use_names = ["Data_Stmt_Object_List", "Data_Stmt_Value_List"]
3617 
3618  @staticmethod
3619  def match(string):
3620  if not string.endswith("/"):
3621  return
3622  line, repmap = string_replace_map(string)
3623  i = line.find("/")
3624  if i == -1:
3625  return
3626  data_stmt_object_list = Data_Stmt_Object_List(repmap(line[:i].rstrip()))
3627  data_stmt_value_list = Data_Stmt_Value_List(repmap(line[i + 1 : -1].strip()))
3628  return data_stmt_object_list, data_stmt_value_list
3629 
3630  data_stmt_object_list = property(lambda self: self.items[0])
3631  data_stmt_value_list = property(lambda self: self.items[1])
3632 
3633  def tostr(self):
3634  return "%s / %s /" % tuple(self.items)
3635 
3636 
3637 class Data_Stmt_Object(Base): # R526
3638  """
3639  :F03R:526::
3640  <data-stmt-object> = <variable>
3641  | <data-implied-do>
3642  """
3643 
3644  subclass_names = ["Variable", "Data_Implied_Do"]
3645 
3646 
3647 class Data_Implied_Do(Base): # R527
3648  """
3649  :F03R:527::
3650  <data-implied-do> = ( <data-i-do-object-list> ,
3651  <data-i-do-variable> = <scalar-int-expr > ,
3652  <scalar-int-expr> [ , <scalar-int-expr> ] )
3653  """
3654 
3655  subclass_names = []
3656  use_names = ["Data_I_Do_Object_List", "Data_I_Do_Variable", "Scalar_Int_Expr"]
3657 
3658  @staticmethod
3659  def match(string):
3660  if not (string.startswith("(") and string.endswith(")")):
3661  return
3662  line, repmap = string_replace_map(string[1:-1].strip())
3663  s = line.split("=", 1)
3664  if len(s) != 2:
3665  return
3666  lhs = s[0].rstrip()
3667  rhs = s[1].lstrip()
3668  s1 = lhs.rsplit(",", 1)
3669  if len(s1) != 2:
3670  return
3671  s2 = rhs.split(",")
3672  if len(s2) not in [2, 3]:
3673  return
3674  data_i_do_object_list = Data_I_Do_Object_List(repmap(s1[0].rstrip()))
3675  data_i_do_variable = Data_I_Do_Variable(repmap(s1[1].lstrip()))
3676  scalar_int_expr1 = Scalar_Int_Expr(repmap(s2[0].rstrip()))
3677  scalar_int_expr2 = Scalar_Int_Expr(repmap(s2[1].strip()))
3678  if len(s2) == 3:
3679  scalar_int_expr3 = Scalar_Int_Expr(repmap(s2[2].lstrip()))
3680  else:
3681  scalar_int_expr3 = None
3682  return (
3683  data_i_do_object_list,
3684  data_i_do_variable,
3685  scalar_int_expr1,
3686  scalar_int_expr2,
3687  scalar_int_expr3,
3688  )
3689 
3690  data_i_do_object_list = property(lambda self: self.items[0])
3691  data_i_do_variable = property(lambda self: self.items[1])
3692  scalar_int_expr1 = property(lambda self: self.items[2])
3693  scalar_int_expr2 = property(lambda self: self.items[3])
3694  scalar_int_expr3 = property(lambda self: self.items[4])
3695 
3696  def tostr(self):
3697  tmp = "%s, %s = %s, %s" % tuple(self.items[:4])
3698  if self.items[4] is not None:
3699  tmp += ", %s" % (self.items[4])
3700  return "(" + tmp + ")"
3701 
3702 
3703 class Data_I_Do_Object(Base): # R528
3704  """
3705  <data-i-do-object> = <array-element>
3706  | <scalar-structure-component>
3707  | <data-implied-do>
3708  """
3709 
3710  subclass_names = ["Array_Element", "Scalar_Structure_Component", "Data_Implied_Do"]
3711 
3712 
3713 class Data_I_Do_Variable(Base): # R529
3714  """
3715  <data-i-do-variable> = <scalar-int-variable>
3716  """
3717 
3718  subclass_names = ["Scalar_Int_Variable"]
3719 
3720 
3721 class Data_Stmt_Value(Base): # R530
3722  """
3723  <data-stmt-value> = [ <data-stmt-repeat> * ] <data-stmt-constant>
3724  """
3725 
3726  subclass_names = ["Data_Stmt_Constant"]
3727  use_names = ["Data_Stmt_Repeat"]
3728 
3729  @staticmethod
3730  def match(string):
3731  line, repmap = string_replace_map(string)
3732  s = line.split("*", 1)
3733  if len(s) != 2:
3734  return
3735  lhs = repmap(s[0].rstrip())
3736  rhs = repmap(s[1].lstrip())
3737  if not lhs or not rhs:
3738  return
3739  return Data_Stmt_Repeat(lhs), Data_Stmt_Constant(rhs)
3740 
3741  def tostr(self):
3742  return "%s * %s" % self.items
3743 
3744 
3745 class Data_Stmt_Repeat(Base): # R531
3746  """
3747  <data-stmt-repeat> = <scalar-int-constant>
3748  | <scalar-int-constant-subobject>
3749  """
3750 
3751  subclass_names = ["Scalar_Int_Constant", "Scalar_Int_Constant_Subobject"]
3752 
3753 
3754 class Data_Stmt_Constant(Base): # R532
3755  """
3756  <data-stmt-constant> = <scalar-constant>
3757  | <scalar-constant-subobject>
3758  | <signed-int-literal-constant>
3759  | <signed-real-literal-constant>
3760  | <null-init>
3761  | <structure-constructor>
3762  """
3763 
3764  subclass_names = [
3765  "Scalar_Constant",
3766  "Scalar_Constant_Subobject",
3767  "Signed_Int_Literal_Constant",
3768  "Signed_Real_Literal_Constant",
3769  "Null_Init",
3770  "Structure_Constructor",
3771  ]
3772 
3773 
3774 class Int_Constant_Subobject(Base): # R533
3775  """
3776  <int-constant-subobject> = <constant-subobject>
3777  """
3778 
3779  subclass_names = ["Constant_Subobject"]
3780 
3781 
3782 class Constant_Subobject(Base): # R534
3783  """
3784  <constant-subobject> = <designator>
3785  """
3786 
3787  subclass_names = ["Designator"]
3788 
3789 
3790 class Dimension_Stmt(StmtBase): # R535
3791  """
3792  <dimension-stmt> = DIMENSION [ :: ] <array-name> ( <array-spec> )
3793  [ , <array-name> ( <array-spec> ) ]...
3794  """
3795 
3796  subclass_names = []
3797  use_names = ["Array_Name", "Array_Spec"]
3798 
3799  @staticmethod
3800  def match(string):
3801  if string[:9].upper() != "DIMENSION":
3802  return
3803  line, repmap = string_replace_map(string[9:].lstrip())
3804  if line.startswith("::"):
3805  line = line[2:].lstrip()
3806  decls = []
3807  for s in line.split(","):
3808  s = s.strip()
3809  if not s.endswith(")"):
3810  return
3811  i = s.find("(")
3812  if i == -1:
3813  return
3814  decls.append(
3815  (
3816  Array_Name(repmap(s[:i].rstrip())),
3817  Array_Spec(repmap(s[i + 1 : -1].strip())),
3818  )
3819  )
3820  if not decls:
3821  return
3822  return (decls,)
3823 
3824  def tostr(self):
3825  return "DIMENSION :: " + ", ".join(["%s(%s)" % ns for ns in self.items[0]])
3826 
3827 
3828 class Intent_Stmt(StmtBase): # R536
3829  """
3830  <intent-stmt> = INTENT ( <intent-spec> ) [ :: ] <dummy-arg-name-list>
3831  """
3832 
3833  subclass_names = []
3834  use_names = ["Intent_Spec", "Dummy_Arg_Name_List"]
3835 
3836  @staticmethod
3837  def match(string):
3838  if string[:6].upper() != "INTENT":
3839  return
3840  line = string[6:].lstrip()
3841  if not line or not line.startswith("("):
3842  return
3843  i = line.rfind(")")
3844  if i == -1:
3845  return
3846  spec = line[1:i].strip()
3847  if not spec:
3848  return
3849  line = line[i + 1 :].lstrip()
3850  if line.startswith("::"):
3851  line = line[2:].lstrip()
3852  if not line:
3853  return
3854  return Intent_Spec(spec), Dummy_Arg_Name_List(line)
3855 
3856  def tostr(self):
3857  return "INTENT(%s) :: %s" % self.items
3858 
3859 
3860 class Optional_Stmt(StmtBase, WORDClsBase): # R537
3861  """
3862  <optional-stmt> = OPTIONAL [ :: ] <dummy-arg-name-list>
3863  """
3864 
3865  subclass_names = []
3866  use_names = ["Dummy_Arg_Name_List"]
3867 
3868  @staticmethod
3869  def match(string):
3870  return WORDClsBase.match(
3871  "OPTIONAL", Dummy_Arg_Name_List, string, colons=True, require_cls=True
3872  )
3873 
3874  tostr = WORDClsBase.tostr_a
3875 
3876 
3877 class Parameter_Stmt(StmtBase, CALLBase): # R538
3878  """
3879  <parameter-stmt> = PARAMETER ( <named-constant-def-list> )
3880  """
3881 
3882  subclass_names = []
3883  use_names = ["Named_Constant_Def_List"]
3884 
3885  @staticmethod
3886  def match(string):
3887  return CALLBase.match(
3888  "PARAMETER", Named_Constant_Def_List, string, require_rhs=True
3889  )
3890 
3891 
3892 class Named_Constant_Def(KeywordValueBase): # R539
3893  """
3894  <named-constant-def> = <named-constant> = <initialization-expr>
3895  """
3896 
3897  subclass_names = []
3898  use_names = ["Named_Constant", "Initialization_Expr"]
3899 
3900  @staticmethod
3901  def match(string):
3902  return KeywordValueBase.match(Named_Constant, Initialization_Expr, string)
3903 
3904 
3905 class Cray_Pointer_Stmt(StmtBase, WORDClsBase): # pylint: disable=invalid-name
3906  """
3907  cray-pointer-stmt is POINTER cray-pointer-decl-list
3908  """
3909 
3910  subclass_names = []
3911  use_names = ["Cray_Pointer_Decl_List"]
3912 
3913  @staticmethod
3914  def match(string):
3915  """Implements the matching for a Cray-pointer statement.
3916 
3917  :param string: the reader or string to match as a Cray-pointer \
3918  statement.
3919  :type string: \
3920  :py:class:`fparser.common.readfortran.FortranReaderBase` or \
3921  `str`
3922  :return: a tuple of size 2 containing a string with the name \
3923  "POINTER" and a cray-pointer-decl-list, if there is a match, \
3924  or `None` if there is not.
3925  :rtype: (str, Cray_Pointer_Decl_List) or None
3926 
3927  """
3928  from fparser.two.utils import EXTENSIONS
3929 
3930  if "cray-pointer" not in EXTENSIONS:
3931  return None
3932  return WORDClsBase.match(
3933  "POINTER", Cray_Pointer_Decl_List, string, require_cls=True
3934  )
3935 
3936 
3937 class Cray_Pointer_Decl(Base): # pylint: disable=invalid-name
3938  """
3939  cray-pointer-decl is ( cray-pointer-name, cray-pointee-decl )
3940  """
3941 
3942  use_names = ["Cray_Pointer_Name", "Cray_Pointee_Name", "Cray_Pointee_Decl"]
3943 
3944  @staticmethod
3945  def match(string):
3946  """Implements the matching for a Cray-pointer declaration.
3947 
3948  :param str string: the string to match as a Cray-pointer \
3949  declaration.
3950  :return: None if there is no match, otherwise a tuple of size \
3951  2 containing the name of the pointer as the first argument and \
3952  either the name of the pointee as the second argument or a \
3953  Cray-pointee declaration.
3954  :rtype: None, (Name, Name) or (Name, Cray_Pointee_Decl)
3955 
3956  """
3957  if not string:
3958  return None
3959  strip_string = string.strip()
3960  if not strip_string:
3961  return None
3962  if not strip_string[0] == "(":
3963  return None
3964  if not strip_string[-1] == ")":
3965  return None
3966  strip_string_nobr = strip_string[1:-1].strip()
3967  line, repmap = string_replace_map(strip_string_nobr)
3968  split_list = line.split(",")
3969  if len(split_list) != 2:
3970  return None
3971  pointer_name = repmap(split_list[0]).strip()
3972  pointee_str = repmap(split_list[1]).strip()
3973  if pointee_str[-1] == ")":
3974  return Cray_Pointer_Name(pointer_name), Cray_Pointee_Decl(pointee_str)
3975  return Cray_Pointer_Name(pointer_name), Cray_Pointee_Name(pointee_str)
3976 
3977  def tostr(self):
3978  """
3979  :return: this Cray-pointee declaration as a string
3980  :rtype: str
3981  :raises InternalError: if the internal items list variable is \
3982  not the expected size.
3983  :raises InternalError: if the first element of the internal \
3984  items list is None or is empty.
3985  :raises InternalError: if the second element of the internal \
3986  items list is None or is empty.
3987  """
3988  if len(self.items) != 2:
3989  raise InternalError(
3990  "Cray_Pointer_Decl.tostr(). 'Items' should be of size 2 but "
3991  "found '{0}'.".format(len(self.items))
3992  )
3993  if not self.items[0]:
3994  raise InternalError(
3995  "Cray_Pointer_Decl_Stmt.tostr(). 'Items' "
3996  "entry 0 should be a pointer name but it is "
3997  "empty"
3998  )
3999  if not self.items[1]:
4000  raise InternalError(
4001  "Cray_Pointer_Decl_Stmt.tostr(). 'Items' "
4002  "entry 1 should be a pointee name or pointee "
4003  "declaration but it is empty"
4004  )
4005  return "({0}, {1})".format(self.items[0], self.items[1])
4006 
4007 
4008 class Cray_Pointee_Decl(CallBase): # pylint: disable=invalid-name
4009  """
4010  cray-pointee-decl is cray-pointee-name ( cray-pointee-array-spec )
4011 
4012  """
4013 
4014  subclass_names = []
4015  use_names = ["Cray_Pointee_Name", "Cray_Pointee_Array_Spec"]
4016 
4017  @staticmethod
4018  def match(string):
4019  """Implements the matching for a Cray-pointee declaration.
4020 
4021  :param str string: the string to match as a Cray-pointee \
4022  declaration.
4023  :return: None if there is no match, otherwise a tuple of size \
4024  2 containing the name of the pointee as the first argument and \
4025  a Cray-pointee array spec as the second argument.
4026  :rtype: None or (Name, Cray_Pointee_Array_Spec)
4027 
4028  """
4029  return CallBase.match(
4030  Cray_Pointee_Name, Cray_Pointee_Array_Spec, string, require_rhs=True
4031  )
4032 
4033 
4034 class Cray_Pointee_Array_Spec(Base): # pylint: disable=invalid-name
4035  """cray-pointee-array-spec is explicit-shape-spec-list
4036  or assumed-size-spec
4037 
4038  The above two forms of declaration are the only ones allowed
4039  according to
4040  http://pubs.cray.com/content/S-3901/8.6/
4041  cray-fortran-reference-manual-s-3901-86/types) or
4042  https://docs.oracle.com/cd/E19957-01/805-4941/z40000a54ba7/index.html
4043 
4044  """
4045 
4046  subclass_names = ["Assumed_Size_Spec", "Explicit_Shape_Spec_List"]
4047 
4048 
4049 class Pointer_Stmt(StmtBase, WORDClsBase): # R540
4050  """
4051  <pointer-stmt> = POINTER [ :: ] <pointer-decl-list>
4052  """
4053 
4054  subclass_names = []
4055  use_names = ["Pointer_Decl_List"]
4056 
4057  @staticmethod
4058  def match(string):
4059  return WORDClsBase.match(
4060  "POINTER", Pointer_Decl_List, string, colons=True, require_cls=True
4061  )
4062 
4063  tostr = WORDClsBase.tostr_a
4064 
4065 
4066 class Pointer_Decl(CallBase): # R541
4067  """
4068  <pointer-decl> = <object-name> [ ( <deferred-shape-spec-list> ) ]
4069  | <proc-entity-name>
4070  """
4071 
4072  subclass_names = ["Proc_Entity_Name", "Object_Name"]
4073  use_names = ["Deferred_Shape_Spec_List"]
4074 
4075  @staticmethod
4076  def match(string):
4077  return CallBase.match(
4078  Object_Name, Deferred_Shape_Spec_List, string, require_rhs=True
4079  )
4080 
4081 
4082 class Protected_Stmt(StmtBase, WORDClsBase): # R542
4083  """
4084  <protected-stmt> = PROTECTED [ :: ] <entity-name-list>
4085  """
4086 
4087  subclass_names = []
4088  use_names = ["Entity_Name_List"]
4089 
4090  @staticmethod
4091  def match(string):
4092  return WORDClsBase.match(
4093  "PROTECTED", Entity_Name_List, string, colons=True, require_cls=True
4094  )
4095 
4096  tostr = WORDClsBase.tostr_a
4097 
4098 
4099 class Save_Stmt(StmtBase, WORDClsBase): # R543
4100  """
4101  <save-stmt> = SAVE [ [ :: ] <saved-entity-list> ]
4102  """
4103 
4104  subclass_names = []
4105  use_names = ["Saved_Entity_List"]
4106 
4107  @staticmethod
4108  def match(string):
4109  return WORDClsBase.match(
4110  "SAVE", Saved_Entity_List, string, colons=True, require_cls=False
4111  )
4112 
4113  tostr = WORDClsBase.tostr_a
4114 
4115 
4116 class Saved_Entity(BracketBase): # R544
4117  """
4118  <saved-entity> = <object-name>
4119  | <proc-pointer-name>
4120  | / <common-block-name> /
4121  """
4122 
4123  subclass_names = ["Object_Name", "Proc_Pointer_Name"]
4124  use_names = ["Common_Block_Name"]
4125 
4126  @staticmethod
4127  def match(string):
4128  return BracketBase.match("//", Common_Block_Name, string)
4129 
4130 
4131 class Proc_Pointer_Name(Base): # R545
4132  """
4133  <proc-pointer-name> = <name>
4134  """
4135 
4136  subclass_names = ["Name"]
4137 
4138 
4140  """
4141  <target-entity-decl> = <object-name> [ ( <array-spec> ) ]
4142  """
4143 
4144  subclass_names = []
4145  use_names = ["Object_Name", "Array_Spec"]
4146 
4147  @staticmethod
4148  def match(string):
4149  return Entity_Decl.match(string, target=True)
4150 
4151 
4152 class Target_Stmt(StmtBase): # R546
4153  """
4154  <target-stmt> = TARGET [ :: ] <target-entity-decl-list>
4155  """
4156 
4157  subclass_names = []
4158  use_names = ["Target_Entity_Decl_List"]
4159 
4160  @staticmethod
4161  def match(string):
4162  if string[:6].upper() != "TARGET":
4163  return
4164  line = string[6:].lstrip()
4165  if line.startswith("::"):
4166  line = line[2:].lstrip()
4167  return (Target_Entity_Decl_List(line),)
4168 
4169  def tostr(self):
4170  return "TARGET :: %s" % (self.items[0])
4171 
4172 
4173 class Value_Stmt(StmtBase, WORDClsBase): # R547
4174  """
4175  <value-stmt> = VALUE [ :: ] <dummy-arg-name-list>
4176  """
4177 
4178  subclass_names = []
4179  use_names = ["Dummy_Arg_Name_List"]
4180 
4181  @staticmethod
4182  def match(string):
4183  return WORDClsBase.match(
4184  "VALUE", Dummy_Arg_Name_List, string, colons=True, require_cls=True
4185  )
4186 
4187  tostr = WORDClsBase.tostr_a
4188 
4189 
4190 class Volatile_Stmt(StmtBase, WORDClsBase): # R548
4191  """
4192  <volatile-stmt> = VOLATILE [ :: ] <object-name-list>
4193  """
4194 
4195  subclass_names = []
4196  use_names = ["Object_Name_List"]
4197 
4198  @staticmethod
4199  def match(string):
4200  return WORDClsBase.match(
4201  "VOLATILE", Object_Name_List, string, colons=True, require_cls=True
4202  )
4203 
4204  tostr = WORDClsBase.tostr_a
4205 
4206 
4207 class Implicit_Stmt(StmtBase): # R549
4208  """
4209  ::
4210  <implicit-stmt> = IMPLICIT <implicit-spec-list>
4211  | IMPLICIT NONE
4212 
4213  Attributes
4214  ----------
4215  items : ({'NONE', Implicit_Spec_List},)
4216  """
4217 
4218  subclass_names = []
4219  use_names = ["Implicit_Spec_List"]
4220 
4221  @staticmethod
4222  def match(string):
4223  if string[:8].upper() != "IMPLICIT":
4224  return
4225  line = string[8:].lstrip()
4226  if len(line) == 4 and line.upper() == "NONE":
4227  return ("NONE",)
4228  return (Implicit_Spec_List(line),)
4229  for w, cls in [
4230  (pattern.abs_implicit_none, None),
4231  ("IMPLICIT", Implicit_Spec_List),
4232  ]:
4233  try:
4234  obj = WORDClsBase.match(w, cls, string)
4235  except NoMatchError:
4236  obj = None
4237  if obj is not None:
4238  return obj
4239  return None
4240 
4241  def tostr(self):
4242  return "IMPLICIT %s" % (self.items[0])
4243 
4244 
4245 class Implicit_Spec(CallBase): # R550
4246  """
4247  <implicit-spec> = <declaration-type-spec> ( <letter-spec-list> )
4248  """
4249 
4250  subclass_names = []
4251  use_names = ["Declaration_Type_Spec", "Letter_Spec_List"]
4252 
4253  @staticmethod
4254  def match(string):
4255  if not string.endswith(")"):
4256  return
4257  i = string.rfind("(")
4258  if i == -1:
4259  return
4260  s1 = string[:i].rstrip()
4261  s2 = string[i + 1 : -1].strip()
4262  if not s1 or not s2:
4263  return
4264  return Declaration_Type_Spec(s1), Letter_Spec_List(s2)
4265 
4266 
4267 class Letter_Spec(Base): # R551
4268  """
4269  <letter-spec> = <letter> [ - <letter> ]
4270  """
4271 
4272  subclass_names = []
4273 
4274  @staticmethod
4275  def match(string):
4276  if len(string) == 1:
4277  lhs = string.upper()
4278  if "A" <= lhs <= "Z":
4279  return lhs, None
4280  return
4281  if "-" not in string:
4282  return
4283  lhs, rhs = string.split("-", 1)
4284  lhs = lhs.strip().upper()
4285  rhs = rhs.strip().upper()
4286  if not len(lhs) == len(rhs) == 1:
4287  return
4288  if not ("A" <= lhs <= rhs <= "Z"):
4289  return
4290  return lhs, rhs
4291 
4292  def tostr(self):
4293  if self.items[1] is None:
4294  return str(self.items[0])
4295  return "%s - %s" % tuple(self.items)
4296 
4297 
4298 class Namelist_Stmt(StmtBase): # R552
4299  """
4300  ::
4301  <namelist-stmt> = NAMELIST / <namelist-group-name> /
4302  <namelist-group-object-list> [ [ , ] / <namelist-group-name> /
4303  <namelist-group-object-list> ]...
4304 
4305  Attributes
4306  ----------
4307  items : (Namelist_Group_Name, Namelist_Group_Object_List)-tuple
4308  """
4309 
4310  subclass_names = []
4311  use_names = ["Namelist_Group_Name", "Namelist_Group_Object_List"]
4312 
4313  @staticmethod
4314  def match(string):
4315  if string[:8].upper() != "NAMELIST":
4316  return
4317  line = string[8:].lstrip()
4318  parts = line.split("/")
4319  items = []
4320  fst = parts.pop(0)
4321  assert not fst, repr((fst, parts))
4322  while len(parts) >= 2:
4323  name, lst = parts[:2]
4324  del parts[:2]
4325  name = name.strip()
4326  lst = lst.strip()
4327  if lst.endswith(","):
4328  lst = lst[:-1].rstrip()
4329  items.append((Namelist_Group_Name(name), Namelist_Group_Object_List(lst)))
4330  assert not parts, repr(parts)
4331  return tuple(items)
4332 
4333  def tostr(self):
4334  return "NAMELIST " + ", ".join(
4335  "/%s/ %s" % (name_lst) for name_lst in self.items
4336  )
4337 
4338 
4339 class Namelist_Group_Object(Base): # R553
4340  """
4341  <namelist-group-object> = <variable-name>
4342  """
4343 
4344  subclass_names = ["Variable_Name"]
4345 
4346 
4347 class Equivalence_Stmt(StmtBase, WORDClsBase): # R554
4348  """
4349  <equivalence-stmt> = EQUIVALENCE <equivalence-set-list>
4350  """
4351 
4352  subclass_names = []
4353  use_names = ["Equivalence_Set_List"]
4354 
4355  @staticmethod
4356  def match(string):
4357  return WORDClsBase.match("EQUIVALENCE", Equivalence_Set_List, string)
4358 
4359 
4360 class Equivalence_Set(Base): # R555
4361  """
4362  <equivalence-set> = ( <equivalence-object> , <equivalence-object-list> )
4363  """
4364 
4365  subclass_names = []
4366  use_names = ["Equivalence_Object", "Equivalence_Object_List"]
4367 
4368  @staticmethod
4369  def match(string):
4370  if not string or string[0] + string[-1] != "()":
4371  return
4372  line = string[1:-1].strip()
4373  if not line:
4374  return
4375  tmp = Equivalence_Object_List(line)
4376  obj = tmp.items[0]
4377  tmp.items = tmp.items[1:]
4378  if not tmp.items:
4379  return
4380  return obj, tmp
4381 
4382  def tostr(self):
4383  return "(%s, %s)" % tuple(self.items)
4384 
4385 
4386 class Equivalence_Object(Base): # R556
4387  """
4388  <equivalence-object> = <variable-name>
4389  | <array-element>
4390  | <substring>
4391  """
4392 
4393  subclass_names = ["Variable_Name", "Array_Element", "Substring"]
4394 
4395 
4396 class Common_Stmt(StmtBase): # R557
4397  """
4398  <common-stmt> = COMMON [ / [ <common-block-name> ] / ]
4399  <common-block-object-list> [ [ , ] / [ <common-block-name> ]
4400  / <common-block-object-list> ]...
4401  """
4402 
4403  subclass_names = []
4404  use_names = ["Common_Block_Name", "Common_Block_Object_List"]
4405 
4406  @staticmethod
4407  def match(string):
4408  if string[:6].upper() != "COMMON":
4409  return
4410  line = string[6:]
4411  if not line or "A" <= line[0].upper() <= "Z" or line[0] == "_":
4412  return
4413  line, repmap = string_replace_map(line.lstrip())
4414  items = []
4415  if line.startswith("/"):
4416  i = line.find("/", 1)
4417  if i == -1:
4418  return
4419  name = line[1:i].strip() or None
4420  if name is not None:
4421  name = Common_Block_Name(name)
4422  line = line[i + 1 :].lstrip()
4423  i = line.find("/")
4424  if i == -1:
4425  lst = Common_Block_Object_List(repmap(line))
4426  line = ""
4427  else:
4428  tmp = line[:i].rstrip()
4429  if tmp.endswith(","):
4430  tmp = tmp[:-1].rstrip()
4431  if not tmp:
4432  return
4433  lst = Common_Block_Object_List(repmap(tmp))
4434  line = line[i:].lstrip()
4435  else:
4436  name = None
4437  i = line.find("/")
4438  if i == -1:
4439  lst = Common_Block_Object_List(repmap(line))
4440  line = ""
4441  else:
4442  tmp = line[:i].rstrip()
4443  if tmp.endswith(","):
4444  tmp = tmp[:-1].rstrip()
4445  if not tmp:
4446  return
4447  lst = Common_Block_Object_List(repmap(tmp))
4448  line = line[i:].lstrip()
4449  items.append((name, lst))
4450  while line:
4451  if line.startswith(","):
4452  line = line[1:].lstrip()
4453  if not line.startswith("/"):
4454  return
4455  i = line.find("/", 1)
4456  name = line[1:i].strip() or None
4457  if name is not None:
4458  name = Common_Block_Name(name)
4459  line = line[i + 1 :].lstrip()
4460  i = line.find("/")
4461  if i == -1:
4462  lst = Common_Block_Object_List(repmap(line))
4463  line = ""
4464  else:
4465  tmp = line[:i].rstrip()
4466  if tmp.endswith(","):
4467  tmp = tmp[:-1].rstrip()
4468  if not tmp:
4469  return
4470  lst = Common_Block_Object_List(repmap(tmp))
4471  line = line[i:].lstrip()
4472  items.append((name, lst))
4473  return (items,)
4474 
4475  def tostr(self):
4476  s = "COMMON"
4477  for (name, lst) in self.items[0]:
4478  if name is not None:
4479  s += " /%s/ %s" % (name, lst)
4480  else:
4481  s += " // %s" % (lst)
4482  return s
4483 
4484 
4485 class Common_Block_Object(CallBase): # R558
4486  """
4487  <common-block-object> = <variable-name> [ ( <explicit-shape-spec-list> ) ]
4488  | <proc-pointer-name>
4489  """
4490 
4491  subclass_names = ["Proc_Pointer_Name", "Variable_Name"]
4492  use_names = ["Variable_Name", "Explicit_Shape_Spec_List"]
4493 
4494  @staticmethod
4495  def match(string):
4496  return CallBase.match(
4497  Variable_Name, Explicit_Shape_Spec_List, string, require_rhs=True
4498  )
4499 
4500 
4501 #
4502 # SECTION 6
4503 #
4504 
4505 
4506 class Variable(Base): # R601
4507  """
4508  <variable> = <designator>
4509  """
4510 
4511  subclass_names = ["Designator"]
4512 
4513 
4514 class Variable_Name(Base): # R602
4515  """
4516  <variable-name> = <name>
4517  """
4518 
4519  subclass_names = ["Name"]
4520 
4521 
4522 class Designator(Base): # R603
4523  """
4524  Fortran 2003 rule 603
4525 
4526  designator is object-name
4527  or array-element
4528  or array-section
4529  or structure-component
4530  or substring
4531 
4532  """
4533 
4534  # At the moment some array section text, and all structure
4535  # component and substring text will match the array-element
4536  # rule. This is because the associated rule constraints
4537  # (e.g. C617, C618 and C619) and specification text (see note 6.6)
4538  # are not currently enforced. Note, these constraints can not be
4539  # enforced until issue #201 has been addressed.
4540  subclass_names = [
4541  "Object_Name",
4542  "Array_Element",
4543  "Array_Section",
4544  "Structure_Component",
4545  "Substring",
4546  ]
4547 
4548 
4549 class Logical_Variable(Base): # R604
4550  """
4551  <logical-variable> = <variable>
4552  """
4553 
4554  subclass_names = ["Variable"]
4555 
4556 
4557 class Default_Logical_Variable(Base): # R605
4558  """
4559  <default-logical-variable> = <variable>
4560  """
4561 
4562  subclass_names = ["Variable"]
4563 
4564 
4565 class Char_Variable(Base): # R606
4566  """
4567  <char-variable> = <variable>
4568  """
4569 
4570  subclass_names = ["Variable"]
4571 
4572 
4573 class Default_Char_Variable(Base): # R607
4574  """
4575  <default-char-variable> = <variable>
4576  """
4577 
4578  subclass_names = ["Variable"]
4579 
4580 
4581 class Int_Variable(Base): # R608
4582  """
4583  <int-variable> = <variable>
4584  """
4585 
4586  subclass_names = ["Variable"]
4587 
4588 
4589 class Substring(CallBase): # R609
4590  """
4591  <substring> = <parent-string> ( <substring-range> )
4592  """
4593 
4594  subclass_names = []
4595  use_names = ["Parent_String", "Substring_Range"]
4596 
4597  @staticmethod
4598  def match(string):
4599  return CallBase.match(Parent_String, Substring_Range, string, require_rhs=True)
4600 
4601 
4602 class Parent_String(Base): # R610
4603  """
4604  <parent-string> = <scalar-variable-name>
4605  | <array-element>
4606  | <scalar-structure-component>
4607  | <scalar-constant>
4608  """
4609 
4610  subclass_names = [
4611  "Scalar_Variable_Name",
4612  "Array_Element",
4613  "Scalar_Structure_Component",
4614  "Scalar_Constant",
4615  ]
4616 
4617 
4618 class Substring_Range(SeparatorBase): # R611
4619  """
4620  <substring-range> = [ <scalar-int-expr> ] : [ <scalar-int-expr> ]
4621  """
4622 
4623  subclass_names = []
4624  use_names = ["Scalar_Int_Expr"]
4625 
4626  @staticmethod
4627  def match(string):
4628  return SeparatorBase.match(Scalar_Int_Expr, Scalar_Int_Expr, string)
4629 
4630 
4631 class Data_Ref(SequenceBase):
4632  """
4633  Fortran 2003 Rule R612
4634 
4635  data-ref is part-ref [ % part-ref ] ...
4636 
4637  If there is only one part-ref then return a 'Part_Ref' object (or
4638  another object from a matching sub-rule). If there is more than
4639  one part-ref then return a 'Data_Ref' object containing the
4640  part-ref's.
4641 
4642  """
4643 
4644  subclass_names = ["Part_Ref"]
4645  use_names = []
4646 
4647  @staticmethod
4648  def match(string):
4649  """Implements the matching for a data-reference. This defines a series
4650  of dereferences e.g. a%b%c.
4651 
4652  If there is more than one part-ref then return a 'Data_Ref'
4653  object containing the part-ref's, otherwise return 'None'. A
4654  single 'part-ref' is purposely not matched here.
4655 
4656  :param str string: Fortran code to check for a match
4657 
4658  :return: `None` if there is no match, or a tuple containing \
4659  the matched operator as a string and another tuple \
4660  containing the matched subclasses.
4661 
4662  :rtype: NoneType or (str, (obj, obj, ...))
4663 
4664  """
4665  # Use SequenceBase as normal, then force no match when there is
4666  # only one entry in the sequence.
4667  result = SequenceBase.match(r"%", Part_Ref, string)
4668  entries = result[1]
4669  if len(entries) > 1:
4670  # There is more than one part-ref so return a Data_Ref
4671  # object containing the part-refs.
4672  return result
4673  # There is only one part-ref so return None to indicate there
4674  # is no match and allow the subclass_names Part_Ref class to
4675  # match instead.
4676  return None
4677 
4678 
4679 class Part_Ref(CallBase): # R613
4680  """
4681  <part-ref> = <part-name> [ ( <section-subscript-list> ) ]
4682  """
4683 
4684  subclass_names = ["Part_Name"]
4685  use_names = ["Section_Subscript_List"]
4686 
4687  @staticmethod
4688  def match(string):
4689  return CallBase.match(
4690  Part_Name, Section_Subscript_List, string, require_rhs=True
4691  )
4692 
4693 
4694 class Structure_Component(Base): # R614
4695  """
4696  <structure-component> = <data-ref>
4697  """
4698 
4699  subclass_names = ["Data_Ref"]
4700 
4701 
4702 class Type_Param_Inquiry(BinaryOpBase): # R615
4703  """
4704  <type-param-inquiry> = <designator> % <type-param-name>
4705  """
4706 
4707  subclass_names = []
4708  use_names = ["Designator", "Type_Param_Name"]
4709 
4710  @staticmethod
4711  def match(string):
4712  return BinaryOpBase.match(
4713  Designator, pattern.percent_op.named(), Type_Param_Name, string
4714  )
4715 
4716 
4717 class Array_Element(Base): # R616
4718  """
4719  <array-element> = <data-ref>
4720  """
4721 
4722  subclass_names = ["Data_Ref"]
4723 
4724 
4725 class Array_Section(CallBase): # R617
4726  """
4727  <array-section> = <data-ref> [ ( <substring-range> ) ]
4728  """
4729 
4730  subclass_names = ["Data_Ref"]
4731  use_names = ["Substring_Range"]
4732 
4733  @staticmethod
4734  def match(string):
4735  return CallBase.match(Data_Ref, Substring_Range, string, require_rhs=True)
4736 
4737 
4738 class Subscript(Base): # R618
4739  """
4740  <subscript> = <scalar-int-expr>
4741  """
4742 
4743  subclass_names = ["Scalar_Int_Expr"]
4744 
4745 
4746 class Section_Subscript(Base): # R619
4747  """
4748  <section-subscript> = <subscript>
4749  | <subscript-triplet>
4750  | <vector-subscript>
4751  """
4752 
4753  subclass_names = ["Subscript_Triplet", "Vector_Subscript", "Subscript"]
4754 
4755 
4756 class Subscript_Triplet(Base): # R620
4757  """
4758  <subscript-triplet> = [ <subscript> ] : [ <subscript> ] [ : <stride> ]
4759  """
4760 
4761  subclass_names = []
4762  use_names = ["Subscript", "Stride"]
4763 
4764  @staticmethod
4765  def match(string):
4766  line, repmap = string_replace_map(string)
4767  t = line.split(":")
4768  if len(t) <= 1 or len(t) > 3:
4769  return
4770  lhs_obj, rhs_obj, stride_obj = None, None, None
4771  if len(t) == 2:
4772  lhs, rhs = t[0].rstrip(), t[1].lstrip()
4773  else:
4774  lhs, rhs, stride = t[0].rstrip(), t[1].strip(), t[2].lstrip()
4775  if stride:
4776  stride_obj = Stride(repmap(stride))
4777  if lhs:
4778  lhs_obj = Subscript(repmap(lhs))
4779  if rhs:
4780  rhs_obj = Subscript(repmap(rhs))
4781  return lhs_obj, rhs_obj, stride_obj
4782 
4783  def tostr(self):
4784  s = ""
4785  if self.items[0] is not None:
4786  s += str(self.items[0]) + " :"
4787  else:
4788  s += ":"
4789  if self.items[1] is not None:
4790  s += " " + str(self.items[1])
4791  if self.items[2] is not None:
4792  s += " : " + str(self.items[2])
4793  return s
4794 
4795 
4796 class Stride(Base): # R621
4797  """
4798  <stride> = <scalar-int-expr>
4799  """
4800 
4801  subclass_names = ["Scalar_Int_Expr"]
4802 
4803 
4804 class Vector_Subscript(Base): # R622
4805  """
4806  <vector-subscript> = <int-expr>
4807  """
4808 
4809  subclass_names = ["Int_Expr"]
4810 
4811 
4812 class Allocate_Stmt(StmtBase): # R623
4813  """
4814  Fortran2003 rule R623
4815  allocate-stmt is ALLOCATE ( [ type-spec :: ] allocation-list
4816  [, alloc-opt-list ] )
4817 
4818  Subject to the following constraints:
4819 
4820  C622 (R629) Each allocate-object shall be a nonprocedure pointer or an
4821  allocatable variable.
4822  C623 (R623) If any allocate-object in the statement has a deferred type
4823  parameter, either type-spec or SOURCE= shall appear.
4824  C624 (R623) If a type-spec appears, it shall specify a type with which
4825  each allocate-object is type compatible.
4826  C625 (R623) If any allocate-object is unlimited polymorphic, either
4827  type-spec or SOURCE= shall appear.
4828  C626 (R623) A type-param-value in a type-spec shall be an asterisk if and
4829  only if each allocate-object is a dummy argument for which the
4830  corresponding type parameter is assumed.
4831  C627 (R623) If a type-spec appears, the kind type parameter values of each
4832  allocate-object shall be the same as the corresponding type
4833  parameter values of the type-spec.
4834  C628 (R628) An allocate-shape-spec-list shall appear if and only if the
4835  allocate-object is an array.
4836  C629 (R628) The number of allocate-shape-specs in an
4837  allocate-shape-spec-list shall be the same as the rank of the
4838  allocate-object.
4839  C630 (R624) No alloc-opt shall appear more than once in a given
4840  alloc-opt-list.
4841  C631 (R623) If SOURCE= appears, type-spec shall not appear and
4842  allocation-list shall contain only one allocate-object, which
4843  shall be type compatible (5.1.1.2) with source-expr.
4844  C632 (R623) The source-expr shall be a scalar or have the same rank as
4845  allocate-object.
4846  C633 (R623) Corresponding kind type parameters of allocate-object and
4847  source-expr shall have the same values.
4848 
4849  None of these constraints are currently applied - issue #355.
4850 
4851  """
4852 
4853  subclass_names = []
4854  use_names = ["Type_Spec", "Allocation_List", "Alloc_Opt_List"]
4855 
4856  @classmethod
4857  def match(cls, string):
4858  """
4859  Attempts to match the supplied string as an Allocate_Stmt.
4860 
4861  :param str string: the string to attempt to match.
4862 
4863  :returns: A 2-tuple giving the Type_Spec and Allocation_List if the \
4864  match is successful, None otherwise.
4865  :rtype: Optional[ \
4866  Tuple[Optional[:py:class:`fparser.two.Fortran2003.Type_Spec`], \
4867  :py:class:`fparser.two.Fortran2003.Allocation_List`]]
4868  """
4869  if string[:8].upper() != "ALLOCATE":
4870  return None
4871  line = string[8:].lstrip()
4872  if not line or line[0] != "(" or line[-1] != ")":
4873  return None
4874  line, repmap = string_replace_map(line[1:-1].strip())
4875  idx = line.find("::")
4876  spec = None
4877  if idx != -1:
4878  spec = Type_Spec(repmap(line[:idx].rstrip()))
4879  line = line[idx + 2 :].lstrip()
4880  idx = line.find("=")
4881  opts = None
4882  if idx != -1:
4883  jdx = line[:idx].rfind(",")
4884  if jdx == -1:
4885  # There must be at least one positional argument before any
4886  # named arguments.
4887  return None
4888  # Use the class 'alloc_opt_list' property to ensure we use the
4889  # correct class depending on whether 'cls' is associated with
4890  # Fortran2003 or Fortran2008.
4891  opts = cls.alloc_opt_list()(repmap(line[jdx + 1 :].lstrip()))
4892  line = line[:jdx].rstrip()
4893  return spec, Allocation_List(repmap(line)), opts
4894 
4895  @classmethod
4896  def alloc_opt_list(cls):
4897  """
4898  :returns: the Fortran2003 flavour of Alloc_Opt_List.
4899  :rtype: type
4900  """
4901  return Alloc_Opt_List
4902 
4903  def tostr(self):
4904  spec, lst, opts = self.items
4905  if spec is not None:
4906  if opts is not None:
4907  return "ALLOCATE(%s::%s, %s)" % (spec, lst, opts)
4908  else:
4909  return "ALLOCATE(%s::%s)" % (spec, lst)
4910  elif opts is not None:
4911  return "ALLOCATE(%s, %s)" % (lst, opts)
4912  else:
4913  return "ALLOCATE(%s)" % (lst)
4914 
4915 
4916 class Stat_Variable(Base): # R625
4917  """
4918  <stat-variable> = <scalar-int-variable>
4919  """
4920 
4921  subclass_names = ["Scalar_Int_Variable"]
4922 
4923 
4924 class Errmsg_Variable(Base): # R626
4925  """
4926  <errmsg-variable> = <scalar-default-char-variable>
4927  """
4928 
4929  subclass_names = ["Scalar_Default_Char_Variable"]
4930 
4931 
4932 class Source_Expr(Base): # R627
4933  """
4934  <source-expr> = <expr>
4935  """
4936 
4937  subclass_names = ["Expr"]
4938 
4939 
4940 class Alloc_Opt(KeywordValueBase): # R624
4941  """
4942  <alloc-opt> = STAT = <stat-variable>
4943  | ERRMSG = <errmsg-variable>
4944  | SOURCE = <source-expr>
4945  """
4946 
4947  subclass_names = []
4948  use_names = ["Stat_Variable", "Errmsg_Variable", "Source_Expr"]
4949  #: The keywords tested for in the match() method.
4950  _keyword_pairs = [
4951  ("STAT", Stat_Variable),
4952  ("ERRMSG", Errmsg_Variable),
4953  ("SOURCE", Source_Expr),
4954  ]
4955 
4956  @classmethod
4957  def match(cls, string):
4958  for (k, v) in cls._keyword_pairs:
4959  obj = KeywordValueBase.match(k, v, string, upper_lhs=True)
4960  if obj is not None:
4961  return obj
4962  return None
4963 
4964 
4965 class Allocation(CallBase): # R628
4966  """
4967  <allocation> = <allocate-object> [ ( <allocate-shape-spec-list> ) ]
4968  | <variable-name>
4969  """
4970 
4971  subclass_names = ["Variable_Name", "Allocate_Object"]
4972  use_names = ["Allocate_Shape_Spec_List"]
4973 
4974  @staticmethod
4975  def match(string):
4976  return CallBase.match(
4977  Allocate_Object, Allocate_Shape_Spec_List, string, require_rhs=True
4978  )
4979 
4980 
4981 class Allocate_Object(Base): # R629
4982  """
4983  <allocate-object> = <variable-name>
4984  | <structure-component>
4985  """
4986 
4987  subclass_names = ["Variable_Name", "Structure_Component"]
4988 
4989 
4990 class Allocate_Shape_Spec(SeparatorBase): # R630
4991  """
4992  <allocate-shape-spec> = [ <lower-bound-expr> : ] <upper-bound-expr>
4993  """
4994 
4995  subclass_names = []
4996  use_names = ["Lower_Bound_Expr", "Upper_Bound_Expr"]
4997 
4998  @staticmethod
4999  def match(string):
5000  line, repmap = string_replace_map(string)
5001  if ":" not in line:
5002  return None, Upper_Bound_Expr(string)
5003  lower, upper = line.split(":", 1)
5004  lower = lower.rstrip()
5005  upper = upper.lstrip()
5006  if not upper:
5007  return
5008  if not lower:
5009  return
5010  return Lower_Bound_Expr(repmap(lower)), Upper_Bound_Expr(repmap(upper))
5011 
5012  def tostr(self):
5013  if self.items[0] is None:
5014  return str(self.items[1])
5015  return SeparatorBase.tostr(self)
5016 
5017 
5018 class Lower_Bound_Expr(Base): # R631
5019  """
5020  <lower-bound-expr> = <scalar-int-expr>
5021  """
5022 
5023  subclass_names = ["Scalar_Int_Expr"]
5024 
5025 
5026 class Upper_Bound_Expr(Base): # R632
5027  """
5028  <upper-bound-expr> = <scalar-int-expr>
5029  """
5030 
5031  subclass_names = ["Scalar_Int_Expr"]
5032 
5033 
5034 class Nullify_Stmt(StmtBase, CALLBase): # R633
5035  """
5036  <nullify-stmt> = NULLIFY ( <pointer-object-list> )
5037  """
5038 
5039  subclass_names = []
5040  use_names = ["Pointer_Object_List"]
5041 
5042  @staticmethod
5043  def match(string):
5044  return CALLBase.match("NULLIFY", Pointer_Object_List, string, require_rhs=True)
5045 
5046 
5047 class Pointer_Object(Base): # R634
5048  """
5049  <pointer-object> = <variable-name>
5050  | <structure-component>
5051  | <proc-pointer-name>
5052  """
5053 
5054  subclass_names = ["Variable_Name", "Structure_Component", "Proc_Pointer_Name"]
5055 
5056 
5057 class Deallocate_Stmt(StmtBase): # R635
5058  """
5059  <deallocate-stmt> = DEALLOCATE ( <allocate-object-list> [
5060  , <dealloc-opt-list> ] )
5061  """
5062 
5063  subclass_names = []
5064  use_names = ["Allocate_Object_List", "Dealloc_Opt_List"]
5065 
5066  @staticmethod
5067  def match(string):
5068  if string[:10].upper() != "DEALLOCATE":
5069  return
5070  line = string[10:].lstrip()
5071  if not line or line[0] != "(" or line[-1] != ")":
5072  return
5073  line, repmap = string_replace_map(line[1:-1].strip())
5074  i = line.find("=")
5075  opts = None
5076  if i != -1:
5077  j = line[:i].rfind(",")
5078  assert j != -1, repr((i, j, line))
5079  opts = Dealloc_Opt_List(repmap(line[j + 1 :].lstrip()))
5080  line = line[:j].rstrip()
5081  return Allocate_Object_List(repmap(line)), opts
5082 
5083  def tostr(self):
5084  if self.items[1] is not None:
5085  return "DEALLOCATE(%s, %s)" % (self.items)
5086  return "DEALLOCATE(%s)" % (self.items[0])
5087 
5088 
5089 class Dealloc_Opt(KeywordValueBase): # R636
5090  """
5091  <dealloc-opt> = STAT = <stat-variable>
5092  | ERRMSG = <errmsg-variable>
5093  """
5094 
5095  subclass_names = []
5096  use_names = ["Stat_Variable", "Errmsg_Variable"]
5097 
5098  @staticmethod
5099  def match(string):
5100  for (k, v) in [("STAT", Stat_Variable), ("ERRMSG", Errmsg_Variable)]:
5101  try:
5102  obj = KeywordValueBase.match(k, v, string, upper_lhs=True)
5103  except NoMatchError:
5104  obj = None
5105  if obj is not None:
5106  return obj
5107  return None
5108 
5109 
5111  subclass_names = ["Char_Initialization_Expr"]
5112 
5113 
5114 #
5115 # SECTION 7
5116 #
5117 
5118 
5119 class Primary(Base): # R701
5120  """Fortran 2003 rule R701
5121 
5122  primary is intrinsic_function_reference
5123  or constant
5124  or designator
5125  or array-constructor
5126  or structure-constructor
5127  or function-reference
5128  or type-param-inquiry
5129  or type-param-name
5130  or ( expr )
5131 
5132  `intrinsic_function_reference` is not part of rule R701 but is
5133  required for fparser to recognise intrinsic functions. This is
5134  placed before array-constructor in the `subclass_names` list so
5135  that an intrinsic is not (incorrectly) matched as an array (as
5136  class `Base` matches rules in list order).
5137 
5138  Note, ( expr ) is implemented in the Parenthesis subclass.
5139 
5140  """
5141 
5142  subclass_names = [
5143  "Intrinsic_Function_Reference",
5144  "Constant",
5145  "Designator",
5146  "Array_Constructor",
5147  "Structure_Constructor",
5148  "Function_Reference",
5149  "Type_Param_Inquiry",
5150  "Type_Param_Name",
5151  "Parenthesis",
5152  ]
5153 
5154 
5155 class Parenthesis(BracketBase):
5156  """
5157  Part of Fortran 2003 rule R701
5158 
5159  parenthesis = ( expr )
5160 
5161  """
5162 
5163  subclass_names = []
5164  use_names = ["Expr"]
5165 
5166  @staticmethod
5167  def match(string):
5168  """Implements the matching of round brackets surrounding an expression
5169  which is specified as one of the matches in R701.
5170 
5171  :param str string: Fortran code to check for a match.
5172 
5173  :returns: `None` if there is no match, or a 3-tuple containing \
5174  the left bracket, the matched expression and the right \
5175  bracket.
5176  :rtype: NoneType or (str, subclass of \
5177  :py:class:`fparser.two.utils.Base`, str)
5178 
5179  """
5180  return BracketBase.match("()", Expr, string)
5181 
5182 
5183 class Level_1_Expr(UnaryOpBase): # R702
5184  """
5185  <level-1-expr> = [ <defined-unary-op> ] <primary>
5186  <defined-unary-op> = . <letter> [ <letter> ]... .
5187  """
5188 
5189  subclass_names = ["Primary"]
5190  use_names = []
5191 
5192  @staticmethod
5193  def match(string):
5194  return UnaryOpBase.match(pattern.defined_unary_op.named(), Primary, string)
5195 
5196  # exclude_op_pattern = pattern.non_defined_binary_op)
5197 
5198 
5199 class Defined_Unary_Op(Base): # pylint: disable=invalid-name
5200  """
5201  Fortran 2003 rule R703
5202 
5203  defined-unary-op is . letter [ letter ]... .
5204 
5205  C704 (R703) A defined-unary-op shall not contain more than 63
5206  letters and shall not be the same as any intrinsic-operator or
5207  logical-literal-constant.
5208 
5209  Implemented in Defined_Op class.
5210 
5211  """
5212 
5213  subclass_names = ["Defined_Op"]
5214 
5215 
5216 class Defined_Op(STRINGBase): # pylint: disable=invalid-name
5217  """
5218  Utility class that Implements the functionality of rules R703 and
5219  R723 (as the rules are the same)
5220 
5221  defined-op is . letter [ letter ]... .
5222 
5223  C704 (R723) A defined-binary-op shall not contain more than 63
5224  letters and shall not be the same as any intrinsic-operator or
5225  logical-literal-constant.
5226 
5227  C704 (R703) A defined-unary-op shall not contain more than 63
5228  letters and shall not be the same as any intrinsic-operator or
5229  logical-literal-constant.
5230 
5231  """
5232 
5233  subclass_names = []
5234 
5235  @staticmethod
5236  def match(string):
5237  """Implements the matching for a (user) Defined Unary or Binary
5238  Operator.
5239 
5240  :param str string: Fortran code to check for a match
5241  :return: `None` if there is no match, or a tuple containing \
5242  the matched operator as a string
5243  :rtype: None or (str)
5244 
5245  """
5246  strip_string = string.strip()
5247  if len(strip_string) > 65:
5248  # C704. Must be 63 letters or fewer (Test for >65 due
5249  # to the two dots).
5250  return None
5251  if pattern.non_defined_binary_op.match(strip_string):
5252  # C704. Must not match with an intrinsic-operator or
5253  # logical-literal-constant
5254  return None
5255  return STRINGBase.match(pattern.abs_defined_op, strip_string)
5256 
5257 
5258 class Mult_Operand(BinaryOpBase): # R704
5259  """
5260  <mult-operand> = <level-1-expr> [ <power-op> <mult-operand> ]
5261  <power-op> = **
5262  """
5263 
5264  subclass_names = ["Level_1_Expr"]
5265  use_names = ["Mult_Operand"]
5266 
5267  @staticmethod
5268  def match(string):
5269  return BinaryOpBase.match(
5270  Level_1_Expr, pattern.power_op.named(), Mult_Operand, string, right=False
5271  )
5272 
5273 
5274 class Add_Operand(BinaryOpBase): # pylint: disable=invalid-name
5275  """Fortran 2003 rule R705
5276 
5277  add-operand is [ add-operand mult-op ] mult-operand
5278 
5279  Rule R705 is implemented in two parts, the first with the optional
5280  part included (in the match method for this class) and the second
5281  without the optional part (specified in subclass_names).
5282 
5283  Note rule R708 (mult-op is * or /) is implemented directly here as
5284  the mult_op pattern.
5285 
5286  There is potential to accidentally match a sign in an exponent as the
5287  plus/minus sign in a level-2-expr. If this were to happen then it is
5288  possible to end up matching a * or / (a level 1 expression) before
5289  matching a valid + or - which would normally result in no match
5290  overall as * or / are matched after + or -. This situation is
5291  avoided by tokenising the string before performing the match so
5292  that any numerical constants involving exponents are replaced by
5293  simple symbols. (The tokenisation is performed by
5294  `fparser.common.splitline.string_replace_map`.)
5295 
5296  """
5297 
5298  subclass_names = ["Mult_Operand"]
5299  use_names = ["Mult_Operand"]
5300 
5301  @staticmethod
5302  def match(string):
5303  """Implement the matching for the add-operand rule. Makes use of the
5304  pre-defined mult_op pattern and the BinaryOpBase baseclass.
5305 
5306  :param str string: the string to match.
5307 
5308  :returns: a tuple of size 3 containing an fparser2 class \
5309  instance matching a level-2-expr expression, a string \
5310  containing the matched operator and an fparser2 class \
5311  instance matching a mult-operand if there is a match, or \
5312  None if there is not.
5313  :rtype: (subclass of :py:class:`fparser.two.utils.Base`, str, \
5314  subclass of :py:class:`fparser.two.utils.Base`) or NoneType
5315 
5316  """
5317  return BinaryOpBase.match(
5318  Add_Operand, pattern.mult_op.named(), Mult_Operand, string
5319  )
5320 
5321 
5322 class Level_2_Expr(BinaryOpBase): # R706
5323  """
5324  <level-2-expr> = [ [ <level-2-expr> ] <add-op> ] <add-operand>
5325  <level-2-expr> = [ <level-2-expr> <add-op> ] <add-operand>
5326  | <level-2-unary-expr>
5327  <add-op> = +
5328  | -
5329  """
5330 
5331  subclass_names = ["Level_2_Unary_Expr"]
5332  use_names = ["Level_2_Expr"]
5333 
5334  @staticmethod
5335  def match(string):
5336  return BinaryOpBase.match(
5337  Level_2_Expr, pattern.add_op.named(), Add_Operand, string
5338  )
5339 
5340 
5341 class Level_2_Unary_Expr(UnaryOpBase): # R706.c
5342  """
5343  <level-2-unary-expr> = [ <add-op> ] <add-operand>
5344  """
5345 
5346  subclass_names = ["Add_Operand"]
5347  use_names = []
5348 
5349  @staticmethod
5350  def match(string):
5351  return UnaryOpBase.match(pattern.add_op.named(), Add_Operand, string)
5352 
5353 
5354 # R707: power-op is **
5355 # R708: mult-op is * or /
5356 # R709: add-op is + or -
5357 
5358 
5359 class Level_3_Expr(BinaryOpBase): # R710
5360  """
5361  <level-3-expr> = [ <level-3-expr> <concat-op> ] <level-2-expr>
5362  <concat-op> = //
5363  """
5364 
5365  subclass_names = ["Level_2_Expr"]
5366  use_names = ["Level_3_Expr"]
5367 
5368  @staticmethod
5369  def match(string):
5370  return BinaryOpBase.match(
5371  Level_3_Expr, pattern.concat_op.named(), Level_2_Expr, string
5372  )
5373 
5374 
5375 # R711: <concat-op> = //
5376 
5377 
5378 class Level_4_Expr(BinaryOpBase): # R712
5379  """
5380  <level-4-expr> = [ <level-3-expr> <rel-op> ] <level-3-expr>
5381  <rel-op> = .EQ. | .NE. | .LT. | .LE. | .GT. | .GE. | == |
5382  /= | < | <= | > | >=
5383  """
5384 
5385  subclass_names = ["Level_3_Expr"]
5386  use_names = []
5387 
5388  @staticmethod
5389  def match(string):
5390  return BinaryOpBase.match(
5391  Level_3_Expr, pattern.rel_op.named(), Level_3_Expr, string
5392  )
5393 
5394 
5395 # R713: <rel-op> = .EQ. | .NE. | .LT. | .LE. | .GT. | .GE. |
5396 # == | /= | < | <= | > | >=
5397 
5398 
5399 class And_Operand(UnaryOpBase): # R714
5400  """
5401  <and-operand> = [ <not-op> ] <level-4-expr>
5402  <not-op> = .NOT.
5403  """
5404 
5405  subclass_names = ["Level_4_Expr"]
5406  use_names = []
5407 
5408  @staticmethod
5409  def match(string):
5410  return UnaryOpBase.match(pattern.not_op.named(), Level_4_Expr, string)
5411 
5412 
5413 class Or_Operand(BinaryOpBase): # R715
5414  """
5415  <or-operand> = [ <or-operand> <and-op> ] <and-operand>
5416  <and-op> = .AND.
5417  """
5418 
5419  subclass_names = ["And_Operand"]
5420  use_names = ["Or_Operand", "And_Operand"]
5421 
5422  @staticmethod
5423  def match(string):
5424  return BinaryOpBase.match(
5425  Or_Operand, pattern.and_op.named(), And_Operand, string
5426  )
5427 
5428 
5429 class Equiv_Operand(BinaryOpBase): # R716
5430  """
5431  <equiv-operand> = [ <equiv-operand> <or-op> ] <or-operand>
5432  <or-op> = .OR.
5433  """
5434 
5435  subclass_names = ["Or_Operand"]
5436  use_names = ["Equiv_Operand"]
5437 
5438  @staticmethod
5439  def match(string):
5440  return BinaryOpBase.match(
5441  Equiv_Operand, pattern.or_op.named(), Or_Operand, string
5442  )
5443 
5444 
5445 class Level_5_Expr(BinaryOpBase): # R717
5446  """
5447  <level-5-expr> = [ <level-5-expr> <equiv-op> ] <equiv-operand>
5448  <equiv-op> = .EQV.
5449  | .NEQV.
5450  """
5451 
5452  subclass_names = ["Equiv_Operand"]
5453  use_names = ["Level_5_Expr"]
5454 
5455  @staticmethod
5456  def match(string):
5457  return BinaryOpBase.match(
5458  Level_5_Expr, pattern.equiv_op.named(), Equiv_Operand, string
5459  )
5460 
5461 
5462 # R718: <not-op> = .NOT.
5463 # R719: <and-op> = .AND.
5464 # R720: <or-op> = .OR.
5465 # R721: <equiv-op> = .EQV. | .NEQV.
5466 
5467 
5468 class Expr(BinaryOpBase): # R722
5469  """
5470  <expr> = [ <expr> <defined-binary-op> ] <level-5-expr>
5471  <defined-binary-op> = . <letter> [ <letter> ]... .
5472  """
5473 
5474  subclass_names = ["Level_5_Expr"]
5475  use_names = ["Expr"]
5476 
5477  @staticmethod
5478  def match(string):
5479  return BinaryOpBase.match(
5480  Expr,
5481  pattern.defined_binary_op.named(),
5482  Level_5_Expr,
5483  string,
5484  exclude_op_pattern=pattern.non_defined_binary_op,
5485  )
5486 
5487 
5488 class Defined_Binary_Op(Base): # pylint: disable=invalid-name
5489  """
5490  Fortran 2003 rule R723
5491 
5492  defined-binary-op is . letter [ letter ]... .
5493 
5494  C704 (R723) A defined-binary-op shall not contain more than 63
5495  letters and shall not be the same as any intrinsic-operator or
5496  logical-literal-constant.
5497 
5498  Implemented in Defined_Op class.
5499 
5500  """
5501 
5502  subclass_names = ["Defined_Op"]
5503 
5504 
5505 class Logical_Expr(Base): # pylint: disable=invalid-name
5506  """
5507  Fortran 2003 rule R724
5508 
5509  logical-expr is expr
5510 
5511  C705 logical-expr shall be of type logical.
5512 
5513  """
5514 
5515  subclass_names = []
5516 
5517  @staticmethod
5518  def match(string):
5519  """Implements the matching for a logical expression.
5520 
5521  Note, whilst we exclude Signed_Int_Literal_Constant and
5522  Signed_Real_Literal_Constant, it seems that it is not possible
5523  to create these from code as a "-" sign is treated as a unary
5524  operator.
5525 
5526  :param str string: Fortran code to check for a match.
5527  :returns: `None` if there is no match, or an fparser2 class \
5528  instance containing the matched expression.
5529  :rtype: NoneType or :py:class:`fparser.two.utils.Base`
5530 
5531  """
5532  excluded = (
5533  Signed_Int_Literal_Constant,
5534  Int_Literal_Constant,
5535  Binary_Constant,
5536  Octal_Constant,
5537  Hex_Constant,
5538  Signed_Real_Literal_Constant,
5539  Real_Literal_Constant,
5540  Complex_Literal_Constant,
5541  Char_Literal_Constant,
5542  )
5543  # Attempt to match as a general expression.
5544  result = Expr(string)
5545  # C705: the match should fail if the result is not a logical
5546  # expression. This is difficult to check in general so for the
5547  # time being check that, in the case where a literal constant
5548  # is returned, this is not of the wrong type.
5549  if isinstance(result, excluded):
5550  return None
5551  return result
5552 
5553 
5554 class Char_Expr(Base): # pylint: disable=invalid-name
5555  """
5556  Fortran 2003 rule R725
5557 
5558  char-expr is expr
5559 
5560  C706 char-expr shall be of type character.
5561 
5562  """
5563 
5564  subclass_names = []
5565 
5566  @staticmethod
5567  def match(string):
5568  """Implements the matching for a character expression.
5569 
5570  :param str string: Fortran code to check for a match.
5571  :returns: `None` if there is no match, or an fparser2 class \
5572  instance containing the matched expression.
5573  :rtype: NoneType or :py:class:`fparser.two.utils.Base`
5574 
5575  """
5576  excluded = (
5577  Signed_Int_Literal_Constant,
5578  Int_Literal_Constant,
5579  Binary_Constant,
5580  Octal_Constant,
5581  Hex_Constant,
5582  Signed_Real_Literal_Constant,
5583  Real_Literal_Constant,
5584  Complex_Literal_Constant,
5585  Logical_Literal_Constant,
5586  )
5587  # Attempt to match as a general expression.
5588  result = Expr(string)
5589  # C706: the match should fail if the result is not a character
5590  # expression. This is difficult to check in general so for the
5591  # time being check that, in the case where a literal constant
5592  # is returned, this is not of the wrong type.
5593  if isinstance(result, excluded):
5594  return None
5595  return result
5596 
5597 
5598 class Default_Char_Expr(Base): # pylint: disable=invalid-name
5599  """
5600  Fortran 2003 rule R726
5601 
5602  default-char-expr is expr
5603 
5604  C707 default-char-expr shall be of type default character.
5605 
5606  """
5607 
5608  subclass_names = []
5609 
5610  @staticmethod
5611  def match(string):
5612  """Implements the matching for a default character expression.
5613 
5614  :param str string: Fortran code to check for a match.
5615  :returns: `None` if there is no match, or an fparser2 class \
5616  instance containing the matched expression.
5617  :rtype: NoneType or :py:class:`fparser.two.utils.Base`
5618 
5619  """
5620  excluded = (
5621  Signed_Int_Literal_Constant,
5622  Int_Literal_Constant,
5623  Binary_Constant,
5624  Octal_Constant,
5625  Hex_Constant,
5626  Signed_Real_Literal_Constant,
5627  Real_Literal_Constant,
5628  Complex_Literal_Constant,
5629  Logical_Literal_Constant,
5630  )
5631  # Attempt to match as a general expression.
5632  result = Expr(string)
5633  # C707: the match should fail if the result is not a character
5634  # expression. This is difficult to check in general so for the
5635  # time being check that, in the case where a literal constant
5636  # is returned, this is not of the wrong type.
5637  if isinstance(result, excluded):
5638  return None
5639  return result
5640 
5641 
5642 class Int_Expr(Base): # pylint: disable=invalid-name
5643  """
5644  Fortran 2003 rule R727
5645 
5646  int-expr is expr
5647 
5648  C708 int-expr shall be of type integer.
5649 
5650  """
5651 
5652  subclass_names = []
5653 
5654  @staticmethod
5655  def match(string):
5656  """Implements the matching for an integer expression.
5657 
5658  :param str string: Fortran code to check for a match.
5659  :returns: `None` if there is no match, or an fparser2 class \
5660  instance containing the matched expression.
5661  :rtype: NoneType or :py:class:`fparser.two.utils.Base`
5662 
5663  """
5664  excluded = (
5665  Binary_Constant,
5666  Octal_Constant,
5667  Hex_Constant,
5668  Signed_Real_Literal_Constant,
5669  Real_Literal_Constant,
5670  Complex_Literal_Constant,
5671  Char_Literal_Constant,
5672  Logical_Literal_Constant,
5673  )
5674  # Attempt to match as a general expression.
5675  result = Expr(string)
5676  # C708: the match should fail if the result is not an integer
5677  # expression. This is difficult to check in general so for the
5678  # time being check that, in the case where a literal constant
5679  # is returned, this is not of the wrong type.
5680  if isinstance(result, excluded):
5681  return None
5682  return result
5683 
5684 
5685 class Numeric_Expr(Base): # pylint: disable=invalid-name
5686  """
5687  Fortran 2003 rule R728
5688 
5689  numeric-expr is expr
5690 
5691  C709 numeric-expr shall be of type integer, real or complex.
5692 
5693  """
5694 
5695  subclass_names = []
5696 
5697  @staticmethod
5698  def match(string):
5699  """Implements the matching for a numeric expression.
5700 
5701  :param str string: Fortran code to check for a match.
5702  :returns: `None` if there is no match, or an fparser2 class \
5703  instance containing the matched expression.
5704  :rtype: NoneType or :py:class:`fparser.two.utils.Base`
5705 
5706  """
5707  excluded = (
5708  Binary_Constant,
5709  Octal_Constant,
5710  Hex_Constant,
5711  Char_Literal_Constant,
5712  Logical_Literal_Constant,
5713  )
5714  # Attempt to match as a general expression.
5715  result = Expr(string)
5716  # C709: the match should fail if the result is not an integer,
5717  # real or complex expression. This is difficult to check in
5718  # general so for the time being check that, in the case where
5719  # a literal constant is returned, this is not of the wrong
5720  # type.
5721  if isinstance(result, excluded):
5722  return None
5723  return result
5724 
5725 
5726 class Specification_Expr(Base): # R729
5727  """
5728  <specification-expr> = <scalar-int-expr>
5729  """
5730 
5731  subclass_names = ["Scalar_Int_Expr"]
5732 
5733 
5734 class Initialization_Expr(Base): # R730
5735  """
5736  <initialization-expr> = <expr>
5737  """
5738 
5739  subclass_names = ["Expr"]
5740 
5741 
5742 class Char_Initialization_Expr(Base): # R731
5743  """
5744  <char-initialization-expr> = <char-expr>
5745  """
5746 
5747  subclass_names = ["Char_Expr"]
5748 
5749 
5750 class Int_Initialization_Expr(Base): # R732
5751  """
5752  <int-initialization-expr> = <int-expr>
5753  """
5754 
5755  subclass_names = ["Int_Expr"]
5756 
5757 
5758 class Logical_Initialization_Expr(Base): # R733
5759  """
5760  <logical-initialization-expr> = <logical-expr>
5761  """
5762 
5763  subclass_names = ["Logical_Expr"]
5764 
5765 
5766 class Assignment_Stmt(StmtBase, BinaryOpBase): # R734
5767  """
5768  <assignment-stmt> = <variable> = <expr>
5769  """
5770 
5771  subclass_names = []
5772  use_names = ["Variable", "Expr"]
5773 
5774  @staticmethod
5775  def match(string):
5776  return BinaryOpBase.match(Variable, "=", Expr, string, right=False)
5777 
5778 
5779 class Pointer_Assignment_Stmt(StmtBase): # R735
5780  """
5781  <pointer-assignment-stmt> = <data-pointer-object> [
5782  ( <bounds-spec-list> ) ] => <data-target>
5783  | <data-pointer-object> ( <bounds-remapping-list> ) => <data-target>
5784  | <proc-pointer-object> => <proc-target>
5785  """
5786 
5787  subclass_names = []
5788  use_names = [
5789  "Data_Pointer_Object",
5790  "Bounds_Spec_List",
5791  "Data_Target",
5792  "Bounds_Remapping_List",
5793  "Proc_Pointer_Object",
5794  "Proc_Target",
5795  ]
5796 
5797  @staticmethod
5798  def match(string):
5799  line, repmap = string_replace_map(string)
5800  i = line.find("=>")
5801  if i == -1:
5802  return
5803  lhs = line[:i].rstrip()
5804  rhs = repmap(line[i + 2 :].lstrip())
5805  if lhs.endswith(")"):
5806  i = lhs.rfind("(")
5807  if i == -1:
5808  return
5809  o = repmap(lhs[:i].rstrip())
5810  tmp = repmap(lhs[i + 1 : -1].strip())
5811  try:
5812  return Data_Pointer_Object(o), Bounds_Spec_List(tmp), Data_Target(rhs)
5813  except NoMatchError as msg:
5814  return (
5816  Bounds_Remapping_List(tmp),
5817  Data_Target(rhs),
5818  )
5819  else:
5820  lhs = repmap(lhs)
5821  try:
5822  return Data_Pointer_Object(lhs), None, Data_Target(rhs)
5823  except NoMatchError as msg:
5824  return Proc_Pointer_Object(lhs), None, Proc_Target(rhs)
5825 
5826  def tostr(self):
5827  if self.items[1] is None:
5828  return "%s => %s" % (self.items[0], self.items[2])
5829  return "%s(%s) => %s" % (self.items)
5830 
5831 
5832 class Data_Pointer_Object(BinaryOpBase): # R736
5833  """
5834  <data-pointer-object> = <variable-name>
5835  | <variable> % <data-pointer-component-name>
5836  """
5837 
5838  subclass_names = ["Variable_Name"]
5839  use_names = ["Variable", "Data_Pointer_Component_Name"]
5840 
5841  @staticmethod
5842  def match(string):
5843  return BinaryOpBase.match(Variable, r"%", Data_Pointer_Component_Name, string)
5844 
5845 
5846 class Bounds_Spec(SeparatorBase): # R737
5847  """
5848  <bounds-spec> = <lower-bound-expr> :
5849  """
5850 
5851  subclass_names = []
5852  use_names = ["Lower_Bound_Expr"]
5853 
5854  @staticmethod
5855  def match(string):
5856  return SeparatorBase.match(Lower_Bound_Expr, None, string, require_lhs=True)
5857 
5858 
5859 class Bounds_Remapping(SeparatorBase): # R738
5860  """
5861  <bounds-remapping> = <lower-bound-expr> : <upper-bound-expr>
5862  """
5863 
5864  subclass_names = []
5865  use_classes = ["Lower_Bound_Expr", "Upper_Bound_Expr"]
5866 
5867  @staticmethod
5868  def match(string):
5869  return SeparatorBase.match(
5870  Lower_Bound_Expr,
5871  Upper_Bound_Expr,
5872  string,
5873  require_lhs=True,
5874  require_rhs=True,
5875  )
5876 
5877 
5878 class Data_Target(Base): # R739
5879  """
5880  <data-target> = <variable>
5881  | <expr>
5882  """
5883 
5884  subclass_names = ["Variable", "Expr"]
5885 
5886 
5887 class Proc_Pointer_Object(Base): # R740
5888  """
5889  <proc-pointer-object> = <proc-pointer-name>
5890  | <proc-component-ref>
5891  """
5892 
5893  subclass_names = ["Proc_Pointer_Name", "Proc_Component_Ref"]
5894 
5895 
5896 class Proc_Component_Ref(BinaryOpBase): # R741
5897  """
5898  <proc-component-ref> = <variable> % <procedure-component-name>
5899  """
5900 
5901  subclass_names = []
5902  use_names = ["Variable", "Procedure_Component_Name"]
5903 
5904  @staticmethod
5905  def match(string):
5906  return BinaryOpBase.match(Variable, r"%", Procedure_Component_Name, string)
5907 
5908 
5909 class Proc_Target(Base): # R742
5910  """
5911  <proc-target> = <expr>
5912  | <procedure-name>
5913  | <proc-component-ref>
5914  """
5915 
5916  subclass_names = ["Proc_Component_Ref", "Procedure_Name", "Expr"]
5917 
5918 
5919 class Where_Stmt(StmtBase): # R743
5920  """
5921  <where-stmt> = WHERE ( <mask-expr> ) <where-assignment-stmt>
5922  """
5923 
5924  subclass_names = []
5925  use_names = ["Mask_Expr", "Where_Assignment_Stmt"]
5926 
5927  @staticmethod
5928  def match(string):
5929  if string[:5].upper() != "WHERE":
5930  return
5931  line, repmap = string_replace_map(string[5:].lstrip())
5932  if not line.startswith("("):
5933  return
5934  i = line.find(")")
5935  if i == -1:
5936  return
5937  stmt = repmap(line[i + 1 :].lstrip())
5938  if not stmt:
5939  return
5940  expr = repmap(line[1:i].strip())
5941  if not expr:
5942  return
5943  return Mask_Expr(expr), Where_Assignment_Stmt(stmt)
5944 
5945  def tostr(self):
5946  return "WHERE (%s) %s" % tuple(self.items)
5947 
5948 
5949 class Where_Construct(BlockBase): # R744
5950  """
5951  <where-construct> = <where-construct-stmt>
5952  [ <where-body-construct> ]...
5953  [ <masked-elsewhere-stmt>
5954  [ <where-body-construct> ]...
5955  ]...
5956  [ <elsewhere-stmt>
5957  [ <where-body-construct> ]... ]
5958  <end-where-stmt>
5959  """
5960 
5961  subclass_names = []
5962  use_names = [
5963  "Where_Construct_Stmt",
5964  "Where_Body_Construct",
5965  "Masked_Elsewhere_Stmt",
5966  "Elsewhere_Stmt",
5967  "End_Where_Stmt",
5968  ]
5969 
5970  @staticmethod
5971  def match(string):
5972  return BlockBase.match(
5973  Where_Construct_Stmt,
5974  [
5975  Where_Body_Construct,
5976  Masked_Elsewhere_Stmt,
5977  Where_Body_Construct,
5978  Elsewhere_Stmt,
5979  Where_Body_Construct,
5980  ],
5981  End_Where_Stmt,
5982  string,
5983  match_names=True, # C730
5984  strict_match_names=True, # C730
5985  match_name_classes=(
5986  Masked_Elsewhere_Stmt,
5987  Elsewhere_Stmt,
5988  End_Where_Stmt,
5989  ), # C730
5990  enable_where_construct_hook=True,
5991  )
5992 
5993  def tofortran(self, tab="", isfix=None):
5994  """
5995  Converts this node (and all children) into Fortran.
5996 
5997  :param str tab: white space to prefix to output.
5998  :param bool isfix: whether or not to generate fixed-format output.
5999 
6000  :returns: Fortran code.
6001  :rtype: str
6002 
6003  """
6004  tmp = []
6005  start = self.content[0]
6006  end = self.content[-1]
6007  tmp.append(start.tofortran(tab=tab, isfix=isfix))
6008  for item in self.content[1:-1]:
6009  if isinstance(item, (Masked_Elsewhere_Stmt, Elsewhere_Stmt)):
6010  tmp.append(item.tofortran(tab=tab, isfix=isfix))
6011  else:
6012  tmp.append(item.tofortran(tab=tab + " ", isfix=isfix))
6013  tmp.append(end.tofortran(tab=tab, isfix=isfix))
6014  return "\n".join(tmp)
6015 
6016 
6017 class Where_Construct_Stmt(StmtBase): # R745
6018  """
6019  <where-construct-stmt> = [ <where-construct-name> : ] WHERE ( <mask-expr> )
6020  """
6021 
6022  subclass_names = []
6023  use_names = ["Where_Construct_Name", "Mask_Expr"]
6024 
6025  @staticmethod
6026  def match(string):
6027  if string[:5].upper() != "WHERE":
6028  return
6029  line = string[5:].lstrip()
6030  if not line:
6031  return
6032  if line[0] + line[-1] != "()":
6033  return
6034  line = line[1:-1].strip()
6035  if not line:
6036  return
6037  return (Mask_Expr(line),)
6038 
6039  def tostr(self):
6040  return "WHERE (%s)" % tuple(self.items)
6041 
6042  def get_start_name(self):
6043  return self.item.name
6044 
6045 
6046 class Where_Body_Construct(Base): # R746
6047  """
6048  ::
6049  <where-body-construct> = <where-assignment-stmt>
6050  | <where-stmt>
6051  | <where-construct>
6052  """
6053 
6054  subclass_names = ["Where_Assignment_Stmt", "Where_Stmt", "Where_Construct"]
6055 
6056 
6057 class Where_Assignment_Stmt(Base): # R747
6058  """
6059  ::
6060  <where-assignment-stmt> = <assignment-stmt>
6061  """
6062 
6063  subclass_names = ["Assignment_Stmt"]
6064 
6065 
6066 class Mask_Expr(Base): # R748
6067  """
6068  <mask-expr> = <logical-expr>
6069  """
6070 
6071  subclass_names = ["Logical_Expr"]
6072 
6073 
6074 class Masked_Elsewhere_Stmt(StmtBase): # R749
6075  """
6076  <masked-elsewhere-stmt> = ELSEWHERE
6077  ( <mask-expr> ) [ <where-construct-name> ]
6078  """
6079 
6080  import re
6081 
6082  subclass_names = []
6083  use_names = ["Mask_Expr", "Where_Construct_Name"]
6084 
6085  @staticmethod
6086  def match(string):
6087  if not Elsewhere_Stmt._regex.match(string):
6088  return
6089  idx = string.upper().index("WHERE")
6090  line = string[idx + 5 :].lstrip()
6091 
6092  if not line.startswith("("):
6093  return
6094  i = line.rfind(")")
6095  if i == -1:
6096  return
6097  expr = line[1:i].strip()
6098  if not expr:
6099  return
6100  line = line[i + 1 :].rstrip()
6101  if line:
6102  return Mask_Expr(expr), Where_Construct_Name(line)
6103  return Mask_Expr(expr), None
6104 
6105  def tostr(self):
6106  if self.items[1] is None:
6107  return "ELSEWHERE(%s)" % (self.items[0])
6108  return "ELSEWHERE(%s) %s" % self.items
6109 
6110  def get_end_name(self):
6111  """
6112  :return: the name at the END of this block, if it exists
6113  :rtype: str or NoneType
6114  """
6115  name = self.items[1]
6116  if name is not None:
6117  return name.string
6118  return None
6119 
6120 
6121 class Elsewhere_Stmt(StmtBase, WORDClsBase): # R750
6122  """
6123  <elsewhere-stmt> = ELSEWHERE [ <where-construct-name> ]
6124  """
6125 
6126  subclass_names = []
6127  use_names = ["Where_Construct_Name"]
6128  _regex = re.compile(r"ELSE\s*WHERE", re.I)
6129 
6130  @staticmethod
6131  def match(string):
6132  if not Elsewhere_Stmt._regex.match(string):
6133  return
6134  idx = string.upper().index("WHERE")
6135  line = string[idx + 5 :].lstrip()
6136  if line:
6137  return "ELSEWHERE", Where_Construct_Name(line)
6138  return "ELSEWHERE", None
6139 
6140  def get_end_name(self):
6141  """
6142  :return: the name at the END of this block, if it exists
6143  :rtype: str or NoneType
6144  """
6145  name = self.items[1]
6146  if name is not None:
6147  return name.string
6148  return None
6149 
6150 
6151 class End_Where_Stmt(EndStmtBase): # R751
6152  """
6153  <end-where-stmt> = END WHERE [ <where-construct-name> ]
6154  """
6155 
6156  subclass_names = []
6157  use_names = ["Where_Construct_Name"]
6158 
6159  @staticmethod
6160  def match(string):
6161  return EndStmtBase.match(
6162  "WHERE", Where_Construct_Name, string, require_stmt_type=True
6163  )
6164 
6165 
6166 class Forall_Construct(BlockBase): # R752
6167  """
6168  <forall-construct> = <forall-construct-stmt>
6169  [ <forall-body-construct> ]...
6170  <end-forall-stmt>
6171  """
6172 
6173  subclass_names = []
6174  use_names = ["Forall_Construct_Stmt", "Forall_Body_Construct", "End_Forall_Stmt"]
6175 
6176  @staticmethod
6177  def match(reader):
6178  return BlockBase.match(
6179  Forall_Construct_Stmt,
6180  [Forall_Body_Construct],
6181  End_Forall_Stmt,
6182  reader,
6183  match_names=True, # C732
6184  strict_match_names=True, # C732
6185  )
6186 
6187 
6188 class Forall_Construct_Stmt(StmtBase, WORDClsBase): # R753
6189  """
6190  <forall-construct-stmt> = [ <forall-construct-name> : ]
6191  FORALL <forall-header>
6192  """
6193 
6194  subclass_names = []
6195  use_names = ["Forall_Construct_Name", "Forall_Header"]
6196 
6197  @staticmethod
6198  def match(string):
6199  return WORDClsBase.match("FORALL", Forall_Header, string, require_cls=True)
6200 
6201  def get_start_name(self):
6202  return self.item.name
6203 
6204 
6205 class Forall_Header(Base): # pylint: disable=invalid-name
6206  """
6207  Fortran 2003 rule R754
6208  forall-header is ( forall-triplet-spec-list [, scalar-mask-expr ] )
6209 
6210  """
6211 
6212  subclass_names = []
6213  use_names = ["Forall_Triplet_Spec_List", "Scalar_Mask_Expr"]
6214 
6215  @staticmethod
6216  def match(string):
6217  """Implements the matching for a Forall_Header.
6218 
6219  :param str string: A string containing the code to match.
6220  :return: `None` if there is no match, otherwise a `tuple` of \
6221  size 2 containing a class of type \
6222  `Forall_Triplet_Spec_List` and a class of type \
6223  `Scalar_Mask_Expr` if there is a scalar mask \
6224  expresssion and `None` if not.
6225  :rtype: (`Forall_Triplet_Spec_List`, `Scalar_Mask_Expr`) or \
6226  (`Forall_Triplet_Spec_List`, `None`) or `None`
6227 
6228  """
6229  strip_string = string.strip()
6230  if not strip_string:
6231  # Input only contains white space
6232  return None
6233  if strip_string[0] + strip_string[-1] != "()":
6234  # Input does not start with '(' and end with ')'
6235  return None
6236  strip_string_nobr = strip_string[1:-1].strip()
6237  try:
6238  # first try to match without a scalar mask expression
6239  return Forall_Triplet_Spec_List(strip_string_nobr), None
6240  except NoMatchError:
6241  # The match failed so try to match with the optional
6242  # scalar mask expression. Use repmap to remove any
6243  # unexpected "," e.g. an array access a(i,j), when
6244  # splitting the string.
6245  mapped_string, repmap = string_replace_map(strip_string_nobr)
6246  split_string = mapped_string.rsplit(",", 1)
6247  if len(split_string) != 2:
6248  return None
6249  left_str = repmap(split_string[0].rstrip())
6250  right_str = repmap(split_string[1].lstrip())
6251  return (Forall_Triplet_Spec_List(left_str), Scalar_Mask_Expr(right_str))
6252 
6253  def tostr(self):
6254  """:return: this Forall Header as a string
6255  :rtype: str
6256  :raises InternalError: if the length of the internal items \
6257  list is not 2.
6258  :raises InternalError: if the first entry of the internal \
6259  items list has no content, as a Forall_Triplet_List is \
6260  expected.
6261 
6262  """
6263  if len(self.items) != 2:
6264  raise InternalError(
6265  "Forall_Header.tostr(). 'items' should be of size 2 but "
6266  "found '{0}'.".format(len(self.items))
6267  )
6268  if not self.items[0]:
6269  raise InternalError(
6270  "Forall_Header.tostr(). 'items[0]' should be a "
6271  "Forall_Triplet_Spec_List instance but it is empty."
6272  )
6273  if not self.items[1]:
6274  # there is no scalar mask expression
6275  return "({0})".format(self.items[0])
6276  return "({0}, {1})".format(self.items[0], self.items[1])
6277 
6278 
6279 class Forall_Triplet_Spec(Base): # R755
6280  """
6281  <forall-triplet-spec> = <index-name> = <subscript> :
6282  <subscript> [ : <stride> ]
6283  """
6284 
6285  subclass_names = []
6286  use_names = ["Index_Name", "Subscript", "Stride"]
6287 
6288  @staticmethod
6289  def match(string):
6290  line, repmap = string_replace_map(string)
6291  i = line.find("=")
6292  if i == -1:
6293  return
6294  n = Index_Name(repmap(line[:i].rstrip()))
6295  line = line[i + 1 :].lstrip()
6296  s = [repmap(s.strip()) for s in line.split(":")]
6297  if len(s) == 2:
6298  return n, Subscript(s[0]), Subscript(s[1]), None
6299  if len(s) == 3:
6300  return n, Subscript(s[0]), Subscript(s[1]), Stride(s[2])
6301 
6302  def tostr(self):
6303  if self.items[3] is None:
6304  return "%s = %s : %s" % (self.items[:3])
6305  return "%s = %s : %s : %s" % (self.items)
6306 
6307 
6308 class Forall_Body_Construct(Base): # R756
6309  """
6310  <forall-body-construct> = <forall-assignment-stmt>
6311  | <where-stmt>
6312  | <where-construct>
6313  | <forall-construct>
6314  | <forall-stmt>
6315  """
6316 
6317  subclass_names = [
6318  "Forall_Assignment_Stmt",
6319  "Where_Stmt",
6320  "Where_Construct",
6321  "Forall_Construct",
6322  "Forall_Stmt",
6323  ]
6324 
6325 
6326 class Forall_Assignment_Stmt(Base): # R757
6327  """
6328  <forall-assignment-stmt> = <assignment-stmt>
6329  | <pointer-assignment-stmt>
6330  """
6331 
6332  subclass_names = ["Assignment_Stmt", "Pointer_Assignment_Stmt"]
6333 
6334 
6335 class End_Forall_Stmt(EndStmtBase): # R758
6336  """
6337  <end-forall-stmt> = END FORALL [ <forall-construct-name> ]
6338  """
6339 
6340  subclass_names = []
6341  use_names = ["Forall_Construct_Name"]
6342 
6343  @staticmethod
6344  def match(string):
6345  return EndStmtBase.match(
6346  "FORALL", Forall_Construct_Name, string, require_stmt_type=True
6347  )
6348 
6349 
6350 class Forall_Stmt(StmtBase): # pylint: disable=invalid-name
6351  """
6352  Fortran 2003 rule R759
6353  forall-stmt is FORALL forall-header forall-assignment-stmt
6354 
6355  """
6356 
6357  subclass_names = []
6358  use_names = ["Forall_Header", "Forall_Assignment_Stmt"]
6359 
6360  @staticmethod
6361  def match(string):
6362  """Implements the matching for a forall statement.
6363 
6364  :param string: A string or the fortran reader containing the \
6365  line of code that we are trying to match.
6366  :type string: `str` or \
6367  :py:class:`fparser.common.readfortran.FortranReader`
6368  :return: `None` if there is no match or a `tuple` of size 2 \
6369  containing an instance of the Forall_Header class followed by \
6370  an instance of the Forall_Assignment_Stmt class.
6371  :rtype: `None` or ( \
6372  :py:class:`fparser.two.Fortran2003.Forall_Header`, \
6373  :py:class:`fparser.two.Fortran2003.Forall_Assignment_Stmt`)
6374 
6375  """
6376  strip_string = string.strip()
6377  if strip_string[:6].upper() != "FORALL":
6378  return None
6379  line, repmap = string_replace_map(strip_string[6:].lstrip())
6380  if not line.startswith("("):
6381  return None
6382  index = line.find(")")
6383  if index == -1:
6384  return None
6385  header = repmap(line[: index + 1])
6386  # No need to check if header variable is empty as we know it
6387  # will contain brackets at least
6388  line = repmap(line[index + 1 :].lstrip())
6389  if not line:
6390  return None
6391  return Forall_Header(header), Forall_Assignment_Stmt(line)
6392 
6393  def tostr(self):
6394  """
6395  :return: this forall statement as a string
6396  :rtype: str
6397  :raises InternalError: if the internal items list variable is \
6398  not the expected size.
6399  :raises InternalError: if the first element of the internal \
6400  items list is None or is an empty string.
6401  :raises InternalError: if the second element of the internal \
6402  items list is None or is an empty string.
6403  """
6404  if len(self.items) != 2:
6405  raise InternalError(
6406  "Class Forall_Stmt method tostr() has '{0}' items, "
6407  "but expecting 2.".format(len(self.items))
6408  )
6409  if not self.items[0]:
6410  raise InternalError(
6411  "Class Forall_Stmt method tostr(). 'Items' entry 0 "
6412  "should be a valid Forall_Header."
6413  )
6414  if not self.items[1]:
6415  raise InternalError(
6416  "Class Forall_Stmt method tostr(). 'Items' entry 1 should "
6417  "be a valid Forall_Assignment_Stmt"
6418  )
6419  return "FORALL {0} {1}".format(self.items[0], self.items[1])
6420 
6421 
6422 #
6423 # SECTION 8
6424 #
6425 
6426 
6427 class Block(BlockBase): # R801
6428  """
6429  <block> = [ <execution-part-construct> ]...
6430  """
6431 
6432  subclass_names = []
6433  use_names = ["Execution_Part_Construct"]
6434 
6435  @staticmethod
6436  def match(string):
6437  return BlockBase.match(None, [Execution_Part_Construct], None, string)
6438 
6439 
6440 class If_Construct(BlockBase): # R802
6441  """
6442  <if-construct> = <if-then-stmt>
6443  <block>
6444  [ <else-if-stmt>
6445  <block>
6446  ]...
6447  [ <else-stmt>
6448  <block>
6449  ]
6450  <end-if-stmt>
6451  """
6452 
6453  subclass_names = []
6454  use_names = ["If_Then_Stmt", "Block", "Else_If_Stmt", "Else_Stmt", "End_If_Stmt"]
6455 
6456  @staticmethod
6457  def match(string):
6458  return BlockBase.match(
6459  If_Then_Stmt,
6460  [
6461  Execution_Part_Construct,
6462  Else_If_Stmt,
6463  Execution_Part_Construct,
6464  Else_Stmt,
6465  Execution_Part_Construct,
6466  ],
6467  End_If_Stmt,
6468  string,
6469  match_names=True, # C801
6470  strict_match_names=True, # C801
6471  match_name_classes=(Else_If_Stmt, Else_Stmt, End_If_Stmt),
6472  enable_if_construct_hook=True,
6473  )
6474 
6475  def tofortran(self, tab="", isfix=None):
6476  """
6477  Converts this node (and all children) into Fortran.
6478 
6479  :param str tab: white space to prefix to output.
6480  :param bool isfix: whether or not to generate fixed-format output.
6481 
6482  :returns: Fortran code.
6483  :rtype: str
6484 
6485  """
6486  tmp = []
6487  start = self.content[0]
6488  end = self.content[-1]
6489  tmp.append(start.tofortran(tab=tab, isfix=isfix))
6490  for item in self.content[1:-1]:
6491  if isinstance(item, (Else_If_Stmt, Else_Stmt)):
6492  tmp.append(item.tofortran(tab=tab, isfix=isfix))
6493  else:
6494  tmp.append(item.tofortran(tab=tab + " ", isfix=isfix))
6495  tmp.append(end.tofortran(tab=tab, isfix=isfix))
6496  return "\n".join(tmp)
6497 
6498 
6499 class If_Then_Stmt(StmtBase): # R803
6500  """
6501  <if-then-stmt> = [ <if-construct-name> : ]
6502  IF ( <scalar-logical-expr> ) THEN
6503  """
6504 
6505  subclass_names = []
6506  use_names = ["If_Construct_Name", "Scalar_Logical_Expr"]
6507 
6508  @staticmethod
6509  def match(string):
6510  if string[:2].upper() != "IF":
6511  return
6512  if string[-4:].upper() != "THEN":
6513  return
6514  line = string[2:-4].strip()
6515  if not line:
6516  return
6517  if line[0] + line[-1] != "()":
6518  return
6519  return (Scalar_Logical_Expr(line[1:-1].strip()),)
6520 
6521  def tostr(self):
6522  return "IF (%s) THEN" % self.items
6523 
6524  def get_start_name(self):
6525  return self.item.name
6526 
6527 
6528 class Else_If_Stmt(StmtBase): # R804
6529  """
6530  <else-if-stmt> = ELSE IF ( <scalar-logical-expr> ) THEN
6531  [ <if-construct-name> ]
6532  """
6533 
6534  subclass_names = []
6535  use_names = ["Scalar_Logical_Expr", "If_Construct_Name"]
6536 
6537  @staticmethod
6538  def match(string):
6539  if string[:4].upper() != "ELSE":
6540  return
6541  line = string[4:].lstrip()
6542  if line[:2].upper() != "IF":
6543  return
6544  line = line[2:].lstrip()
6545  if not line.startswith("("):
6546  return
6547  i = line.rfind(")")
6548  if i == -1:
6549  return
6550  expr = line[1:i].strip()
6551  line = line[i + 1 :].lstrip()
6552  if line[:4].upper() != "THEN":
6553  return
6554  line = line[4:].lstrip()
6555  if line:
6556  return Scalar_Logical_Expr(expr), If_Construct_Name(line)
6557  return Scalar_Logical_Expr(expr), None
6558 
6559  def tostr(self):
6560  if self.items[1] is None:
6561  return "ELSE IF (%s) THEN" % (self.items[0])
6562  return "ELSE IF (%s) THEN %s" % self.items
6563 
6564  def get_end_name(self):
6565  """
6566  :return: the name at the END of this block, if it exists
6567  :rtype: str or NoneType
6568  """
6569  name = self.items[1]
6570  if name is not None:
6571  return name.string
6572  return None
6573 
6574 
6575 class Else_Stmt(StmtBase): # R805
6576  """
6577  <else-stmt> = ELSE [ <if-construct-name> ]
6578  """
6579 
6580  subclass_names = []
6581  use_names = ["If_Construct_Name"]
6582 
6583  @staticmethod
6584  def match(string):
6585  if string[:4].upper() != "ELSE":
6586  return
6587  line = string[4:].lstrip()
6588  if line:
6589  return (If_Construct_Name(line),)
6590  return (None,)
6591 
6592  def tostr(self):
6593  if self.items[0] is None:
6594  return "ELSE"
6595  return "ELSE %s" % self.items
6596 
6597  def get_end_name(self):
6598  """
6599  :return: the name at the END of this block, if it exists
6600  :rtype: str or NoneType
6601  """
6602  name = self.items[0]
6603  if name is not None:
6604  return name.string
6605  return None
6606 
6607 
6608 class End_If_Stmt(EndStmtBase): # R806
6609  """
6610  <end-if-stmt> = END IF [ <if-construct-name> ]
6611  """
6612 
6613  subclass_names = []
6614  use_names = ["If_Construct_Name"]
6615 
6616  @staticmethod
6617  def match(string):
6618  return EndStmtBase.match(
6619  "IF", If_Construct_Name, string, require_stmt_type=True
6620  )
6621 
6622 
6623 class If_Stmt(StmtBase): # R807
6624  """
6625  Fortran 2003 rule R807
6626 
6627  if-stmt is IF ( scalar-logical-expr ) action-stmt
6628 
6629  C802 (R807) The action-stmt in the if-stmt shall not be an if-stmt,
6630  end-program-stmt, end-function-stmt, or end-subroutine-stmt.
6631 
6632  """
6633 
6634  subclass_names = []
6635  use_names = ["Scalar_Logical_Expr", "Action_Stmt_C802"]
6636  action_stmt_cls = Action_Stmt_C802
6637 
6638  @classmethod
6639  def match(cls, string):
6640  """Implements the matching for an if statement that controls a single
6641  action statement
6642 
6643  This is implemented as a class method to allow parameterizing the
6644  type that is used to match the action-stmt. It is specified by the
6645  attribute :py:attr:`action_stmt_cls`, which can be overwritten in
6646  derived classes to specify an updated version, so done for example
6647  in the Fortran 2008 version :py:class:`fparser.two.Fortran2008.If_Stmt`.
6648 
6649  :param str string: Text that we are trying to match.
6650 
6651  :returns: None if there is no match or, if there is a match, a \
6652  2-tuple containing the logical expression as an object matched by \
6653  :py:class:`fparser.two.Fortran2003.Scalar_Logical_Expr` and the \
6654  action statement as an object matching ``cls.action_stmt_cls``.
6655  :rtype: (:py:class:`fparser.two.Fortran2003.Scalar_Logical_Expr`,
6656  :py:class:`fparser.two.Fortran2003.Action_Stmt_C802`) \
6657  or NoneType
6658 
6659  """
6660  if string[:2].upper() != "IF":
6661  return
6662  line, repmap = string_replace_map(string)
6663  line = line[2:].lstrip()
6664  if not line.startswith("("):
6665  return
6666  i = line.find(")")
6667  if i == -1:
6668  return
6669  expr = repmap(line[1:i].strip())
6670  stmt = repmap(line[i + 1 :].lstrip())
6671  return Scalar_Logical_Expr(expr), cls.action_stmt_cls(stmt)
6672 
6673  def tostr(self):
6674  return "IF (%s) %s" % self.items
6675 
6676 
6677 class Case_Construct(BlockBase): # R808
6678  """
6679  <case-construct> = <select-case-stmt>
6680  [ <case-stmt>
6681  <block> == [<execution-part-construct>]..
6682  ]..
6683  <end-select-stmt>
6684  """
6685 
6686  subclass_names = []
6687  use_names = [
6688  "Select_Case_Stmt",
6689  "Case_Stmt",
6690  "End_Select_Stmt",
6691  "Execution_Part_Construct",
6692  ]
6693 
6694  @staticmethod
6695  def match(reader):
6696  return BlockBase.match(
6697  Select_Case_Stmt,
6698  [Case_Stmt, Execution_Part_Construct, Case_Stmt],
6699  End_Select_Stmt,
6700  reader,
6701  match_names=True, # C803
6702  strict_match_names=True, # C803
6703  match_name_classes=(Case_Stmt),
6704  )
6705 
6706  def tofortran(self, tab="", isfix=None):
6707  """
6708  Converts this node (and all children) into Fortran.
6709 
6710  :param str tab: white space to prefix to output.
6711  :param bool isfix: whether or not to generate fixed-format output.
6712 
6713  :returns: Fortran code.
6714  :rtype: str
6715 
6716  """
6717  tmp = []
6718  start = self.content[0]
6719  end = self.content[-1]
6720  tmp.append(start.tofortran(tab=tab, isfix=isfix))
6721  for item in self.content[1:-1]:
6722  if isinstance(item, Case_Stmt):
6723  tmp.append(item.tofortran(tab=tab, isfix=isfix))
6724  else:
6725  tmp.append(item.tofortran(tab=tab + " ", isfix=isfix))
6726  tmp.append(end.tofortran(tab=tab, isfix=isfix))
6727  return "\n".join(tmp)
6728 
6729 
6730 class Select_Case_Stmt(StmtBase, CALLBase): # R809
6731  """
6732  <select-case-stmt> = [ <case-construct-name> : ]
6733  SELECT CASE ( <case-expr> )
6734  """
6735 
6736  subclass_names = []
6737  use_names = ["Case_Construct_Name", "Case_Expr"]
6738 
6739  @staticmethod
6740  def match(string):
6741  if string[:6].upper() != "SELECT":
6742  return
6743  line = string[6:].lstrip()
6744  if line[:4].upper() != "CASE":
6745  return
6746  line = line[4:].lstrip()
6747  if not line or line[0] + line[-1] != "()":
6748  return
6749  line = line[1:-1].strip()
6750  return (Case_Expr(line),)
6751 
6752  def tostr(self):
6753  return "SELECT CASE (%s)" % (self.items[0])
6754 
6755  def get_start_name(self):
6756  return self.item.name
6757 
6758 
6759 class Case_Stmt(StmtBase): # R810
6760  """
6761  <case-stmt> = CASE <case-selector> [ <case-construct-name> ]
6762  """
6763 
6764  subclass_names = []
6765  use_names = ["Case_Selector", "Case_Construct_Name"]
6766 
6767  @staticmethod
6768  def match(string):
6769  if string[:4].upper() != "CASE":
6770  return
6771  line, repmap = string_replace_map(string[4:].lstrip())
6772  if line.startswith("("):
6773  i = line.find(")")
6774  if i == -1:
6775  return
6776  n = line[i + 1 :].lstrip() or None
6777  if n:
6778  n = Case_Construct_Name(repmap(n))
6779  return Case_Selector(repmap(line[: i + 1].rstrip())), n
6780  if line[:7].upper() == "DEFAULT":
6781  n = repmap(line[7:].lstrip()) or None
6782  if n:
6783  n = Case_Construct_Name(repmap(n))
6784  return Case_Selector(line[:7]), n
6785 
6786  def tostr(self):
6787  if self.items[1] is None:
6788  return "CASE %s" % (self.items[0])
6789  return "CASE %s %s" % (self.items)
6790 
6791  def get_end_name(self):
6792  """
6793  :return: the name at the END of this block, if it exists
6794  :rtype: str or NoneType
6795  """
6796  name = self.items[1]
6797  if name is not None:
6798  return name.string
6799  return None
6800 
6801 
6802 class End_Select_Stmt(EndStmtBase): # R811
6803  """
6804  <end-select-stmt> = END SELECT [ <case-construct-name> ]
6805  """
6806 
6807  subclass_names = []
6808  use_names = ["Case_Construct_Name"]
6809 
6810  @staticmethod
6811  def match(string):
6812  return EndStmtBase.match(
6813  "SELECT", Case_Construct_Name, string, require_stmt_type=True
6814  )
6815 
6816 
6817 class Case_Expr(Base): # R812
6818  """
6819  <case-expr> = <scalar-int-expr>
6820  | <scalar-char-expr>
6821  | <scalar-logical-expr>
6822  """
6823 
6824  subclass_names = []
6825  subclass_names = ["Scalar_Int_Expr", "Scalar_Char_Expr", "Scalar_Logical_Expr"]
6826 
6827 
6828 class Case_Selector(Base): # R813
6829  """
6830  <case-selector> = ( <case-value-range-list> )
6831  | DEFAULT
6832  """
6833 
6834  subclass_names = []
6835  use_names = ["Case_Value_Range_List"]
6836 
6837  @staticmethod
6838  def match(string):
6839  if len(string) == 7 and string.upper() == "DEFAULT":
6840  return (None,)
6841  if not (string.startswith("(") and string.endswith(")")):
6842  return
6843  return (Case_Value_Range_List(string[1:-1].strip()),)
6844 
6845  def tostr(self):
6846  if self.items[0] is None:
6847  return "DEFAULT"
6848  return "(%s)" % (self.items[0])
6849 
6850 
6851 class Case_Value_Range(SeparatorBase): # R814
6852  """
6853  <case-value-range> = <case-value>
6854  | <case-value> :
6855  | : <case-value>
6856  | <case-value> : <case-value>
6857  """
6858 
6859  subclass_names = ["Case_Value"]
6860 
6861  @staticmethod
6862  def match(string):
6863  return SeparatorBase.match(Case_Value, Case_Value, string)
6864 
6865 
6866 class Case_Value(Base): # R815
6867  """
6868  <case-value> = <scalar-int-initialization-expr>
6869  | <scalar-char-initialization-expr>
6870  | <scalar-logical-initialization-expr>
6871  """
6872 
6873  subclass_names = [
6874  "Scalar_Int_Initialization_Expr",
6875  "Scalar_Char_Initialization_Expr",
6876  "Scalar_Logical_Initialization_Expr",
6877  ]
6878 
6879 
6880 class Associate_Construct(BlockBase): # R816
6881  """
6882  <associate-construct> = <associate-stmt>
6883  <block> == [ <execution-part-construct> ]...
6884  <end-associate-stmt>
6885  """
6886 
6887  subclass_names = []
6888  use_names = ["Associate_Stmt", "Execution_Part_Construct", "End_Associate_Stmt"]
6889 
6890  @staticmethod
6891  def match(reader):
6892  return BlockBase.match(
6893  Associate_Stmt,
6894  [Execution_Part_Construct],
6895  End_Associate_Stmt,
6896  reader,
6897  match_names=True, # C810
6898  strict_match_names=True, # C810
6899  )
6900 
6901 
6902 class Associate_Stmt(StmtBase, CALLBase): # R817
6903  """
6904  <associate-stmt> = [ <associate-construct-name> : ]
6905  ASSOCIATE ( <association-list> )
6906  """
6907 
6908  subclass_names = []
6909  use_names = ["Associate_Construct_Name", "Association_List"]
6910 
6911  @staticmethod
6912  def match(string):
6913  return CALLBase.match("ASSOCIATE", Association_List, string)
6914 
6915  def get_start_name(self):
6916  return self.item.name
6917 
6918 
6919 class Association(BinaryOpBase): # R818
6920  """
6921  <association> = <associate-name> => <selector>
6922  """
6923 
6924  subclass_names = []
6925  use_names = ["Associate_Name", "Selector"]
6926 
6927  @staticmethod
6928  def match(string):
6929  return BinaryOpBase.match(Associate_Name, "=>", Selector, string)
6930 
6931 
6932 class Selector(Base): # R819
6933  """
6934  <selector> = <expr>
6935  | <variable>
6936  """
6937 
6938  subclass_names = ["Expr", "Variable"]
6939 
6940 
6941 class End_Associate_Stmt(EndStmtBase): # R820
6942  """
6943  <end-associate-stmt> = END ASSOCIATE [ <associate-construct-name> ]
6944  """
6945 
6946  subclass_names = []
6947  use_names = ["Associate_Construct_Name"]
6948 
6949  @staticmethod
6950  def match(string):
6951  return EndStmtBase.match(
6952  "ASSOCIATE", Associate_Construct_Name, string, require_stmt_type=True
6953  )
6954 
6955 
6956 class Select_Type_Construct(BlockBase): # R821
6957  """
6958  <select-type-construct> = <select-type-stmt>
6959  [ <type-guard-stmt>
6960  <block> == [<execution-part-construct>]..
6961  ]...
6962  <end-select-type-stmt>
6963  """
6964 
6965  subclass_names = []
6966  use_names = [
6967  "Select_Type_Stmt",
6968  "Type_Guard_Stmt",
6969  "Execution_Part_Construct",
6970  "End_Select_Type_Stmt",
6971  ]
6972 
6973  @staticmethod
6974  def match(reader):
6975  return BlockBase.match(
6976  Select_Type_Stmt,
6977  [Type_Guard_Stmt, Execution_Part_Construct, Type_Guard_Stmt],
6978  End_Select_Type_Stmt,
6979  reader,
6980  match_names=True, # C819
6981  strict_match_names=True, # C819
6982  match_name_classes=(Type_Guard_Stmt),
6983  )
6984 
6985 
6986 class Select_Type_Stmt(StmtBase): # R822
6987  """
6988  <select-type-stmt> = [ <select-construct-name> : ] SELECT TYPE
6989  ( [ <associate-name> => ] <selector> )
6990  """
6991 
6992  subclass_names = []
6993  use_names = ["Select_Construct_Name", "Associate_Name", "Selector"]
6994 
6995  @staticmethod
6996  def match(string):
6997  if string[:6].upper() != "SELECT":
6998  return
6999  line = string[6:].lstrip()
7000  if line[:4].upper() != "TYPE":
7001  return
7002  line = line[4:].lstrip()
7003  if not line or line[0] + line[-1] != "()":
7004  return
7005  line = line[1:-1].strip()
7006  i = line.find("=>")
7007  if i != -1:
7008  return Associate_Name(line[:i].rstrip()), Selector(line[i + 2 :].lstrip())
7009  return None, Selector(line)
7010 
7011  def tostr(self):
7012  if self.items[0] is None:
7013  return "SELECT TYPE(%s)" % (self.items[1])
7014  return "SELECT TYPE(%s=>%s)" % (self.items)
7015 
7016  def get_start_name(self):
7017  return self.item.name
7018 
7019 
7020 class Type_Guard_Stmt(StmtBase): # R823
7021  """
7022  ::
7023  <type-guard-stmt> = TYPE IS ( <type-spec> ) [ <select-construct-name> ]
7024  | CLASS IS ( <type-spec> ) [ <select-construct-name> ]
7025  | CLASS DEFAULT [ <select-construct-name> ]
7026 
7027  Attributes
7028  ----------
7029  items : ({'TYPE IS', 'CLASS IS', 'CLASS DEFAULT'}, Type_Spec,
7030  Select_Construct_Name)
7031  """
7032 
7033  subclass_names = []
7034  use_names = ["Type_Spec", "Select_Construct_Name"]
7035 
7036  @staticmethod
7037  def match(string):
7038  if string[:4].upper() == "TYPE":
7039  line = string[4:].lstrip()
7040  if not line[:2].upper() == "IS":
7041  return
7042  line = line[2:].lstrip()
7043  kind = "TYPE IS"
7044  elif string[:5].upper() == "CLASS":
7045  line = string[5:].lstrip()
7046  if line[:2].upper() == "IS":
7047  line = line[2:].lstrip()
7048  kind = "CLASS IS"
7049  elif line[:7].upper() == "DEFAULT":
7050  line = line[7:].lstrip()
7051  if line:
7052  if isalnum(line[0]):
7053  return
7054  return "CLASS DEFAULT", None, Select_Construct_Name(line)
7055  return "CLASS DEFAULT", None, None
7056  else:
7057  return
7058  else:
7059  return
7060  if not line.startswith("("):
7061  return
7062  i = line.rfind(")")
7063  if i == -1:
7064  return
7065  tmp = line[1:i].strip()
7066  if not tmp:
7067  return
7068  line = line[i + 1 :].lstrip()
7069  if line:
7070  return kind, Type_Spec(tmp), Select_Construct_Name(line)
7071  return kind, Type_Spec(tmp), None
7072 
7073  def tostr(self):
7074  s = str(self.items[0])
7075  if self.items[1] is not None:
7076  s += " (%s)" % (self.items[1])
7077  if self.items[2] is not None:
7078  s += " %s" % (self.items[2])
7079  return s
7080 
7081  def get_end_name(self):
7082  """
7083  :return: the name at the END of this block, if it exists
7084  :rtype: str or NoneType
7085  """
7086  name = self.items[-1]
7087  if name is not None:
7088  return name.string
7089  return None
7090 
7091 
7092 class End_Select_Type_Stmt(EndStmtBase): # R824
7093  """
7094  <end-select-type-stmt> = END SELECT [ <select-construct-name> ]
7095  """
7096 
7097  subclass_names = []
7098  use_names = ["Select_Construct_Name"]
7099 
7100  @staticmethod
7101  def match(string):
7102  return EndStmtBase.match(
7103  "SELECT", Select_Construct_Name, string, require_stmt_type=True
7104  )
7105 
7106 
7107 class Do_Construct(Base): # pylint: disable=invalid-name
7108  """
7109  R825
7110 
7111  <do-construct> = <block-do-construct>
7112  | <nonblock-do-construct>
7113  """
7114 
7115  subclass_names = ["Block_Do_Construct", "Nonblock_Do_Construct"]
7116 
7117 
7118 class Block_Do_Construct(Base): # pylint: disable=invalid-name
7119  """
7120  R826
7121 
7122  <block-do-construct> = <block-label-do-construct>
7123  | <block-nonlabel-do-construct>
7124  """
7125 
7126  subclass_names = ["Block_Label_Do_Construct", "Block_Nonlabel_Do_Construct"]
7127 
7128 
7129 class Block_Label_Do_Construct(BlockBase): # pylint: disable=invalid-name
7130  """
7131  R826_1
7132 
7133  <block-label-do-construct> = <label-do-stmt>
7134  [ <execution-part-construct> ]...
7135  <end-do>
7136  """
7137 
7138  subclass_names = []
7139  use_names = ["Label_Do_Stmt", "Execution_Part_Construct", "End_Do"]
7140 
7141  @staticmethod
7142  def match(reader):
7143  """
7144  :param reader: instance of `FortranReaderBase` class
7145  :type reader: :py:class:`FortranReaderBase`
7146  :return: code block matching the labeled "DO" construct
7147  :rtype: string
7148  """
7149  return BlockBase.match(
7150  Label_Do_Stmt,
7151  [Execution_Part_Construct],
7152  End_Do,
7153  reader,
7154  match_labels=True,
7155  enable_do_label_construct_hook=True,
7156  )
7157 
7158  def tofortran(self, tab="", isfix=None):
7159  """
7160  :param str tab: tab character or empty string.
7161  :param bool isfix: whether the reader is in fixed format.
7162 
7163  :return: parsed representation of the labeled "DO" construct.
7164  :rtype: str
7165  """
7166  lblock = []
7167  start = self.content[0]
7168  end = self.content[-1]
7169  extra_tab = " "
7170  lblock.append(start.tofortran(tab=tab, isfix=isfix))
7171  for item in self.content[1:-1]:
7172  lblock.append(item.tofortran(tab=tab + extra_tab, isfix=isfix))
7173  if len(self.content) > 1:
7174  lblock.append(end.tofortran(tab=tab, isfix=isfix))
7175  return "\n".join(lblock)
7176 
7177 
7178 class Block_Nonlabel_Do_Construct(BlockBase): # pylint: disable=invalid-name
7179  """
7180  R826_2
7181 
7182  <block-nonlabel-do-construct> = <nonlabel-do-stmt>
7183  [ <execution-part-construct> ]...
7184  <end-do-stmt>
7185  """
7186 
7187  subclass_names = []
7188  use_names = ["Nonlabel_Do_Stmt", "Execution_Part_Construct", "End_Do_Stmt"]
7189 
7190  @staticmethod
7191  def match(reader):
7192  """
7193  :param reader: instance of `FortranReaderBase` class
7194  :type reader: :py:class:`FortranReaderBase`
7195  :return: code block matching the nonlabeled "DO" construct
7196  :rtype: string
7197  """
7198  return BlockBase.match(
7199  Nonlabel_Do_Stmt,
7200  [Execution_Part_Construct],
7201  End_Do_Stmt,
7202  reader,
7203  match_names=True, # C821
7204  strict_match_names=True, # C821
7205  )
7206 
7207 
7208 class Do_Stmt(Base): # pylint: disable=invalid-name
7209  """
7210  R827
7211 
7212  <do-stmt> = <label-do-stmt>
7213  | <nonlabel-do-stmt>
7214  """
7215 
7216  subclass_names = ["Label_Do_Stmt", "Nonlabel_Do_Stmt"]
7217 
7218 
7219 class Label_Do_Stmt(StmtBase): # pylint: disable=invalid-name
7220  """
7221  R828
7222 
7223  <label-do-stmt> = [ <do-construct-name> : ] DO <label> [ <loop-control> ]
7224  """
7225 
7226  subclass_names = []
7227  use_names = ["Do_Construct_Name", "Label", "Loop_Control"]
7228 
7229  @staticmethod
7230  def match(string):
7231  """
7232  :param string: (source of) Fortran string to parse
7233  :type string: str or :py:class:`FortranReaderBase`
7234  :return: 3-tuple containing strings and instances of the classes
7235  determining labeled "DO" statement (optional statement name,
7236  label and loop control expression if present)
7237  :rtype: 3-tuple of objects
7238  """
7239  # do-construct-name is determined by reader
7240  if string[:2].upper() != "DO":
7241  return
7242  line = string[2:].lstrip()
7243  mpat = pattern.label.match(line)
7244  if mpat is None:
7245  return
7246  label = mpat.group()
7247  line = line[mpat.end() :].lstrip()
7248  if line:
7249  return None, Label(label), Loop_Control(line)
7250  return None, Label(label), None
7251 
7252  def tostr(self):
7253  """
7254  :return: string containing Fortran code for the parsed
7255  labeled "DO" statement
7256  :rtype: string
7257  """
7258  # pylint: disable=unbalanced-tuple-unpacking
7259  name, label, loop_control = self.items
7260  if name is None:
7261  dostmt = "DO %s" % (label)
7262  else:
7263  dostmt = "%s: DO %s" % (label)
7264  if loop_control is not None:
7265  dostmt += " %s" % (loop_control)
7266  return dostmt
7267 
7268  def get_start_name(self):
7269  """
7270  :return: optional labeled "DO" statement name
7271  :rtype: string
7272  """
7273  return self.item.name
7274 
7275  def get_start_label(self):
7276  """
7277  :return: label of "DO" statement
7278  :rtype: string
7279  """
7280  return int(self.items[1])
7281 
7282  do_construct_name = property(lambda self: self.items[0])
7283  label = property(lambda self: self.items[1])
7284  loop_control = property(lambda self: self.items[2])
7285 
7286 
7287 class Nonlabel_Do_Stmt(StmtBase, WORDClsBase): # pylint: disable=invalid-name
7288  """
7289  R829
7290 
7291  <nonlabel-do-stmt> = [ <do-construct-name> : ] DO [ <loop-control> ]
7292  """
7293 
7294  subclass_names = []
7295  use_names = ["Do_Construct_Name", "Loop_Control"]
7296 
7297  @staticmethod
7298  def match(string):
7299  """
7300  :param str string: Fortran code to check for a match
7301  :return: code line matching the nonlabeled "DO" statement
7302  :rtype: string
7303  """
7304  return WORDClsBase.match("DO", Loop_Control, string)
7305 
7306  def get_start_name(self):
7307  """
7308  :return: optional labeled "DO" statement name
7309  :rtype: string
7310  """
7311  return self.item.name
7312 
7313 
7314 class Loop_Control(Base): # pylint: disable=invalid-name
7315  """
7316  R830
7317 
7318  <loop-control> = [ , ] <do-variable> = scalar-int-expr,
7319  scalar-int-expr
7320  [ , <scalar-int-expr> ]
7321  | [ , ] WHILE ( <scalar-logical-expr> )
7322  """
7323 
7324  subclass_names = []
7325  use_names = ["Do_Variable", "Scalar_Int_Expr", "Scalar_Logical_Expr"]
7326 
7327  @staticmethod
7328  def match(string):
7329  """
7330  :param str string: Fortran code to check for a match
7331  :return: 3-tuple containing strings and instances of the classes
7332  determining loop control (optional comma delimiter,
7333  optional scalar logical expression describing "WHILE"
7334  condition or optional counter expression containing loop
7335  counter and scalar integer expression)
7336  :rtype: 3-tuple of objects or nothing for an "infinite loop"
7337  """
7338  # pylint: disable=unbalanced-tuple-unpacking
7339  optional_delim = None
7340  # Match optional delimiter
7341  if string.startswith(","):
7342  line, repmap = string_replace_map(string[1:].lstrip())
7343  optional_delim = ", "
7344  else:
7345  line, repmap = string_replace_map(string)
7346  # Match "WHILE" scalar logical expression
7347  if line[:5].upper() == "WHILE" and line[5:].lstrip().startswith("("):
7348  lbrak = line[5:].lstrip()
7349  i = lbrak.find(")")
7350  if i != -1 and i == len(lbrak) - 1:
7351  scalar_logical_expr = Scalar_Logical_Expr(repmap(lbrak[1:i].strip()))
7352  return scalar_logical_expr, None, optional_delim
7353  # Match counter expression
7354  # More than one '=' in counter expression
7355  if line.count("=") != 1:
7356  return
7357  var, rhs = line.split("=")
7358  rhs = [s.strip() for s in rhs.lstrip().split(",")]
7359  # Incorrect number of elements in counter expression
7360  if not 2 <= len(rhs) <= 3:
7361  return
7362  counter_expr = (
7363  Variable(repmap(var.rstrip())),
7364  list(map(Scalar_Int_Expr, list(map(repmap, rhs)))),
7365  )
7366  return None, counter_expr, optional_delim
7367 
7368  def tostr(self):
7369  """
7370  :return: parsed representation of loop control construct
7371  :rtype: string
7372  """
7373  # pylint: disable=unbalanced-tuple-unpacking
7374  scalar_logical_expr, counter_expr, optional_delim = self.items
7375  # Return loop control construct containing "WHILE" condition and
7376  # its <scalar-logical-expr>
7377  if scalar_logical_expr is not None:
7378  loopctrl = "WHILE (%s)" % scalar_logical_expr
7379  # Return loop control construct containing counter expression:
7380  # <do-variable> as LHS and <scalar-int-expr> list as RHS
7381  elif counter_expr[0] is not None and counter_expr[1] is not None:
7382  loopctrl = "%s = %s" % (
7383  counter_expr[0],
7384  ", ".join(map(str, counter_expr[1])),
7385  )
7386  # Add optional delimiter to loop control construct if present
7387  if optional_delim is not None:
7388  loopctrl = optional_delim + loopctrl
7389  return loopctrl
7390 
7391 
7392 class Do_Variable(Base): # pylint: disable=invalid-name
7393  """
7394  R831
7395 
7396  <do-variable> = <scalar-int-variable>
7397  """
7398 
7399  subclass_names = ["Scalar_Int_Variable"]
7400 
7401 
7402 class Do_Block(BlockBase): # pylint: disable=invalid-name
7403  """
7404  R832
7405 
7406  <do-block> = [ <execution-part-construct> ]...
7407  """
7408 
7409  subclass_names = ["Block"]
7410  subclass_names = []
7411  use_names = ["Execution_Part_Construct"]
7412 
7413  @staticmethod
7414  def match(string):
7415  """
7416  :param str string: Fortran code to check for a match
7417  :return: code block matching the execution part construct within
7418  the "DO" block
7419  :rtype: string
7420  """
7421  return BlockBase.match(None, [Execution_Part_Construct], None, string)
7422 
7423 
7424 class End_Do(Base): # pylint: disable=invalid-name
7425  """
7426  R833
7427 
7428  <end-do> = <end-do-stmt>
7429  | <continue-stmt>
7430  """
7431 
7432  subclass_names = ["End_Do_Stmt", "Continue_Stmt"]
7433 
7434 
7435 class End_Do_Stmt(EndStmtBase): # pylint: disable=invalid-name
7436  """
7437  R834
7438 
7439  <end-do-stmt> = END DO [ <do-construct-name> ]
7440  """
7441 
7442  subclass_names = []
7443  use_names = ["Do_Construct_Name"]
7444 
7445  @staticmethod
7446  def match(string):
7447  """
7448  :param str string: Fortran code to check for a match
7449  :return: code line matching the "END DO" statement
7450  :rtype: string
7451  """
7452  return EndStmtBase.match(
7453  "DO", Do_Construct_Name, string, require_stmt_type=True
7454  )
7455 
7456 
7457 class Nonblock_Do_Construct(Base): # pylint: disable=invalid-name
7458  """
7459  R835
7460 
7461  <nonblock-do-stmt> = <action-term-do-construct>
7462  | <outer-shared-do-construct>
7463  """
7464 
7465  subclass_names = ["Action_Term_Do_Construct", "Outer_Shared_Do_Construct"]
7466 
7467 
7468 class Action_Term_Do_Construct(BlockBase): # R836
7469  """
7470  ::
7471  <action-term-do-construct> = <label-do-stmt>
7472  <do-body>
7473  <do-term-action-stmt>
7474 
7475  ::
7476  <action-term-do-construct> = <label-do-stmt>
7477  [ <execution-part-construct> ]...
7478  <do-term-action-stmt>
7479  """
7480 
7481  subclass_names = []
7482  use_names = ["Label_Do_Stmt", "Execution_Part_Construct", "Do_Term_Action_Stmt"]
7483 
7484  @staticmethod
7485  def match(reader):
7486  return BlockBase.match(
7487  Label_Do_Stmt,
7488  [Execution_Part_Construct],
7489  Do_Term_Action_Stmt,
7490  reader,
7491  match_labels=True,
7492  enable_do_label_construct_hook=True,
7493  )
7494 
7495  def tofortran(self, tab="", isfix=None):
7496  """
7497  Converts this node (and all children) into Fortran.
7498 
7499  :param str tab: white space to prefix to output.
7500  :param bool isfix: whether or not to generate fixed-format output.
7501 
7502  :returns: Fortran code.
7503  :rtype: str
7504 
7505  """
7506  line = []
7507  start = self.content[0]
7508  end = self.content[-1]
7509  extra_tab = " "
7510  line.append(start.tofortran(tab=tab, isfix=isfix))
7511  for item in self.content[1:-1]:
7512  line.append(item.tofortran(tab=tab + extra_tab, isfix=isfix))
7513  if isinstance(item, Label_Do_Stmt):
7514  extra_tab += " "
7515  if len(self.content) > 1:
7516  line.append(end.tofortran(tab=tab, isfix=isfix))
7517  return "\n".join(line)
7518 
7519 
7520 class Do_Body(BlockBase): # R837
7521  """
7522  <do-body> = [ <execution-part-construct> ]...
7523  """
7524 
7525  subclass_names = []
7526  use_names = ["Execution_Part_Construct"]
7527 
7528  @staticmethod
7529  def match(string):
7530  return BlockBase.match(None, [Execution_Part_Construct], None, string)
7531 
7532 
7533 class Do_Term_Action_Stmt(StmtBase): # R838
7534  """
7535  ::
7536  <do-term-action-stmt> = <action-stmt>
7537 
7538  Notes
7539  -----
7540  C824: <do-term-action-stmt> shall not be <continue-stmt>, <goto-stmt>,
7541  <return-stmt>, <stop-stmt>, <exit-stmt>, <cycle-stmt>,
7542  <end-function-stmt>, <end-subroutine-stmt>, <end-program-stmt>,
7543  <arithmetic-if-stmt>
7544  """
7545 
7546  subclass_names = ["Action_Stmt_C824"]
7547 
7548 
7549 class Outer_Shared_Do_Construct(BlockBase): # R839
7550  """
7551  <outer-shared-do-construct> = <label-do-stmt>
7552  <do-body>
7553  <shared-term-do-construct>
7554  """
7555 
7556  subclass_names = []
7557  use_names = ["Label_Do_Stmt", "Do_Body", "Shared_Term_Do_Construct"]
7558 
7559  @staticmethod
7560  def match(reader):
7561  content = []
7562  for cls in [Label_Do_Stmt, Do_Body, Shared_Term_Do_Construct]:
7563  obj = cls(reader)
7564  if obj is None: # todo: restore reader
7565  return
7566  content.append(obj)
7567  return (content,)
7568 
7569 
7570 class Shared_Term_Do_Construct(Base): # R840
7571  """
7572  <shared-term-do-construct> = <outer-shared-do-construct>
7573  | <inner-shared-do-construct>
7574  """
7575 
7576  subclass_names = ["Outer_Shared_Do_Construct", "Inner_Shared_Do_Construct"]
7577 
7578 
7579 class Inner_Shared_Do_Construct(BlockBase): # R841
7580  """
7581  <inner-shared-do-construct> = <label-do-stmt>
7582  <do-body>
7583  <do-term-shared-stmt>
7584  """
7585 
7586  subclass_names = []
7587  use_names = ["Label_Do_Stmt", "Do_Body", "Do_Term_Shared_Stmt"]
7588 
7589  @staticmethod
7590  def match(reader):
7591  content = []
7592  for cls in [Label_Do_Stmt, Do_Body, Do_Term_Shared_Stmt]:
7593  obj = cls(reader)
7594  if obj is None: # todo: restore reader
7595  return
7596  content.append(obj)
7597  return (content,)
7598 
7599 
7600 class Do_Term_Shared_Stmt(StmtBase): # R842
7601  """
7602  <do-term-shared-stmt> = <action-stmt>
7603  C826: see C824 above.
7604  """
7605 
7606  subclass_names = ["Action_Stmt"]
7607 
7608 
7609 class Cycle_Stmt(StmtBase, WORDClsBase): # R843
7610  """
7611  <cycle-stmt> = CYCLE [ <do-construct-name> ]
7612  """
7613 
7614  subclass_names = []
7615  use_names = ["Do_Construct_Name"]
7616 
7617  @staticmethod
7618  def match(string):
7619  return WORDClsBase.match("CYCLE", Do_Construct_Name, string)
7620 
7621 
7622 class Exit_Stmt(StmtBase, WORDClsBase): # R844
7623  """
7624  <exit-stmt> = EXIT [ <do-construct-name> ]
7625  """
7626 
7627  subclass_names = []
7628  use_names = ["Do_Construct_Name"]
7629 
7630  @staticmethod
7631  def match(string):
7632  return WORDClsBase.match("EXIT", Do_Construct_Name, string)
7633 
7634 
7635 class Goto_Stmt(StmtBase): # R845
7636  """
7637  <goto-stmt> = GO TO <label>
7638  """
7639 
7640  subclass_names = []
7641  use_names = ["Label"]
7642 
7643  @staticmethod
7644  def match(string):
7645  if string[:2].upper() != "GO":
7646  return
7647  line = string[2:].lstrip()
7648  if line[:2].upper() != "TO":
7649  return
7650  return (Label(line[2:].lstrip()),)
7651 
7652  def tostr(self):
7653  return "GO TO %s" % (self.items[0])
7654 
7655 
7656 class Computed_Goto_Stmt(StmtBase): # R846
7657  """
7658  <computed-goto-stmt> = GO TO ( <label-list> ) [ , ] <scalar-int-expr>
7659  """
7660 
7661  subclass_names = []
7662  use_names = ["Label_List", "Scalar_Int_Expr"]
7663 
7664  @staticmethod
7665  def match(string):
7666  if string[:2].upper() != "GO":
7667  return
7668  line = string[2:].lstrip()
7669  if line[:2].upper() != "TO":
7670  return
7671  line = line[2:].lstrip()
7672  if not line.startswith("("):
7673  return
7674  i = line.find(")")
7675  if i == -1:
7676  return
7677  lst = line[1:i].strip()
7678  if not lst:
7679  return
7680  line = line[i + 1 :].lstrip()
7681  if line.startswith(","):
7682  line = line[1:].lstrip()
7683  if not line:
7684  return
7685  return Label_List(lst), Scalar_Int_Expr(line)
7686 
7687  def tostr(self):
7688  return "GO TO (%s), %s" % self.items
7689 
7690 
7691 class Arithmetic_If_Stmt(StmtBase): # R847
7692  """
7693  <arithmetic-if-stmt> = IF ( <scalar-numeric-expr> ) <label> ,
7694  <label> , <label>
7695  """
7696 
7697  subclass_names = []
7698  use_names = ["Scalar_Numeric_Expr", "Label"]
7699 
7700  @staticmethod
7701  def match(string):
7702  if string[:2].upper() != "IF":
7703  return
7704  line = string[2:].lstrip()
7705  if not line.startswith("("):
7706  return
7707  i = line.rfind(")")
7708  if i == -1:
7709  return
7710  labels = line[i + 1 :].lstrip().split(",")
7711  if len(labels) != 3:
7712  return
7713  labels = [Label(l.strip()) for l in labels]
7714  return (Scalar_Numeric_Expr(line[1:i].strip()),) + tuple(labels)
7715 
7716  def tostr(self):
7717  return "IF (%s) %s, %s, %s" % self.items
7718 
7719 
7720 class Continue_Stmt(StmtBase, STRINGBase): # R848
7721  """
7722  <continue-stmt> = CONTINUE
7723  """
7724 
7725  subclass_names = []
7726 
7727  @staticmethod
7728  def match(string):
7729  return STRINGBase.match("CONTINUE", string)
7730 
7731  def get_end_label(self):
7732  return self.item.label
7733 
7734 
7735 class Stop_Stmt(StmtBase, WORDClsBase): # R849
7736  """
7737  <stop-stmt> = STOP [ <stop-code> ]
7738  """
7739 
7740  subclass_names = []
7741  use_names = ["Stop_Code"]
7742 
7743  @staticmethod
7744  def match(string):
7745  return WORDClsBase.match("STOP", Stop_Code, string)
7746 
7747 
7748 class Stop_Code(StringBase): # R850
7749  """
7750  <stop-code> = <scalar-char-constant>
7751  | <digit> [ <digit> [ <digit> [ <digit> [ <digit> ] ] ] ]
7752  """
7753 
7754  subclass_names = ["Scalar_Char_Constant"]
7755 
7756  @staticmethod
7757  def match(string):
7758  return StringBase.match(pattern.abs_label, string)
7759 
7760 
7761 #
7762 # SECTION 9
7763 #
7764 
7765 
7766 class Io_Unit(StringBase): # R901
7767  """
7768  <io-unit> = <file-unit-number>
7769  | *
7770  | <internal-file-variable>
7771  """
7772 
7773  subclass_names = ["File_Unit_Number", "Internal_File_Variable"]
7774 
7775  @staticmethod
7776  def match(string):
7777  return StringBase.match("*", string)
7778 
7779 
7780 class File_Unit_Number(Base): # R902
7781  """
7782  <file-unit-number> = <scalar-int-expr>
7783  """
7784 
7785  subclass_names = ["Scalar_Int_Expr"]
7786 
7787 
7788 class Internal_File_Variable(Base): # R903
7789  """
7790  <internal-file-variable> = <char-variable>
7791  C901: <char-variable> shall not be an array section with a
7792  vector subscript.
7793  """
7794 
7795  subclass_names = ["Char_Variable"]
7796 
7797 
7798 class Open_Stmt(StmtBase, CALLBase): # R904
7799  """
7800  <open-stmt> = OPEN ( <connect-spec-list> )
7801  """
7802 
7803  subclass_names = []
7804  use_names = ["Connect_Spec_List"]
7805 
7806  @staticmethod
7807  def match(string):
7808  # The Connect_Spec_List class is generated automatically
7809  # by code at the end of this module
7810  return CALLBase.match("OPEN", Connect_Spec_List, string, require_rhs=True)
7811 
7812 
7813 class Connect_Spec(KeywordValueBase):
7814  """
7815  R905
7816  <connect-spec> = [ UNIT = ] <file-unit-number>
7817  | ACCESS = <scalar-default-char-expr>
7818  | ACTION = <scalar-default-char-expr>
7819  | ASYNCHRONOUS = <scalar-default-char-expr>
7820  | BLANK = <scalar-default-char-expr>
7821  | DECIMAL = <scalar-default-char-expr>
7822  | DELIM = <scalar-default-char-expr>
7823  | ENCODING = <scalar-default-char-expr>
7824  | ERR = <label>
7825  | FILE = <file-name-expr>
7826  | FORM = <scalar-default-char-expr>
7827  | IOMSG = <iomsg-variable>
7828  | IOSTAT = <scalar-int-variable>
7829  | PAD = <scalar-default-char-expr>
7830  | POSITION = <scalar-default-char-expr>
7831  | RECL = <scalar-int-expr>
7832  | ROUND = <scalar-default-char-expr>
7833  | SIGN = <scalar-default-char-expr>
7834  | STATUS = <scalar-default-char-expr>
7835  """
7836 
7837  subclass_names = []
7838  use_names = [
7839  "File_Unit_Number",
7840  "Scalar_Default_Char_Expr",
7841  "Label",
7842  "File_Name_Expr",
7843  "Iomsg_Variable",
7844  "Scalar_Int_Expr",
7845  "Scalar_Int_Variable",
7846  ]
7847 
7848  @staticmethod
7849  def match(string):
7850  """
7851  :param str string: Fortran code to check for a match
7852  :return: 2-tuple containing the keyword and value or None if the
7853  supplied string is not a match
7854  :rtype: 2-tuple containing keyword (e.g. "UNIT") and associated value
7855  """
7856  if "=" not in string:
7857  # The only argument which need not be named is the unit number
7858  return "UNIT", File_Unit_Number(string)
7859  # We have a keyword-value pair. Check whether it is valid...
7860  for (keyword, value) in [
7861  (
7862  [
7863  "ACCESS",
7864  "ACTION",
7865  "ASYNCHRONOUS",
7866  "BLANK",
7867  "DECIMAL",
7868  "DELIM",
7869  "ENCODING",
7870  "FORM",
7871  "PAD",
7872  "POSITION",
7873  "ROUND",
7874  "SIGN",
7875  "STATUS",
7876  ],
7877  Scalar_Default_Char_Expr,
7878  ),
7879  ("ERR", Label),
7880  ("FILE", File_Name_Expr),
7881  ("IOSTAT", Scalar_Int_Variable),
7882  ("IOMSG", Iomsg_Variable),
7883  ("RECL", Scalar_Int_Expr),
7884  ("UNIT", File_Unit_Number),
7885  ]:
7886  try:
7887  obj = KeywordValueBase.match(keyword, value, string, upper_lhs=True)
7888  except NoMatchError:
7889  obj = None
7890  if obj is not None:
7891  return obj
7892  return None
7893 
7894 
7895 class File_Name_Expr(Base): # R906
7896  """
7897  <file-name-expr> = <scalar-default-char-expr>
7898  """
7899 
7900  subclass_names = ["Scalar_Default_Char_Expr"]
7901 
7902 
7903 class Iomsg_Variable(Base): # R907
7904  """
7905  <iomsg-variable> = <scalar-default-char-variable>
7906  """
7907 
7908  subclass_names = ["Scalar_Default_Char_Variable"]
7909 
7910 
7911 class Close_Stmt(StmtBase, CALLBase): # R908
7912  """
7913  <close-stmt> = CLOSE ( <close-spec-list> )
7914  """
7915 
7916  subclass_names = []
7917  use_names = ["Close_Spec_List"]
7918 
7919  @staticmethod
7920  def match(string):
7921  return CALLBase.match("CLOSE", Close_Spec_List, string, require_rhs=True)
7922 
7923 
7924 class Close_Spec(KeywordValueBase): # R909
7925  """
7926  <close-spec> = [ UNIT = ] <file-unit-number>
7927  | IOSTAT = <scalar-int-variable>
7928  | IOMSG = <iomsg-variable>
7929  | ERR = <label>
7930  | STATUS = <scalar-default-char-expr>
7931  """
7932 
7933  subclass_names = []
7934  use_names = [
7935  "File_Unit_Number",
7936  "Scalar_Default_Char_Expr",
7937  "Label",
7938  "Iomsg_Variable",
7939  "Scalar_Int_Variable",
7940  ]
7941 
7942  @staticmethod
7943  def match(string):
7944  for (k, v) in [
7945  ("ERR", Label),
7946  ("IOSTAT", Scalar_Int_Variable),
7947  ("IOMSG", Iomsg_Variable),
7948  ("STATUS", Scalar_Default_Char_Expr),
7949  ("UNIT", File_Unit_Number),
7950  ]:
7951  try:
7952  obj = KeywordValueBase.match(k, v, string, upper_lhs=True)
7953  except NoMatchError:
7954  obj = None
7955  if obj is not None:
7956  return obj
7957  return "UNIT", File_Unit_Number(string)
7958 
7959 
7960 class Read_Stmt(StmtBase): # R910
7961  """
7962  :F03R:`910`::
7963  <read-stmt> = READ ( <io-control-spec-list> ) [ <input-item-list> ]
7964  | READ <format> [ , <input-item-list> ]
7965 
7966  Attributes
7967  ----------
7968  items : (Io_Control_Spec_List, Format, Input_Item_List)
7969  """
7970 
7971  subclass_names = []
7972  use_names = ["Io_Control_Spec_List", "Input_Item_List", "Format"]
7973 
7974  @staticmethod
7975  def match(string):
7976  if string[:4].upper() != "READ":
7977  return
7978  line = string[4:].lstrip()
7979  if line.startswith("("):
7980  line, repmap = string_replace_map(line)
7981  idx = line.find(")")
7982  if idx == -1:
7983  return
7984  trimline = line[1:idx].strip()
7985  if not trimline:
7986  return
7987  if idx == len(line) - 1:
7988  return Io_Control_Spec_List(repmap(trimline)), None, None
7989  return (
7990  Io_Control_Spec_List(repmap(trimline)),
7991  None,
7992  Input_Item_List(repmap(line[idx + 1 :].lstrip())),
7993  )
7994  if not line:
7995  return
7996  char = line[0].upper()
7997  # No parentheses therefore first argument must be a format
7998  # specifier (either a string or a line/label number
7999  if "A" <= char <= "Z" or char == "_":
8000  return
8001  line, repmap = string_replace_map(line.lstrip())
8002  # There must be a comma betwee the format specifier and the following
8003  # list of values/variables
8004  idx = line.find(",")
8005  if idx == -1:
8006  return None
8007  trimline = repmap(line[idx + 1 :].lstrip())
8008  if not trimline:
8009  return
8010  return (None, Format(repmap(line[:idx].rstrip())), Output_Item_List(trimline))
8011 
8012  def tostr(self):
8013  if self.items[0] is not None:
8014  assert self.items[1] is None, repr(self.items)
8015  if self.items[2] is None:
8016  return "READ(%s)" % (self.items[0])
8017  return "READ(%s) %s" % (self.items[0], self.items[2])
8018  assert self.items[1] is not None, repr(self.items)
8019  if self.items[2] is None:
8020  return "READ %s" % (self.items[1])
8021  return "READ %s, %s" % (self.items[1], self.items[2])
8022 
8023 
8024 class Write_Stmt(StmtBase): # pylint: disable=invalid-name
8025  """
8026  :F03R:`911`::
8027 
8028  Fortran 2003 rule R911
8029  that specifies syntax of a "WRITE" statement.
8030 
8031  <write-stmt> = WRITE ( <io-control-spec-list> ) [ <output-item-list> ]
8032  """
8033 
8034  subclass_names = []
8035  use_names = ["Io_Control_Spec_List", "Output_Item_List"]
8036 
8037  @staticmethod
8038  def match(string):
8039  """
8040  :param str string: Fortran code to check for a match
8041  :return: 2-tuple containing strings and instances of the classes
8042  describing "WRITE" statement (mandatory IO control
8043  specification list and optional output item list.
8044  :rtype: 2-tuple of objects (1 mandatory and 1 optional)
8045  """
8046  if string[:5].upper() != "WRITE":
8047  return
8048  line = string[5:].lstrip()
8049  # Look for mandatory IO control specification list and
8050  # return without a match if it is not found
8051  if not line.startswith("("):
8052  return
8053  line, repmap = string_replace_map(line)
8054  i = line.find(")")
8055  if i == -1:
8056  return
8057  tmp = line[1:i].strip()
8058  if not tmp:
8059  return
8060  tmp = repmap(tmp)
8061  if i == len(line) - 1:
8062  return Io_Control_Spec_List(tmp), None
8063  # Return optional output item list as well
8064  return (
8065  Io_Control_Spec_List(tmp),
8066  Output_Item_List(repmap(line[i + 1 :].lstrip())),
8067  )
8068 
8069  def tostr(self):
8070  """
8071  :return: parsed representation of a "WRITE" statement
8072  :rtype: str
8073  """
8074  if self.items[1] is None:
8075  return "WRITE(%s)" % (self.items[0])
8076  return "WRITE(%s) %s" % tuple(self.items)
8077 
8078 
8079 class Print_Stmt(StmtBase): # R912
8080  """
8081  :F03R:`912`::
8082  <print-stmt> = PRINT <format> [ , <output-item-list> ]
8083 
8084  Parameters
8085  ----------
8086  items : (Format, Output_Item_List)
8087  """
8088 
8089  subclass_names = []
8090  use_names = ["Format", "Output_Item_List"]
8091 
8092  @staticmethod
8093  def match(string):
8094  if string[:5].upper() != "PRINT":
8095  return
8096  line = string[5:]
8097  if not line:
8098  return
8099  c = line[0].upper()
8100  if "A" <= c <= "Z" or c == "_" or "0" <= c <= "9":
8101  return
8102  line, repmap = string_replace_map(line.lstrip())
8103  i = line.find(",")
8104  if i == -1:
8105  return Format(repmap(line)), None
8106  tmp = repmap(line[i + 1 :].lstrip())
8107  if not tmp:
8108  return
8109  return Format(repmap(line[:i].rstrip())), Output_Item_List(tmp)
8110 
8111  def tostr(self):
8112  if self.items[1] is None:
8113  return "PRINT %s" % (self.items[0])
8114  return "PRINT %s, %s" % tuple(self.items)
8115 
8116 
8117 class Io_Control_Spec_List(SequenceBase):
8118  """
8119  Rule 913 - Control information list.
8120 
8121  io-control-spec-list is a list of io-control-spec items.
8122 
8123  Subject to the following constraints:
8124 
8125  C909 No specifier shall appear more than once in a given
8126  io-control-spec-list.
8127  C910 An io-unit shall be specified; if the optional characters UNIT= are
8128  omitted, the io-unit shall be the first item in the
8129  io-control-spec-list.
8130  C911 A DELIM= or SIGN= specifier shall not appear in a read-stmt.
8131  C912 A BLANK=, PAD=, END=, EOR=, or SIZE=specifier shall not appear in a
8132  write-stmt.
8133  C913 The label in the ERR=, EOR=, or END= specifier shall be the statement
8134  label of a branch target statement that appears in the same scoping
8135  unit as the data transfer statement.
8136  C914 A namelist-group-name shall be the name of a namelist group.
8137  C915 A namelist-group-name shall not appear if an input-item-list or an
8138  output-item-list appears in the data transfer statement.
8139  C916 An io-control-spec-list shall not contain both a format and a
8140  namelist-group-name.
8141  C917 If format appears without a preceding FMT=, it shall be the second
8142  item in the iocontrol-spec-list and the first item shall be io-unit.
8143  C918 If namelist-group-name appears without a preceding NML=, it shall be
8144  the second item in the io-control-spec-list and the first item shall
8145  be io-unit.
8146  C919 If io-unit is not a file-unit-number, the io-control-spec-list shall
8147  not contain a REC= specifier or a POS= specifier.
8148  C920 If the REC= specifier appears, an END= specifier shall not appear, a
8149  namelist-groupname shall not appear, and the format, if any, shall not
8150  be an asterisk.
8151  C921 An ADVANCE= specifier may appear only in a formatted sequential or
8152  stream input/output statement with explicit format specification
8153  (10.1) whose control information list does not contain an
8154  internal-file-variable as the io-unit.
8155  C922 If an EOR= specifier appears, an ADVANCE= specifier also shall appear.
8156  C923 If a SIZE= specifier appears, an ADVANCE= specifier also shall appear.
8157  C924 The scalar-char-initialization-expr in an ASYNCHRONOUS= specifier
8158  shall be of type default character and shall have the value YES or NO.
8159  C925 An ASYNCHRONOUS= specifier with a value YES shall not appear unless
8160  io-unit is a file-unit-number.
8161  C926 If an ID= specifier appears, an ASYNCHRONOUS= specifier with the value
8162  YES shall also appear.
8163  C927 If a POS= specifier appears, the io-control-spec-list shall not
8164  contain a REC= specifier.
8165  C928 If a DECIMAL=, BLANK=, PAD=, SIGN=, or ROUND= specifier appears, a
8166  format or namelist-group-name shall also appear.
8167  C929 If a DELIM= specifier appears, either format shall be an asterisk or
8168  namelist-group-name shall appear.
8169 
8170  TODO #267. Of these constraints, only C910 & C916-918 are currently
8171  enforced.
8172 
8173  """
8174 
8175  subclass_names = []
8176  use_names = ["Io_Control_Spec", "Namelist_Group_Name", "Format"]
8177 
8178  @staticmethod
8179  def match(string):
8180  """
8181  Attempts to match the supplied string with a list of Io_Control_Spec
8182  items. We have to override the base implementation because the first
8183  two items in the list have specific meanings if they are not explictly
8184  named: the first must be the unit number and the second may be either
8185  a format specifier *or* a namelist-group-name.
8186 
8187  :param str string: the string that is checked for a match.
8188 
8189  :returns: a tuple of Io_Control_Spec objects if the match is \
8190  successful, None otherwise.
8191  :rtype: tuple of :py:class:`fparser.two.Fortran2003.Io_Control_Spec` \
8192  objects or NoneType
8193 
8194  """
8195  line, repmap = string_replace_map(string)
8196  splitted = line.split(",")
8197  lst = []
8198 
8199  # Examine the first entry in the list. If it is not named then it must
8200  # be a unit number (C910).
8201  have_unit = False
8202  have_unnamed_nml_or_fmt = False
8203  spec = splitted.pop(0).strip()
8204  spec = repmap(spec)
8205 
8206  try:
8207 
8208  try:
8209  Io_Unit(spec)
8210  # We matched an unamed unit number. We now need to construct an
8211  # Io_Control_Spec for it. In order to do so we have to
8212  # temporarily name it so that Io_Control_Spec matches it.
8213  io_spec = Io_Control_Spec("unit=" + spec)
8214  # Remove the name from the new object
8215  io_spec.items = (None, io_spec.items[1])
8216  lst.append(io_spec)
8217  # Record that we have found a unit number for the purpose of
8218  # performing validation checks.
8219  have_unit = True
8220 
8221  if not splitted:
8222  # The list only has one entry and it is an IO unit
8223  return ",", tuple(lst)
8224 
8225  # Since the unit-number was not named, the following item may
8226  # also not be named if it is a format specifier or namelist
8227  # group name.
8228  spec = splitted.pop(0).strip()
8229  spec = repmap(spec)
8230  for cls, name in [(Namelist_Group_Name, "nml"), (Format, "fmt")]:
8231  try:
8232  if cls(spec):
8233  # We have a match on an un-named entry. We
8234  # temporarily add the name so that Io_Control_Spec
8235  # matches the correct one.
8236  io_spec = Io_Control_Spec(name + "=" + spec)
8237  # Remove the name from the new object
8238  io_spec.items = (None, io_spec.items[1])
8239  lst.append(io_spec)
8240  have_unnamed_nml_or_fmt = True
8241  break
8242  except NoMatchError:
8243  pass
8244  else:
8245  raise NoMatchError("Not an un-named nml-group-name or fmt")
8246 
8247  except NoMatchError:
8248  # If we get here we failed to match an un-named spec so from
8249  # here on, they must all be named.
8250  lst.append(Io_Control_Spec(spec))
8251 
8252  # Deal with the remainder of the list entries. These must all be
8253  # named.
8254  for spec in splitted:
8255  mapped_spec = repmap(spec.strip())
8256  lst.append(Io_Control_Spec(mapped_spec))
8257 
8258  except NoMatchError:
8259  return None
8260 
8261  # At this point we need to check the list and apply constraints.
8262  # TODO #267 enforce remaining constraints.
8263  have_nml = False
8264  have_fmt = False
8265  for spec in lst:
8266  if spec.children[0] == "UNIT":
8267  have_unit = True
8268  elif spec.children[0] == "NML":
8269  have_nml = True
8270  elif spec.children[0] == "FMT":
8271  have_fmt = True
8272  # C910: An io-unit shall be specified
8273  if not have_unit:
8274  return None
8275  # C916: an io-control-spec-list shall not contain both a format
8276  # and a namelist-group-name
8277  if have_nml and have_fmt:
8278  return None
8279  if have_unnamed_nml_or_fmt and (have_nml or have_fmt):
8280  return None
8281 
8282  return ",", tuple(lst)
8283 
8284 
8285 class Io_Control_Spec(KeywordValueBase):
8286  """
8287  This class implements *partial* support for Rule 913:
8288 
8289  <io-control-spec> is [UNIT = ] <io-unit>
8290  | [ FMT = ] <format>
8291  | [ NML = ] <namelist-group-name>
8292  | ADVANCE = <scalar-default-char-expr>
8293  | ASYNCHRONOUS = <scalar-char-initialization-expr>
8294  | BLANK = <scalar-default-char-expr>
8295  | DECIMAL = <scalar-default-char-expr>
8296  | DELIM = <scalar-default-char-expr>
8297  | END = <label>
8298  | EOR = <label>
8299  | ERR = <label>
8300  | ID = <scalar-int-variable>
8301  | IOMSG = <iomsg-variable>
8302  | IOSTAT = <scalar-int-variable>
8303  | PAD = <scalar-default-char-expr>
8304  | POS = <scalar-int-expr>
8305  | REC = <scalar-int-expr>
8306  | ROUND = <scalar-default-char-expr>
8307  | SIGN = <scalar-default-char-expr>
8308  | SIZE = <scalar-int-variable>
8309 
8310  The support is partial because this class requires that every spec be
8311  named. The specs that may not be named are explicitly handled in
8312  Io_Control_Spec_List.match().
8313 
8314  """
8315 
8316  subclass_names = []
8317  use_names = [
8318  "Io_Unit",
8319  "Format",
8320  "Namelist_Group_Name",
8321  "Scalar_Default_Char_Expr",
8322  "Scalar_Char_Initialization_Expr",
8323  "Label",
8324  "Scalar_Int_Variable",
8325  "Iomsg_Variable",
8326  "Scalar_Int_Expr",
8327  ]
8328 
8329  @staticmethod
8330  def match(string):
8331  for (k, v) in [
8332  ("UNIT", Io_Unit),
8333  ("FMT", Format),
8334  ("NML", Namelist_Group_Name),
8335  (
8336  ["ADVANCE", "BLANK", "DECIMAL", "DELIM", "PAD", "ROUND", "SIGN"],
8337  Scalar_Default_Char_Expr,
8338  ),
8339  ("ASYNCHRONOUS", Scalar_Char_Initialization_Expr),
8340  (["END", "EOR", "ERR"], Label),
8341  (["ID", "IOSTAT", "SIZE"], Scalar_Int_Variable),
8342  ("IOMSG", Iomsg_Variable),
8343  (["POS", "REC"], Scalar_Int_Expr),
8344  ]:
8345  obj = KeywordValueBase.match(k, v, string, upper_lhs=True)
8346  if obj:
8347  return obj
8348  return None
8349 
8350 
8351 class Format(StringBase): # R914
8352  """
8353  <format> = <default-char-expr>
8354  | <label>
8355  | *
8356  """
8357 
8358  subclass_names = ["Label", "Default_Char_Expr"]
8359 
8360  @staticmethod
8361  def match(string):
8362  return StringBase.match("*", string)
8363 
8364 
8365 class Input_Item(Base): # R915
8366  """
8367  <input-item> = <variable>
8368  | <io-implied-do>
8369  """
8370 
8371  subclass_names = ["Variable", "Io_Implied_Do"]
8372 
8373 
8374 class Output_Item(Base): # R916
8375  """
8376  <output-item> = <expr>
8377  | <io-implied-do>
8378  """
8379 
8380  subclass_names = ["Expr", "Io_Implied_Do"]
8381 
8382 
8383 class Io_Implied_Do(Base): # R917
8384  """
8385  <io-implied-do> = ( <io-implied-do-object-list> , <io-implied-do-control> )
8386  """
8387 
8388  subclass_names = []
8389  use_names = ["Io_Implied_Do_Object_List", "Io_Implied_Do_Control"]
8390 
8391  @staticmethod
8392  def match(string):
8393  if len(string) <= 9 or string[0] != "(" or string[-1] != ")":
8394  return
8395  line, repmap = string_replace_map(string[1:-1].strip())
8396  i = line.rfind("=")
8397  if i == -1:
8398  return
8399  j = line[:i].rfind(",")
8400  if j == -1:
8401  return
8402  return (
8403  Io_Implied_Do_Object_List(repmap(line[:j].rstrip())),
8404  Io_Implied_Do_Control(repmap(line[j + 1 :].lstrip())),
8405  )
8406 
8407  def tostr(self):
8408  return "(%s, %s)" % (self.items)
8409 
8410 
8411 class Io_Implied_Do_Object(Base): # R918
8412  """
8413  <io-implied-do-object> = <input-item>
8414  | <output-item>
8415  """
8416 
8417  subclass_names = ["Input_Item", "Output_Item"]
8418 
8419 
8420 class Io_Implied_Do_Control(Base): # R919
8421  """
8422  <io-implied-do-control> = <do-variable> = <scalar-int-expr> ,
8423  <scalar-int-expr> [ , <scalar-int-expr> ]
8424  """
8425 
8426  subclass_names = []
8427  use_names = ["Do_Variable", "Scalar_Int_Expr"]
8428 
8429  @staticmethod
8430  def match(string):
8431  line, repmap = string_replace_map(string)
8432  if "=" not in line:
8433  return
8434  v, exprs = line.split("=", 1)
8435  v = Do_Variable(repmap(v.rstrip()))
8436  exprs = exprs.lstrip().split(",")
8437  if len(exprs) not in [2, 3]:
8438  return
8439  exprs = tuple([Scalar_Int_Expr(repmap(e.strip())) for e in exprs])
8440  if len(exprs) == 2:
8441  return (v,) + exprs + (None,)
8442  return (v,) + exprs
8443 
8444  def tostr(self):
8445  if self.items[3] is not None:
8446  return "%s = %s, %s, %s" % (self.items)
8447  return "%s = %s, %s" % (self.items[:-1])
8448 
8449 
8450 class Dtv_Type_Spec(CALLBase): # R920
8451  """
8452  <dtv-type-spec> = TYPE ( <derived-type-spec> )
8453  | CLASS ( <derived-type-spec> )
8454  """
8455 
8456  subclass_names = []
8457  use_names = ["Derived_Type_Spec"]
8458 
8459  @staticmethod
8460  def match(string):
8461  return CALLBase.match(
8462  ["TYPE", "CLASS"], Derived_Type_Spec, string, require_rhs=True
8463  )
8464 
8465 
8466 class Wait_Stmt(StmtBase, CALLBase): # R921
8467  """
8468  <wait-stmt> = WAIT ( <wait-spec-list> )
8469  """
8470 
8471  subclass_names = []
8472  use_names = ["Wait_Spec_List"]
8473 
8474  @staticmethod
8475  def match(string):
8476  return CALLBase.match("WAIT", Wait_Spec_List, string, require_rhs=True)
8477 
8478 
8479 class Wait_Spec(KeywordValueBase): # R922
8480  """
8481  <wait-spec> = [ UNIT = ] <file-unit-number>
8482  | END = <label>
8483  | EOR = <label>
8484  | ERR = <label>
8485  | ID = <scalar-int-expr>
8486  | IOMSG = <iomsg-variable>
8487  | IOSTAT = <scalar-int-variable>
8488  """
8489 
8490  subclass_names = []
8491  use_names = [
8492  "File_Unit_Number",
8493  "Label",
8494  "Scalar_Int_Expr",
8495  "Iomsg_Variable",
8496  "Scalar_Int_Variable",
8497  ]
8498 
8499  @staticmethod
8500  def match(string):
8501  for (k, v) in [
8502  (["END", "EOR", "ERR"], Label),
8503  ("IOSTAT", Scalar_Int_Variable),
8504  ("IOMSG", Iomsg_Variable),
8505  ("ID", Scalar_Int_Expr),
8506  ("UNIT", File_Unit_Number),
8507  ]:
8508  try:
8509  obj = KeywordValueBase.match(k, v, string, upper_lhs=True)
8510  except NoMatchError:
8511  obj = None
8512  if obj is not None:
8513  return obj
8514  return "UNIT", File_Unit_Number(string)
8515 
8516 
8517 class Backspace_Stmt(StmtBase): # R923
8518  """
8519  :F03R:`923`::
8520  <backspace-stmt> = BACKSPACE <file-unit-number>
8521  | BACKSPACE ( <position-spec-list> )
8522 
8523  Attributes
8524  ----------
8525  items : (File_Unit_Number, Position_Spec_List)
8526  """
8527 
8528  subclass_names = []
8529  use_names = ["File_Unit_Number", "Position_Spec_List"]
8530 
8531  @staticmethod
8532  def match(string):
8533  if string[:9].upper() != "BACKSPACE":
8534  return
8535  line = string[9:].lstrip()
8536  if line.startswith("("):
8537  if not line.endswith(")"):
8538  return
8539  return None, Position_Spec_List(line[1:-1].strip())
8540  return File_Unit_Number(line), None
8541 
8542  def tostr(self):
8543  if self.items[0] is not None:
8544  assert self.items[1] is None, repr(self.items)
8545  return "BACKSPACE %s" % (self.items[0])
8546  return "BACKSPACE(%s)" % (self.items[1])
8547 
8548 
8549 class Endfile_Stmt(StmtBase): # R924
8550  """
8551  :F03R:`924`::
8552  <endfile-stmt> = ENDFILE <file-unit-number>
8553  | ENDFILE ( <position-spec-list> )
8554 
8555  Attributes
8556  ----------
8557  items : (File_Unit_Number, Position_Spec_List)
8558  """
8559 
8560  subclass_names = []
8561  use_names = ["File_Unit_Number", "Position_Spec_List"]
8562 
8563  @staticmethod
8564  def match(string):
8565  if string[:7].upper() != "ENDFILE":
8566  return
8567  line = string[7:].lstrip()
8568  if line.startswith("("):
8569  if not line.endswith(")"):
8570  return
8571  return None, Position_Spec_List(line[1:-1].strip())
8572  return File_Unit_Number(line), None
8573 
8574  def tostr(self):
8575  if self.items[0] is not None:
8576  assert self.items[1] is None, repr(self.items)
8577  return "ENDFILE %s" % (self.items[0])
8578  return "ENDFILE(%s)" % (self.items[1])
8579 
8580 
8581 class Rewind_Stmt(StmtBase): # R925
8582  """
8583  :F03R:`925`::
8584  <rewind-stmt> = REWIND <file-unit-number>
8585  | REWIND ( <position-spec-list> )
8586 
8587  Attributes
8588  ----------
8589  items : (File_Unit_Number, Position_Spec_List)
8590  """
8591 
8592  subclass_names = []
8593  use_names = ["File_Unit_Number", "Position_Spec_List"]
8594 
8595  @staticmethod
8596  def match(string):
8597  if string[:6].upper() != "REWIND":
8598  return
8599  line = string[6:].lstrip()
8600  if line.startswith("("):
8601  if not line.endswith(")"):
8602  return
8603  return None, Position_Spec_List(line[1:-1].strip())
8604  return File_Unit_Number(line), None
8605 
8606  def tostr(self):
8607  if self.items[0] is not None:
8608  assert self.items[1] is None, repr(self.items)
8609  return "REWIND %s" % (self.items[0])
8610  return "REWIND(%s)" % (self.items[1])
8611 
8612 
8613 class Position_Spec(KeywordValueBase): # R926
8614  """
8615  <position-spec> = [ UNIT = ] <file-unit-number>
8616  | IOMSG = <iomsg-variable>
8617  | IOSTAT = <scalar-int-variable>
8618  | ERR = <label>
8619  """
8620 
8621  subclass_names = []
8622  use_names = ["File_Unit_Number", "Iomsg_Variable", "Scalar_Int_Variable", "Label"]
8623 
8624  @staticmethod
8625  def match(string):
8626  for (k, v) in [
8627  ("ERR", Label),
8628  ("IOSTAT", Scalar_Int_Variable),
8629  ("IOMSG", Iomsg_Variable),
8630  ("UNIT", File_Unit_Number),
8631  ]:
8632  try:
8633  obj = KeywordValueBase.match(k, v, string, upper_lhs=True)
8634  except NoMatchError:
8635  obj = None
8636  if obj is not None:
8637  return obj
8638  return "UNIT", File_Unit_Number(string)
8639 
8640 
8641 class Flush_Stmt(StmtBase): # R927
8642  """
8643  :F03R:`927`::
8644  <flush-stmt> = FLUSH <file-unit-number>
8645  | FLUSH ( <position-spec-list> )
8646  Attributes
8647  ----------
8648  items : (File_Unit_Number, Position_Spec_List)
8649  """
8650 
8651  subclass_names = []
8652  use_names = ["File_Unit_Number", "Position_Spec_List"]
8653 
8654  @staticmethod
8655  def match(string):
8656  if string[:5].upper() != "FLUSH":
8657  return
8658  line = string[5:].lstrip()
8659  if line.startswith("("):
8660  if not line.endswith(")"):
8661  return
8662  return None, Position_Spec_List(line[1:-1].strip())
8663  return File_Unit_Number(line), None
8664 
8665  def tostr(self):
8666  if self.items[0] is not None:
8667  assert self.items[1] is None, repr(self.items)
8668  return "FLUSH %s" % (self.items[0])
8669  return "FLUSH(%s)" % (self.items[1])
8670 
8671 
8672 class Flush_Spec(KeywordValueBase): # R928
8673  """
8674  :F03R:`928`::
8675  <flush-spec> = [ UNIT = ] <file-unit-number>
8676  | IOMSG = <iomsg-variable>
8677  | IOSTAT = <scalar-int-variable>
8678  | ERR = <label>
8679  Attributes
8680  ----------
8681  items : ({'UNIT', 'IOMSG', 'IOSTAT', 'ERR'}, {File_Unit_Number,
8682  Iomsg_Variable, Scalar_Int_Variable, Label})
8683  """
8684 
8685  subclass_names = []
8686  use_names = ["File_Unit_Number", "Iomsg_Variable", "Scalar_Int_Variable", "Label"]
8687 
8688  @staticmethod
8689  def match(string):
8690  for (k, v) in [
8691  ("ERR", Label),
8692  ("IOSTAT", Scalar_Int_Variable),
8693  ("IOMSG", Iomsg_Variable),
8694  ("UNIT", File_Unit_Number),
8695  ]:
8696  try:
8697  obj = KeywordValueBase.match(k, v, string, upper_lhs=True)
8698  except NoMatchError:
8699  obj = None
8700  if obj is not None:
8701  return obj
8702  return "UNIT", File_Unit_Number(string)
8703 
8704 
8705 class Inquire_Stmt(StmtBase): # R929
8706  """
8707  :F03R:`929`::
8708  <inquire-stmt> = INQUIRE ( <inquire-spec-list> )
8709  | INQUIRE ( IOLENGTH = <scalar-int-variable> )
8710  <output-item-list>
8711  Attributes
8712  ----------
8713  items : (Inquire_Spec_List, Scalar_Int_Variable, Output_Item_List)
8714  """
8715 
8716  subclass_names = []
8717  use_names = ["Inquire_Spec_List", "Scalar_Int_Variable", "Output_Item_List"]
8718 
8719  @staticmethod
8720  def match(string):
8721  if string[:7].upper() != "INQUIRE":
8722  return
8723  line = string[7:].lstrip()
8724  if not line.startswith("("):
8725  return
8726  if line.endswith(")"):
8727  return Inquire_Spec_List(line[1:-1].strip()), None, None
8728  line, repmap = string_replace_map(line)
8729  i = line.find(")")
8730  if i == -1:
8731  return
8732  tmp = repmap(line[1:i])
8733  if tmp[:8].upper() != "IOLENGTH":
8734  return
8735  tmp = tmp[8:].lstrip()
8736  if not tmp.startswith("="):
8737  return
8738  tmp = tmp[1:].lstrip()
8739  return (
8740  None,
8741  Scalar_Int_Variable(tmp),
8742  Output_Item_List(repmap(line[i + 1 :].lstrip())),
8743  )
8744 
8745  def tostr(self):
8746  if self.items[0] is None:
8747  assert None not in self.items[1:], repr(self.items)
8748  return "INQUIRE(IOLENGTH=%s) %s" % (self.items[1:])
8749  return "INQUIRE(%s)" % (self.items[0])
8750 
8751 
8752 class Inquire_Spec(KeywordValueBase): # R930
8753  """
8754  :F03R:`930`::
8755  <inquire-spec> = [ UNIT = ] <file-unit-number>
8756  | FILE = <file-name-expr>
8757  | ACCESS = <scalar-default-char-variable>
8758  | ACTION = <scalar-default-char-variable>
8759  | ASYNCHRONOUS = <scalar-default-char-variable>
8760  | BLANK = <scalar-default-char-variable>
8761  | DECIMAL = <scalar-default-char-variable>
8762  | DELIM = <scalar-default-char-variable>
8763  | DIRECT = <scalar-default-char-variable>
8764  | ENCODING = <scalar-default-char-variable>
8765  | ERR = <label>
8766  | EXIST = <scalar-default-logical-variable>
8767  | FORM = <scalar-default-char-variable>
8768  | FORMATTED = <scalar-default-char-variable>
8769  | ID = <scalar-int-expr>
8770  | IOMSG = <iomsg-variable>
8771  | IOSTAT = <scalar-int-variable>
8772  | NAME = <scalar-default-char-variable>
8773  | NAMED = <scalar-default-logical-variable>
8774  | NEXTREC = <scalar-int-variable>
8775  | NUMBER = <scalar-int-variable>
8776  | OPENED = <scalar-default-logical-variable>
8777  | PAD = <scalar-default-char-variable>
8778  | PENDING = <scalar-default-logical-variable>
8779  | POS = <scalar-int-variable>
8780  | POSITION = <scalar-default-char-variable>
8781  | READ = <scalar-default-char-variable>
8782  | READWRITE = <scalar-default-char-variable>
8783  | RECL = <scalar-int-variable>
8784  | ROUND = <scalar-default-char-variable>
8785  | SEQUENTIAL = <scalar-default-char-variable>
8786  | SIGN = <scalar-default-char-variable>
8787  | SIZE = <scalar-int-variable>
8788  | STREAM = <scalar-default-char-variable>
8789  | UNFORMATTED = <scalar-default-char-variable>
8790  | WRITE = <scalar-default-char-variable>
8791 
8792  Attributes
8793  ----------
8794  items : (str, instance)
8795  """
8796 
8797  subclass_names = []
8798  use_names = [
8799  "File_Unit_Number",
8800  "File_Name_Expr",
8801  "Scalar_Default_Char_Variable",
8802  "Scalar_Default_Logical_Variable",
8803  "Scalar_Int_Variable",
8804  "Scalar_Int_Expr",
8805  "Label",
8806  "Iomsg_Variable",
8807  ]
8808 
8809  @staticmethod
8810  def match(string):
8811  """
8812  :param str string: The string to check for conformance with an
8813  Inquire_Spec
8814  :return: 2-tuple of name (e.g. "UNIT") and value or None if
8815  string is not a valid Inquire_Spec
8816  :rtype: 2-tuple where first object represents the name and the
8817  second the value.
8818  """
8819  if "=" not in string:
8820  # The only argument which need not be named is the unit number
8821  return "UNIT", File_Unit_Number(string)
8822  # We have a keyword-value pair. Check whether it is valid...
8823  for (keyword, value) in [
8824  (
8825  [
8826  "ACCESS",
8827  "ACTION",
8828  "ASYNCHRONOUS",
8829  "BLANK",
8830  "DECIMAL",
8831  "DELIM",
8832  "DIRECT",
8833  "ENCODING",
8834  "FORM",
8835  "NAME",
8836  "PAD",
8837  "POSITION",
8838  "READ",
8839  "READWRITE",
8840  "ROUND",
8841  "SEQUENTIAL",
8842  "SIGN",
8843  "STREAM",
8844  "UNFORMATTED",
8845  "WRITE",
8846  ],
8847  Scalar_Default_Char_Variable,
8848  ),
8849  ("ERR", Label),
8850  (["EXIST", "NAMED", "PENDING", "OPENED"], Scalar_Default_Logical_Variable),
8851  ("ID", Scalar_Int_Expr),
8852  (
8853  ["IOSTAT", "NEXTREC", "NUMBER", "POS", "RECL", "SIZE"],
8854  Scalar_Int_Variable,
8855  ),
8856  ("IOMSG", Iomsg_Variable),
8857  ("FILE", File_Name_Expr),
8858  ("UNIT", File_Unit_Number),
8859  ]:
8860  try:
8861  obj = KeywordValueBase.match(keyword, value, string, upper_lhs=True)
8862  except NoMatchError:
8863  obj = None
8864  if obj is not None:
8865  return obj
8866  return None
8867 
8868 
8869 #
8870 # SECTION 10
8871 #
8872 
8873 
8874 class Format_Stmt(StmtBase, WORDClsBase): # R1001
8875  """
8876  <format-stmt> = FORMAT <format-specification>
8877  """
8878 
8879  subclass_names = []
8880  use_names = ["Format_Specification"]
8881 
8882  @staticmethod
8883  def match(string):
8884  return WORDClsBase.match(
8885  "FORMAT", Format_Specification, string, require_cls=True
8886  )
8887 
8888 
8889 class Format_Item_List(SequenceBase): # pylint: disable=invalid-name
8890  """This class replaces the one generated by fparser. This class is
8891  required as support for hollerith strings makes matching more
8892  complicated.
8893 
8894  """
8895 
8896  use_names = []
8897  subclass_names = ["Format_Item"]
8898 
8899  @staticmethod
8900  def match(string):
8901  """Implements the matching for a list of format items.
8902 
8903  Supporting Hollerith strings makes it very difficult to
8904  correctly split the input string into items a-priori. The
8905  reason for this can be seen in the following example:
8906 
8907  `2H,x,e2.2` is `2H,x` and `e2.2` but when split with commas
8908  incorrectly gives `2H`, `x` and `e2.2`.
8909 
8910  Further, hollerith strings could also confuse any code that
8911  tried to determine whether code was inside quotes or not. For
8912  example:
8913 
8914  `2H"x,2H"x` does not mean that `x,2H` is part of a string.
8915 
8916  The solution chosen is to match one item at a time, first
8917  checking for a valid Hollerith string and then checking for
8918  any other valid input.
8919 
8920  :param str string: the string to match as a Format List.
8921  :return: None if there is no match or a tuple of size 2 \
8922  containing a string with a comma followed by a tuple \
8923  containing a list which itself contains the matched \
8924  format items.
8925  :rtype: (`str`, \
8926  ([:py:class:`fparser.two.Fortran2003.Format_Item`s])) or `NoneType`
8927 
8928  """
8929  if not string:
8930  return None
8931  current_string = string.lstrip()
8932  if not current_string:
8933  return None
8934  item_list = []
8935  while current_string:
8936  # Look for a slash edit descriptor with repeat modifier
8937  found, index = skip_digits(current_string)
8938  if found and current_string[index] == "/":
8939  item_list.append(Control_Edit_Desc(current_string[: index + 1]))
8940  current_string = current_string[index + 1 :].lstrip()
8941  # Rule C1002 allows omitting a comma after slash edit descriptors,
8942  # so skip the comma if it exists and carry on
8943  if current_string and current_string[0] == ",":
8944  current_string = current_string[1:].lstrip()
8945  continue
8946 
8947  # Look for a colon edit descriptor or a slash edit descriptor without
8948  # a repeat modifier
8949  if current_string[0] in ":/":
8950  item_list.append(Control_Edit_Desc(current_string[0]))
8951  current_string = current_string[index + 1 :].lstrip()
8952  # Rule C1002 allows omitting a comma after colon or slash edit
8953  # descriptors, so skip the comma if it exists and carry on
8954  if current_string and current_string[0] == ",":
8955  current_string = current_string[1:].lstrip()
8956  continue
8957 
8958  # Does the current item match the start of a
8959  # hollerith string?
8960  my_pattern = Hollerith_Item.match_pattern
8961  match = re.search(my_pattern, current_string)
8962  if match:
8963  # The current item matches with a hollerith string.
8964  match_str = match.group(0)
8965  hol_length_str = match_str[:-1]
8966  hol_length = int(hol_length_str)
8967  num_chars = len(match_str) + hol_length
8968  if len(current_string) < num_chars:
8969  # The string is not long enough.
8970  return None
8971  item_list.append(Hollerith_Item(current_string[:num_chars]))
8972  current_string = current_string[num_chars:].lstrip()
8973  if current_string:
8974  if current_string[0] == ",":
8975  # Remove the next comma and any white space.
8976  current_string = current_string[1:].lstrip()
8977  elif current_string[0] == "/":
8978  # Commas aren't required before a slash edit descriptor without
8979  # repeat modifier (C1002)
8980  pass
8981  elif current_string[0] == ":":
8982  # Commas aren't required before a colon edit descriptor (C1002)
8983  pass
8984  else:
8985  return None
8986  else:
8987  # Current item does not match with a hollerith string
8988  # so get the next format item by splitting on ',', '/' or ':'
8989  # after applying string_replace_map.
8990  line, repmap = string_replace_map(current_string)
8991  match = re.search("[,/:]", line)
8992  if match:
8993  item_list.append(Format_Item(repmap(line[: match.start()])))
8994  current_string = repmap(line[match.start() :])
8995  if match.group() == ",":
8996  # skip the comma
8997  current_string = current_string[1:].lstrip()
8998  else:
8999  item_list.append(Format_Item(repmap(line)))
9000  current_string = ""
9001  return ",", tuple(item_list)
9002 
9003 
9004 class Format_Specification(BracketBase): # pylint: disable=invalid-name
9005  """
9006  Fortran 2003 rule R1002
9007 
9008  format-specification = ( [ format-item-list ] )
9009 
9010  C1002 is implemented in a separate class Format_Item_C1002
9011 
9012  C1002 (R1002) The comma used to separate format-items in a
9013  format-item-list may be omitted
9014 
9015  (1) Between a P edit descriptor and an immediately following F, E,
9016  EN, ES, D, or G edit descriptor, possibly preceded by a repeat
9017  specifier,
9018 
9019  (2) Before a slash edit descriptor when the optional repeat
9020  specification is not present,
9021 
9022  (3) After a slash edit descriptor, or
9023 
9024  (4) Before or after a colon edit descriptor.
9025 
9026  """
9027 
9028  subclass_names = []
9029  use_names = ["Format_Item_List"]
9030 
9031  @staticmethod
9032  def match(string):
9033  """Implements the matching for a format specification.
9034 
9035  :param str string: The string to check for conformance with a \
9036  format specification.
9037  :return: `None` if there is no match, otherwise a tuple of \
9038  size three, the first entry being a string containing a left \
9039  bracket and the third being a string containing a right \
9040  bracket. The second entry is either a Format_Item or a \
9041  Format_Item_List.
9042  :rtype: `NoneType` or ( `str`, \
9043  :py:class:`fparser.two.Fortran2003.Format_Item` or \
9044  :py:class:`fparser.two.Fortran2003.Format_Item_List`, `str` )
9045 
9046  """
9047  return BracketBase.match("()", Format_Item_List, string, require_cls=False)
9048 
9049 
9050 def skip_digits(string):
9051  """Skips over any potential digits (including spaces) to the next
9052  non-digit character and return its index. If no such character is
9053  found or if the first character in the string is not a digit then
9054  specify that the skip has failed.
9055 
9056  :param str string: The string to search
9057  :returns: a 2-tuple with the first entry indicating if a valid \
9058  character has been found and the second entry indicating the index \
9059  of this character in the 'string' argument.
9060  :rtype: (bool, int)
9061 
9062  """
9063  found = False
9064  index = 0
9065  for index, char in enumerate(string):
9066  if not (char.isdigit() or char == " "):
9067  if index > 0:
9068  found = True
9069  break
9070  return found, index
9071 
9072 
9073 class Format_Item_C1002(Base): # pylint: disable=invalid-name
9074  """
9075  Fortran 2003 constraint C1002
9076 
9077  format-item-c1002 is kP [,] (F|D)w.d | (E|EN|ES|G)w.d[Ee]
9078  or [r]/ [,] format-item
9079  or : [,] format-item
9080  or format-item [,] / [[,] format-item]
9081  or format-item [,] : [[,] format-item]
9082 
9083  C1002 (R1002) The comma used to separate format-items in a
9084  format-item-list may be omitted
9085 
9086  (1) Between a P edit descriptor and an immediately following F, E,
9087  EN, ES, D, or G edit descriptor, possibly preceded by a repeat
9088  specifier,
9089 
9090  (2) Before a slash edit descriptor when the optional repeat
9091  specification is not present (10.7.2),
9092 
9093  (3) After a slash edit descriptor, or
9094 
9095  (4) Before or after a colon edit descriptor.
9096 
9097  """
9098 
9099  subclass_names = []
9100  use_names = ["K", "W", "D", "E", "Format_Item", "R"]
9101 
9102  @staticmethod
9103  def match(string):
9104  """Implements the matching for the C1002 Format Item constraint. The
9105  constraints specify certain combinations of format items that
9106  do not need a comma to separate them. Rather than sorting this
9107  out when parsing the list, it was decided to treat these
9108  separately and match them in this class. As a result the
9109  generated class hierarchy is a little more complicated.
9110 
9111  :param str string: The string to check for conformance with a \
9112  C1002 format item constraint.
9113  :return: `None` if there is no match, otherwise a tuple of \
9114  size 2 containing a mixture of Control_Edit_Descriptor and \
9115  Format_Item classes depending on what has been matched.
9116 
9117  :rtype: `NoneType` or ( \
9118  :py:class:`fparser.two.Control_Edit_Desc`, \
9119  :py:class:`fparser.two.Format_Item` ) or \
9120  (:py:class:`fparser.two.Format_Item`, \
9121  :py:class:`fparser.two.Control_Edit_Desc`) or \
9122  (:py:class:`fparser.two.Format_Item`, \
9123  :py:class:`fparser.two.Format_Item`)
9124 
9125  """
9126  if not string:
9127  return None
9128  strip_string = string.strip()
9129  if len(strip_string) <= 1:
9130  return None
9131  if strip_string[0] in ":/":
9132  # No comma is required after slash edit descriptor (3) or
9133  # after a colon edit descriptor (4)
9134  return (
9135  Control_Edit_Desc(strip_string[0]),
9136  Format_Item(strip_string[1:].lstrip()),
9137  )
9138  if strip_string[-1] in ":/":
9139  # No comma is required before a slash edit descriptor,
9140  # when the optional repeat specification is not present
9141  # (2), or before a colon edit descriptor (4). Note, if an
9142  # optional repeat specification is present it will be
9143  # treated as if it is part of the previous item.
9144  return (
9145  Format_Item(strip_string[:-1].rstrip()),
9146  Control_Edit_Desc(strip_string[-1]),
9147  )
9148  # We may have a P edit descriptor (which requires a number
9149  # before the 'P') (1) or a slash edit descriptor with a repeat
9150  # specifier (3) so look for the repeat specifier.
9151  found, index = skip_digits(strip_string)
9152  if found:
9153  # We found a possible repeat specifier (which may contain
9154  # white space after the first digit)
9155  result = strip_string[index].upper()
9156  if result == "/":
9157  # We found a possible slash edit descriptor with a
9158  # repeat specifier (3).
9159  return (
9160  Control_Edit_Desc(strip_string[: index + 1]),
9161  Format_Item(strip_string[index + 1 :].lstrip()),
9162  )
9163  if result == "P":
9164  # We found a possible P edit descriptor (1).
9165  # Rule C1002 only allows a comma to be ommited between
9166  # a P edit descriptor and a following F, E, EN, ES, D,
9167  # or G edit descriptor with an optional repeat
9168  # specifier. In fparser2 this translates to a
9169  # Format_Item instance containing a Data_Edit_Desc, or
9170  # Data_Edit_Desc_C1002 instance as its second item
9171  # with the data edit descriptor instance's first item
9172  # specifying the type of edit descriptor.
9173  lhs = Control_Edit_Desc(strip_string[: index + 1])
9174  rhs = Format_Item(strip_string[index + 1 :].lstrip())
9175  if not isinstance(rhs, Format_Item):
9176  # Matched with a subclass of Format_item or no match.
9177  return None
9178  descriptor_object = rhs.items[1]
9179  if not isinstance(
9180  descriptor_object, (Data_Edit_Desc, Data_Edit_Desc_C1002)
9181  ):
9182  return None
9183  edit_descriptor = descriptor_object.items[0]
9184  if edit_descriptor.upper() not in ["F", "E", "EN", "ES", "D", "G"]:
9185  return None
9186  return lhs, rhs
9187 
9188  # Replace any content inside strings etc. so we dont split the
9189  # line in the wrong place.
9190  line, repmap = string_replace_map(strip_string)
9191 
9192  # Slash and colon edit descriptors may have no comma's both
9193  # before and after them (2,3,4) e.g. ('a' / 'b'). To match this
9194  # situation we split the line with the first potential descriptor found
9195  # in the string and try to match the lhs and rhs separately
9196  # (adding the edit descriptor to the RHS).
9197  for option in "/:":
9198  if option in line:
9199  left, right = line.split(option, 1)
9200  return (
9201  Format_Item(repmap(left.rstrip())),
9202  Format_Item(option + repmap(right.lstrip())),
9203  )
9204 
9205  def tostr(self):
9206  """
9207  :return: Parsed representation of two format items
9208  :rtype: str
9209 
9210  :raises InternalError: if the length of the internal items \
9211  list is not 2.
9212  :raises InternalError: if the first entry of the internal \
9213  items list has no content.
9214  :raises InternalError: if the second entry of the internal \
9215  items list has no content.
9216 
9217  """
9218  if len(self.items) != 2:
9219  raise InternalError(
9220  "Class Format_Item_C1002 method tostr(): internal items list "
9221  "should be length 2 but found '{0}'".format(len(self.items))
9222  )
9223  if not self.items[0]:
9224  raise InternalError(
9225  "Class Format_Item_C1002 method tostr() items entry 0 should "
9226  "contain a format items object but it is empty or None"
9227  )
9228  if not self.items[1]:
9229  raise InternalError(
9230  "Class Format_Item_C1002 method tostr() items entry 1 should "
9231  "contain a format items object but it is empty or None"
9232  )
9233  return "{0}, {1}".format(self.items[0], self.items[1])
9234 
9235 
9236 class Hollerith_Item(Base): # pylint: disable=invalid-name
9237  """Hollerith strings take the form `nHx`, where `n` is an integer and
9238  `x` is a sequence of characters of length `n`.
9239 
9240  Note, the Hollerith format was deprecated in Fortran77 and removed in
9241  Fortran95. However, Fortran compilers still support it. See, for example
9242  https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gfortran/
9243  Hollerith-constants-support.html
9244 
9245  """
9246 
9247  subclass_names = []
9248  use_names = []
9249  match_pattern = "^[1-9][0-9 ]*[hH]"
9250 
9251  @staticmethod
9252  def match(string):
9253  """Implements the matching for a Hollerith string.
9254 
9255  :param str string: The string to check for conformance with a \
9256  Hollerith string
9257  :return: String containing the contents of the Hollerith \
9258  string.
9259  :rtype: str
9260 
9261  """
9262  from fparser.two.utils import EXTENSIONS
9263 
9264  if "hollerith" not in EXTENSIONS:
9265  return None
9266  if not string:
9267  return None
9268  # Only strip space to the left as space to the right could be
9269  # part of the hollerith string.
9270  strip_string = string.lstrip()
9271  match = re.search(Hollerith_Item.match_pattern, strip_string)
9272  if not match:
9273  return None
9274  # Current item matches with a hollerith string.
9275  match_str = match.group(0)
9276  hol_length_str = match_str[:-1].replace(" ", "")
9277  hol_length = int(hol_length_str)
9278  num_chars = len(match_str) + hol_length
9279  if len(strip_string) < num_chars:
9280  # The string is too short
9281  return None
9282  if len(strip_string) > num_chars:
9283  # The string is too long
9284  if strip_string[num_chars:].strip():
9285  # The extra is not just white space
9286  return None
9287  return (strip_string[len(match_str) : num_chars],)
9288 
9289  def tostr(self):
9290  """
9291  :return: Parsed representation of a Hollerith String.
9292  :rtype: str
9293 
9294  :raises InternalError: if the length of the internal items \
9295  list is not 1.
9296  :raises InternalError: if the first entry of the internal \
9297  items list has no content.
9298 
9299  """
9300  if len(self.items) != 1:
9301  raise InternalError(
9302  "Class Hollerith_Item method tostr(): internal items list "
9303  "should be of length 1 but found '{0}'".format(len(self.items))
9304  )
9305  if not self.items[0]:
9306  raise InternalError(
9307  "Class Hollerith_Item method tostr() items entry 0 should be "
9308  "a valid Hollerith string but it is empty or None"
9309  )
9310  return "{0}H{1}".format(len(self.items[0]), self.items[0])
9311 
9312 
9313 class Format_Item(Base): # pylint: disable=invalid-name
9314  """
9315  Fortran 2003 rule R1003
9316  format-item is [ r ] data-edit-desc
9317  or control-edit-desc
9318  or char-string-edit-desc
9319  or [ r ] ( format-item-list )
9320  or format-item-c1002
9321  or hollerith-item
9322 
9323  """
9324 
9325  subclass_names = [
9326  "Hollerith_Item",
9327  "Control_Edit_Desc",
9328  "Char_String_Edit_Desc",
9329  "Format_Item_C1002",
9330  ]
9331  use_names = ["R", "Format_Item_List", "Data_Edit_Desc"]
9332 
9333  @staticmethod
9334  def match(string):
9335  """Implements the matching of a Format Item. This method matches '[ r
9336  ] data-edit-desc' and '[ r ] ( format-item-list )'. The
9337  remaining options are matched via subclasses specified in the
9338  subclass_names variable.
9339 
9340  :param str string: A string or the Fortran reader containing the \
9341  line of code that we are trying to match.
9342  :return: `None` if there is no match or a `tuple` of size 2 \
9343  containing an instance of the R class followed by an \
9344  instance of either the Format_Item_List or the Data_Edit_Desc \
9345  class.
9346  :rtype: `None` or ( :py:class:`fparser.two.Fortran2003.R`, \
9347  :py:class:`fparser.two.Fortran2003.Format_Item_List` or \
9348  :py:class:`fparser.two.Fortran2003.Data_Edit_Desc`)
9349 
9350  """
9351  if not string:
9352  return None
9353  strip_string = string.strip()
9354  if not strip_string:
9355  return None
9356  index = 0
9357  # Look for an optional repeat specifier (the 'r' in this rule)
9358  found, index = skip_digits(strip_string)
9359  rpart = None
9360  my_string = strip_string
9361  if found:
9362  # We found a repeat specifier (with content after it) so
9363  # create an R class using the value
9364  rpart = R(strip_string[:index])
9365  my_string = strip_string[index:].lstrip()
9366  # We deal with format-item-list and data-edit-desc in this
9367  # match method. Other matches are performed by the subclasses.
9368  if my_string[0] == "(" and my_string[-1] == ")":
9369  # This could be a format-item-list
9370  rest = Format_Item_List(my_string[1:-1].lstrip())
9371  else:
9372  # This is not a format-item-list so see if it is a
9373  # data-edit-descriptor
9374  rest = Data_Edit_Desc(my_string)
9375  return rpart, rest
9376 
9377  def tostr(self):
9378  """
9379  :return: Parsed representation of a Format Item.
9380  :rtype: str
9381 
9382  :raises InternalError: if the length of the internal items \
9383  list is not 2.
9384  :raises InternalError: if the first entry of the internal \
9385  items list has no content.
9386 
9387  """
9388  if len(self.items) != 2:
9389  raise InternalError(
9390  "Class Format_Item method tostr(): internal items list "
9391  "should be of length 2 but found '{0}'".format(len(self.items))
9392  )
9393  if not self.items[1]:
9394  raise InternalError(
9395  "Class Format_Item method tostr(): items list second entry "
9396  "should be a valid descriptor but it is empty or None"
9397  )
9398  rpart = self.items[0]
9399  rest = self.items[1]
9400 
9401  rpart_str = rpart if rpart else ""
9402  if isinstance(rest, (Data_Edit_Desc, Data_Edit_Desc_C1002)):
9403  return "{0}{1}".format(rpart_str, rest)
9404  return "{0}({1})".format(rpart_str, rest)
9405 
9406 
9407 class R(Base): # R1004
9408  """
9409  ::
9410  <r> = <int-literal-constant>
9411 
9412  Notes
9413  -----
9414  C1003, C1004: <r> shall be positive and without kind parameter specified.
9415  """
9416 
9417  subclass_names = ["Digit_String"]
9418 
9419 
9421  """This class helps implement the matching for the first part of the
9422  Fortran 2003 Constraint C1002 which constrains rule R1002. In
9423  particular it matches with the subset of edit descriptors that can
9424  follow a P edit descriptor without needing a comma, see below:
9425 
9426  C1002 (applied to R1002) The comma used to separate format-items
9427  in a format-item-list may be omitted
9428 
9429  (1) Between a P edit descriptor and an immediately following F, E,
9430  EN, ES, D, or G edit descriptor, possibly preceded by a
9431  repeat specifier.
9432 
9433  [Remaining constraint clauses ommitted as they are not relevant
9434  here.]
9435 
9436  data-edit-desc is F w . d
9437  or E w . d [ E e ]
9438  or EN w . d [ E e ]
9439  or ES w . d [ E e]
9440  or G w . d [ E e ]
9441  or D w . d
9442 
9443  """
9444 
9445  subclass_names = []
9446  use_names = ["W", "D", "E"]
9447 
9448  @staticmethod
9449  def match(string):
9450  """Check whether the input matches the rule.
9451 
9452  param str string: contains the Fortran that we are trying to \
9453  match.
9454  :return: `None` if there is no match, otherwise a `tuple` of \
9455  size 4, the first entry containing a string with one of ['F', \
9456  'E', 'EN', 'ES', 'G', 'D'], the second entry containing a W \
9457  class instance, the third entry containing D class instance \
9458  and the fourth entry containing either None or an E class \
9459  instance.
9460  :rtype: `NoneType`, (`str`, :py:class:`fparser.two.W`, \
9461  :py:class:`fparser.two.D`, `NoneType`) or, (`str`, \
9462  :py:class:`fparser.two.W`, :py:class:`fparser.two.D`, \
9463  :py:class:`fparser.two.E`)
9464 
9465  """
9466  if not string:
9467  return None
9468  strip_string = string.strip()
9469  if not strip_string:
9470  return None
9471  char = strip_string[0].upper()
9472  if char in ["F", "D"]:
9473  # match w . d
9474  my_str = strip_string[1:].lstrip().upper()
9475  if "." in my_str:
9476  left, right = my_str.split(".", 1)
9477  left = left.rstrip()
9478  right = right.lstrip()
9479  return char, W(left), D(right), None
9480  return None
9481  if char in ["E", "G"]:
9482  # match w . d [ E e ]
9483  # Format descriptor could also be 'ES' or 'EN'
9484  my_str = strip_string[1:].lstrip().upper()
9485  char2 = my_str[0]
9486  if char == "E" and char2 in ["S", "N"]:
9487  my_str = my_str[1:].lstrip()
9488  else:
9489  char2 = ""
9490  if "." not in my_str:
9491  return None
9492  left, right = my_str.split(".", 1)
9493  left = left.rstrip()
9494  right = right.lstrip()
9495  # Can optionally specify the number of digits for the
9496  # exponent
9497  if right.count("E") >= 1:
9498  middle, right = right.split("E", 1)
9499  middle = middle.rstrip()
9500  right = right.lstrip()
9501  return char + char2, W(left), D(middle), E(right)
9502  return char + char2, W(left), D(right), None
9503  # Invalid char
9504  return None
9505 
9506  def tostr(self):
9507  """
9508  :return: parsed representation of a Data Edit Descriptor \
9509  conforming to constraint C1002.
9510  :rtype: str
9511 
9512  :raises InternalError: if the length of the internal items \
9513  list is not 4.
9514  :raises InternalError: if the first, second or third entry of \
9515  the internal items list has no content.
9516  :raises InternalError: if the value of the first entry is \
9517  unsupported.
9518  :raises InternalError: if the value of the first entry is 'F' \
9519  or 'D' and the fourth entry has content.
9520  :raises InternalError: if the value of the first entry is 'E', \
9521  'EN', 'ES' or 'G' and the fourth entry is empty or None.
9522 
9523  """
9524  if not len(self.items) == 4:
9525  raise InternalError(
9526  "Class Data_Edit_Desc_C1002 method tostr() has '{0}' items, "
9527  "but expecting 4.".format(len(self.items))
9528  )
9529  if not self.items[0]:
9530  raise InternalError(
9531  "items[0] in Class Data_Edit_Desc_C1002 method tostr() "
9532  "should be a descriptor name but is empty or None"
9533  )
9534  if not self.items[1]:
9535  raise InternalError(
9536  "items[1] in Class Data_Edit_Desc_C1002 method tostr() "
9537  "should be the w value but is empty or None"
9538  )
9539  if not self.items[2]:
9540  raise InternalError(
9541  "items[2] in Class Data_Edit_Desc_C1002 method tostr() "
9542  "should be the m value but is empty or None"
9543  )
9544  descriptor_name = self.items[0]
9545  if descriptor_name in ["F", "D"]:
9546  if self.items[3]:
9547  raise InternalError(
9548  "items[3] in Class Data_Edit_Desc_C1002 method tostr() "
9549  "has an exponent value '{0}' but this is not allowed for "
9550  "'F' and 'D' descriptors and should therefore be "
9551  "None".format(self.items[3])
9552  )
9553  return "{0}{1}.{2}".format(descriptor_name, self.items[1], self.items[2])
9554  elif descriptor_name in ["E", "EN", "ES", "G"]:
9555  if self.items[3] is None:
9556  return "{0}{1}.{2}".format(
9557  descriptor_name, self.items[1], self.items[2]
9558  )
9559  return "{0}{1}.{2}E{3}".format(
9560  descriptor_name, self.items[1], self.items[2], self.items[3]
9561  )
9562  raise InternalError(
9563  "Unexpected descriptor name '{0}' in Class Data_Edit_Desc_C1002 "
9564  "method tostr()".format(descriptor_name)
9565  )
9566 
9567 
9568 class Data_Edit_Desc(Base): # R1005
9569  """
9570  ::
9571  <data-edit-desc> = I <w> [ . <m> ]
9572  | B <w> [ . <m> ]
9573  | O <w> [ . <m> ]
9574  | Z <w> [ . <m> ]
9575  | L <w>
9576  | A [ <w> ]
9577  | DT [ <char-literal-constant> ] [ ( <v-list> ) ]
9578  | <data-edit-desc-c1002>
9579  """
9580 
9581  subclass_names = ["Data_Edit_Desc_C1002"]
9582  use_names = ["W", "M", "Char_Literal_Constant", "V_List"]
9583 
9584  @staticmethod
9585  def match(string):
9586  c = string[0].upper()
9587  if c in ["I", "B", "O", "Z"]:
9588  line = string[1:].lstrip()
9589  if "." in line:
9590  i1, i2 = line.split(".", 1)
9591  i1 = i1.rstrip()
9592  i2 = i2.lstrip()
9593  return c, W(i1), M(i2), None, Int_Literal_Constant
9594  return c, W(line), None, None
9595  if c == "L":
9596  line = string[1:].lstrip()
9597  if not line:
9598  return
9599  return c, W(line), None, None
9600  if c == "A":
9601  line = string[1:].lstrip()
9602  if not line:
9603  return c, None, None, None
9604  return c, W(line), None, None
9605  c = string[:2].upper()
9606  if len(c) != 2:
9607  return
9608  if c == "DT":
9609  line = string[2:].lstrip()
9610  if not line:
9611  return c, None, None, None
9612  lst = None
9613  if line.endswith(")"):
9614  i = line.rfind("(")
9615  if i == -1:
9616  return
9617  tmp = line[i + 1 : -1].strip()
9618  if not tmp:
9619  return
9620  lst = V_List(tmp)
9621  line = line[:i].rstrip()
9622  if not line:
9623  return c, None, lst, None
9624  return c, Char_Literal_Constant(line), lst, None
9625  return None
9626 
9627  def tostr(self):
9628  c = self.items[0]
9629  if c in ["I", "B", "O", "Z", "A", "L"]:
9630  if self.items[2] is None:
9631  if self.items[1] is None:
9632  return c
9633  return "%s%s" % (c, self.items[1])
9634  return "%s%s.%s" % (c, self.items[1], self.items[2])
9635  if c == "DT":
9636  if self.items[1] is None:
9637  if self.items[2] is None:
9638  return c
9639  else:
9640  return "%s(%s)" % (c, self.items[2])
9641  else:
9642  if self.items[2] is None:
9643  return "%s%s" % (c, self.items[1])
9644  else:
9645  return "%s%s(%s)" % (c, self.items[1], self.items[2])
9646  raise NotImplementedError(repr(c))
9647 
9648 
9649 class W(Base): # R1006
9650  """
9651  ::
9652  <w> = <int-literal-constant> == <digit-string>
9653 
9654  Notes
9655  -----
9656  C1006, C1007: <w> is zero or postive and without kind parameters.
9657  """
9658 
9659  subclass_names = ["Digit_String"]
9660 
9661 
9662 class M(Base): # R1007
9663  """
9664  ::
9665  <m> = <int-literal-constant>
9666 
9667  Notes
9668  -----
9669  C1007: <w> is without kind parameters.
9670  """
9671 
9672  subclass_names = ["Int_Literal_Constant"]
9673 
9674 
9675 class D(Base): # R1008
9676  """
9677  ::
9678  <d> = <int-literal-constant>
9679 
9680  Notes
9681  -----
9682  C1007: <d> is without kind parameters.
9683  """
9684 
9685  subclass_names = ["Int_Literal_Constant"]
9686 
9687 
9688 class E(Base): # R1009
9689  """
9690  ::
9691  <e> = <int-literal-constant>
9692 
9693  Notes
9694  -----
9695  C1005, C1007: <e> is postive and without kind parameters.
9696  """
9697 
9698  subclass_names = ["Digit_String"]
9699 
9700 
9701 class V(Base): # R1010
9702  """
9703  ::
9704  <v> = <signed-int-literal-constant>
9705 
9706  Notes
9707  -----
9708  C1007: <w> is without kind parameters.
9709  """
9710 
9711  subclass_names = ["Signed_Int_Literal_Constant"]
9712 
9713 
9714 class Control_Edit_Desc(Base): # pylint: disable=invalid-name
9715  """
9716  Fortran 2003 rule R1011
9717 
9718  control-edit-desc is position-edit-desc
9719  or [ r ] /
9720  or :
9721  or sign-edit-desc
9722  or k P
9723  or blank-interp-edit-desc
9724  or round-edit-desc
9725  or decimal-edit-desc
9726  or $
9727 
9728  '$' is used to suppress the carriage return on output. Note that
9729  this is an extension to the Fortran standard.
9730 
9731  """
9732 
9733  subclass_names = [
9734  "Position_Edit_Desc",
9735  "Sign_Edit_Desc",
9736  "Blank_Interp_Edit_Desc",
9737  "Round_Edit_Desc",
9738  "Decimal_Edit_Desc",
9739  ]
9740  use_names = ["R", "K"]
9741 
9742  @staticmethod
9743  def match(string):
9744  """Check whether the input matches the rule.
9745 
9746  param str string: contains the Fortran that we are trying to \
9747  match.
9748  :return: `None` if there is no match, otherwise a `tuple` of \
9749  size 2 containing, None and a string with one of '/', ':', or \
9750  '$', an R class and a string containing '/' or a K class and a \
9751  string containing 'P'.
9752  :rtype: `NoneType`, (`NoneType`, `str`), \
9753  (:py:class:`fparser.two.Fortran2003.R`, `str`), or \
9754  (:py:class:`fparser.two.Fortran2003.K`, `str`)
9755 
9756  """
9757  if not string:
9758  return None
9759  strip_string = string.strip()
9760  if not strip_string:
9761  return None
9762  if len(strip_string) == 1 and strip_string in "/:$":
9763  from fparser.two.utils import EXTENSIONS
9764 
9765  if strip_string == "$" and "dollar-descriptor" not in EXTENSIONS:
9766  return None
9767  return None, strip_string
9768  if strip_string[-1] == "/":
9769  return R(strip_string[:-1].rstrip()), "/"
9770  if strip_string[-1].upper() == "P":
9771  return K(strip_string[:-1].rstrip()), "P"
9772  return None
9773 
9774  def tostr(self):
9775  """
9776  :return: parsed representation of a Control Edit Descriptor
9777  :rtype: str
9778  :raises InternalError: if the length of the internal items \
9779  list is not 2.
9780  :raises InternalError: if the second entry of the internal \
9781  items list has no content.
9782 
9783  """
9784  if len(self.items) != 2:
9785  raise InternalError(
9786  "Class Control_Edit_Desc method tostr() has '{0}' items, "
9787  "but expecting 2.".format(len(self.items))
9788  )
9789  if not self.items[1]:
9790  raise InternalError(
9791  "items[1] in Class Control_Edit_Desc method tostr() should "
9792  "be an edit descriptor name but is empty or None"
9793  )
9794  if self.items[0] is not None:
9795  return "{0}{1}".format(self.items[0], self.items[1])
9796  return "{0}".format(self.items[1])
9797 
9798 
9799 class K(Base): # R1012
9800  """
9801  ::
9802  <k> = <signed-int-literal-constant>
9803 
9804  Notes
9805  -----
9806  C1009: <k> is without kind parameters.
9807  """
9808 
9809  subclass_names = ["Signed_Int_Literal_Constant"]
9810 
9811 
9812 class Position_Edit_Desc(Base): # R1013
9813  """
9814  Fortran 2003 rule R1013
9815 
9816  position-edit-desc is T n
9817  or TL n
9818  or TR n
9819  or n X
9820 
9821  where n is a positive integer.
9822 
9823  If the extensions list includes the string 'x-format' then 'X'
9824  without a preceeding integer is also matched. This is a common
9825  extension in Fortran compilers.
9826 
9827  """
9828 
9829  subclass_names = []
9830  use_names = ["N"]
9831 
9832  @staticmethod
9833  def match(string):
9834  """Check whether the input matches the rule.
9835 
9836  param str string: contains the Fortran that we are trying to \
9837  match.
9838  :return: `None` if there is no match, otherwise a `tuple` of \
9839  size 2 either containing a `string` which is one of "T", "TL" \
9840  or "TR", followed by an `N` class, or containing an `N` class, \
9841  or `None`, followed by an "X".
9842  :rtype: `NoneType`, (`str`, \
9843  :py:class:`fparser.two.Fortran2003.N`), \
9844  (:py:class:`fparser.two.Fortran2003.N`, `str`) or (`NoneType`, \
9845  `str`)
9846 
9847  """
9848  if not string:
9849  return None
9850  strip_string_upper = string.strip().upper()
9851  if not strip_string_upper:
9852  # empty input string
9853  return None
9854  if strip_string_upper[0] == "T":
9855  if not len(strip_string_upper) > 1:
9856  # string is not long enough to be valid
9857  return None
9858  if strip_string_upper[1] in "LR":
9859  # We match TL* or TR* where * is stored in variable
9860  # rest
9861  start = strip_string_upper[:2]
9862  rest = strip_string_upper[2:].lstrip()
9863  else:
9864  # We match T* where * is stored in variable rest
9865  start = strip_string_upper[0]
9866  rest = strip_string_upper[1:].lstrip()
9867  # Note, if class N does not match it raises an exception
9868  number_obj = N(rest)
9869  return start, number_obj
9870  if strip_string_upper[-1] == "X":
9871  # We match *X
9872  from fparser.two.utils import EXTENSIONS
9873 
9874  if "x-format" in EXTENSIONS and len(strip_string_upper) == 1:
9875  # The match just contains 'X' which is not valid
9876  # fortran 2003 but is an accepted extension
9877  return None, "X"
9878  # Note, if class N does not match it raises an
9879  # exception
9880  number_obj = N(strip_string_upper[:-1].rstrip())
9881  return number_obj, "X"
9882  else:
9883  return None
9884 
9885  def tostr(self):
9886  """
9887  :return: parsed representation of a Position Edit Descriptor
9888  :rtype: str
9889  :raises InternalError: if the length of the internal items \
9890  list is not 2.
9891  :raises InternalError: if the second entry of the internal \
9892  items list has no content.
9893 
9894  """
9895  if not len(self.items) == 2:
9896  raise InternalError(
9897  "Class Position_Edit_Desc method tostr() has '{0}' items, "
9898  "but expecting 2.".format(len(self.items))
9899  )
9900  if not self.items[1]:
9901  raise InternalError(
9902  "items[1] in Class Position_Edit_Desc method tostr() is "
9903  "empty or None"
9904  )
9905  if self.items[0]:
9906  return "{0}{1}".format(self.items[0], self.items[1])
9907  # This output is only required for the "x-format" extension.
9908  return "{0}".format(self.items[1])
9909 
9910 
9911 class N(Base): # R1014
9912  """
9913  ::
9914  <n> = <int-literal-constant> == <digit-string>
9915 
9916  C1010, C1011: <n> is positive and without kind parameter.
9917  """
9918 
9919  subclass_names = ["Digit_String"]
9920 
9921 
9922 class Sign_Edit_Desc(STRINGBase): # R1015
9923  """
9924  <sign-edit-desc> = SS
9925  | SP
9926  | S
9927  """
9928 
9929  subclass_names = []
9930 
9931  @staticmethod
9932  def match(string):
9933  return STRINGBase.match(["SS", "SP", "S"], string)
9934 
9935 
9936 class Blank_Interp_Edit_Desc(STRINGBase): # R1016
9937  """
9938  <blank-interp-edit-desc> = BN
9939  | BZ
9940  """
9941 
9942  subclass_names = []
9943 
9944  @staticmethod
9945  def match(string):
9946  return STRINGBase.match(["BN", "BZ"], string)
9947 
9948 
9949 class Round_Edit_Desc(STRINGBase): # R1017
9950  """
9951  <round-edit-desc> = RU
9952  | RD
9953  | RZ
9954  | RN
9955  | RC
9956  | RP
9957 
9958  """
9959 
9960  subclass_names = []
9961 
9962  @staticmethod
9963  def match(string):
9964  return STRINGBase.match(["RU", "RD", "RZ", "RN", "RC", "RP"], string)
9965 
9966 
9967 class Decimal_Edit_Desc(STRINGBase): # R1018
9968  """
9969  <decimal-edit-desc> = DC
9970  | DP
9971  """
9972 
9973  subclass_names = []
9974 
9975  @staticmethod
9976  def match(string):
9977  return STRINGBase.match(["DC", "DP"], string)
9978 
9979 
9980 class Char_String_Edit_Desc(Base): # R1019
9981  """
9982  <char-string-edit-desc> = <char-literal-constant>
9983  """
9984 
9985  subclass_names = ["Char_Literal_Constant"]
9986 
9987 
9988 #
9989 # SECTION 11
9990 #
9991 
9992 
9993 class Main_Program(BlockBase): # R1101 [C1101, C1102, C1103]
9994  """Fortran 2003 rule R1101
9995 
9996  This class does not cater for the case where there is no
9997  program-stmt. The separate Main_Program0() class matches this
9998  situation. See Class Program() method match() for how this is
9999  implemented.
10000 
10001  main-program is program-stmt
10002  [ specification-part ]
10003  [ execution-part ]
10004  [ internal-subprogram-part ]
10005  end-program-stmt
10006 
10007  C1101 In a main-program, the execution-part shall not contain a
10008  RETURN statement or an ENTRY statement. This is currently not
10009  checked, see issue #140.
10010 
10011  C1102 The program-name may be included in the end-program-stmt
10012  only if the optional program-stmt is used and, if included, shall
10013  be identical to the program-name specified in the program-stmt.
10014 
10015  C1103 An automatic object shall not appear in the
10016  specification-part (R204) of a main program. This is currently not
10017  checked, see issue #140.
10018 
10019  """
10020 
10021  subclass_names = []
10022  use_names = [
10023  "Program_Stmt",
10024  "Specification_Part",
10025  "Execution_Part",
10026  "Internal_Subprogram_Part",
10027  "End_Program_Stmt",
10028  ]
10029 
10030  @staticmethod
10031  def match(reader):
10032  """Implements the matching of a main program which has a Program
10033  statement. See class Main_Program0 for matching without a
10034  Program Statement. Matching uses `BlockBase` as it conforms to
10035  the start/end with optional content pattern. `match_names` is
10036  set to `True` so that different names e.g. `program x` and
10037  `end program y` will not match.
10038 
10039  :param reader: the Fortran reader containing the line(s) of \
10040  code that we are trying to match
10041  :type reader: :py:class:`fparser.common.readfortran.FortranReaderBase`
10042 
10043  :returns: `None` if there is not match or, if there is a match, \
10044  a `tuple` containing a single `list`, with minimum \
10045  size 2 and maximum size 5, which contains instances \
10046  of the classes that have matched. The first entry in \
10047  the list will be a `Program_Stmt` and the last entry \
10048  in the list will be an `End_Program_Stmt`. In-between \
10049  these two instances will be an optional \
10050  `Specification_Part` followed by an optional \
10051  `Execution_Part` followed by an optional \
10052  `Internal_Subprogram_Part`.
10053  :rtype: `NoneType` or \
10054  ([:py:class:`fparser.two.Fortran2003.Program_Stmt`, \
10055  optional \
10056  :py:class:`fparser.two.Fortran2003.Specification_Part`, \
10057  optional \
10058  :py:class:`fparser.two.Fortran2003.Execution_Part`, \
10059  optional \
10060  :py:class:`fparser.two.Fortran2003.Internal_Subprogram_Part`, \
10061  :py:class:`fparser.two.Fortran2003.End_Program_Stmt`])
10062 
10063  """
10064  return BlockBase.match(
10065  Program_Stmt,
10066  [Specification_Part, Execution_Part, Internal_Subprogram_Part],
10067  End_Program_Stmt,
10068  reader,
10069  match_names=True,
10070  strict_order=True,
10071  )
10072 
10073 
10074 class Main_Program0(BlockBase):
10075  """
10076  Rule 1101 specifies that the opening 'program-stmt' is optional. This
10077  class handles the special case when it is not supplied and thus
10078  matches on:
10079 
10080  <main-program> =
10081  [ <specification-part> ]
10082  [ <execution-part> ]
10083  [ <internal-subprogram-part> ]
10084  <end-program-stmt>
10085 
10086  C1102 The program-name may be included in the end-program-stmt
10087  only if the optional program-stmt is used and, if included, shall
10088  be identical to the program-name specified in the
10089  program-stmt.
10090 
10091  In this class an end program name is not allowed due to C1102.
10092 
10093  """
10094 
10095  subclass_names = []
10096  use_names = [
10097  "Program_Stmt",
10098  "Specification_Part",
10099  "Execution_Part",
10100  "Internal_Subprogram_Part",
10101  "End_Program_Stmt",
10102  ]
10103 
10104  @staticmethod
10105  def match(reader):
10106  """
10107  Attempts to match the content in the reader with a program that is
10108  missing the optional opening program-stmt (R1101). If the match
10109  is successful, a symbol table named "fparser2:main_program" is
10110  also created.
10111 
10112  :param reader: Content to check for match
10113  :type reader: str or instance of :py:class:`FortranReaderBase`
10114 
10115  :return: 2-tuple of (list of matched classes, None) or None \
10116  if no match is found.
10117  :rtype: (list of matched classes, None) or NoneType
10118 
10119  """
10120  # For this special case we have to supply a name for the top-level
10121  # symbol table. We include a ':' so that it is not a valid Fortran
10122  # name and therefore cannot clash with any routine names.
10123  table_name = "fparser2:main_program"
10124  SYMBOL_TABLES.enter_scope(table_name)
10125 
10126  result = BlockBase.match(
10127  None,
10128  [Specification_Part, Execution_Part, Internal_Subprogram_Part],
10129  End_Program_Stmt,
10130  reader,
10131  )
10132 
10133  SYMBOL_TABLES.exit_scope()
10134  if not result:
10135  # The match failed so remove the associated symbol table
10136  SYMBOL_TABLES.remove(table_name)
10137 
10138  return result
10139 
10140 
10141 class Program_Stmt(StmtBase, WORDClsBase): # R1102
10142  """
10143  Fortran 2003 rule R1102
10144  program-stmt is PROGRAM program-name
10145 
10146  """
10147 
10148  subclass_names = []
10149  use_names = ["Program_Name"]
10150 
10151  @staticmethod
10152  def match(string):
10153  """Implements the matching for a Program Statement. Makes use of
10154  `WORDClsBase`, as the required match is a string followed by a
10155  class. The class is made compulsory for the match as the
10156  PROGRAM keyword is not valid without a program name.
10157 
10158  :param str string: Fortran code to check for a match
10159  :returns: `None` if there is no match or, if there is a match, \
10160  a tuple of size 2 with the first entry being the \
10161  string 'PROGRAM' and the second entry being a `Name` \
10162  class containing the name of the program.
10163  :rtype: `NoneType` or ( `str`, \
10164  :py:class:`fparser.two.Fortran2003.Name` )
10165 
10166  """
10167  return WORDClsBase.match("PROGRAM", Program_Name, string, require_cls=True)
10168 
10169  def get_name(self):
10170  """Provides the program name as an instance of the `Name` class.
10171 
10172  :returns: the program name as a :py:class:`Name` class
10173  :rtype: :py:class:`Name`
10174 
10175  """
10176  return self.items[1]
10177 
10178  def get_start_name(self):
10179  """Provides the program name as a string. This is used for matching
10180  with the equivalent `end program` name if there is one.
10181 
10182  :returns: the program name as a string
10183  :rtype: str
10184 
10185  """
10186  return self.get_name().string
10187 
10188 
10189 class End_Program_Stmt(EndStmtBase): # R1103
10190  """
10191  <end-program-stmt> = END [ PROGRAM [ <program-name> ] ]
10192  """
10193 
10194  subclass_names = []
10195  use_names = ["Program_Name"]
10196 
10197  @staticmethod
10198  def match(string):
10199  return EndStmtBase.match("PROGRAM", Program_Name, string)
10200 
10201 
10202 class Module(BlockBase): # R1104
10203  """
10204  <module> = <module-stmt>
10205  [ <specification-part> ]
10206  [ <module-subprogram-part> ]
10207  <end-module-stmt>
10208  """
10209 
10210  subclass_names = []
10211  use_names = [
10212  "Module_Stmt",
10213  "Specification_Part",
10214  "Module_Subprogram_Part",
10215  "End_Module_Stmt",
10216  ]
10217 
10218  @staticmethod
10219  def match(reader):
10220  return BlockBase.match(
10221  Module_Stmt,
10222  [Specification_Part, Module_Subprogram_Part],
10223  End_Module_Stmt,
10224  reader,
10225  )
10226 
10227 
10228 class Module_Stmt(StmtBase, WORDClsBase): # R1105
10229  """
10230  <module-stmt> = MODULE <module-name>
10231  """
10232 
10233  subclass_names = []
10234  use_names = ["Module_Name"]
10235 
10236  @staticmethod
10237  def match(string):
10238  return WORDClsBase.match("MODULE", Module_Name, string, require_cls=True)
10239 
10240  def get_name(self):
10241  return self.items[1]
10242 
10243 
10244 class End_Module_Stmt(EndStmtBase): # R1106
10245  """
10246  <end-module-stmt> = END [ MODULE [ <module-name> ] ]
10247  """
10248 
10249  subclass_names = []
10250  use_names = ["Module_Name"]
10251 
10252  @staticmethod
10253  def match(string):
10254  return EndStmtBase.match("MODULE", Module_Name, string)
10255 
10256 
10257 class Module_Subprogram_Part(BlockBase): # R1107
10258  """
10259  <module-subprogram-part> = <contains-stmt>
10260  <module-subprogram>
10261  [ <module-subprogram> ]...
10262  """
10263 
10264  subclass_names = []
10265  use_names = ["Contains_Stmt", "Module_Subprogram"]
10266 
10267  @staticmethod
10268  def match(reader):
10269  return BlockBase.match(Contains_Stmt, [Module_Subprogram], None, reader)
10270 
10271 
10272 class Module_Subprogram(Base): # R1108
10273  """
10274  <module-subprogram> = <function-subprogram>
10275  | <subroutine-subprogram>
10276  """
10277 
10278  subclass_names = ["Function_Subprogram", "Subroutine_Subprogram"]
10279 
10280 
10281 class Use_Stmt(StmtBase): # pylint: disable=invalid-name
10282  """
10283  Fortran 2003 rule R1109
10284 
10285  use-stmt is USE [ [ , module-nature ] :: ] module-name [ , rename-list ]
10286  or USE [ [ , module-nature ] :: ] module-name ,
10287  ONLY : [ only-list ]
10288 
10289  """
10290 
10291  subclass_names = []
10292  use_names = ["Module_Nature", "Module_Name", "Rename_List", "Only_List"]
10293 
10294  @staticmethod
10295  def match(string):
10296  """
10297  Wrapper for the match method that captures any successfully-matched
10298  use statements in the symbol table associated with the current scope
10299  (if there is one).
10300 
10301  :param str string: Fortran code to check for a match.
10302 
10303  :return: 5-tuple containing strings and instances of the classes
10304  describing a module (optional module nature, optional
10305  double colon delimiter, mandatory module name, optional
10306  "ONLY" specification and optional "Rename" or "Only" list)
10307  or None if the match fails.
10308  :rtype: 5-tuple of objects (module name and 4 optional) or NoneType
10309 
10310  :raises InternalError: if an Only_List is found to contain anything \
10311  other than Name or Rename objects.
10312 
10313  """
10314  result = Use_Stmt._match(string)
10315  if result:
10316  table = SYMBOL_TABLES.current_scope
10317  if table:
10318  only_list = None
10319  rename_list = None
10320  if "only" in result[3].lower():
10321  only_list = []
10322  if isinstance(result[4], Only_List):
10323  # An Only_List can contain either Name or Rename entries.
10324  for child in result[4].children:
10325  if isinstance(child, Name):
10326  only_list.append((child.string, None))
10327  elif isinstance(child, Rename):
10328  only_list.append(
10329  (child.children[1].string, child.children[2].string)
10330  )
10331  else:
10332  raise InternalError(
10333  f"An Only_List can contain only Name or Rename "
10334  f"entries but found '{type(child).__name__}' when matching '{string}'"
10335  )
10336  elif isinstance(result[4], Rename_List):
10337  renames = walk(result[4], Rename)
10338  # Tuples of <local-name>, <use-name>
10339  rename_list = [
10340  (rename.children[1].string, rename.children[2].string)
10341  for rename in renames
10342  ]
10343 
10344  table.add_use_symbols(str(result[2]), only_list, rename_list)
10345 
10346  return result
10347 
10348  @staticmethod
10349  def _match(string):
10350  """
10351  :param str string: Fortran code to check for a match.
10352 
10353  :return: 5-tuple containing strings and instances of the classes
10354  describing a module (optional module nature, optional
10355  double colon delimiter, mandatory module name, optional
10356  "ONLY" specification and optional "Rename" or "Only" list).
10357  :rtype: 5-tuple of objects (module name and 4 optional)
10358 
10359  """
10360  line = string.strip()
10361  # Incorrect 'USE' statement or line too short
10362  if line[:3].upper() != "USE":
10363  return
10364  line = line[3:]
10365  # Empty string after 'USE'
10366  if not line:
10367  return
10368  # No separation between 'USE' statement and its specifiers
10369  if line[0].isalnum():
10370  return
10371  line = line.lstrip()
10372  i = line.find("::")
10373  nature = None
10374  dcolon = None
10375  if i != -1:
10376  # The nature of the module ("intrinsic" or
10377  # "non-intrinsic") is specified
10378  dcolon = "::"
10379  if line.startswith(","):
10380  line_nat = line[1:i].strip()
10381  # Missing Module_Nature between ',' and '::'
10382  if not line_nat:
10383  return
10384  nature = Module_Nature(line_nat)
10385  line = line[i + 2 :].lstrip()
10386  # No Module_Name after 'USE, Module_Nature ::'
10387  if not line:
10388  return
10389  else:
10390  # Check for missing '::' after Module_Nature
10391  items = re.findall(r"[\w']+", line)
10392  for item in items:
10393  try:
10394  nature = Module_Nature(item)
10395  except NoMatchError:
10396  pass
10397  # Missing '::' after Module_Nature
10398  if nature is not None:
10399  return
10400 
10401  position = line.find(",")
10402  if position == -1:
10403  return nature, dcolon, Module_Name(line), "", None
10404  name = line[:position].rstrip()
10405  # Missing Module_Name before Only_List
10406  if not name:
10407  return
10408  name = Module_Name(name)
10409  line = line[position + 1 :].lstrip()
10410  # Missing 'ONLY' specification after 'USE Module_Name,'
10411  if not line:
10412  return
10413  if line[:4].upper() == "ONLY":
10414  line = line[4:].lstrip()
10415  if not line:
10416  # Expected ':' but there is nothing after the 'ONLY'
10417  # specification
10418  return
10419  if line[0] != ":":
10420  # Expected ':' but there is a different character
10421  # after the 'ONLY' specification
10422  return
10423  line = line[1:].lstrip()
10424  if not line:
10425  # Missing Only_List after 'USE Module_Name, ONLY:'
10426  return nature, dcolon, name, ", ONLY:", None
10427  return nature, dcolon, name, ", ONLY:", Only_List(line)
10428  return nature, dcolon, name, ",", Rename_List(line)
10429 
10430  def tostr(self):
10431  """
10432  :return: parsed representation of "USE" statement
10433  :rtype: string
10434  :raises InternalError: if items array is not the expected size
10435  :raises InternalError: if items array[2] is not a string or is an \
10436  empty string
10437  :raises InternalError: if items array[3] is 'None' as it should be \
10438  a string
10439  """
10440  if len(self.items) != 5:
10441  raise InternalError(
10442  "Use_Stmt.tostr(). 'Items' should be of size 5 but found "
10443  "'{0}'.".format(len(self.items))
10444  )
10445  if not self.items[2]:
10446  raise InternalError(
10447  "Use_Stmt.tostr(). 'Items' entry 2 should "
10448  "be a module name but it is empty"
10449  )
10450  if self.items[3] is None:
10451  raise InternalError(
10452  "Use_Stmt.tostr(). 'Items' entry 3 should "
10453  "be a string but found 'None'"
10454  )
10455  usestmt = "USE"
10456  # Add optional Module_Nature ("INTRINSIC" or "NON_INTRINSIC")
10457  # followed by a double colon to "USE" statement
10458  if self.items[0] and self.items[1]:
10459  usestmt += ", {0} {1}".format(self.items[0], self.items[1])
10460  # Add optional double colon after "USE" statement without
10461  # Module_Nature (valid Fortran)
10462  elif not self.items[0] and self.items[1]:
10463  usestmt += " {0}".format(self.items[1])
10464  # Add Module_Name and optional "ONLY" specifier if present
10465  usestmt += " {0}{1}".format(self.items[2], self.items[3])
10466  # Add optional Only_List or Rename_List if present
10467  if self.items[4] is not None:
10468  usestmt += " {0}".format(self.items[4])
10469  return usestmt
10470 
10471 
10472 class Module_Nature(STRINGBase): # pylint: disable=invalid-name
10473  """
10474  R1110
10475 
10476  <module-nature> = INTRINSIC
10477  | NON_INTRINSIC
10478  """
10479 
10480  subclass_names = []
10481 
10482  @staticmethod
10483  def match(string):
10484  """
10485  :param str string: Fortran code to check for a match
10486  :return: keyword describing module nature ("INTRINSIC" or
10487  "NON_INTRINSIC") or nothing if no match is found
10488  :rtype: string
10489  """
10490  return STRINGBase.match(["INTRINSIC", "NON_INTRINSIC"], string)
10491 
10492 
10493 class Rename(Base): # R1111
10494  """
10495  <rename> = <local-name> => <use-name>
10496  | OPERATOR(<local-defined-operator>) =>
10497  OPERATOR(<use-defined-operator>)
10498  """
10499 
10500  subclass_names = []
10501  use_names = [
10502  "Local_Name",
10503  "Use_Name",
10504  "Local_Defined_Operator",
10505  "Use_Defined_Operator",
10506  ]
10507 
10508  @staticmethod
10509  def match(string):
10510  s = string.split("=>", 1)
10511  if len(s) != 2:
10512  return
10513  lhs, rhs = s[0].rstrip(), s[1].lstrip()
10514  if not lhs or not rhs:
10515  return
10516  if lhs[:8].upper() == "OPERATOR" and rhs[:8].upper() == "OPERATOR":
10517  tmp = lhs[8:].lstrip()
10518  r = rhs[8:].lstrip()
10519  if tmp and r and tmp[0] + tmp[-1] == "()":
10520  if r[0] + r[-1] != "()":
10521  return
10522  tmp = tmp[1:-1].strip()
10523  r = r[1:-1].strip()
10524  if not tmp or not r:
10525  return
10526  return "OPERATOR", Local_Defined_Operator(tmp), Use_Defined_Operator(r)
10527  return None, Local_Name(lhs), Use_Name(rhs)
10528 
10529  def tostr(self):
10530  if not self.items[0]:
10531  return "%s => %s" % self.items[1:]
10532  return "%s(%s) => %s(%s)" % (
10533  self.items[0],
10534  self.items[1],
10535  self.items[0],
10536  self.items[2],
10537  )
10538 
10539 
10540 class Only(Base): # R1112
10541  """
10542  <only> = <generic-spec>
10543  | <only-use-name>
10544  | <rename>
10545  """
10546 
10547  subclass_names = ["Generic_Spec", "Only_Use_Name", "Rename"]
10548 
10549 
10550 class Only_Use_Name(Base): # R1113
10551  """
10552  <only-use-name> = <name>
10553  """
10554 
10555  subclass_names = ["Name"]
10556 
10557 
10558 class Local_Defined_Operator(Base): # R1114
10559  """
10560  <local-defined-operator> = <defined-unary-op>
10561  | <defined-binary-op>
10562  """
10563 
10564  subclass_names = ["Defined_Unary_Op", "Defined_Binary_Op"]
10565 
10566 
10567 class Use_Defined_Operator(Base): # R1115
10568  """
10569  <use-defined-operator> = <defined-unary-op>
10570  | <defined-binary-op>
10571  """
10572 
10573  subclass_names = ["Defined_Unary_Op", "Defined_Binary_Op"]
10574 
10575 
10576 class Block_Data(BlockBase): # R1116
10577  """
10578  ::
10579  <block-data> = <block-data-stmt>
10580  [ <specification-part> ]
10581  <end-block-data-stmt>
10582  """
10583 
10584  subclass_names = []
10585  use_names = ["Block_Data_Stmt", "Specification_Part", "End_Block_Data_Stmt"]
10586 
10587  @staticmethod
10588  def match(reader):
10589  return BlockBase.match(
10590  Block_Data_Stmt, [Specification_Part], End_Block_Data_Stmt, reader
10591  )
10592 
10593 
10594 class Block_Data_Stmt(StmtBase): # R1117
10595  """
10596  ::
10597  <block-data-stmt> = BLOCK DATA [ <block-data-name> ]
10598  """
10599 
10600  subclass_names = []
10601  use_names = ["Block_Data_Name"]
10602 
10603  @staticmethod
10604  def match(string):
10605  if string[:5].upper() != "BLOCK":
10606  return
10607  line = string[5:].lstrip()
10608  if line[:4].upper() != "DATA":
10609  return
10610  line = line[4:].lstrip()
10611  if not line:
10612  return (None,)
10613  return (Block_Data_Name(line),)
10614 
10615  def tostr(self):
10616  if self.items[0] is None:
10617  return "BLOCK DATA"
10618  return "BLOCK DATA %s" % self.items
10619 
10620  def get_name(self):
10621  return self.items[0]
10622 
10623 
10624 class End_Block_Data_Stmt(EndStmtBase): # R1118
10625  """
10626  ::
10627  <end-block-data-stmt> = END [ BLOCK DATA [ <block-data-name> ] ]
10628  """
10629 
10630  subclass_names = []
10631  use_names = ["Block_Data_Name"]
10632 
10633  @staticmethod
10634  def match(string):
10635  return EndStmtBase.match("BLOCK DATA", Block_Data_Name, string)
10636 
10637 
10638 #
10639 # SECTION 12
10640 #
10641 
10642 
10643 class Interface_Block(BlockBase): # R1201
10644  """
10645  ::
10646  <interface-block> = <interface-stmt>
10647  [ <interface-specification> ]...
10648  <end-interface-stmt>
10649  """
10650 
10651  subclass_names = []
10652  use_names = ["Interface_Stmt", "Interface_Specification", "End_Interface_Stmt"]
10653 
10654  @staticmethod
10655  def match(reader):
10656  return BlockBase.match(
10657  Interface_Stmt, [Interface_Specification], End_Interface_Stmt, reader
10658  )
10659 
10660 
10661 class Interface_Specification(Base): # R1202
10662  """
10663  <interface-specification> = <interface-body>
10664  | <procedure-stmt>
10665  """
10666 
10667  subclass_names = ["Interface_Body", "Procedure_Stmt"]
10668 
10669 
10670 class Interface_Stmt(StmtBase): # R1203
10671  """
10672  ::
10673  <interface-stmt> = INTERFACE [ <generic-spec> ]
10674  | ABSTRACT INTERFACE
10675 
10676  Attributes
10677  ----------
10678  items : ({Generic_Spec, 'ABSTRACT'},)
10679  """
10680 
10681  subclass_names = []
10682  use_names = ["Generic_Spec"]
10683 
10684  @staticmethod
10685  def match(string):
10686  if string[:9].upper() == "INTERFACE":
10687  line = string[9:].strip()
10688  if not line:
10689  return (None,)
10690  return (Generic_Spec(line),)
10691  if string[:8].upper() == "ABSTRACT":
10692  line = string[8:].strip()
10693  if line.upper() == "INTERFACE":
10694  return ("ABSTRACT",)
10695 
10696  def tostr(self):
10697  if self.items[0] == "ABSTRACT":
10698  return "ABSTRACT INTERFACE"
10699  if self.items[0] is None:
10700  return "INTERFACE"
10701  return "INTERFACE %s" % (self.items[0])
10702 
10703 
10704 class End_Interface_Stmt(EndStmtBase): # R1204
10705  """
10706  ::
10707  <end-interface-stmt> = END INTERFACE [ <generic-spec> ]
10708 
10709  Attributes
10710  ----------
10711  items : (Generic_Spec, )
10712  """
10713 
10714  subclass_names = []
10715  use_names = ["Generic_Spec"]
10716 
10717  @staticmethod
10718  def match(string):
10719  return EndStmtBase.match(
10720  "INTERFACE", Generic_Spec, string, require_stmt_type=True
10721  )
10722 
10723 
10724 class Function_Body(BlockBase):
10725  """
10726  ::
10727  <function-body> = <function-stmt>
10728  [ <specification-part> ]
10729  <end-function-stmt>
10730  """
10731 
10732  subclass_names = []
10733  use_names = ["Function_Stmt", "Specification_Part", "End_Function_Stmt"]
10734 
10735  @staticmethod
10736  def match(reader):
10737  return BlockBase.match(
10738  Function_Stmt, [Specification_Part], End_Function_Stmt, reader
10739  )
10740 
10741 
10742 class Subroutine_Body(BlockBase):
10743  """
10744  ::
10745  <subroutine-body> = <subroutine-stmt>
10746  [ <specification-part> ]
10747  <end-subroutine-stmt>
10748  """
10749 
10750  subclass_names = []
10751  use_names = ["Subroutine_Stmt", "Specification_Part", "End_Subroutine_Stmt"]
10752 
10753  @staticmethod
10754  def match(reader):
10755  return BlockBase.match(
10756  Subroutine_Stmt, [Specification_Part], End_Subroutine_Stmt, reader
10757  )
10758 
10759 
10760 class Interface_Body(Base): # R1205
10761  """
10762  ::
10763  <interface-body> = <function-body> | <subroutine-body>
10764 
10765  See also
10766  --------
10767  Function_Body, Subroutine_Body
10768  """
10769 
10770  subclass_names = ["Function_Body", "Subroutine_Body"]
10771  use_names = []
10772 
10773 
10774 class Procedure_Stmt(StmtBase): # R1206
10775  """
10776  ::
10777  <procedure-stmt> = [ MODULE ] PROCEDURE <procedure-name-list>
10778 
10779  Attributes
10780  ----------
10781  items : (Procedure_Name_List, )
10782  """
10783 
10784  subclass_names = []
10785  use_names = ["Procedure_Name_List"]
10786 
10787  @staticmethod
10788  def match(string):
10789  if string[:6].upper() == "MODULE":
10790  line = string[6:].lstrip()
10791  else:
10792  line = string
10793  if line[:9].upper() != "PROCEDURE":
10794  return
10795  line = line[9:].lstrip()
10796  return (Procedure_Name_List(line),)
10797 
10798  def tostr(self):
10799  return "MODULE PROCEDURE %s" % (self.items[0])
10800 
10801 
10802 class Generic_Spec(Base): # R1207
10803  """
10804  ::
10805  <generic-spec> = <generic-name>
10806  | OPERATOR ( <defined-operator> )
10807  | ASSIGNMENT ( = )
10808  | <dtio-generic-spec>
10809  Attributes
10810  ----------
10811  items : ({'OPERATOR', 'ASSIGNMENT'}, {Defined_Operator, '='})
10812  """
10813 
10814  subclass_names = ["Generic_Name", "Dtio_Generic_Spec"]
10815  use_names = ["Defined_Operator"]
10816 
10817  @staticmethod
10818  def match(string):
10819  if string[:8].upper() == "OPERATOR":
10820  line = string[8:].lstrip()
10821  if not line or line[0] != "(" or line[-1] != ")":
10822  return
10823  return "OPERATOR", Defined_Operator(line[1:-1].strip())
10824  if string[:10].upper() == "ASSIGNMENT":
10825  line = string[10:].lstrip()
10826  if not line or line[0] != "(" or line[-1] != ")":
10827  return
10828  if line[1:-1].strip() == "=":
10829  return "ASSIGNMENT", "="
10830 
10831  def tostr(self):
10832  return "%s(%s)" % (self.items)
10833 
10834 
10835 class Dtio_Generic_Spec(Base): # R1208
10836  """
10837  ::
10838  <dtio-generic-spec> = READ ( FORMATTED )
10839  | READ ( UNFORMATTED )
10840  | WRITE ( FORMATTED )
10841  | WRITE ( UNFORMATTED )
10842  Attributes
10843  ----------
10844  items : (str, )
10845  """
10846 
10847  subclass_names = []
10848 
10849  @staticmethod
10850  def match(string):
10851  for rw in ["READ", "WRITE"]:
10852  if string[: len(rw)].upper() == rw:
10853  line = string[len(rw) :].lstrip()
10854  if not line:
10855  return
10856  if line[0] != "(" or line[-1] != ")":
10857  return
10858  line = line[1:-1].strip().upper()
10859  if line in ["FORMATTED", "UNFORMATTED"]:
10860  return ("%s(%s)" % (rw, line),)
10861 
10862  def tostr(self):
10863  return "%s" % (self.items[0])
10864 
10865 
10866 class Import_Stmt(StmtBase, WORDClsBase): # pylint: disable=invalid-name
10867  """
10868  Fortran 2003 rule R1209
10869  import-stmt is IMPORT [[ :: ] import-name-list ]
10870 
10871  C1210 (R1209) The IMPORT statement is allowed only in an
10872  interface-body. Note, this constraint is not currently enforced.
10873 
10874  C1211 (R1209) Each import-name shall be the name of an entity in
10875  the host scoping unit. This constraint is not currently enforced
10876  and can not be generally enforced as the name may come from a use
10877  statement without an only clause.
10878 
10879  """
10880 
10881  subclass_names = []
10882  use_names = ["Import_Name_List"]
10883  tostr = WORDClsBase.tostr_a
10884 
10885  @staticmethod
10886  def match(string):
10887  """
10888  Implements the matching for the import-stmt rule.
10889 
10890  Makes use of the WORDClsBase base class.
10891 
10892  :param str string: the string to match.
10893 
10894  :returns: None if there is no match, otherwise a tuple of size \
10895  2 containing the string `IMPORT` as the first entry and \
10896  an object of type `Import_Name_List` if names are \
10897  specified in the string or `None` if not.
10898 
10899  :rtype: None, or (str, \
10900  :py:class:`fparser.two.Fortran2003.Import_Name_List`) or \
10901  (str, None)
10902 
10903  """
10904  return WORDClsBase.match(
10905  "IMPORT", Import_Name_List, string, colons=True, require_cls=False
10906  )
10907 
10908 
10909 class External_Stmt(StmtBase, WORDClsBase): # R1210
10910  """
10911  <external-stmt> = EXTERNAL [ :: ] <external-name-list>
10912  """
10913 
10914  subclass_names = []
10915  use_names = ["External_Name_List"]
10916 
10917  @staticmethod
10918  def match(string):
10919  return WORDClsBase.match(
10920  "EXTERNAL", External_Name_List, string, colons=True, require_cls=True
10921  )
10922 
10923  tostr = WORDClsBase.tostr_a
10924 
10925 
10926 class Procedure_Declaration_Stmt(StmtBase): # R1211
10927  """
10928  ::
10929  <procedure-declaration-stmt> = PROCEDURE ( [ <proc-interface> ] )
10930  [ [ , <proc-attr-spec> ]... :: ] <proc-decl-list>
10931 
10932  Attributes
10933  ----------
10934  items : (Proc_Interface, Proc_Attr_Spec_List, Proc_Decl_List)
10935  """
10936 
10937  subclass_names = []
10938  use_names = ["Proc_Interface", "Proc_Attr_Spec_List", "Proc_Decl_List"]
10939 
10940  @staticmethod
10941  def match(string):
10942  if string[:9].upper() != "PROCEDURE":
10943  return
10944  line = string[9:].lstrip()
10945  if not line.startswith("("):
10946  return
10947  line, repmap = string_replace_map(line)
10948  i = line.find(")")
10949  if i == -1:
10950  return
10951  tmp = line[1:i].strip()
10952  proc_interface = Proc_Interface(repmap(tmp)) if tmp else None
10953  line = line[i + 1 :].lstrip()
10954  i = line.find("::")
10955  proc_attr_spec_list = None
10956  if i != -1:
10957  tmp = line[:i].rstrip()
10958  if tmp and tmp[0] == ",":
10959  proc_attr_spec_list = Proc_Attr_Spec_List(repmap(tmp[1:].lstrip()))
10960  line = line[i + 2 :].lstrip()
10961  return proc_interface, proc_attr_spec_list, Proc_Decl_List(repmap(line))
10962 
10963  def tostr(self):
10964  r = "PROCEDURE"
10965  if self.items[0] is not None:
10966  r += "(%s)" % (self.items[0])
10967  else:
10968  r += "()"
10969  if self.items[1] is not None:
10970  r += ", %s ::" % (self.items[1])
10971  return "%s %s" % (r, self.items[2])
10972 
10973 
10974 class Proc_Interface(Base): # R1212
10975  """
10976  <proc-interface> = <interface-name>
10977  | <declaration-type-spec>
10978  """
10979 
10980  subclass_names = ["Interface_Name", "Declaration_Type_Spec"]
10981 
10982 
10983 class Proc_Attr_Spec(Base): # R1213
10984  """
10985  <proc-attr-spec> = <access-spec>
10986  | <proc-language-binding-spec>
10987  | INTENT ( <intent-spec> )
10988  | OPTIONAL
10989  | POINTER
10990  | PROTECTED
10991  | SAVE
10992 
10993  Attributes
10994  ----------
10995  items : ({'INTENT', 'OPTIONAL', 'POINTER', 'PROTECTED', 'SAVE'}, Intent_Spec)
10996  """
10997 
10998  subclass_names = ["Access_Spec", "Proc_Language_Binding_Spec"]
10999  use_names = ["Intent_Spec"]
11000 
11001  @staticmethod
11002  def match(string):
11003  """
11004  Matches procedure arguments.
11005 
11006  :param str string: Candidate string.
11007  :return: Discovered arguments.
11008  :rtype: tuple, str or None
11009  """
11010  if string[:6].upper() == "INTENT":
11011  line = string[6:].lstrip()
11012  if not line:
11013  return
11014  if line[0] != "(" or line[-1] != ")":
11015  return
11016  return "INTENT", Intent_Spec(line[1:-1].strip())
11017  if len(string) == 8 and string.upper() == "OPTIONAL":
11018  return "OPTIONAL", None
11019  if len(string) == 7 and string.upper() == "POINTER":
11020  return "POINTER", None
11021  if len(string) == 9 and string.upper() == "PROTECTED":
11022  return "PROTECTED", None
11023  if len(string) == 4 and string.upper() == "SAVE":
11024  return "SAVE", None
11025 
11026  def tostr(self):
11027  if self.items[1] is None:
11028  return "%s" % (self.items[0])
11029  return "%s(%s)" % (self.items)
11030 
11031 
11032 class Proc_Decl(BinaryOpBase): # R1214
11033  """
11034  ::
11035  <proc-decl> = <procedure-entity-name> [ => <null-init> ]
11036 
11037  Attributes
11038  ----------
11039  items : (Procedure_Entity_Name, Null_Init)
11040  """
11041 
11042  subclass_names = ["Procedure_Entity_Name"]
11043  use_names = ["Null_Init"]
11044 
11045  @staticmethod
11046  def match(string):
11047  return BinaryOpBase.match(Procedure_Entity_Name, "=>", Null_Init, string)
11048 
11049 
11050 class Interface_Name(Base): # R1215
11051  """
11052  <interface-name> = <name>
11053  """
11054 
11055  subclass_names = ["Name"]
11056 
11057 
11058 class Intrinsic_Stmt(StmtBase, WORDClsBase): # R1216
11059  """
11060  <intrinsic-stmt> = INTRINSIC [ :: ] <intrinsic-procedure-name-list>
11061  """
11062 
11063  subclass_names = []
11064  use_names = ["Intrinsic_Procedure_Name_List"]
11065 
11066  @staticmethod
11067  def match(string):
11068  return WORDClsBase.match(
11069  "INTRINSIC",
11070  Intrinsic_Procedure_Name_List,
11071  string,
11072  colons=True,
11073  require_cls=True,
11074  )
11075 
11076  tostr = WORDClsBase.tostr_a
11077 
11078 
11079 class Function_Reference(CallBase): # R1217
11080  """
11081  <function-reference> = <procedure-designator>
11082  ( [ <actual-arg-spec-list> ] )
11083  """
11084 
11085  subclass_names = []
11086  use_names = ["Procedure_Designator", "Actual_Arg_Spec_List"]
11087 
11088  @staticmethod
11089  def match(string):
11090  return CallBase.match(Procedure_Designator, Actual_Arg_Spec_List, string)
11091 
11092 
11093 class Intrinsic_Name(STRINGBase): # No explicit rule
11094  """Represents the name of a Fortran intrinsic function.
11095 
11096  All generic intrinsic names are specified as keys in the
11097  `generic_function_names` dictionary, with their values indicating
11098  the minimum and maximum number of arguments allowed for this
11099  intrinsic function. A `-1` indicates an unlimited number of
11100  arguments. The names are split into the categories specified in
11101  the Fortran2003 specification document.
11102 
11103  All specific intrinsic names (which have a different name to their
11104  generic counterpart) are specified as keys in the
11105  `specific_function_names` dictionary, with their values indicating
11106  which generic function they are associated with.
11107 
11108  """
11109 
11110  numeric_names = {
11111  "ABS": {"min": 1, "max": 1},
11112  "AIMAG": {"min": 1, "max": 1},
11113  "AINT": {"min": 1, "max": 2},
11114  "ANINT": {"min": 1, "max": 2},
11115  "CEILING": {"min": 1, "max": 2},
11116  "CMPLX": {"min": 1, "max": 3},
11117  "CONJG": {"min": 1, "max": 1},
11118  "DBLE": {"min": 1, "max": 1},
11119  "DIM": {"min": 2, "max": 2},
11120  "DPROD": {"min": 2, "max": 2},
11121  "FLOOR": {"min": 1, "max": 2},
11122  "INT": {"min": 1, "max": 2},
11123  "MAX": {"min": 2, "max": None},
11124  "MIN": {"min": 2, "max": None},
11125  "MOD": {"min": 2, "max": 2},
11126  "MODULO": {"min": 2, "max": 2},
11127  "NINT": {"min": 1, "max": 2},
11128  "REAL": {"min": 1, "max": 2},
11129  "SIGN": {"min": 2, "max": 2},
11130  }
11131 
11132  mathematical_names = {
11133  "ACOS": {"min": 1, "max": 1},
11134  "ASIN": {"min": 1, "max": 1},
11135  "ATAN": {"min": 1, "max": 1},
11136  "ATAN2": {"min": 2, "max": 2},
11137  "COS": {"min": 1, "max": 1},
11138  "COSH": {"min": 1, "max": 1},
11139  "EXP": {"min": 1, "max": 1},
11140  "LOG": {"min": 1, "max": 1},
11141  "LOG10": {"min": 1, "max": 1},
11142  "SIN": {"min": 1, "max": 1},
11143  "SINH": {"min": 1, "max": 1},
11144  "SQRT": {"min": 1, "max": 1},
11145  "TAN": {"min": 1, "max": 1},
11146  "TANH": {"min": 1, "max": 1},
11147  }
11148 
11149  # Removed max and min from this dictionary as they already appear
11150  # in numeric_function_names.
11151  character_names = {
11152  "ACHAR": {"min": 1, "max": 2},
11153  "ADJUSTL": {"min": 1, "max": 1},
11154  "ADJUSTR": {"min": 1, "max": 1},
11155  "CHAR": {"min": 1, "max": 2},
11156  "IACHAR": {"min": 1, "max": 2},
11157  "ICHAR": {"min": 1, "max": 2},
11158  "INDEX": {"min": 2, "max": 4},
11159  "LEN_TRIM": {"min": 1, "max": 2},
11160  "LGE": {"min": 2, "max": 2},
11161  "LGT": {"min": 2, "max": 2},
11162  "LLE": {"min": 2, "max": 2},
11163  "LLT": {"min": 2, "max": 2},
11164  "REPEAT": {"min": 2, "max": 2},
11165  "SCAN": {"min": 2, "max": 4},
11166  "TRIM": {"min": 1, "max": 1},
11167  "VERIFY": {"min": 2, "max": 4},
11168  }
11169 
11170  kind_names = {
11171  "KIND": {"min": 1, "max": 1},
11172  "SELECTED_CHAR_KIND": {"min": 1, "max": 1},
11173  "SELECTED_INT_KIND": {"min": 1, "max": 1},
11174  "SELECTED_REAL_KIND": {"min": 1, "max": 2},
11175  }
11176 
11177  miscellaneous_type_conversion_names = {
11178  "LOGICAL": {"min": 1, "max": 2},
11179  "TRANSFER": {"min": 2, "max": 3},
11180  }
11181 
11182  numeric_inquiry_names = {
11183  "DIGITS": {"min": 1, "max": 1},
11184  "EPSILON": {"min": 1, "max": 1},
11185  "HUGE": {"min": 1, "max": 1},
11186  "MAXEXPONENT": {"min": 1, "max": 1},
11187  "MINEXPONENT": {"min": 1, "max": 1},
11188  "PRECISION": {"min": 1, "max": 1},
11189  "RADIX": {"min": 1, "max": 1},
11190  "RANGE": {"min": 1, "max": 1},
11191  "TINY": {"min": 1, "max": 1},
11192  }
11193 
11194  array_inquiry_names = {
11195  "LBOUND": {"min": 1, "max": 3},
11196  "SHAPE": {"min": 1, "max": 2},
11197  "SIZE": {"min": 1, "max": 3},
11198  "UBOUND": {"min": 1, "max": 3},
11199  }
11200 
11201  other_inquiry_names = {
11202  "ALLOCATED": {"min": 1, "max": 1},
11203  "ASSOCIATED": {"min": 1, "max": 2},
11204  "BIT_SIZE": {"min": 1, "max": 1},
11205  "EXTENDS_TYPE_OF": {"min": 2, "max": 2},
11206  "LEN": {"min": 1, "max": 2},
11207  "NEW_LINE": {"min": 1, "max": 1},
11208  "PRESENT": {"min": 1, "max": 1},
11209  "SAME_TYPE_AS": {"min": 2, "max": 2},
11210  }
11211 
11212  bit_manipulation_names = {
11213  "BTEST": {"min": 2, "max": 2},
11214  "IAND": {"min": 2, "max": 2},
11215  "IBCLR": {"min": 2, "max": 2},
11216  "IBITS": {"min": 3, "max": 3},
11217  "IBSET": {"min": 2, "max": 2},
11218  "IEOR": {"min": 2, "max": 2},
11219  "IOR": {"min": 2, "max": 2},
11220  "ISHFT": {"min": 2, "max": 2},
11221  "ISHFTC": {"min": 2, "max": 3},
11222  "MVBITS": {"min": 5, "max": 5},
11223  "NOT": {"min": 1, "max": 1},
11224  }
11225 
11226  floating_point_manipulation_names = {
11227  "EXPONENT": {"min": 1, "max": 1},
11228  "FRACTION": {"min": 1, "max": 1},
11229  "NEAREST": {"min": 2, "max": 2},
11230  "RRSPACING": {"min": 1, "max": 1},
11231  "SCALE": {"min": 2, "max": 2},
11232  "SET_EXPONENT": {"min": 2, "max": 2},
11233  "SPACING": {"min": 1, "max": 1},
11234  }
11235 
11236  vector_and_matrix_multiply_names = {
11237  "DOT_PRODUCT": {"min": 2, "max": 2},
11238  "MATMUL": {"min": 2, "max": 2},
11239  }
11240 
11241  array_reduction_names = {
11242  "ALL": {"min": 1, "max": 2},
11243  "ANY": {"min": 1, "max": 2},
11244  "COUNT": {"min": 1, "max": 3},
11245  "MAXVAL": {"min": 1, "max": 3},
11246  "MINVAL": {"min": 1, "max": 3},
11247  "PRODUCT": {"min": 1, "max": 3},
11248  "SUM": {"min": 1, "max": 3},
11249  }
11250 
11251  array_construction_names = {
11252  "CSHIFT": {"min": 2, "max": 3},
11253  "EOSHIFT": {"min": 2, "max": 4},
11254  "MERGE": {"min": 3, "max": 3},
11255  "PACK": {"min": 2, "max": 3},
11256  "RESHAPE": {"min": 2, "max": 4},
11257  "SPREAD": {"min": 3, "max": 3},
11258  "TRANSPOSE": {"min": 1, "max": 1},
11259  "UNPACK": {"min": 3, "max": 3},
11260  }
11261 
11262  array_location_names = {
11263  "MAXLOC": {"min": 1, "max": 4},
11264  "MINLOC": {"min": 1, "max": 4},
11265  }
11266 
11267  null_names = {"NULL": {"min": 0, "max": 1}}
11268 
11269  allocation_transfer_names = {"MOVE_ALLOC": {"min": 2, "max": 2}}
11270 
11271  random_number_names = {
11272  "RANDOM_NUMBER": {"min": 1, "max": 1},
11273  "RANDOM_SEED": {"min": 0, "max": 3},
11274  }
11275 
11276  system_environment_names = {
11277  "COMMAND_ARGUMENT_COUNT": {"min": 0, "max": 0},
11278  "CPU_TIME": {"min": 1, "max": 1},
11279  "DATE_AND_TIME": {"min": 0, "max": 4},
11280  "GET_COMMAND": {"min": 0, "max": 3},
11281  "GET_COMMAND_ARGUMENT": {"min": 1, "max": 4},
11282  "GET_ENVIRONMENT_VARIABLE": {"min": 1, "max": 5},
11283  "IS_IOSTAT_END": {"min": 1, "max": 1},
11284  "IS_IOSTAT_EOR": {"min": 1, "max": 1},
11285  "SYSTEM_CLOCK": {"min": 0, "max": 3},
11286  }
11287 
11288  # A map from specific function names to their generic equivalent.
11289  specific_function_names = {
11290  "ALOG": "LOG",
11291  "ALOG10": "LOG10",
11292  "AMAX0": "MAX",
11293  "AMAX1": "MAX",
11294  "AMIN0": "MIN",
11295  "AMIN1": "MIN",
11296  "AMOD": "MOD",
11297  "CABS": "ABS",
11298  "CCOS": "COS",
11299  "CEXP": "EXP",
11300  "CLOG": "LOG",
11301  "CSIN": "SIN",
11302  "CSQRT": "SQRT",
11303  "DABS": "ABS",
11304  "DACOS": "ACOS",
11305  "DASIN": "ASIN",
11306  "DATAN": "ATAN",
11307  "DATAN2": "ATAN2",
11308  "DCOS": "COS",
11309  "DCOSH": "COSH",
11310  "DDIM": "DIM",
11311  "DEXP": "EXP",
11312  "DINT": "AINT",
11313  "DLOG": "LOG",
11314  "DLOG10": "LOG10",
11315  "DMAX1": "MAX",
11316  "DMIN1": "MIN",
11317  "DMOD": "MOD",
11318  "DNINT": "ANINT",
11319  "DSIGN": "SIGN",
11320  "DSIN": "SIN",
11321  "DSINH": "SINH",
11322  "DSQRT": "SQRT",
11323  "DTAN": "TAN",
11324  "DTANH": "TANH",
11325  "FLOAT": "REAL",
11326  "IABS": "ABS",
11327  "IDIM": "DIM",
11328  "IDINT": "INT",
11329  "IDNINT": "NINT",
11330  "IFIX": "INT",
11331  "ISIGN": "SIGN",
11332  "MAX0": "MAX",
11333  "MAX1": "MAX",
11334  "MIN0": "MIN",
11335  "MIN1": "MIN",
11336  "SNGL": "REAL",
11337  }
11338 
11339  generic_function_names = {}
11340  generic_function_names.update(numeric_names)
11341  generic_function_names.update(mathematical_names)
11342  generic_function_names.update(character_names)
11343  generic_function_names.update(kind_names)
11344  generic_function_names.update(miscellaneous_type_conversion_names)
11345  generic_function_names.update(numeric_inquiry_names)
11346  generic_function_names.update(array_inquiry_names)
11347  generic_function_names.update(other_inquiry_names)
11348  generic_function_names.update(bit_manipulation_names)
11349  generic_function_names.update(floating_point_manipulation_names)
11350  generic_function_names.update(vector_and_matrix_multiply_names)
11351  generic_function_names.update(array_reduction_names)
11352  generic_function_names.update(array_construction_names)
11353  generic_function_names.update(array_location_names)
11354  generic_function_names.update(null_names)
11355  generic_function_names.update(allocation_transfer_names)
11356  generic_function_names.update(random_number_names)
11357  generic_function_names.update(system_environment_names)
11358 
11359  # A list of all function names
11360  function_names = list(generic_function_names.keys()) + list(
11361  specific_function_names.keys()
11362  )
11363 
11364  subclass_names = []
11365 
11366  @staticmethod
11367  def match(string):
11368  """Attempt to match the input `string` with the intrinsic function
11369  names defined in `generic_function_names` or
11370  `specific_function_names`. If there is a match the resultant
11371  string will be converted to upper case.
11372 
11373  :param str string: The pattern to be matched.
11374 
11375  :returns: A tuple containing the matched string (converted to \
11376  upper case) if there is a match or None if there is not.
11377  :rtype: (str,) or NoneType
11378 
11379  """
11380  return STRINGBase.match(Intrinsic_Name.function_names, string)
11381 
11382 
11383 class Intrinsic_Function_Reference(CallBase): # No explicit rule
11384  """Represents Fortran intrinsics.
11385 
11386  function-reference is intrinsic-name ( [ actual-arg-spec-list ] )
11387 
11388  """
11389 
11390  subclass_names = []
11391  use_names = ["Intrinsic_Name", "Actual_Arg_Spec_List"]
11392 
11393  @staticmethod
11394  def match(string):
11395  """Match the string as an intrinsic function. Also check that the
11396  number of arguments provided matches the number expected by
11397  the intrinsic.
11398 
11399  :param str string: the string to match with the pattern rule.
11400 
11401  :return: a tuple of size 2 containing the name of the \
11402  intrinsic and its arguments if there is a match, or None if \
11403  there is not.
11404  :rtype: (:py:class:`fparser.two.Fortran2003.Intrinsic_Name`, \
11405  :py:class:`fparser.two.Fortran2003.Actual_Arg_Spec_List`) or \
11406  NoneType
11407 
11408  :raises InternalSyntaxError: If the number of arguments \
11409  provided does not match the number of arguments expected by \
11410  the intrinsic.
11411 
11412  """
11413  result = CallBase.match(Intrinsic_Name, Actual_Arg_Spec_List, string)
11414  if result:
11415  # There is a match so check the number of args provided
11416  # matches the number of args expected by the intrinsic.
11417  function_name = str(result[0])
11418  function_args = result[1]
11419 
11420  # Check that that this name is not being shadowed (i.e. overridden)
11421  # by a symbol in scope at this point.
11422  table = SYMBOL_TABLES.current_scope
11423  try:
11424  table.lookup(function_name)
11425  # We found a matching name so refuse to match this intrinsic.
11426  return None
11427  except (KeyError, AttributeError):
11428  # There is either no matching name in the table or we have
11429  # no current scoping region.
11430  pass
11431 
11432  # This if/else will not be needed once issue #170 has been
11433  # addressed.
11434  if isinstance(function_args, Actual_Arg_Spec_List):
11435  nargs = len(function_args.items)
11436  elif function_args is None:
11437  nargs = 0
11438  else:
11439  nargs = 1
11440 
11441  if function_name in Intrinsic_Name.specific_function_names.keys():
11442  # If this is a specific function then use its generic
11443  # name to test min and max number of arguments.
11444  test_name = Intrinsic_Name.specific_function_names[function_name]
11445  else:
11446  test_name = function_name
11447 
11448  min_nargs = Intrinsic_Name.generic_function_names[test_name]["min"]
11449  max_nargs = Intrinsic_Name.generic_function_names[test_name]["max"]
11450 
11451  if max_nargs is None:
11452  if nargs < min_nargs:
11453  # None indicates an unlimited number of arguments
11454  raise InternalSyntaxError(
11455  "Intrinsic '{0}' expects at least {1} args but found "
11456  "{2}.".format(function_name, min_nargs, nargs)
11457  )
11458  # The number of arguments is valid. Return here as
11459  # further tests will fail due to max_args being
11460  # None.
11461  return result
11462  if min_nargs == max_nargs and nargs != min_nargs:
11463  raise InternalSyntaxError(
11464  "Intrinsic '{0}' expects {1} arg(s) but found {2}."
11465  "".format(function_name, min_nargs, nargs)
11466  )
11467  if min_nargs < max_nargs and (nargs < min_nargs or nargs > max_nargs):
11468  raise InternalSyntaxError(
11469  "Intrinsic '{0}' expects between {1} and {2} args but "
11470  "found {3}.".format(function_name, min_nargs, max_nargs, nargs)
11471  )
11472  return result
11473 
11474 
11475 class Call_Stmt(StmtBase): # R1218
11476  """
11477  <call-stmt> = CALL <procedure-designator>
11478  [ ( [ <actual-arg-spec-list> ] ) ]
11479 
11480  Attributes
11481  ----------
11482  items : (Procedure_Designator, Actual_Arg_Spec_List)
11483  """
11484 
11485  subclass_names = []
11486  use_names = ["Procedure_Designator", "Actual_Arg_Spec_List"]
11487 
11488  @staticmethod
11489  def match(string):
11490  if string[:4].upper() != "CALL":
11491  return
11492  line, repmap = string_replace_map(string[4:].lstrip())
11493  if line.endswith(")"):
11494  i = line.rfind("(")
11495  if i == -1:
11496  return
11497  args = repmap(line[i + 1 : -1].strip())
11498  if args:
11499  return (
11500  Procedure_Designator(repmap(line[:i].rstrip())),
11501  Actual_Arg_Spec_List(args),
11502  )
11503  return Procedure_Designator(repmap(line[:i].rstrip())), None
11504  return Procedure_Designator(string[4:].lstrip()), None
11505 
11506  def tostr(self):
11507  if self.items[1] is None:
11508  return "CALL %s" % (self.items[0])
11509  return "CALL %s(%s)" % self.items
11510 
11511 
11512 class Procedure_Designator(BinaryOpBase): # R1219
11513  """
11514  <procedure-designator> = <procedure-name>
11515  | <proc-component-ref>
11516  | <data-ref> % <binding-name>
11517  """
11518 
11519  subclass_names = ["Procedure_Name", "Proc_Component_Ref"]
11520  use_names = ["Data_Ref", "Binding_Name"]
11521 
11522  @staticmethod
11523  def match(string):
11524  return BinaryOpBase.match(
11525  Data_Ref, pattern.percent_op.named(), Binding_Name, string
11526  )
11527 
11528 
11529 class Actual_Arg_Spec(KeywordValueBase): # R1220
11530  """
11531  <actual-arg-spec> = [ <keyword> = ] <actual-arg>
11532  """
11533 
11534  subclass_names = ["Actual_Arg"]
11535  use_names = ["Keyword"]
11536 
11537  @staticmethod
11538  def match(string):
11539  return KeywordValueBase.match(Keyword, Actual_Arg, string)
11540 
11541 
11542 class Actual_Arg(Base): # R1221
11543  """
11544  <actual-arg> = <expr>
11545  | <variable>
11546  | <procedure-name>
11547  | <proc-component-ref>
11548  | <alt-return-spec>
11549  """
11550 
11551  subclass_names = [
11552  "Expr",
11553  "Procedure_Name",
11554  "Proc_Component_Ref",
11555  "Alt_Return_Spec",
11556  "Variable",
11557  ]
11558 
11559 
11560 class Alt_Return_Spec(Base): # R1222
11561  """
11562  <alt-return-spec> = * <label>
11563  """
11564 
11565  subclass_names = []
11566  use_names = ["Label"]
11567 
11568  @staticmethod
11569  def match(string):
11570  if not string.startswith("*"):
11571  return
11572  line = string[1:].lstrip()
11573  if not line:
11574  return
11575  return (Label(line),)
11576 
11577  def tostr(self):
11578  return "*%s" % (self.items[0])
11579 
11580 
11581 class Function_Subprogram(BlockBase): # R1223
11582  """
11583  <function-subprogram> = <function-stmt>
11584  [ <specification-part> ]
11585  [ <execution-part> ]
11586  [ <internal-subprogram-part> ]
11587  <end-function-stmt>
11588  """
11589 
11590  subclass_names = []
11591  use_names = [
11592  "Function_Stmt",
11593  "Specification_Part",
11594  "Execution_Part",
11595  "Internal_Subprogram_Part",
11596  "End_Function_Stmt",
11597  ]
11598 
11599  @staticmethod
11600  def match(reader):
11601  return BlockBase.match(
11602  Function_Stmt,
11603  [Specification_Part, Execution_Part, Internal_Subprogram_Part],
11604  End_Function_Stmt,
11605  reader,
11606  )
11607 
11608 
11609 class Function_Stmt(StmtBase): # R1224
11610  """
11611  <function-stmt> = [ <prefix> ] FUNCTION <function-name>
11612  ( [ <dummy-arg-name-list> ] ) [ <suffix> ]
11613 
11614  C1242 (R1227) A prefix shall not specify ELEMENTAL if
11615  proc-language-binding-spec appears in the function-stmt or
11616  subroutine-stmt. The spec associates this constraint with R1227
11617  but it needs to be checked here.
11618 
11619  """
11620 
11621  subclass_names = []
11622  use_names = ["Prefix", "Function_Name", "Dummy_Arg_Name_List", "Suffix"]
11623 
11624  @staticmethod
11625  def match(string):
11626  line, repmap = string_replace_map(string)
11627  m = pattern.function.search(line)
11628  if m is None:
11629  return
11630  prefix = line[: m.start()].rstrip() or None
11631  if prefix is not None:
11632  prefix = Prefix(repmap(prefix))
11633  line = line[m.end() :].lstrip()
11634  m = pattern.name.match(line)
11635  if m is None:
11636  return
11637  name = Function_Name(m.group())
11638  line = line[m.end() :].lstrip()
11639  if not line.startswith("("):
11640  return
11641  i = line.find(")")
11642  if i == -1:
11643  return
11644  dummy_args = line[1:i].strip() or None
11645  if dummy_args is not None:
11646  dummy_args = Dummy_Arg_List(repmap(dummy_args))
11647  line = line[i + 1 :].lstrip()
11648  suffix = None
11649  if line:
11650  suffix = Suffix(repmap(line))
11651  if suffix:
11652  # A suffix may or may not contain a binding spec.
11653  binding_spec = walk(suffix, Language_Binding_Spec)
11654  # Check that we conform to C1242.
11655  if not c1242_valid(prefix, binding_spec):
11656  return None
11657  return prefix, name, dummy_args, suffix
11658 
11659  def tostr(self):
11660  prefix, name, dummy_args, suffix = self.items
11661  if prefix is not None:
11662  s = "%s FUNCTION %s" % (prefix, name)
11663  else:
11664  s = "FUNCTION %s" % (name)
11665  if dummy_args is not None:
11666  s += "(%s)" % (dummy_args)
11667  else:
11668  s += "()"
11669  if suffix is not None:
11670  s += " %s" % (suffix)
11671  return s
11672 
11673  def get_name(self):
11674  """Provides the function name as an instance of the :py:class:`Name` class.
11675 
11676  :rtype: :py:class:`Name`
11677  """
11678  return self.items[1]
11679 
11680 
11681 class Proc_Language_Binding_Spec(Base): # 1225
11682  """
11683  <proc-language-binding-spec> = <language-binding-spec>
11684  """
11685 
11686  subclass_names = ["Language_Binding_Spec"]
11687 
11688 
11689 class Dummy_Arg_Name(Base): # R1226
11690  """
11691  <dummy-arg-name> = <name>
11692  """
11693 
11694  subclass_names = ["Name"]
11695 
11696 
11697 class Prefix(SequenceBase):
11698  """Fortran2003 rule R1227
11699 
11700  prefix is prefix-spec [ prefix-spec ] ...
11701 
11702  C1240 (R1227) A prefix shall contain at most one of each
11703  prefix-spec. Checked below.
11704 
11705  C1241 (R1227) A prefix shall not specify both ELEMENTAL and
11706  RECURSIVE. Checked below.
11707 
11708  C1242 (R1227) A prefix shall not specify ELEMENTAL if
11709  proc-language-binding-spec appears in the function-stmt or
11710  subroutine-stmt. This constraint can not be checked here, it is
11711  checked in R1224 and R1232.
11712 
11713  """
11714 
11715  subclass_names = []
11716 
11717  @staticmethod
11718  def match(string):
11719  """Match a space separated list of Prefix_Spec objects. Objects may be
11720  separated by 1 or more spaces.
11721 
11722  :returns: A tuple of size 2 containing the separator and a \
11723  tuple containing one or more Prefix_Spec objects if there is a \
11724  match and None if not.
11725 
11726  :rtype: (str, (:class:py:`fparser.two.Fortran2003.Prefix_Spec`,)) \
11727  or NoneType
11728 
11729  """
11730  start_match_list = []
11731  end_match_list = []
11732  decl_spec_list = []
11733  keyword_list = []
11734  split = string.split()
11735  # Match prefix-spec (apart from declaration-type-spec) from
11736  # the left end of the string. These can be tokenised with a
11737  # simple split as they are guaranteed to not contain any
11738  # whitespace (as they are keywords).
11739  while split and split[0].upper() in Prefix_Spec.keywords:
11740  start_match_list.append(Prefix_Spec(split[0]))
11741  keyword_list.append(split[0].upper())
11742  split = split[1:]
11743  # Match prefix-spec (apart from declaration-type-spec) from
11744  # the right end of the string.
11745  while split and split[-1].upper() in Prefix_Spec.keywords:
11746  end_match_list.insert(0, Prefix_Spec(split[-1]))
11747  keyword_list.append(split[-1].upper())
11748  split = split[:-1]
11749  # What is remaining must be a declaration-type-spec (or is
11750  # empty) as only one of each prefix-spec is allowed in a
11751  # prefix (C1240). This may contain internal white space so
11752  # join the remaining parts together.
11753  remaining = " ".join(split)
11754  if remaining:
11755  decl_spec_list = [Declaration_Type_Spec(remaining)]
11756  if len(set(keyword_list)) != len(keyword_list):
11757  # C1240 A prefix shall contain at most one of each
11758  # prefix-spec. No need to check declaration-type-spec as
11759  # that is limited to at most one by design.
11760  return None
11761  if "ELEMENTAL" in keyword_list and "RECURSIVE" in keyword_list:
11762  # C1241 A prefix shall not specify both ELEMENTAL and RECURSIVE.
11763  return None
11764  result_list = start_match_list + decl_spec_list + end_match_list
11765  if result_list:
11766  return " ", tuple(result_list)
11767  # A prefix must contain at least one prefix-spec.
11768  return None
11769 
11770 
11771 class Prefix_Spec(STRINGBase): # R1228
11772  """
11773  <prefix-spec> = <declaration-type-spec>
11774  | ELEMENTAL
11775  | IMPURE
11776  | MODULE
11777  | PURE
11778  | RECURSIVE
11779  """
11780 
11781  subclass_names = ["Declaration_Type_Spec"]
11782  # issue #221. IMPURE and MODULE are Fortran2008.
11783  keywords = ["ELEMENTAL", "IMPURE", "MODULE", "PURE", "RECURSIVE"]
11784 
11785  @staticmethod
11786  def match(string):
11787  """
11788  Matches procedure prefixes.
11789 
11790  :param str string: Candidate string.
11791  :return: Discovered prefix.
11792  :rtype: str
11793  """
11794  return STRINGBase.match(Prefix_Spec.keywords, string)
11795 
11796 
11797 class Suffix(Base): # R1229
11798  """
11799  <suffix> = <proc-language-binding-spec> [ RESULT ( <result-name> ) ]
11800  | RESULT ( <result-name> ) [ <proc-language-binding-spec> ]
11801  """
11802 
11803  subclass_names = ["Proc_Language_Binding_Spec"]
11804  use_names = ["Result_Name"]
11805 
11806  @staticmethod
11807  def match(string):
11808  if string[:6].upper() == "RESULT":
11809  line = string[6:].lstrip()
11810  if not line.startswith("("):
11811  return
11812  i = line.find(")")
11813  if i == -1:
11814  return
11815  name = line[1:i].strip()
11816  if not name:
11817  return
11818  line = line[i + 1 :].lstrip()
11819  if line:
11820  return Result_Name(name), Proc_Language_Binding_Spec(line)
11821  return Result_Name(name), None
11822  if not string.endswith(")"):
11823  return
11824  i = string.rfind("(")
11825  if i == -1:
11826  return
11827  name = string[i + 1 : -1].strip()
11828  if not name:
11829  return
11830  line = string[:i].rstrip()
11831  if line[-6:].upper() != "RESULT":
11832  return
11833  line = line[:-6].rstrip()
11834  if not line:
11835  return
11836  return Result_Name(name), Proc_Language_Binding_Spec(line)
11837 
11838  def tostr(self):
11839  if self.items[1] is None:
11840  return "RESULT(%s)" % (self.items[0])
11841  return "RESULT(%s) %s" % self.items
11842 
11843 
11844 class End_Function_Stmt(EndStmtBase): # R1230
11845  """
11846  <end-function-stmt> = END [ FUNCTION [ <function-name> ] ]
11847  """
11848 
11849  subclass_names = []
11850  use_names = ["Function_Name"]
11851 
11852  @staticmethod
11853  def match(string):
11854  return EndStmtBase.match("FUNCTION", Function_Name, string)
11855 
11856 
11857 class Subroutine_Subprogram(BlockBase): # R1231
11858  """
11859  <subroutine-subprogram> = <subroutine-stmt>
11860  [ <specification-part> ]
11861  [ <execution-part> ]
11862  [ <internal-subprogram-part> ]
11863  <end-subroutine-stmt>
11864  """
11865 
11866  subclass_names = []
11867  use_names = [
11868  "Subroutine_Stmt",
11869  "Specification_Part",
11870  "Execution_Part",
11871  "Internal_Subprogram_Part",
11872  "End_Subroutine_Stmt",
11873  ]
11874 
11875  @staticmethod
11876  def match(reader):
11877  return BlockBase.match(
11878  Subroutine_Stmt,
11879  [Specification_Part, Execution_Part, Internal_Subprogram_Part],
11880  End_Subroutine_Stmt,
11881  reader,
11882  )
11883 
11884 
11885 def c1242_valid(prefix, binding_spec):
11886  """If prefix and binding-spec exist then check whether they conform to
11887  constraint C1242 : "A prefix shall not specify ELEMENTAL if
11888  proc-language-binding-spec appears in the function-stmt or
11889  subroutine-stmt."
11890 
11891  :param prefix: matching prefix instance if one exists.
11892  :type: :py:class:`fparser.two.Fortran2003.Prefix` or `NoneType`
11893  :param binding_spec: matching binding specification instance if \
11894  one exists.
11895  :type binding_spec: \
11896  :py:class:`fparser.two.Fortran2003.Language_Binding_Spec` or
11897  `NoneType`
11898  :returns: False if prefix and binding-spec break constraint C1242, \
11899  otherwise True.
11900  :rtype: bool
11901 
11902  """
11903  if binding_spec and prefix:
11904  # Prefix(es) may or may not be of type ELEMENTAL
11905  elemental = any(
11906  "ELEMENTAL" in str(child) for child in walk(prefix.items, Prefix_Spec)
11907  )
11908  if elemental:
11909  # Constraint C1242. A prefix shall not specify ELEMENTAL if
11910  # proc-language-binding-spec appears in the function-stmt or
11911  # subroutine-stmt.
11912  return False
11913  return True
11914 
11915 
11916 class Subroutine_Stmt(StmtBase): # R1232
11917  """<subroutine-stmt>
11918  = [ <prefix> ] SUBROUTINE <subroutine-name>
11919  [ ( [ <dummy-arg-list> ] ) [ <proc-language-binding-spec> ] ]
11920 
11921  C1242 (R1227) A prefix shall not specify ELEMENTAL if
11922  proc-language-binding-spec appears in the function-stmt or
11923  subroutine-stmt. The spec associates this constraint with R1227
11924  but it needs to be checked here.
11925 
11926  """
11927 
11928  subclass_names = []
11929  use_names = [
11930  "Prefix",
11931  "Subroutine_Name",
11932  "Dummy_Arg_List",
11933  "Proc_Language_Binding_Spec",
11934  ]
11935 
11936  @staticmethod
11937  def match(string):
11938  line, repmap = string_replace_map(string)
11939  m = pattern.subroutine.search(line)
11940  if m is None:
11941  return
11942  prefix = line[: m.start()].rstrip() or None
11943  if prefix is not None:
11944  prefix = Prefix(repmap(prefix))
11945  line = line[m.end() :].lstrip()
11946  m = pattern.name.match(line)
11947  if m is None:
11948  return
11949  name = Subroutine_Name(m.group())
11950  line = line[m.end() :].lstrip()
11951  dummy_args = None
11952  if line.startswith("("):
11953  i = line.find(")")
11954  if i == -1:
11955  return
11956  dummy_args = line[1:i].strip() or None
11957  if dummy_args is not None:
11958  dummy_args = Dummy_Arg_List(repmap(dummy_args))
11959  line = line[i + 1 :].lstrip()
11960  binding_spec = None
11961  if line:
11962  binding_spec = Proc_Language_Binding_Spec(repmap(line))
11963  if not c1242_valid(prefix, binding_spec):
11964  return None
11965  return prefix, name, dummy_args, binding_spec
11966 
11967  def get_name(self):
11968  return self.items[1]
11969 
11970  def tostr(self):
11971  if self.items[0] is not None:
11972  s = "%s SUBROUTINE %s" % (self.items[0], self.items[1])
11973  else:
11974  s = "SUBROUTINE %s" % (self.items[1])
11975  if self.items[2] is not None:
11976  s += "(%s)" % (self.items[2])
11977  if self.items[3] is not None:
11978  s += " %s" % (self.items[3])
11979  return s
11980 
11981 
11982 class Dummy_Arg(StringBase): # R1233
11983  """
11984  <dummy-arg> = <dummy-arg-name>
11985  | *
11986  """
11987 
11988  subclass_names = ["Dummy_Arg_Name"]
11989 
11990  @staticmethod
11991  def match(string):
11992  return StringBase.match("*", string)
11993 
11994 
11995 class End_Subroutine_Stmt(EndStmtBase): # R1234
11996  """
11997  <end-subroutine-stmt> = END [ SUBROUTINE [ <subroutine-name> ] ]
11998  """
11999 
12000  subclass_names = []
12001  use_names = ["Subroutine_Name"]
12002 
12003  @staticmethod
12004  def match(string):
12005  return EndStmtBase.match("SUBROUTINE", Subroutine_Name, string)
12006 
12007 
12008 class Entry_Stmt(StmtBase): # R1235
12009  """
12010  ::
12011  <entry-stmt> = ENTRY <entry-name> [ ( [ <dummy-arg-list> ] ) [ <suffix> ] ]
12012 
12013  Attributes
12014  ----------
12015  items : (Entry_Name, Dummy_Arg_List, Suffix)
12016  """
12017 
12018  subclass_names = []
12019  use_names = ["Entry_Name", "Dummy_Arg_List", "Suffix"]
12020 
12021  @staticmethod
12022  def match(string):
12023  if string[:5].upper() != "ENTRY":
12024  return
12025  line = string[5:].lstrip()
12026  i = line.find("(")
12027  if i == -1:
12028  return Entry_Name(line), None, None
12029  name = Entry_Name(line[:i].rstrip())
12030  line, repmap = string_replace_map(line[i:])
12031  i = line.find(")")
12032  if i == -1:
12033  return
12034  args = line[1:i].strip()
12035  args = Dummy_Arg_List(repmap(args)) if args else None
12036  line = line[i + 1 :].lstrip()
12037  if line:
12038  return name, args, Suffix(repmap(line))
12039  return name, args, None
12040 
12041  def tostr(self):
12042  name, args, suffix = self.items
12043  if suffix is None:
12044  if args is None:
12045  return "ENTRY %s()" % (name)
12046  return "ENTRY %s(%s)" % (name, args)
12047  elif args is None:
12048  return "ENTRY %s() %s" % (name, suffix)
12049  return "ENTRY %s(%s) %s" % (name, args, suffix)
12050 
12051 
12052 class Return_Stmt(StmtBase): # R1236
12053  """
12054  <return-stmt> = RETURN [ <scalar-int-expr> ]
12055  """
12056 
12057  subclass_names = []
12058  use_names = ["Scalar_Int_Expr"]
12059 
12060  @staticmethod
12061  def match(string):
12062  start = string[:6].upper()
12063  if start != "RETURN":
12064  return
12065  if len(string) == 6:
12066  return (None,)
12067  return (Scalar_Int_Expr(string[6:].lstrip()),)
12068 
12069  def tostr(self):
12070  if self.items[0] is None:
12071  return "RETURN"
12072  return "RETURN %s" % self.items
12073 
12074 
12075 class Contains_Stmt(StmtBase, STRINGBase): # R1237
12076  """
12077  <contains-stmt> = CONTAINS
12078  """
12079 
12080  subclass_names = []
12081 
12082  @staticmethod
12083  def match(string):
12084  return STRINGBase.match("CONTAINS", string)
12085 
12086 
12087 class Stmt_Function_Stmt(StmtBase): # R1238
12088  """
12089  <stmt-function-stmt>
12090  = <function-name> ( [ <dummy-arg-name-list> ] ) = Scalar_Expr
12091  """
12092 
12093  subclass_names = []
12094  use_names = ["Function_Name", "Dummy_Arg_Name_List", "Scalar_Expr"]
12095 
12096  @staticmethod
12097  def match(string):
12098  i = string.find("=")
12099  if i == -1:
12100  return
12101  expr = string[i + 1 :].lstrip()
12102  if not expr:
12103  return
12104  line = string[:i].rstrip()
12105  if not line or not line.endswith(")"):
12106  return
12107  i = line.find("(")
12108  if i == -1:
12109  return
12110  name = line[:i].rstrip()
12111  if not name:
12112  return
12113  args = line[i + 1 : -1].strip()
12114  if args:
12115  return Function_Name(name), Dummy_Arg_Name_List(args), Scalar_Expr(expr)
12116  return Function_Name(name), None, Scalar_Expr(expr)
12117 
12118  def tostr(self):
12119  if self.items[1] is None:
12120  return "%s () = %s" % (self.items[0], self.items[2])
12121  return "%s (%s) = %s" % self.items
12122 
12123 
12124 #
12125 # GENERATE Scalar_, _List, _Name CLASSES
12126 #
12127 
12128 
12129 ClassType = type(Base)
12130 _names = dir()
12131 for clsname in _names:
12132  my_cls = eval(clsname)
12133  if not (
12134  isinstance(my_cls, ClassType)
12135  and issubclass(my_cls, Base)
12136  and not my_cls.__name__.endswith("Base")
12137  ):
12138  continue
12139 
12140  names = getattr(my_cls, "subclass_names", []) + getattr(my_cls, "use_names", [])
12141  for n in names:
12142  if n in _names:
12143  continue
12144  if n.endswith("_List"):
12145  _names.append(n)
12146  n = n[:-5]
12147  # Generate 'list' class
12148  exec(
12149  """\
12150 class %s_List(SequenceBase):
12151  subclass_names = [\'%s\']
12152  use_names = []
12153  def match(string): return SequenceBase.match(r\',\', %s, string)
12154 
12155 """
12156  % (n, n, n)
12157  )
12158  elif n.endswith("_Name"):
12159  _names.append(n)
12160  n = n[:-5]
12161  exec(
12162  """\
12163 class %s_Name(Base):
12164  subclass_names = [\'Name\']
12165 """
12166  % (n)
12167  )
12168  elif n.startswith("Scalar_"):
12169  _names.append(n)
12170  n = n[7:]
12171  exec(
12172  """\
12173 class Scalar_%s(Base):
12174  subclass_names = [\'%s\']
12175 """
12176  % (n, n)
12177  )
12178 
12179 
12180 DynamicImport().import_now()
def restore_reader(self, reader)
Definition: Fortran2003.py:181
def __new__(cls, string, parent_cls=None)
Definition: Fortran2003.py:128