Skip to content

Commit

Permalink
Merge pull request #134 from stfc/empty_input
Browse files Browse the repository at this point in the history
Support Empty input files
  • Loading branch information
arporter committed Nov 28, 2018
2 parents d8066f6 + dbc13b2 commit 87ccdae
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Modifications by (in alphabetical order):
* A. R. Porter, Science & Technology Facilities Council, UK
* P. Vitt, University of Siegen, Germany

28/11/2018 PR #134 for issue #119. Bug fix for parsing files that contain
nothing or just white space.

23/11/2018 PR #122 for issue #118. Bug fix for reporting invalid
Fortran when parsing `use module_name, only:` in fparser2.

Expand Down
5 changes: 5 additions & 0 deletions doc/fparser2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ found in the code. Nodes representing in-line comments will be added
immediately following the node representing the code in which they
were encountered.

Note that empty input, or input that consists of purely white space
and/or newlines, is not treated as invalid Fortran and an empty AST is
returned. Whilst this is not strictly valid, most compilers have this
behaviour so we follow their lead.

If the code is invalid Fortran then a `FortranSyntaxError` exception
will be raised which indicates the offending line of code and its line
number. For example:
Expand Down
6 changes: 4 additions & 2 deletions src/fparser/two/Fortran2003.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,10 @@ def __new__(cls, string):
'''
try:
return Base.__new__(cls, string)
except NoMatchError as error:
raise FortranSyntaxError(string, error)
except NoMatchError:
# At the moment there is no useful information provided by
# NoMatchError so we pass on an empty string.
raise FortranSyntaxError(string, "")

@staticmethod
def match(reader):
Expand Down
17 changes: 16 additions & 1 deletion src/fparser/two/tests/fortran2003/test_program_r201.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
# (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 R201 : This file tests the support for one
'''Test Fortran 2003 rule R201 : This file tests the support for zero
or more program-units.
'''
Expand All @@ -42,6 +42,21 @@
from fparser.api import get_reader
from fparser.two.Fortran2003 import Program

# Test no content or just white space. This is not officially a
# Fortran rule but fortran compilers tend to accept empty content so
# we follow their lead.


def test_empty_input(f2003_create):
'''Test that empty input or input only containing white space can be
parsed succesfully
'''
for code in ["", " ", " \n \n\n"]:
reader = get_reader(code)
ast = Program(reader)
assert str(ast) == ""

# Test single program units


Expand Down
37 changes: 31 additions & 6 deletions src/fparser/two/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ class FparserException(Exception):
'''Base class exception for fparser. This allows an external tool to
capture all exceptions if required.
:param str info: a string giving contextual error information.
'''
def __init__(self, info):
Exception.__init__(self, info)


class NoMatchError(FparserException):
Expand All @@ -105,23 +109,27 @@ class FortranSyntaxError(FparserException):
'''
def __init__(self, reader, info):
location = "at unknown location"
output = "at unknown location"
if isinstance(reader, FortranReaderBase):
location = "at line {0}\n>>>{1}".format(
output = "at line {0}\n>>>{1}\n".format(
reader.linecount,
reader.source_lines[reader.linecount-1])
Exception.__init__(self, "{0}\n{1}".format(location, info))
if info:
output += "{0}".format(info)
FparserException.__init__(self, output)


class InternalError(FparserException):
'''An exception indicating that an unexpected error has occured in the
parser.
:param str info: a string giving contextual error information.
'''
def __init__(self, info):
new_info = ("'{0}'. Please report this to the "
"authors.".format(info))
Exception.__init__(self, new_info)
FparserException.__init__(self, new_info)


def show_result(func):
Expand Down Expand Up @@ -286,9 +294,26 @@ def __new__(cls, string, parent_cls=None):
raise AssertionError(repr(result))
# If we get to here then we've failed to match the current line
if isinstance(string, FortranReaderBase):
content = False
for index in range(string.linecount):
# Check all lines up to this one for content. We
# should be able to only check the current line but
# but as the line number returned is not always
# correct (due to coding errors) we can not assume the
# line pointed to is the line where the error actually
# happened.
if string.source_lines[index].strip():
content = True
break
if not content:
# There are no lines in the input or all lines up to
# this one are empty or contain only white space. This
# is typically accepted by fortran compilers so we
# follow their lead and do not raise an exception.
return
line = string.source_lines[string.linecount-1]
errmsg = "at line {0}\n>>>{1}\n".format(
string.linecount,
string.source_lines[string.linecount-1])
string.linecount, line)
else:
errmsg = "{0}: '{1}'".format(cls.__name__, string)
raise NoMatchError(errmsg)
Expand Down

0 comments on commit 87ccdae

Please sign in to comment.