1 | //===-- lib/Parser/stmt-parser.h --------------------------------*- C++ -*-===// |
---|---|
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef FORTRAN_PARSER_STMT_PARSER_H_ |
10 | #define FORTRAN_PARSER_STMT_PARSER_H_ |
11 | |
12 | // Basic parsing of statements. |
13 | |
14 | #include "basic-parsers.h" |
15 | #include "token-parsers.h" |
16 | |
17 | namespace Fortran::parser { |
18 | |
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. |
22 | |
23 | // R611 label -> digit [digit]... |
24 | constexpr auto label{space >> digitString64 / spaceCheck}; |
25 | |
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)); |
31 | } |
32 | |
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'>{})}; |
36 | |
37 | constexpr auto endOfLine{ |
38 | "\n"_ch>> ok || fail( "expected end of line"_err_en_US)}; |
39 | |
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'>{})}; |
45 | |
46 | template <typename PA> inline constexpr auto statement(const PA &p) { |
47 | return unterminatedStatement(p) / endOfStmt; |
48 | } |
49 | |
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) { |
53 | return space >> |
54 | sourced(construct<UnlabeledStatement<typename PA::resultType>>(p)); |
55 | } |
56 | |
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; |
65 | } |
66 | |
67 | constexpr auto ignoredStatementPrefix{ |
68 | skipStuffBeforeStatement >> maybe(label) >> maybe(name / ":") >> space}; |
69 | |
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>()}; |
74 | |
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>()}; |
79 | |
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}; |
89 | |
90 | // END statement error recovery |
91 | constexpr auto missingOptionalName{pure<std::optional<Name>>()}; |
92 | constexpr auto noNameEnd{"END">> missingOptionalName}; |
93 | |
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}; |
104 | |
105 | constexpr auto progUnitEndStmtErrorRecovery{ |
106 | (many(!"END"_tok>> SkipPast<'\n'>{}) >> |
107 | ("END"_tok>> SkipTo<'\n'>{} || consumedAllInput)) >> |
108 | missingOptionalName}; |
109 | |
110 | constexpr auto beginDirective{skipStuffBeforeStatement >> "!"_ch}; |
111 | constexpr auto endDirective{space >> endOfLine}; |
112 | |
113 | } // namespace Fortran::parser |
114 | #endif // FORTRAN_PARSER_STMT_PARSER_H_ |
115 |
Definitions
- label
- unterminatedStatement
- atEndOfStmt
- checkEndOfKnownStmt
- endOfLine
- semicolons
- endOfStmt
- forceEndOfStmt
- statement
- unlabeledStatement
- unambiguousStatement
- ignoredStatementPrefix
- inStmtErrorRecovery
- skipStmtErrorRecovery
- stmtErrorRecoveryStart
- skipBadLine
- executionPartErrorRecovery
- missingOptionalName
- noNameEnd
- progUnitEndStmt
- constructEndStmtErrorRecovery
- namedConstructEndStmtErrorRecovery
- progUnitEndStmtErrorRecovery
- beginDirective
Improve your Profiling and Debugging skills
Find out more