1 //===-- lib/Parser/stmt-parser.h --------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef FORTRAN_PARSER_STMT_PARSER_H_
10 #define FORTRAN_PARSER_STMT_PARSER_H_
12 // Basic parsing of statements.
14 #include "basic-parsers.h"
15 #include "token-parsers.h"
17 namespace Fortran::parser
{
19 // statement(p) parses Statement<P> for some statement type P that is the
20 // result type of the argument parser p, while also handling labels and
21 // end-of-statement markers.
23 // R611 label -> digit [digit]...
24 constexpr auto label
{space
>> digitString64
/ spaceCheck
};
26 template <typename PA
>
27 inline constexpr auto unterminatedStatement(const PA
&p
) {
28 return skipStuffBeforeStatement
>>
29 sourced(construct
<Statement
<typename
PA::resultType
>>(
30 maybe(label
), space
>> p
));
33 constexpr auto atEndOfStmt
{space
>>
34 withMessage("expected end of statement"_err_en_US
, lookAhead(";\n"_ch
))};
35 constexpr auto checkEndOfKnownStmt
{recovery(atEndOfStmt
, SkipTo
<'\n'>{})};
37 constexpr auto endOfLine
{
38 "\n"_ch
>> ok
|| fail("expected end of line"_err_en_US
)};
40 constexpr auto semicolons
{";"_ch
>> skipMany(";"_tok
) / space
/ maybe("\n"_ch
)};
41 constexpr auto endOfStmt
{
42 space
>> withMessage("expected end of statement"_err_en_US
,
43 semicolons
|| endOfLine
)};
44 constexpr auto forceEndOfStmt
{recovery(endOfStmt
, SkipPast
<'\n'>{})};
46 template <typename PA
> inline constexpr auto statement(const PA
&p
) {
47 return unterminatedStatement(p
) / endOfStmt
;
50 // unlabeledStatement() is basically statement() for those few situations
51 // in Fortran where a statement cannot have a label.
52 template <typename PA
> inline constexpr auto unlabeledStatement(const PA
&p
) {
54 sourced(construct
<UnlabeledStatement
<typename
PA::resultType
>>(p
));
57 // This unambiguousStatement() variant of statement() provides better error
58 // recovery for contexts containing statements that might have trailing
59 // garbage, but it must be used only when no instance of the statement in
60 // question could also be a legal prefix of some other statement that might
61 // be valid at that point. It only makes sense to use this within "some()"
62 // or "many()" so as to not end the list of statements.
63 template <typename PA
> inline constexpr auto unambiguousStatement(const PA
&p
) {
64 return unterminatedStatement(p
) / forceEndOfStmt
;
67 constexpr auto ignoredStatementPrefix
{
68 skipStuffBeforeStatement
>> maybe(label
) >> maybe(name
/ ":") >> space
};
70 // Error recovery within a statement() call: skip *to* the end of the line,
71 // unless at an END or CONTAINS statement.
72 constexpr auto inStmtErrorRecovery
{!"END"_tok
>> !"CONTAINS"_tok
>>
73 SkipTo
<'\n'>{} >> construct
<ErrorRecovery
>()};
75 // Error recovery within statement sequences: skip *past* the end of the line,
76 // but not over an END or CONTAINS statement.
77 constexpr auto skipStmtErrorRecovery
{!"END"_tok
>> !"CONTAINS"_tok
>>
78 SkipPast
<'\n'>{} >> construct
<ErrorRecovery
>()};
80 // Error recovery across statements: skip the line, unless it looks
81 // like it might end the containing construct.
82 constexpr auto stmtErrorRecoveryStart
{ignoredStatementPrefix
};
83 constexpr auto skipBadLine
{SkipPast
<'\n'>{} >> construct
<ErrorRecovery
>()};
84 constexpr auto executionPartErrorRecovery
{stmtErrorRecoveryStart
>>
85 !"END"_tok
>> !"CONTAINS"_tok
>> !"ELSE"_tok
>> !"CASE"_tok
>>
86 !"TYPE IS"_tok
>> !"CLASS"_tok
>> !"RANK"_tok
>>
87 !("!$ACC "_sptok
>> "END"_tok
) >>
88 !("!$OMP "_sptok
>> ("END"_tok
|| "SECTION"_id
)) >> skipBadLine
};
90 // END statement error recovery
91 constexpr auto missingOptionalName
{pure
<std::optional
<Name
>>()};
92 constexpr auto noNameEnd
{"END" >> missingOptionalName
};
94 // For unrecognizable construct END statements. Be sure to not consume
95 // a program unit's END statement.
96 constexpr auto progUnitEndStmt
{
97 "END" >> (lookAhead("\n"_ch
) || "SUBROUTINE"_tok
|| "FUNCTION"_tok
||
98 "PROCEDURE"_tok
|| "MODULE"_tok
|| "SUBMODULE"_tok
||
99 "PROGRAM"_tok
|| "BLOCK DATA"_tok
)};
100 constexpr auto constructEndStmtErrorRecovery
{
101 !progUnitEndStmt
>> ("END"_tok
>> SkipTo
<'\n'>{} || ok
)};
102 constexpr auto namedConstructEndStmtErrorRecovery
{
103 constructEndStmtErrorRecovery
>> missingOptionalName
};
105 constexpr auto progUnitEndStmtErrorRecovery
{
106 (many(!"END"_tok
>> SkipPast
<'\n'>{}) >>
107 ("END"_tok
>> SkipTo
<'\n'>{} || consumedAllInput
)) >>
108 missingOptionalName
};
110 constexpr auto beginDirective
{skipStuffBeforeStatement
>> "!"_ch
};
111 constexpr auto endDirective
{space
>> endOfLine
};
113 } // namespace Fortran::parser
114 #endif // FORTRAN_PARSER_STMT_PARSER_H_