fortran-src
fortran-src copied to clipboard
F90 parsing failure for multiple comments in case constructs
The following code fails to parse in the f90 and above parsers
program main
integer x
select case(x)
! comment uno
! comment dos
case (2):
print *, "foo"
end select
end program main
Outputting:
ProgramFilefortran-src: case-comments.f90, 5:14: case-comments.f90: parsing failed.
Last parsed token: TComment (5:1)-(5:13) " comment dos".
CallStack (from HasCallStack):
error, called at app/Main.hs:108:36 in main:Main
It appears the MAYBE_COMMENT
grammar used in quite a few places, seems to only accept a single comment, but is structured such that getting it to accept multiple comments causes other grammars to fail. Having a single comment (or oddly an inline comment after select case (x)
and another line comment), parses correctly.
(For info on trying to solve this, single comments were enabled by this commit: https://github.com/camfort/fortran-src/commit/401fd71679e3c1fcc564f28b35d4eaa790377523)
Nice catch. The relevant parser snippet in F90 is here:
-- We store line comments as statements, but this raises an issue: we have
-- nowhere to place comments after a SELECT CASE but before a CASE. So we drop
-- them. The inner CASES_ rule does /not/ use this, because comments can always
-- be parsed as belonging to to the above CASE block.
CASES :: { ([(AList Index A0, [Block A0])], Maybe [Block A0], SrcSpan, Maybe (Expression A0)) }
: COMMENT_BLOCK CASES_ { $2 }
| CASES_ { $1 }
CASES_ :: { ([(AList Index A0, [Block A0])], Maybe [Block A0], SrcSpan, Maybe (Expression A0)) }
: maybe(INTEGER_LITERAL) case '(' INDICIES ')' MAYBE_COMMENT NEWLINE BLOCKS CASES_
{ let (clauses, defaultCase, endSpan, endLabel) = $9
in ((fromReverseList $4, reverse $8) : clauses, defaultCase, endSpan, endLabel) }
| maybe(INTEGER_LITERAL) case default MAYBE_COMMENT NEWLINE BLOCKS END_SELECT
{ let (endSpan, endLabel) = $7
in ([], Just $6, endSpan, endLabel) }
| END_SELECT
{ let (endSpan, endLabel) = $1
in ([], Nothing, endSpan, endLabel) }
-- ...
MAYBE_COMMENT :: { Maybe Token }
: comment { Just $1 }
| {- EMPTY -} { Nothing }
Previously, we would fail on parsing any comments there. Maybe we could change from MAYBE_COMMENT
(0 or 1) to COMMENTS
(0-n).