Skip to content

Commit

Permalink
Merge pull request #200 from stfc/sergi_sf_hack
Browse files Browse the repository at this point in the history
issue #171. Removal of statement function matching.
  • Loading branch information
arporter authored Jul 3, 2019
2 parents d02e2b8 + 28044b0 commit 8a53476
Show file tree
Hide file tree
Showing 8 changed files with 393 additions and 35 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Modifications by (in alphabetical order):
* A. R. Porter, Science & Technology Facilities Council, UK
* P. Vitt, University of Siegen, Germany

03/07/2019 PR #200 for #171. Disable Statement Function support
in fparser2.

02/07/2019 PR #205 for #204. Corrects the minimum number of arguments
for the SELECTED_REAL_KIND intrinsic.

Expand Down
21 changes: 21 additions & 0 deletions doc/fparser2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,27 @@ number. For example:
fparser.two.Fortran2003.FortranSyntaxError: at line 2
>>>en

Unsupported Features
--------------------

Statement Functions
+++++++++++++++++++

Fparser2 is currently not able to distinguish between statement
functions and array assignments when one or more array assignment
statements are the first statements after a declaration section. This
limitation leads to these particular array assignments being
incorrectly parsed as statement functions.

To avoid this incorrect behaviour, support for statement functions has
been temporarily removed from fparser2. However, with this change,
statement functions will be incorrectly parsed as array assignments
when one or more statement function statements are the last statements
in a declaration section.

Whilst any incorrect behaviour should be avoided, the behaviour of
this temporary change is considered preferable to the former case, as
array assigments are more common than statement functions.

Extensions
----------
Expand Down
16 changes: 9 additions & 7 deletions src/fparser/scripts/fparser2.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python
# Modified work Copyright (c) 2017-2018 Science and Technology
# Modified work Copyright (c) 2017-2019 Science and Technology
# Facilities Council
# Original work Copyright (c) 1999-2008 Pearu Peterson

Expand Down Expand Up @@ -83,23 +83,26 @@ def runner(_, options, args):
from fparser.two.Fortran2003 import FortranSyntaxError, InternalError
from fparser.common.readfortran import FortranFileReader
if not args:
print ("Error: No fortran files specified")
print("Error: No fortran files specified")
raise SystemExit(1)
for filename in args:
try:
reader = FortranFileReader(filename,
ignore_comments=False)
except IOError as error:
print (error)
print(error)
return
if options.mode != 'auto':
reader.format.from_mode(options.mode)
try:
f2003_parser = ParserFactory().create()
program = f2003_parser(reader)
print (program)
if options.task == "show":
print(program)
if options.task == "repr":
print(repr(program))
except FortranSyntaxError as msg:
print ("Syntax error: {0}".format(str(msg)))
print("Syntax error: {0}".format(str(msg)))
try:
# protect the access to fifo_item[-1] in case the fifo
# buffer is empty
Expand All @@ -110,7 +113,7 @@ def runner(_, options, args):
pass
raise SystemExit(1)
except InternalError as msg:
print ("Internal error in fparser: {0}".format(str(msg)))
print("Internal error in fparser: {0}".format(str(msg)))
raise SystemExit(1)


Expand All @@ -120,7 +123,6 @@ def main():
set_fparser_options(parser)
options, args = parser.parse_args()
runner(parser, options, args)
return


if __name__ == "__main__":
Expand Down
13 changes: 10 additions & 3 deletions src/fparser/scripts/script_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,22 @@ def set_parse_options(parser):
parser.add_option_group(get_fortran_code_group(parser))

def set_fparser_options(parser):
''' Command line options used by the fparser2 script.
:param parser: The OptionParser object.
:type parser: :py:class:`optparse.OptionParser`
'''

parser.set_usage('''\
%prog [options] <Fortran files>
Description:
%prog parses Fortran code.''')
parser.add_option('--task',
default = 'show',
choices = ['show', 'none'],
help = 'Specify parsing result task. Default: %default.'
default='show',
choices=['show', 'repr', 'none'],
help='Specify parsing result task. Default: %default.'
)
parser.add_option('--std',
default = 'f2003',
Expand Down
38 changes: 23 additions & 15 deletions src/fparser/two/Fortran2003.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,23 +419,31 @@ class Implicit_Part_Stmt(Base): # R206


class Declaration_Construct(Base): # R207
"""
:F03R:`207`::
<declaration-construct> = <derived-type-def>
| <entry-stmt>
| <enum-def>
| <format-stmt>
| <interface-block>
| <parameter-stmt>
| <procedure-declaration-stmt>
| <specification-stmt>
| <type-declaration-stmt>
| <stmt-function-stmt>
"""
subclass_names = ['Comment', 'Derived_Type_Def', 'Entry_Stmt', 'Enum_Def',
'''Fortran 2003 rule R207
declaration-construct is derived-type-def
or entry-stmt
or enum-def
or format-stmt
or interface-block
or parameter-stmt
or procedure-declaration-stmt
or specification-stmt
or type-declaration-stmt
or stmt-function-stmt
Note, stmt-function-stmt is not currently matched.
'''
# Commented out Stmt_Function_Stmt as it can falsely match an
# access to an array or function. Reintroducing statement
# functions is captured in issue #202.

# 'Type_Declaration_Stmt', 'Stmt_Function_Stmt']
subclass_names = ['Derived_Type_Def', 'Entry_Stmt', 'Enum_Def',
'Format_Stmt', 'Interface_Block', 'Parameter_Stmt',
'Procedure_Declaration_Stmt', 'Specification_Stmt',
'Type_Declaration_Stmt', 'Stmt_Function_Stmt']
'Type_Declaration_Stmt']


class Execution_Part(BlockBase): # R208
Expand Down
5 changes: 4 additions & 1 deletion src/fparser/two/Fortran2008.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,10 @@ class Declaration_Construct_C1112(Declaration_Construct): # C1112
subclass_names = Declaration_Construct.subclass_names[:]
subclass_names.remove('Format_Stmt')
subclass_names.remove('Entry_Stmt')
subclass_names.remove('Stmt_Function_Stmt')
# Commented out Stmt_Function_Stmt as it can falsely match an
# access to an array or function. Reintroducing statement
# functions is captured in issue #202.
# subclass_names.remove('Stmt_Function_Stmt')


class Submodule(BlockBase): # R1116 [C1112,C1114]
Expand Down
173 changes: 173 additions & 0 deletions src/fparser/two/tests/fortran2003/test_declaration_construct_r207.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Copyright (c) 2019 Science and Technology Facilities Council

# All rights reserved.

# Modifications made as part of the fparser project are distributed
# under the following license:

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:

# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.

# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.

# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

'''Test Fortran 2003 rule R207 : This file tests support for the
Declaration_Construct class.
As this class just uses Base to match with a choice of subclasses we
test that an instance of each subclass can be succesfully
parsed. Detailed checking of the subclass rules are performed by the
subclass tests.
'''

import pytest
from fparser.two.Fortran2003 import Declaration_Construct
from fparser.api import get_reader


def test_derived_type_def(f2003_create):
'''Test a derived type definition statement is supported by the
declaration construct class.
'''
code = ("TYPE :: my_type\n"
"END TYPE my_type")
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Derived_Type_Def" in repr(result)


def test_entry_stmt(f2003_create):
'''Test an entry statement is supported by the declaration construct
class.
'''
code = "ENTRY my_function()"
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Entry_Stmt" in repr(result)


def test_enum_def(f2003_create):
'''Test an enum definition is supported by the declaration construct
class.
'''
code = ("ENUM, BIND(C)\n"
" ENUMERATOR :: a = 1\n"
"END ENUM")
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Enum_Def" in repr(result)


def test_format_statement(f2003_create):
'''Test a format statement is supported by the declaration construct
class.
'''
code = "FORMAT('(x)')"
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Format_Stmt" in repr(result)


def test_interface_block(f2003_create):
'''Test an interface block statement is supported by the declaration
construct class.
'''
code = ("INTERFACE\n"
"END INTERFACE")
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Interface_Block" in repr(result)


def test_parameter_stmt(f2003_create):
'''Test a parameter statement is supported by the declaration
construct class.
'''
code = "PARAMETER(A = 2)"
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Parameter_Stmt" in repr(result)


def test_procedure_declaration_stmt(f2003_create):
'''Test a procedure declaration statement is supported by the
declaration construct class.
'''
code = "PROCEDURE(REAL) FUNC"
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Procedure_Declaration_Stmt" in repr(result)


def test_specification_stmt(f2003_create):
'''Test a specification statement is supported by the declaration
construct class. An access statement is a specification statement,
so check for this.
'''
code = "PUBLIC :: A"
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Access_Stmt" in repr(result)


def test_type_declaration_stmt(f2003_create):
'''Test a type declaration statement is supported by the declaration
construct class.
'''
code = "INTEGER :: X"
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Type_Declaration_Stmt" in repr(result)


@pytest.mark.xfail(reason="#202. Statement Function support removed.")
def test_stmt_function_stmt(f2003_create):
'''Test a statement function statement is supported by the declaration
construct class.
'''
code = "C(F) = 5.0*(F - 32.0)/9.0"
reader = get_reader(code)
result = Declaration_Construct(reader)
assert str(result) == code
assert "Stmt_Function_Stmt" in repr(result)
Loading

0 comments on commit 8a53476

Please sign in to comment.