Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions src/fparser/common/readfortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
import re
import sys
import traceback
from collections import deque
from typing import Optional, Tuple
from io import StringIO

Expand Down Expand Up @@ -594,7 +595,7 @@ def __init__(
self.process_directives = process_directives

self.filo_line = [] # used for un-consuming lines.
self.fifo_item = []
self.fifo_item = deque()
self.source_lines = [] # source lines cache

self.f2py_comment_lines = [] # line numbers of f2py directives
Expand Down Expand Up @@ -825,7 +826,7 @@ def put_item(self, item):
# of the corresponding reader.
self.reader.put_item(item)
else:
self.fifo_item.insert(0, item)
self.fifo_item.appendleft(item)

# Iterator methods:

Expand Down Expand Up @@ -930,11 +931,11 @@ def _next(self, ignore_comments=None):
"""
if ignore_comments is None:
ignore_comments = self._ignore_comments
fifo_item_pop = self.fifo_item.pop
fifo_item_pop = self.fifo_item.popleft
while 1:
try:
# first empty the FIFO item buffer:
item = fifo_item_pop(0)
item = fifo_item_pop()
except IndexError:
# construct a new item from source
item = self.get_source_item()
Expand Down Expand Up @@ -986,8 +987,8 @@ def _next(self, ignore_comments=None):
items.append(new_line)
items.reverse()
for newitem in items:
self.fifo_item.insert(0, newitem)
return fifo_item_pop(0)
self.fifo_item.appendleft(newitem)
return fifo_item_pop()
return item

# Interface to returned items:
Expand Down Expand Up @@ -1663,7 +1664,7 @@ def get_source_item(self):
# blank. If it is a comment, it has been pushed onto the
# fifo_item list.
try:
return self.fifo_item.pop(0)
return self.fifo_item.popleft()
except IndexError:
# A blank line is represented as an empty comment
return Comment("", (startlineno, endlineno), self)
Expand Down
2 changes: 1 addition & 1 deletion src/fparser/one/parsefortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def put_item(self, item):
"""
Pushes the given item to the reader.
"""
self.reader.fifo_item.insert(0, item)
self.reader.fifo_item.appendleft(item)
return

def parse(self):
Expand Down
7 changes: 1 addition & 6 deletions src/fparser/two/Fortran2003.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,8 @@ def match(reader):
# Found a syntax error for this rule. Now look to match
# (via Main_Program0) with a program containing no program
# statement as this is optional in Fortran.
#
result = BlockBase.match(Main_Program0, [], None, reader)
if not result and comments:
# This program only contains comments.
return (content,)
else:
return result
return result
except StopIteration:
# Reader has no more lines.
pass
Expand Down
60 changes: 50 additions & 10 deletions src/fparser/two/tests/test_comments_and_directives.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

import pytest
from fparser.two.Fortran2003 import Program, Comment, Directive, Subroutine_Subprogram
from fparser.two.utils import walk
from fparser.two.utils import walk, FortranSyntaxError
from fparser.api import get_reader

from fparser.two.parser import ParserFactory
Expand Down Expand Up @@ -441,15 +441,11 @@ def test_directive_stmts():
old = reader.get_item()
assert old is not None

out = walk(program, Comment)
comments = 0
for comment in out:
if comment.items[0] != "":
comments = comments + 1
assert comments == 3
assert str(out[1]) == "!$dir inline"
assert str(out[3]) == "! A comment!"
assert str(out[4]) == "!!$ Another comment"
comments = walk(program, Comment)
assert len(comments) == 5
assert str(comments[1]) == "!$dir inline"
assert str(comments[3]) == "! A comment!"
assert str(comments[4]) == "!!$ Another comment"

# Check that passing something that isn't a comment into a Directive
# __new__ call doesn't create a Directive.
Expand Down Expand Up @@ -606,3 +602,47 @@ def test_inline_directive_is_comment():
program = Program(reader)
out = walk(program, Directive)
assert len(out) == 0


def test_syntax_error_with_comments():
"""Test that when we keep comments we still correctly give syntax errors
when the first line of the file is a blank line."""
source = """
Comment thread
sergisiso marked this conversation as resolved.


! This is module m


module m
integer :: x
contains
subroutine foo()
if (.true.)
x = 0
end if
end subroutine
end module"""
reader = get_reader(source, ignore_comments=False)
with pytest.raises(FortranSyntaxError) as err:
program = Program(reader)
assert "at line 11\n" in str(err.value)
assert ">>> if (.true.)\n" in str(err.value)


def test_base_to_fortran_empty_comment():
"""Test that if we have an empty comment we get the correct
to_fortran from the base class implementation (i.e. no tab)"""
source = """
!Comment
program test
end program
"""
reader = get_reader(source, ignore_comments=False)
program = Program(reader)
out = walk(program, Comment)
comment = out[1]
assert comment.tofortran(tab=" ") == " !Comment"
# Change the comment to be an empty comment.
comment.items = [""]
comment.item = ""
assert comment.tofortran(tab=" ") == ""
Loading