9#ifndef FORTRAN_PARSER_BASIC_PARSERS_H_
10#define FORTRAN_PARSER_BASIC_PARSERS_H_
25#include "flang/Common/idioms.h"
26#include "flang/Common/indirection.h"
27#include "flang/Parser/char-block.h"
28#include "flang/Parser/message.h"
29#include "flang/Parser/parse-state.h"
30#include "flang/Parser/provenance.h"
31#include "flang/Parser/user-state.h"
32#include "flang/Support/Fortran-features.h"
47template <
typename A>
class FailParser {
50 constexpr FailParser(
const FailParser &) =
default;
52 std::optional<A> Parse(
ParseState &state)
const {
61template <
typename A = Success>
inline constexpr auto fail(
MessageFixedText t) {
70template <
typename A>
class PureParser {
73 constexpr PureParser(
const PureParser &) =
default;
74 constexpr explicit PureParser(A &&x) : value_(std::move(x)) {}
75 std::optional<A> Parse(
ParseState &)
const {
return value_; }
81template <
typename A>
inline constexpr auto pure(A x) {
85template <
typename A>
class PureDefaultParser {
88 constexpr PureDefaultParser(
const PureDefaultParser &) =
default;
89 constexpr PureDefaultParser() {}
90 std::optional<A> Parse(
ParseState &)
const {
return std::make_optional<A>(); }
93template <
typename A>
inline constexpr auto pure() {
99template <
typename A>
class BacktrackingParser {
101 using resultType =
typename A::resultType;
102 constexpr BacktrackingParser(
const BacktrackingParser &) =
default;
103 constexpr BacktrackingParser(
const A &
parser) : parser_{
parser} {}
104 std::optional<resultType> Parse(
ParseState &state)
const {
105 Messages messages{std::move(state.messages())};
107 std::optional<resultType> result{parser_.Parse(state)};
109 state.messages().Annex(std::move(messages));
111 state = std::move(backtrack);
112 state.messages() = std::move(messages);
121template <
typename A>
inline constexpr auto attempt(
const A &
parser) {
127template <
typename PA>
class NegatedParser {
130 constexpr NegatedParser(
const NegatedParser &) =
default;
131 constexpr NegatedParser(PA p) : parser_{p} {}
132 std::optional<Success> Parse(
ParseState &state)
const {
134 forked.set_deferMessages(
true);
135 if (parser_.Parse(forked)) {
145template <
typename PA,
typename =
typename PA::resultType>
146constexpr auto operator!(PA p) {
152template <
typename PA>
class LookAheadParser {
155 constexpr LookAheadParser(
const LookAheadParser &) =
default;
156 constexpr LookAheadParser(PA p) : parser_{p} {}
157 std::optional<Success> Parse(
ParseState &state)
const {
159 forked.set_deferMessages(
true);
160 if (parser_.Parse(forked)) {
170template <
typename PA>
inline constexpr auto lookAhead(PA p) {
176template <
typename PA>
class MessageContextParser {
178 using resultType =
typename PA::resultType;
179 constexpr MessageContextParser(
const MessageContextParser &) =
default;
181 : text_{t}, parser_{p} {}
182 std::optional<resultType> Parse(
ParseState &state)
const {
183 state.PushContext(text_);
184 std::optional<resultType> result{parser_.Parse(state)};
194template <
typename PA>
202template <
typename PA>
class WithMessageParser {
204 using resultType =
typename PA::resultType;
205 constexpr WithMessageParser(
const WithMessageParser &) =
default;
207 : text_{t}, parser_{p} {}
208 std::optional<resultType> Parse(
ParseState &state)
const {
209 if (state.deferMessages()) {
210 std::optional<resultType> result{parser_.Parse(state)};
212 state.set_anyDeferredMessages();
216 Messages messages{std::move(state.messages())};
217 bool hadAnyTokenMatched{state.anyTokenMatched()};
218 state.set_anyTokenMatched(
false);
219 std::optional<resultType> result{parser_.Parse(state)};
220 bool emitMessage{
false};
222 messages.Annex(std::move(state.messages()));
223 if (hadAnyTokenMatched) {
224 state.set_anyTokenMatched();
226 }
else if (state.anyTokenMatched()) {
227 emitMessage = state.messages().empty();
228 messages.Annex(std::move(state.messages()));
231 if (hadAnyTokenMatched) {
232 state.set_anyTokenMatched();
235 state.messages() = std::move(messages);
247template <
typename PA>
256template <
typename PA,
typename PB>
class SequenceParser {
258 using resultType =
typename PB::resultType;
259 constexpr SequenceParser(
const SequenceParser &) =
default;
260 constexpr SequenceParser(PA pa, PB pb) : pa_{pa}, pb2_{pb} {}
261 std::optional<resultType> Parse(
ParseState &state)
const {
262 if (pa_.Parse(state)) {
263 return pb2_.Parse(state);
274template <
typename PA,
typename PB>
275inline constexpr auto operator>>(PA pa, PB pb) {
279template <
typename PA,
typename PB>
class FollowParser {
281 using resultType =
typename PA::resultType;
282 constexpr FollowParser(
const FollowParser &) =
default;
283 constexpr FollowParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
284 std::optional<resultType> Parse(
ParseState &state)
const {
285 if (std::optional<resultType> ax{pa_.Parse(state)}) {
286 if (pb_.Parse(state)) {
298template <
typename PA,
typename PB>
299inline constexpr auto operator/(PA pa, PB pb) {
303template <
typename PA,
typename... Ps>
class AlternativesParser {
305 using resultType =
typename PA::resultType;
306 constexpr AlternativesParser(PA pa, Ps... ps) : ps_{pa, ps...} {}
307 constexpr AlternativesParser(
const AlternativesParser &) =
default;
308 std::optional<resultType> Parse(
ParseState &state)
const {
309 Messages messages{std::move(state.messages())};
311 std::optional<resultType> result{std::get<0>(ps_).Parse(state)};
312 if constexpr (
sizeof...(Ps) > 0) {
314 ParseRest<1>(result, state, backtrack);
317 state.messages().Annex(std::move(messages));
323 void ParseRest(std::optional<resultType> &result,
ParseState &state,
327 result = std::get<J>(ps_).Parse(state);
329 state.CombineFailedParses(std::move(prevState));
330 if constexpr (J <
sizeof...(Ps)) {
331 ParseRest<J + 1>(result, state, backtrack);
336 const std::tuple<PA, Ps...> ps_;
339template <
typename... Ps>
inline constexpr auto first(Ps... ps) {
343template <
typename PA,
typename PB>
344inline constexpr auto operator||(PA pa, PB pb) {
345 return AlternativesParser<PA, PB>{pa, pb};
352template <
typename PA,
typename PB>
class RecoveryParser {
354 using resultType =
typename PA::resultType;
355 static_assert(std::is_same_v<resultType, typename PB::resultType>);
356 constexpr RecoveryParser(
const RecoveryParser &) =
default;
357 constexpr RecoveryParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
358 std::optional<resultType> Parse(
ParseState &state)
const {
359 bool originallyDeferred{state.deferMessages()};
361 if (!originallyDeferred && state.messages().empty() &&
362 !state.anyErrorRecovery()) {
366 state.set_deferMessages(
true);
367 if (std::optional<resultType> ax{pa_.Parse(state)}) {
368 if (!state.anyDeferredMessages() && !state.anyErrorRecovery()) {
369 state.set_deferMessages(
false);
375 Messages messages{std::move(state.messages())};
376 if (std::optional<resultType> ax{pa_.Parse(state)}) {
377 state.messages().Annex(std::move(messages));
380 messages.Annex(std::move(state.messages()));
381 bool hadDeferredMessages{state.anyDeferredMessages()};
382 bool anyTokenMatched{state.anyTokenMatched()};
383 state = std::move(backtrack);
384 state.set_deferMessages(
true);
385 std::optional<resultType> bx{pb_.Parse(state)};
386 state.messages() = std::move(messages);
387 state.set_deferMessages(originallyDeferred);
388 if (anyTokenMatched) {
389 state.set_anyTokenMatched();
391 if (hadDeferredMessages) {
392 state.set_anyDeferredMessages();
396 CHECK(hadDeferredMessages || state.messages().AnyFatalError());
397 state.set_anyErrorRecovery();
407template <
typename PA,
typename PB>
408inline constexpr auto recovery(PA pa, PB pb) {
415template <
typename PA>
class ManyParser {
416 using paType =
typename PA::resultType;
419 using resultType = std::list<paType>;
420 constexpr ManyParser(
const ManyParser &) =
default;
422 std::optional<resultType> Parse(
ParseState &state)
const {
424 auto at{state.GetLocation()};
425 while (std::optional<paType> x{parser_.Parse(state)}) {
426 result.emplace_back(std::move(*x));
427 if (state.GetLocation() <= at) {
430 at = state.GetLocation();
432 return {std::move(result)};
439template <
typename PA>
inline constexpr auto many(PA
parser) {
447template <
typename PA>
class SomeParser {
448 using paType =
typename PA::resultType;
451 using resultType = std::list<paType>;
452 constexpr SomeParser(
const SomeParser &) =
default;
454 std::optional<resultType> Parse(
ParseState &state)
const {
455 auto start{state.GetLocation()};
456 if (std::optional<paType> first{parser_.Parse(state)}) {
458 result.emplace_back(std::move(*first));
459 if (state.GetLocation() > start) {
460 result.splice(result.end(), many(parser_).Parse(state).value());
462 return {std::move(result)};
471template <
typename PA>
inline constexpr auto some(PA
parser) {
476template <
typename PA>
class SkipManyParser {
479 constexpr SkipManyParser(
const SkipManyParser &) =
default;
480 constexpr SkipManyParser(PA
parser) : parser_{
parser} {}
481 std::optional<Success> Parse(
ParseState &state)
const {
482 for (
auto at{state.GetLocation()};
483 parser_.Parse(state) && state.GetLocation() > at;
484 at = state.GetLocation()) {
493template <
typename PA>
inline constexpr auto skipMany(PA
parser) {
500template <
typename PA>
class SkipManyFastParser {
503 constexpr SkipManyFastParser(
const SkipManyFastParser &) =
default;
504 constexpr SkipManyFastParser(PA
parser) : parser_{
parser} {}
505 std::optional<Success> Parse(
ParseState &state)
const {
506 while (parser_.Parse(state)) {
515template <
typename PA>
inline constexpr auto skipManyFast(PA
parser) {
521template <
typename PA>
class MaybeParser {
522 using paType =
typename PA::resultType;
525 using resultType = std::optional<paType>;
526 constexpr MaybeParser(
const MaybeParser &) =
default;
528 std::optional<resultType> Parse(
ParseState &state)
const {
529 if (resultType result{parser_.Parse(state)}) {
531 return {std::move(result)};
540template <
typename PA>
inline constexpr auto maybe(PA
parser) {
547template <
typename PA>
class DefaultedParser {
549 using resultType =
typename PA::resultType;
550 constexpr DefaultedParser(
const DefaultedParser &) =
default;
551 constexpr DefaultedParser(PA p) : parser_{p} {}
552 std::optional<resultType> Parse(
ParseState &state)
const {
553 std::optional<std::optional<resultType>> ax{maybe(parser_).Parse(state)};
555 return std::move(*ax);
564template <
typename PA>
inline constexpr auto defaulted(PA p) {
589template <
typename... PARSER>
590using ApplyArgs = std::tuple<std::optional<typename PARSER::resultType>...>;
592template <
typename... PARSER, std::size_t... J>
593inline bool ApplyHelperArgs(
const std::tuple<PARSER...> &parsers,
594 ApplyArgs<PARSER...> &args, ParseState &state, std::index_sequence<J...>) {
596 (std::get<J>(args) = std::get<J>(parsers).Parse(state),
597 std::get<J>(args).has_value()));
601template <
typename RESULT,
typename... PARSER>
602using ApplicableFunctionPointer = RESULT (*)(
typename PARSER::resultType &&...);
603template <
typename RESULT,
typename... PARSER>
604using ApplicableFunctionObject =
605 const std::function<RESULT(
typename PARSER::resultType &&...)> &;
607template <
template <
typename...>
class FUNCTION,
typename RESULT,
608 typename... PARSER, std::size_t... J>
609inline RESULT ApplyHelperFunction(FUNCTION<RESULT, PARSER...> f,
610 ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) {
611 return f(std::move(*std::get<J>(args))...);
614template <
template <
typename...>
class FUNCTION,
typename RESULT,
617 using funcType = FUNCTION<RESULT, PARSER...>;
620 using resultType = RESULT;
621 constexpr ApplyFunction(
const ApplyFunction &) =
default;
622 constexpr ApplyFunction(funcType f, PARSER... p)
623 : function_{f}, parsers_{p...} {}
624 std::optional<resultType> Parse(
ParseState &state)
const {
625 ApplyArgs<PARSER...> results;
626 using Sequence = std::index_sequence_for<PARSER...>;
627 if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
628 return ApplyHelperFunction<FUNCTION, RESULT, PARSER...>(
629 function_, std::move(results), Sequence{});
636 const funcType function_;
637 const std::tuple<PARSER...> parsers_;
640template <
typename RESULT,
typename... PARSER>
641inline constexpr auto applyFunction(
642 ApplicableFunctionPointer<RESULT, PARSER...> f,
const PARSER &...
parser) {
643 return ApplyFunction<ApplicableFunctionPointer, RESULT, PARSER...>{
647template <
typename RESULT,
typename... PARSER>
648inline auto applyLambda(
649 ApplicableFunctionObject<RESULT, PARSER...> f,
const PARSER &...parser) {
650 return ApplyFunction<ApplicableFunctionObject, RESULT, PARSER...>{
655template <
typename MEMFUNC,
typename OBJPARSER,
typename... PARSER,
657inline auto ApplyHelperMember(MEMFUNC mfp,
658 ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) {
659 return ((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...);
662template <
typename MEMFUNC,
typename OBJPARSER,
typename... PARSER>
663class ApplyMemberFunction {
664 static_assert(std::is_member_function_pointer_v<MEMFUNC>);
665 using funcType = MEMFUNC;
669 std::invoke_result_t<MEMFUNC,
typename OBJPARSER::resultType, PARSER...>;
671 constexpr ApplyMemberFunction(
const ApplyMemberFunction &) =
default;
672 constexpr ApplyMemberFunction(MEMFUNC f, OBJPARSER o, PARSER... p)
673 : function_{f}, parsers_{o, p...} {}
674 std::optional<resultType> Parse(
ParseState &state)
const {
675 ApplyArgs<OBJPARSER, PARSER...> results;
676 using Sequence1 = std::index_sequence_for<OBJPARSER, PARSER...>;
677 using Sequence2 = std::index_sequence_for<PARSER...>;
678 if (ApplyHelperArgs(parsers_, results, state, Sequence1{})) {
679 return ApplyHelperMember<MEMFUNC, OBJPARSER, PARSER...>(
680 function_, std::move(results), Sequence2{});
687 const funcType function_;
688 const std::tuple<OBJPARSER, PARSER...> parsers_;
691template <
typename MEMFUNC,
typename OBJPARSER,
typename... PARSER>
692inline constexpr auto applyMem(
693 MEMFUNC memfn,
const OBJPARSER &objParser, PARSER...
parser) {
695 memfn, objParser,
parser...};
711template <
typename RESULT,
typename... PARSER, std::size_t... J>
712inline RESULT ApplyHelperConstructor(
713 ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) {
714 return RESULT{std::move(*std::get<J>(args))...};
717template <
typename RESULT,
typename... PARSER>
class ApplyConstructor {
719 using resultType = RESULT;
720 constexpr ApplyConstructor(
const ApplyConstructor &) =
default;
721 constexpr explicit ApplyConstructor(PARSER... p) : parsers_{p...} {}
722 std::optional<resultType> Parse(
ParseState &state)
const {
723 if constexpr (
sizeof...(PARSER) == 0) {
726 if constexpr (
sizeof...(PARSER) == 1) {
727 return ParseOne(state);
729 ApplyArgs<PARSER...> results;
730 using Sequence = std::index_sequence_for<PARSER...>;
731 if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
732 return ApplyHelperConstructor<RESULT, PARSER...>(
733 std::move(results), Sequence{});
741 std::optional<resultType> ParseOne(
ParseState &state)
const {
742 if constexpr (std::is_same_v<
Success,
typename PARSER::resultType...>) {
743 if (std::get<0>(parsers_).Parse(state)) {
746 }
else if (
auto arg{std::get<0>(parsers_).Parse(state)}) {
747 return RESULT{std::move(*arg)};
752 const std::tuple<PARSER...> parsers_;
755template <
typename RESULT,
typename... PARSER>
756inline constexpr auto construct(PARSER... p) {
762template <
typename PA>
inline constexpr auto indirect(PA p) {
763 return construct<common::Indirection<typename PA::resultType>>(p);
771common::IfNoLvalue<std::list<T>, T> prepend(T &&head, std::list<T> &&rest) {
772 rest.push_front(std::move(head));
773 return std::move(rest);
776template <
typename PA,
typename PB>
class NonemptySeparated {
778 using paType =
typename PA::resultType;
781 using resultType = std::list<paType>;
782 constexpr NonemptySeparated(
const NonemptySeparated &) =
default;
783 constexpr NonemptySeparated(PA p, PB sep) : parser_{p}, separator_{sep} {}
784 std::optional<resultType> Parse(
ParseState &state)
const {
785 return applyFunction<std::list<paType>>(
786 prepend<paType>, parser_, many(separator_ >> parser_))
795template <
typename PA,
typename PB>
796inline constexpr auto nonemptySeparated(PA p, PB sep) {
806 constexpr OkParser() {}
807 static constexpr std::optional<Success> Parse(
ParseState &) {
814template <
typename PA,
typename PB>
816 return recovery(withMessage(msg, pa), pb >> pure<typename PA::resultType>());
823 using resultType =
const char *;
824 constexpr NextCh() {}
825 std::optional<const char *> Parse(
ParseState &state)
const {
826 if (std::optional<const char *> result{state.GetNextChar()}) {
829 state.Say(MessageFixedText::endOfFileMessage);
839template <LanguageFeature LF,
typename PA>
class NonstandardParser {
841 using resultType =
typename PA::resultType;
842 constexpr NonstandardParser(
const NonstandardParser &) =
default;
844 : parser_{
parser}, message_{msg} {}
845 constexpr NonstandardParser(PA
parser) : parser_{
parser} {}
846 std::optional<resultType> Parse(
ParseState &state)
const {
847 if (
UserState * ustate{state.userState()}) {
848 if (!ustate->features().IsEnabled(LF)) {
852 auto at{state.GetLocation()};
853 auto result{parser_.Parse(state)};
854 if (result && !message_.empty()) {
856 CharBlock{at, std::max(state.GetLocation(), at + 1)}, LF, message_);
866template <LanguageFeature LF,
typename PA>
871template <LanguageFeature LF,
typename PA>
872inline constexpr auto extension(PA
parser) {
873 return NonstandardParser<LF, PA>(
parser);
879template <LanguageFeature LF,
typename PA>
class DeprecatedParser {
881 using resultType =
typename PA::resultType;
882 constexpr DeprecatedParser(
const DeprecatedParser &) =
default;
883 constexpr DeprecatedParser(PA
parser) : parser_{
parser} {}
884 std::optional<resultType> Parse(
ParseState &state)
const {
885 if (
UserState * ustate{state.userState()}) {
886 if (!ustate->features().IsEnabled(LF)) {
890 auto at{state.GetLocation()};
891 auto result{parser_.Parse(state)};
893 state.Nonstandard(
CharBlock{at, state.GetLocation()}, LF,
894 "deprecated usage"_port_en_US);
903template <LanguageFeature LF,
typename PA>
904inline constexpr auto deprecated(PA
parser) {
909template <
typename PA>
class SourcedParser {
911 using resultType =
typename PA::resultType;
912 constexpr SourcedParser(
const SourcedParser &) =
default;
914 std::optional<resultType> Parse(
ParseState &state)
const {
915 const char *start{state.GetLocation()};
916 auto result{parser_.Parse(state)};
918 const char *end{state.GetLocation()};
919 for (; start < end && start[0] ==
' '; ++start) {
921 for (; start < end && end[-1] ==
' '; --end) {
932template <
typename PA>
inline constexpr auto sourced(PA
parser) {
Definition basic-parsers.h:303
Definition basic-parsers.h:717
Definition basic-parsers.h:616
Definition basic-parsers.h:663
Definition basic-parsers.h:99
Definition char-block.h:26
Definition basic-parsers.h:547
Definition basic-parsers.h:879
Definition basic-parsers.h:47
Definition basic-parsers.h:279
Definition basic-parsers.h:152
Definition basic-parsers.h:415
Definition basic-parsers.h:521
Definition basic-parsers.h:176
Definition basic-parsers.h:127
Definition basic-parsers.h:776
Definition basic-parsers.h:839
Definition parse-state.h:31
Definition basic-parsers.h:85
Definition basic-parsers.h:70
Definition basic-parsers.h:352
Definition basic-parsers.h:256
Definition basic-parsers.h:500
Definition basic-parsers.h:476
Definition basic-parsers.h:447
Definition basic-parsers.h:909
Definition user-state.h:32
Definition user-state.h:34
Definition basic-parsers.h:202
Definition check-expression.h:19
Definition basic-parsers.h:822
Definition basic-parsers.h:804