Reference Guide  2.5.0
utils.py
1 # -----------------------------------------------------------------------------
2 # BSD 3-Clause License
3 #
4 # Copyright (c) 2019-2024, Science and Technology Facilities Council.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 #
10 # * Redistributions of source code must retain the above copyright notice, this
11 # list of conditions and the following disclaimer.
12 #
13 # * Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 #
17 # * Neither the name of the copyright holder nor the names of its
18 # contributors may be used to endorse or promote products derived from
19 # this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 # -----------------------------------------------------------------------------
34 # Authors: R. W. Ford, A. R. Porter, S. Siso and N. Nobre, STFC Daresbury Lab
35 
36 '''Utility module containing classes and functions that are used by
37 the parser modules.
38 
39 '''
40 
41 import io
42 
43 from fparser.two.parser import ParserFactory
44 from fparser.common.readfortran import FortranFileReader
45 from fparser.two.utils import FortranSyntaxError
46 from psyclone.configuration import Config
47 from psyclone.line_length import FortLineLength
48 from psyclone.errors import PSycloneError, InternalError
49 
50 
51 # Exceptions
52 
54  '''Provides a PSyclone-specific error class for the situation when
55  the PSyclone code parsing finds an error in the input.
56 
57  :param str value: the message associated with the error.
58 
59  '''
60  def __init__(self, value):
61  PSycloneError.__init__(self, value)
62  self.valuevaluevalue = "Parse Error: " + str(value)
63 
64 # support functions
65 
66 
67 def check_api(api):
68  '''Check that the supplied API is valid.
69 
70  :param str api: The API to check.
71  :raises ParseError: if the supplied API is not recognised.
72 
73  '''
74  _config = Config.get()
75 
76  if api not in _config.supported_apis:
77  raise ParseError(
78  f"utils.py:check_api: Unsupported API '{api}' specified. "
79  f"Supported types are {_config.supported_apis}.")
80 
81 
82 def check_line_length(filename):
83  '''Check that the code contained within the filename file
84  conforms to the 132 line length limit.
85 
86  :param str filename: The file containing the code.
87 
88  :raises InternalError: if the specified file can not be opened or read.
89  :raises ParseError: if one of more lines are longer than the 132 \
90  line length limit.
91  '''
92  fll = FortLineLength()
93  try:
94  with io.open(filename, "r", encoding='utf8') as myfile:
95  code_str = myfile.read()
96  except IOError as excinfo:
97  raise InternalError(f"In utils.py:check_line_length: {excinfo}")
98 
99  if fll.long_lines(code_str):
100  raise ParseError(
101  f"the file does not conform to the specified {fll.length} line "
102  f"length limit")
103 
104 
105 def parse_fp2(filename):
106  '''Parse a Fortran source file contained in the file 'filename' using
107  fparser2.
108 
109  :param str filename: source file (including path) to read.
110  :returns: fparser2 AST for the source file.
111  :rtype: :py:class:`fparser.two.Fortran2003.Program`
112  :raises ParseError: if the file could not be parsed.
113 
114  '''
115  parser = ParserFactory().create(std="f2008")
116  # We get the directories to search for any Fortran include files from
117  # our configuration object.
118  config = Config.get()
119  try:
120  reader = FortranFileReader(filename, include_dirs=config.include_paths)
121  except IOError as error:
122  raise ParseError(
123  f"algorithm.py:parse_fp2: Failed to parse file '{filename}'. "
124  f"Error returned was ' {error} '.")
125  try:
126  parse_tree = parser(reader)
127  except FortranSyntaxError as msg:
128  raise ParseError(
129  f"algorithm.py:parse_fp2: Syntax error in file '{filename}':\n"
130  f"{msg}")
131  return parse_tree