Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue #171. Removal of statement function matching. #200

Merged
merged 9 commits into from
Jul 3, 2019
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")
arporter marked this conversation as resolved.
Show resolved Hide resolved
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)))
arporter marked this conversation as resolved.
Show resolved Hide resolved
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