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 endOfLine{ 34 "\n"_ch >> ok || fail("expected end of line"_err_en_US)}; 35 36 constexpr auto semicolons{";"_ch >> skipMany(";"_tok) / space / maybe("\n"_ch)}; 37 constexpr auto endOfStmt{ 38 space >> withMessage("expected end of statement"_err_en_US, 39 semicolons || endOfLine)}; 40 constexpr auto forceEndOfStmt{recovery(endOfStmt, SkipPast<'\n'>{})}; 41 42 template <typename PA> inline constexpr auto statement(const PA &p) { 43 return unterminatedStatement(p) / endOfStmt; 44 } 45 46 // unlabeledStatement() is basically statement() for those few situations 47 // in Fortran where a statement cannot have a label. 48 template <typename PA> inline constexpr auto unlabeledStatement(const PA &p) { 49 return space >> 50 sourced(construct<UnlabeledStatement<typename PA::resultType>>(p)); 51 } 52 53 // This unambiguousStatement() variant of statement() provides better error 54 // recovery for contexts containing statements that might have trailing 55 // garbage, but it must be used only when no instance of the statement in 56 // question could also be a legal prefix of some other statement that might 57 // be valid at that point. It only makes sense to use this within "some()" 58 // or "many()" so as to not end the list of statements. 59 template <typename PA> inline constexpr auto unambiguousStatement(const PA &p) { 60 return unterminatedStatement(p) / forceEndOfStmt; 61 } 62 63 constexpr auto ignoredStatementPrefix{ 64 skipStuffBeforeStatement >> maybe(label) >> maybe(name / ":") >> space}; 65 66 // Error recovery within a statement() call: skip *to* the end of the line, 67 // unless at an END or CONTAINS statement. 68 constexpr auto inStmtErrorRecovery{!"END"_tok >> !"CONTAINS"_tok >> 69 SkipTo<'\n'>{} >> construct<ErrorRecovery>()}; 70 71 // Error recovery within statement sequences: skip *past* the end of the line, 72 // but not over an END or CONTAINS statement. 73 constexpr auto skipStmtErrorRecovery{!"END"_tok >> !"CONTAINS"_tok >> 74 SkipPast<'\n'>{} >> construct<ErrorRecovery>()}; 75 76 // Error recovery across statements: skip the line, unless it looks 77 // like it might end the containing construct. 78 constexpr auto stmtErrorRecoveryStart{ignoredStatementPrefix}; 79 constexpr auto skipBadLine{SkipPast<'\n'>{} >> construct<ErrorRecovery>()}; 80 constexpr auto executionPartErrorRecovery{stmtErrorRecoveryStart >> 81 !"END"_tok >> !"CONTAINS"_tok >> !"ELSE"_tok >> !"CASE"_tok >> 82 !"TYPE IS"_tok >> !"CLASS"_tok >> !"RANK"_tok >> 83 !("!$OMP "_sptok >> ("END"_tok || "SECTION"_id)) >> skipBadLine}; 84 85 // END statement error recovery 86 constexpr auto missingOptionalName{defaulted(cut >> maybe(name))}; 87 constexpr auto noNameEnd{"END" >> missingOptionalName}; 88 constexpr auto atEndOfStmt{space >> 89 withMessage("expected end of statement"_err_en_US, lookAhead(";\n"_ch))}; 90 constexpr auto bareEnd{noNameEnd / recovery(atEndOfStmt, SkipTo<'\n'>{})}; 91 92 constexpr auto endStmtErrorRecovery{ 93 ("END"_tok >> SkipTo<'\n'>{} || ok) >> missingOptionalName}; 94 95 constexpr auto progUnitEndStmtErrorRecovery{ 96 (many(!"END"_tok >> SkipPast<'\n'>{}) >> 97 ("END"_tok >> SkipTo<'\n'>{} || consumedAllInput)) >> 98 missingOptionalName}; 99 } // namespace Fortran::parser 100 #endif // FORTRAN_PARSER_STMT_PARSER_H_ 101