1 //===-- lib/Parser/basic-parsers.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_BASIC_PARSERS_H_ 10 #define FORTRAN_PARSER_BASIC_PARSERS_H_ 11 12 // Let a "parser" be an instance of any class that supports this 13 // type definition and member (or static) function: 14 // 15 // using resultType = ...; 16 // std::optional<resultType> Parse(ParseState &) const; 17 // 18 // which either returns a value to signify a successful recognition or else 19 // returns {} to signify failure. On failure, the state cannot be assumed 20 // to still be valid, in general -- see below for exceptions. 21 // 22 // This header defines the fundamental parser class templates and helper 23 // template functions. See parser-combinators.txt for documentation. 24 25 #include "flang/Common/Fortran-features.h" 26 #include "flang/Common/idioms.h" 27 #include "flang/Common/indirection.h" 28 #include "flang/Parser/char-block.h" 29 #include "flang/Parser/message.h" 30 #include "flang/Parser/parse-state.h" 31 #include "flang/Parser/provenance.h" 32 #include "flang/Parser/user-state.h" 33 #include <cstring> 34 #include <functional> 35 #include <list> 36 #include <memory> 37 #include <optional> 38 #include <string> 39 #include <tuple> 40 #include <type_traits> 41 #include <utility> 42 43 namespace Fortran::parser { 44 45 // fail<A>("..."_err_en_US) returns a parser that never succeeds. It reports an 46 // error message at the current position. The result type is unused, 47 // but might have to be specified at the point of call to satisfy 48 // the type checker. The state remains valid. 49 template <typename A> class FailParser { 50 public: 51 using resultType = A; 52 constexpr FailParser(const FailParser &) = default; 53 constexpr explicit FailParser(MessageFixedText t) : text_{t} {} 54 std::optional<A> Parse(ParseState &state) const { 55 state.Say(text_); 56 return std::nullopt; 57 } 58 59 private: 60 const MessageFixedText text_; 61 }; 62 63 template <typename A = Success> inline constexpr auto fail(MessageFixedText t) { 64 return FailParser<A>{t}; 65 } 66 67 // pure(x) returns a parser that always succeeds, does not advance the 68 // parse, and returns a captured value x whose type must be copy-constructible. 69 // 70 // pure<A>() is essentially pure(A{}); it returns a default-constructed A{}, 71 // and works even when A is not copy-constructible. 72 template <typename A> class PureParser { 73 public: 74 using resultType = A; 75 constexpr PureParser(const PureParser &) = default; 76 constexpr explicit PureParser(A &&x) : value_(std::move(x)) {} 77 std::optional<A> Parse(ParseState &) const { return value_; } 78 79 private: 80 const A value_; 81 }; 82 83 template <typename A> inline constexpr auto pure(A x) { 84 return PureParser<A>(std::move(x)); 85 } 86 87 template <typename A> class PureDefaultParser { 88 public: 89 using resultType = A; 90 constexpr PureDefaultParser(const PureDefaultParser &) = default; 91 constexpr PureDefaultParser() {} 92 std::optional<A> Parse(ParseState &) const { return std::make_optional<A>(); } 93 }; 94 95 template <typename A> inline constexpr auto pure() { 96 return PureDefaultParser<A>(); 97 } 98 99 // If a is a parser, attempt(a) is the same parser, but on failure 100 // the ParseState is guaranteed to have been restored to its initial value. 101 template <typename A> class BacktrackingParser { 102 public: 103 using resultType = typename A::resultType; 104 constexpr BacktrackingParser(const BacktrackingParser &) = default; 105 constexpr BacktrackingParser(const A &parser) : parser_{parser} {} 106 std::optional<resultType> Parse(ParseState &state) const { 107 Messages messages{std::move(state.messages())}; 108 ParseState backtrack{state}; 109 std::optional<resultType> result{parser_.Parse(state)}; 110 if (result) { 111 state.messages().Annex(std::move(messages)); 112 } else { 113 state = std::move(backtrack); 114 state.messages() = std::move(messages); 115 } 116 return result; 117 } 118 119 private: 120 const A parser_; 121 }; 122 123 template <typename A> inline constexpr auto attempt(const A &parser) { 124 return BacktrackingParser<A>{parser}; 125 } 126 127 // For any parser x, the parser returned by !x is one that succeeds when 128 // x fails, returning a useless (but present) result. !x fails when x succeeds. 129 template <typename PA> class NegatedParser { 130 public: 131 using resultType = Success; 132 constexpr NegatedParser(const NegatedParser &) = default; 133 constexpr NegatedParser(PA p) : parser_{p} {} 134 std::optional<Success> Parse(ParseState &state) const { 135 ParseState forked{state}; 136 forked.set_deferMessages(true); 137 if (parser_.Parse(forked)) { 138 return std::nullopt; 139 } 140 return Success{}; 141 } 142 143 private: 144 const PA parser_; 145 }; 146 147 template <typename PA, typename = typename PA::resultType> 148 constexpr auto operator!(PA p) { 149 return NegatedParser<PA>(p); 150 } 151 152 // For any parser x, the parser returned by lookAhead(x) is one that succeeds 153 // or fails if x does, but the state is not modified. 154 template <typename PA> class LookAheadParser { 155 public: 156 using resultType = Success; 157 constexpr LookAheadParser(const LookAheadParser &) = default; 158 constexpr LookAheadParser(PA p) : parser_{p} {} 159 std::optional<Success> Parse(ParseState &state) const { 160 ParseState forked{state}; 161 forked.set_deferMessages(true); 162 if (parser_.Parse(forked)) { 163 return Success{}; 164 } 165 return std::nullopt; 166 } 167 168 private: 169 const PA parser_; 170 }; 171 172 template <typename PA> inline constexpr auto lookAhead(PA p) { 173 return LookAheadParser<PA>{p}; 174 } 175 176 // If a is a parser, inContext("..."_en_US, a) runs it in a nested message 177 // context. 178 template <typename PA> class MessageContextParser { 179 public: 180 using resultType = typename PA::resultType; 181 constexpr MessageContextParser(const MessageContextParser &) = default; 182 constexpr MessageContextParser(MessageFixedText t, PA p) 183 : text_{t}, parser_{p} {} 184 std::optional<resultType> Parse(ParseState &state) const { 185 state.PushContext(text_); 186 std::optional<resultType> result{parser_.Parse(state)}; 187 state.PopContext(); 188 return result; 189 } 190 191 private: 192 const MessageFixedText text_; 193 const PA parser_; 194 }; 195 196 template <typename PA> 197 inline constexpr auto inContext(MessageFixedText context, PA parser) { 198 return MessageContextParser{context, parser}; 199 } 200 201 // If a is a parser, withMessage("..."_en_US, a) runs it unchanged if it 202 // succeeds, and overrides its messages with a specific one if it fails and 203 // has matched no tokens. 204 template <typename PA> class WithMessageParser { 205 public: 206 using resultType = typename PA::resultType; 207 constexpr WithMessageParser(const WithMessageParser &) = default; 208 constexpr WithMessageParser(MessageFixedText t, PA p) 209 : text_{t}, parser_{p} {} 210 std::optional<resultType> Parse(ParseState &state) const { 211 Messages messages{std::move(state.messages())}; 212 ParseState backtrack{state}; 213 state.set_anyTokenMatched(false); 214 std::optional<resultType> result{parser_.Parse(state)}; 215 bool emitMessage{false}; 216 if (result) { 217 messages.Annex(std::move(state.messages())); 218 if (backtrack.anyTokenMatched()) { 219 state.set_anyTokenMatched(); 220 } 221 } else if (state.anyTokenMatched()) { 222 emitMessage = state.messages().empty(); 223 messages.Annex(std::move(state.messages())); 224 backtrack.set_anyTokenMatched(); 225 if (state.anyDeferredMessages()) { 226 backtrack.set_anyDeferredMessages(true); 227 } 228 state = std::move(backtrack); 229 } else { 230 emitMessage = true; 231 } 232 state.messages() = std::move(messages); 233 if (emitMessage) { 234 state.Say(text_); 235 } 236 return result; 237 } 238 239 private: 240 const MessageFixedText text_; 241 const PA parser_; 242 }; 243 244 template <typename PA> 245 inline constexpr auto withMessage(MessageFixedText msg, PA parser) { 246 return WithMessageParser{msg, parser}; 247 } 248 249 // If a and b are parsers, then a >> b returns a parser that succeeds when 250 // b succeeds after a does so, but fails when either a or b does. The 251 // result is taken from b. Similarly, a / b also succeeds if both a and b 252 // do so, but the result is that returned by a. 253 template <typename PA, typename PB> class SequenceParser { 254 public: 255 using resultType = typename PB::resultType; 256 constexpr SequenceParser(const SequenceParser &) = default; 257 constexpr SequenceParser(PA pa, PB pb) : pa_{pa}, pb2_{pb} {} 258 std::optional<resultType> Parse(ParseState &state) const { 259 if (pa_.Parse(state)) { 260 return pb2_.Parse(state); 261 } else { 262 return std::nullopt; 263 } 264 } 265 266 private: 267 const PA pa_; 268 const PB pb2_; 269 }; 270 271 template <typename PA, typename PB> 272 inline constexpr auto operator>>(PA pa, PB pb) { 273 return SequenceParser<PA, PB>{pa, pb}; 274 } 275 276 template <typename PA, typename PB> class FollowParser { 277 public: 278 using resultType = typename PA::resultType; 279 constexpr FollowParser(const FollowParser &) = default; 280 constexpr FollowParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {} 281 std::optional<resultType> Parse(ParseState &state) const { 282 if (std::optional<resultType> ax{pa_.Parse(state)}) { 283 if (pb_.Parse(state)) { 284 return ax; 285 } 286 } 287 return std::nullopt; 288 } 289 290 private: 291 const PA pa_; 292 const PB pb_; 293 }; 294 295 template <typename PA, typename PB> 296 inline constexpr auto operator/(PA pa, PB pb) { 297 return FollowParser<PA, PB>{pa, pb}; 298 } 299 300 template <typename PA, typename... Ps> class AlternativesParser { 301 public: 302 using resultType = typename PA::resultType; 303 constexpr AlternativesParser(PA pa, Ps... ps) : ps_{pa, ps...} {} 304 constexpr AlternativesParser(const AlternativesParser &) = default; 305 std::optional<resultType> Parse(ParseState &state) const { 306 Messages messages{std::move(state.messages())}; 307 ParseState backtrack{state}; 308 std::optional<resultType> result{std::get<0>(ps_).Parse(state)}; 309 if constexpr (sizeof...(Ps) > 0) { 310 if (!result) { 311 ParseRest<1>(result, state, backtrack); 312 } 313 } 314 state.messages().Annex(std::move(messages)); 315 return result; 316 } 317 318 private: 319 template <int J> 320 void ParseRest(std::optional<resultType> &result, ParseState &state, 321 ParseState &backtrack) const { 322 ParseState prevState{std::move(state)}; 323 state = backtrack; 324 result = std::get<J>(ps_).Parse(state); 325 if (!result) { 326 state.CombineFailedParses(std::move(prevState)); 327 if constexpr (J < sizeof...(Ps)) { 328 ParseRest<J + 1>(result, state, backtrack); 329 } 330 } 331 } 332 333 const std::tuple<PA, Ps...> ps_; 334 }; 335 336 template <typename... Ps> inline constexpr auto first(Ps... ps) { 337 return AlternativesParser<Ps...>{ps...}; 338 } 339 340 template <typename PA, typename PB> 341 inline constexpr auto operator||(PA pa, PB pb) { 342 return AlternativesParser<PA, PB>{pa, pb}; 343 } 344 345 // If a and b are parsers, then recovery(a,b) returns a parser that succeeds if 346 // a does so, or if a fails and b succeeds. If a succeeds, b is not attempted. 347 // All messages from the first parse are retained. 348 // The two parsers must return values of the same type. 349 template <typename PA, typename PB> class RecoveryParser { 350 public: 351 using resultType = typename PA::resultType; 352 static_assert(std::is_same_v<resultType, typename PB::resultType>); 353 constexpr RecoveryParser(const RecoveryParser &) = default; 354 constexpr RecoveryParser(PA pa, PB pb) : pa_{pa}, pb3_{pb} {} 355 std::optional<resultType> Parse(ParseState &state) const { 356 bool originallyDeferred{state.deferMessages()}; 357 ParseState backtrack{state}; 358 if (!originallyDeferred && state.messages().empty() && 359 !state.anyErrorRecovery()) { 360 // Fast path. There are no messages or recovered errors in the incoming 361 // state. Attempt to parse with messages deferred, expecting that the 362 // parse will succeed silently. 363 state.set_deferMessages(true); 364 if (std::optional<resultType> ax{pa_.Parse(state)}) { 365 if (!state.anyDeferredMessages() && !state.anyErrorRecovery()) { 366 state.set_deferMessages(false); 367 return ax; 368 } 369 } 370 state = backtrack; 371 } 372 Messages messages{std::move(state.messages())}; 373 if (std::optional<resultType> ax{pa_.Parse(state)}) { 374 state.messages().Annex(std::move(messages)); 375 return ax; 376 } 377 messages.Annex(std::move(state.messages())); 378 bool hadDeferredMessages{state.anyDeferredMessages()}; 379 bool anyTokenMatched{state.anyTokenMatched()}; 380 state = std::move(backtrack); 381 state.set_deferMessages(true); 382 std::optional<resultType> bx{pb3_.Parse(state)}; 383 state.messages() = std::move(messages); 384 state.set_deferMessages(originallyDeferred); 385 if (anyTokenMatched) { 386 state.set_anyTokenMatched(); 387 } 388 if (hadDeferredMessages) { 389 state.set_anyDeferredMessages(); 390 } 391 if (bx) { 392 // Error recovery situations must also produce messages. 393 CHECK(state.anyDeferredMessages() || state.messages().AnyFatalError()); 394 state.set_anyErrorRecovery(); 395 } 396 return bx; 397 } 398 399 private: 400 const PA pa_; 401 const PB pb3_; 402 }; 403 404 template <typename PA, typename PB> 405 inline constexpr auto recovery(PA pa, PB pb) { 406 return RecoveryParser<PA, PB>{pa, pb}; 407 } 408 409 // If x is a parser, then many(x) returns a parser that always succeeds 410 // and whose value is a list, possibly empty, of the values returned from 411 // repeated application of x until it fails or does not advance the parse. 412 template <typename PA> class ManyParser { 413 using paType = typename PA::resultType; 414 415 public: 416 using resultType = std::list<paType>; 417 constexpr ManyParser(const ManyParser &) = default; 418 constexpr ManyParser(PA parser) : parser_{parser} {} 419 std::optional<resultType> Parse(ParseState &state) const { 420 resultType result; 421 auto at{state.GetLocation()}; 422 while (std::optional<paType> x{parser_.Parse(state)}) { 423 result.emplace_back(std::move(*x)); 424 if (state.GetLocation() <= at) { 425 break; // no forward progress, don't loop 426 } 427 at = state.GetLocation(); 428 } 429 return {std::move(result)}; 430 } 431 432 private: 433 const BacktrackingParser<PA> parser_; 434 }; 435 436 template <typename PA> inline constexpr auto many(PA parser) { 437 return ManyParser<PA>{parser}; 438 } 439 440 // If x is a parser, then some(x) returns a parser that succeeds if x does 441 // and whose value is a nonempty list of the values returned from repeated 442 // application of x until it fails or does not advance the parse. In other 443 // words, some(x) is a variant of many(x) that has to succeed at least once. 444 template <typename PA> class SomeParser { 445 using paType = typename PA::resultType; 446 447 public: 448 using resultType = std::list<paType>; 449 constexpr SomeParser(const SomeParser &) = default; 450 constexpr SomeParser(PA parser) : parser_{parser} {} 451 std::optional<resultType> Parse(ParseState &state) const { 452 auto start{state.GetLocation()}; 453 if (std::optional<paType> first{parser_.Parse(state)}) { 454 resultType result; 455 result.emplace_back(std::move(*first)); 456 if (state.GetLocation() > start) { 457 result.splice(result.end(), many(parser_).Parse(state).value()); 458 } 459 return {std::move(result)}; 460 } 461 return std::nullopt; 462 } 463 464 private: 465 const PA parser_; 466 }; 467 468 template <typename PA> inline constexpr auto some(PA parser) { 469 return SomeParser<PA>{parser}; 470 } 471 472 // If x is a parser, skipMany(x) is equivalent to many(x) but with no result. 473 template <typename PA> class SkipManyParser { 474 public: 475 using resultType = Success; 476 constexpr SkipManyParser(const SkipManyParser &) = default; 477 constexpr SkipManyParser(PA parser) : parser_{parser} {} 478 std::optional<Success> Parse(ParseState &state) const { 479 for (auto at{state.GetLocation()}; 480 parser_.Parse(state) && state.GetLocation() > at; 481 at = state.GetLocation()) { 482 } 483 return Success{}; 484 } 485 486 private: 487 const BacktrackingParser<PA> parser_; 488 }; 489 490 template <typename PA> inline constexpr auto skipMany(PA parser) { 491 return SkipManyParser<PA>{parser}; 492 } 493 494 // If x is a parser, skipManyFast(x) is equivalent to skipMany(x). 495 // The parser x must always advance on success and never invalidate the 496 // state on failure. 497 template <typename PA> class SkipManyFastParser { 498 public: 499 using resultType = Success; 500 constexpr SkipManyFastParser(const SkipManyFastParser &) = default; 501 constexpr SkipManyFastParser(PA parser) : parser_{parser} {} 502 std::optional<Success> Parse(ParseState &state) const { 503 while (parser_.Parse(state)) { 504 } 505 return Success{}; 506 } 507 508 private: 509 const PA parser_; 510 }; 511 512 template <typename PA> inline constexpr auto skipManyFast(PA parser) { 513 return SkipManyFastParser<PA>{parser}; 514 } 515 516 // If x is a parser returning some type A, then maybe(x) returns a 517 // parser that returns std::optional<A>, always succeeding. 518 template <typename PA> class MaybeParser { 519 using paType = typename PA::resultType; 520 521 public: 522 using resultType = std::optional<paType>; 523 constexpr MaybeParser(const MaybeParser &) = default; 524 constexpr MaybeParser(PA parser) : parser_{parser} {} 525 std::optional<resultType> Parse(ParseState &state) const { 526 if (resultType result{parser_.Parse(state)}) { 527 // permit optional<optional<...>> 528 return {std::move(result)}; 529 } 530 return resultType{}; 531 } 532 533 private: 534 const BacktrackingParser<PA> parser_; 535 }; 536 537 template <typename PA> inline constexpr auto maybe(PA parser) { 538 return MaybeParser<PA>{parser}; 539 } 540 541 // If x is a parser, then defaulted(x) returns a parser that always 542 // succeeds. When x succeeds, its result is that of x; otherwise, its 543 // result is a default-constructed value of x's result type. 544 template <typename PA> class DefaultedParser { 545 public: 546 using resultType = typename PA::resultType; 547 constexpr DefaultedParser(const DefaultedParser &) = default; 548 constexpr DefaultedParser(PA p) : parser_{p} {} 549 std::optional<resultType> Parse(ParseState &state) const { 550 std::optional<std::optional<resultType>> ax{maybe(parser_).Parse(state)}; 551 if (ax.value()) { // maybe() always succeeds 552 return std::move(*ax); 553 } 554 return resultType{}; 555 } 556 557 private: 558 const BacktrackingParser<PA> parser_; 559 }; 560 561 template <typename PA> inline constexpr auto defaulted(PA p) { 562 return DefaultedParser<PA>(p); 563 } 564 565 // If a is a parser, and f is a function mapping an rvalue of a's result type 566 // to some other type T, then applyFunction(f, a) returns a parser that succeeds 567 // iff a does, and whose result value ax has been passed through the function; 568 // the final result is that returned by the call f(std::move(ax)). 569 // 570 // Function application is generalized to functions with more than one 571 // argument with applyFunction(f, a, b, ...) succeeding if all of the parsers 572 // a, b, &c. do so, and the result is the value of applying f to their 573 // results. 574 // 575 // applyLambda(f, ...) is the same concept extended to std::function<> functors. 576 // It is not constexpr. 577 // 578 // Member function application is supported by applyMem(f, a). If the 579 // parser a succeeds and returns some value ax, the result is that returned 580 // by ax.f(). Additional parser arguments can be specified to supply their 581 // results to the member function call, so applyMem(f, a, b) succeeds if 582 // both a and b do so and returns the result of calling ax.f(std::move(bx)). 583 584 // Runs a sequence of parsers until one fails or all have succeeded. 585 // Collects their results in a std::tuple<std::optional<>...>. 586 template <typename... PARSER> 587 using ApplyArgs = std::tuple<std::optional<typename PARSER::resultType>...>; 588 589 template <typename... PARSER, std::size_t... J> 590 inline bool ApplyHelperArgs(const std::tuple<PARSER...> &parsers, 591 ApplyArgs<PARSER...> &args, ParseState &state, std::index_sequence<J...>) { 592 return (... && 593 (std::get<J>(args) = std::get<J>(parsers).Parse(state), 594 std::get<J>(args).has_value())); 595 } 596 597 // Applies a function to the arguments collected by ApplyHelperArgs. 598 template <typename RESULT, typename... PARSER> 599 using ApplicableFunctionPointer = RESULT (*)(typename PARSER::resultType &&...); 600 template <typename RESULT, typename... PARSER> 601 using ApplicableFunctionObject = 602 const std::function<RESULT(typename PARSER::resultType &&...)> &; 603 604 template <template <typename...> class FUNCTION, typename RESULT, 605 typename... PARSER, std::size_t... J> 606 inline RESULT ApplyHelperFunction(FUNCTION<RESULT, PARSER...> f, 607 ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) { 608 return f(std::move(*std::get<J>(args))...); 609 } 610 611 template <template <typename...> class FUNCTION, typename RESULT, 612 typename... PARSER> 613 class ApplyFunction { 614 using funcType = FUNCTION<RESULT, PARSER...>; 615 616 public: 617 using resultType = RESULT; 618 constexpr ApplyFunction(const ApplyFunction &) = default; 619 constexpr ApplyFunction(funcType f, PARSER... p) 620 : function_{f}, parsers_{p...} {} 621 std::optional<resultType> Parse(ParseState &state) const { 622 ApplyArgs<PARSER...> results; 623 using Sequence = std::index_sequence_for<PARSER...>; 624 if (ApplyHelperArgs(parsers_, results, state, Sequence{})) { 625 return ApplyHelperFunction<FUNCTION, RESULT, PARSER...>( 626 function_, std::move(results), Sequence{}); 627 } else { 628 return std::nullopt; 629 } 630 } 631 632 private: 633 const funcType function_; 634 const std::tuple<PARSER...> parsers_; 635 }; 636 637 template <typename RESULT, typename... PARSER> 638 inline constexpr auto applyFunction( 639 ApplicableFunctionPointer<RESULT, PARSER...> f, const PARSER &...parser) { 640 return ApplyFunction<ApplicableFunctionPointer, RESULT, PARSER...>{ 641 f, parser...}; 642 } 643 644 template <typename RESULT, typename... PARSER> 645 inline /* not constexpr */ auto applyLambda( 646 ApplicableFunctionObject<RESULT, PARSER...> f, const PARSER &...parser) { 647 return ApplyFunction<ApplicableFunctionObject, RESULT, PARSER...>{ 648 f, parser...}; 649 } 650 651 // Member function application 652 template <typename OBJPARSER, typename... PARSER> class AMFPHelper { 653 using resultType = typename OBJPARSER::resultType; 654 655 public: 656 using type = void (resultType::*)(typename PARSER::resultType &&...); 657 }; 658 template <typename OBJPARSER, typename... PARSER> 659 using ApplicableMemberFunctionPointer = 660 typename AMFPHelper<OBJPARSER, PARSER...>::type; 661 662 template <typename OBJPARSER, typename... PARSER, std::size_t... J> 663 inline auto ApplyHelperMember( 664 ApplicableMemberFunctionPointer<OBJPARSER, PARSER...> mfp, 665 ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) -> 666 typename OBJPARSER::resultType { 667 ((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...); 668 return std::get<0>(std::move(args)); 669 } 670 671 template <typename OBJPARSER, typename... PARSER> class ApplyMemberFunction { 672 using funcType = ApplicableMemberFunctionPointer<OBJPARSER, PARSER...>; 673 674 public: 675 using resultType = typename OBJPARSER::resultType; 676 constexpr ApplyMemberFunction(const ApplyMemberFunction &) = default; 677 constexpr ApplyMemberFunction(funcType f, OBJPARSER o, PARSER... p) 678 : function_{f}, parsers_{o, p...} {} 679 std::optional<resultType> Parse(ParseState &state) const { 680 ApplyArgs<OBJPARSER, PARSER...> results; 681 using Sequence1 = std::index_sequence_for<OBJPARSER, PARSER...>; 682 using Sequence2 = std::index_sequence_for<PARSER...>; 683 if (ApplyHelperArgs(parsers_, results, state, Sequence1{})) { 684 return ApplyHelperMember<OBJPARSER, PARSER...>( 685 function_, std::move(results), Sequence2{}); 686 } else { 687 return std::nullopt; 688 } 689 } 690 691 private: 692 const funcType function_; 693 const std::tuple<OBJPARSER, PARSER...> parsers_; 694 }; 695 696 template <typename OBJPARSER, typename... PARSER> 697 inline constexpr auto applyMem( 698 ApplicableMemberFunctionPointer<OBJPARSER, PARSER...> mfp, 699 const OBJPARSER &objParser, PARSER... parser) { 700 return ApplyMemberFunction<OBJPARSER, PARSER...>{mfp, objParser, parser...}; 701 } 702 703 // As is done with function application via applyFunction() above, class 704 // instance construction can also be based upon the results of successful 705 // parses. For some type T and zero or more parsers a, b, &c., the call 706 // construct<T>(a, b, ...) returns a parser that succeeds if all of 707 // its argument parsers do so in succession, and whose result is an 708 // instance of T constructed upon the values they returned. 709 // With a single argument that is a parser with no usable value, 710 // construct<T>(p) invokes T's default nullary constructor (T(){}). 711 // (This means that "construct<T>(Foo >> Bar >> ok)" is functionally 712 // equivalent to "Foo >> Bar >> construct<T>()", but I'd like to hold open 713 // the opportunity to make construct<> capture source provenance all of the 714 // time, and the first form will then lead to better error positioning.) 715 716 template <typename RESULT, typename... PARSER, std::size_t... J> 717 inline RESULT ApplyHelperConstructor( 718 ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) { 719 return RESULT{std::move(*std::get<J>(args))...}; 720 } 721 722 template <typename RESULT, typename... PARSER> class ApplyConstructor { 723 public: 724 using resultType = RESULT; 725 constexpr ApplyConstructor(const ApplyConstructor &) = default; 726 constexpr explicit ApplyConstructor(PARSER... p) : parsers_{p...} {} 727 std::optional<resultType> Parse(ParseState &state) const { 728 if constexpr (sizeof...(PARSER) == 0) { 729 return RESULT{}; 730 } else { 731 if constexpr (sizeof...(PARSER) == 1) { 732 return ParseOne(state); 733 } else { 734 ApplyArgs<PARSER...> results; 735 using Sequence = std::index_sequence_for<PARSER...>; 736 if (ApplyHelperArgs(parsers_, results, state, Sequence{})) { 737 return ApplyHelperConstructor<RESULT, PARSER...>( 738 std::move(results), Sequence{}); 739 } 740 } 741 return std::nullopt; 742 } 743 } 744 745 private: 746 std::optional<resultType> ParseOne(ParseState &state) const { 747 if constexpr (std::is_same_v<Success, typename PARSER::resultType...>) { 748 if (std::get<0>(parsers_).Parse(state)) { 749 return RESULT{}; 750 } 751 } else if (auto arg{std::get<0>(parsers_).Parse(state)}) { 752 return RESULT{std::move(*arg)}; 753 } 754 return std::nullopt; 755 } 756 757 const std::tuple<PARSER...> parsers_; 758 }; 759 760 template <typename RESULT, typename... PARSER> 761 inline constexpr auto construct(PARSER... p) { 762 return ApplyConstructor<RESULT, PARSER...>{p...}; 763 } 764 765 // For a parser p, indirect(p) returns a parser that builds an indirect 766 // reference to p's return type. 767 template <typename PA> inline constexpr auto indirect(PA p) { 768 return construct<common::Indirection<typename PA::resultType>>(p); 769 } 770 771 // If a and b are parsers, then nonemptySeparated(a, b) returns a parser 772 // that succeeds if a does. If a succeeds, it then applies many(b >> a). 773 // The result is the list of the values returned from all of the applications 774 // of a. 775 template <typename T> 776 common::IfNoLvalue<std::list<T>, T> prepend(T &&head, std::list<T> &&rest) { 777 rest.push_front(std::move(head)); 778 return std::move(rest); 779 } 780 781 template <typename PA, typename PB> class NonemptySeparated { 782 private: 783 using paType = typename PA::resultType; 784 785 public: 786 using resultType = std::list<paType>; 787 constexpr NonemptySeparated(const NonemptySeparated &) = default; 788 constexpr NonemptySeparated(PA p, PB sep) : parser_{p}, separator_{sep} {} 789 std::optional<resultType> Parse(ParseState &state) const { 790 return applyFunction<std::list<paType>>( 791 prepend<paType>, parser_, many(separator_ >> parser_)) 792 .Parse(state); 793 } 794 795 private: 796 const PA parser_; 797 const PB separator_; 798 }; 799 800 template <typename PA, typename PB> 801 inline constexpr auto nonemptySeparated(PA p, PB sep) { 802 return NonemptySeparated<PA, PB>{p, sep}; 803 } 804 805 // ok is a parser that always succeeds. It is useful when a parser 806 // must discard its result in order to be compatible in type with other 807 // parsers in an alternative, e.g. "x >> ok || y >> ok" is type-safe even 808 // when x and y have distinct result types. 809 struct OkParser { 810 using resultType = Success; 811 constexpr OkParser() {} 812 static constexpr std::optional<Success> Parse(ParseState &) { 813 return Success{}; 814 } 815 }; 816 constexpr OkParser ok; 817 818 // A variant of recovery() above for convenience. 819 template <typename PA, typename PB> 820 inline constexpr auto localRecovery(MessageFixedText msg, PA pa, PB pb) { 821 return recovery(withMessage(msg, pa), pb >> pure<typename PA::resultType>()); 822 } 823 824 // nextCh is a parser that succeeds if the parsing state is not 825 // at the end of its input, returning the next character location and 826 // advancing the parse when it does so. 827 struct NextCh { 828 using resultType = const char *; 829 constexpr NextCh() {} 830 std::optional<const char *> Parse(ParseState &state) const { 831 if (std::optional<const char *> result{state.GetNextChar()}) { 832 return result; 833 } 834 state.Say("end of file"_err_en_US); 835 return std::nullopt; 836 } 837 }; 838 839 constexpr NextCh nextCh; 840 841 // If a is a parser for some nonstandard language feature LF, extension<LF>(a) 842 // is a parser that optionally enabled, sets a strict conformance violation 843 // flag, and may emit a warning message, if those are enabled. 844 template <LanguageFeature LF, typename PA> class NonstandardParser { 845 public: 846 using resultType = typename PA::resultType; 847 constexpr NonstandardParser(const NonstandardParser &) = default; 848 constexpr NonstandardParser(PA parser, MessageFixedText msg) 849 : parser_{parser}, message_{msg} {} 850 std::optional<resultType> Parse(ParseState &state) const { 851 if (UserState * ustate{state.userState()}) { 852 if (!ustate->features().IsEnabled(LF)) { 853 return std::nullopt; 854 } 855 } 856 auto at{state.GetLocation()}; 857 auto result{parser_.Parse(state)}; 858 if (result) { 859 state.Nonstandard( 860 CharBlock{at, std::max(state.GetLocation(), at + 1)}, LF, message_); 861 } 862 return result; 863 } 864 865 private: 866 const PA parser_; 867 const MessageFixedText message_; 868 }; 869 870 template <LanguageFeature LF, typename PA> 871 inline constexpr auto extension(MessageFixedText feature, PA parser) { 872 return NonstandardParser<LF, PA>(parser, feature); 873 } 874 875 // If a is a parser for some deprecated or deleted language feature LF, 876 // deprecated<LF>(a) is a parser that is optionally enabled, sets a strict 877 // conformance violation flag, and may emit a warning message, if enabled. 878 template <LanguageFeature LF, typename PA> class DeprecatedParser { 879 public: 880 using resultType = typename PA::resultType; 881 constexpr DeprecatedParser(const DeprecatedParser &) = default; 882 constexpr DeprecatedParser(PA parser) : parser_{parser} {} 883 std::optional<resultType> Parse(ParseState &state) const { 884 if (UserState * ustate{state.userState()}) { 885 if (!ustate->features().IsEnabled(LF)) { 886 return std::nullopt; 887 } 888 } 889 auto at{state.GetLocation()}; 890 auto result{parser_.Parse(state)}; 891 if (result) { 892 state.Nonstandard(CharBlock{at, state.GetLocation()}, LF, 893 "deprecated usage"_port_en_US); 894 } 895 return result; 896 } 897 898 private: 899 const PA parser_; 900 }; 901 902 template <LanguageFeature LF, typename PA> 903 inline constexpr auto deprecated(PA parser) { 904 return DeprecatedParser<LF, PA>(parser); 905 } 906 907 // Parsing objects with "source" members. 908 template <typename PA> class SourcedParser { 909 public: 910 using resultType = typename PA::resultType; 911 constexpr SourcedParser(const SourcedParser &) = default; 912 constexpr SourcedParser(PA parser) : parser_{parser} {} 913 std::optional<resultType> Parse(ParseState &state) const { 914 const char *start{state.GetLocation()}; 915 auto result{parser_.Parse(state)}; 916 if (result) { 917 const char *end{state.GetLocation()}; 918 for (; start < end && start[0] == ' '; ++start) { 919 } 920 for (; start < end && end[-1] == ' '; --end) { 921 } 922 result->source = CharBlock{start, end}; 923 } 924 return result; 925 } 926 927 private: 928 const PA parser_; 929 }; 930 931 template <typename PA> inline constexpr auto sourced(PA parser) { 932 return SourcedParser<PA>{parser}; 933 } 934 } // namespace Fortran::parser 935 #endif // FORTRAN_PARSER_BASIC_PARSERS_H_ 936