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 const char *start{state.GetLocation()};
218 bool hadAnyTokenMatched{state.anyTokenMatched()};
219 state.set_anyTokenMatched(
false);
220 std::optional<resultType> result{parser_.Parse(state)};
221 bool emitMessage{
false};
222 bool emitAtStart{
false};
224 messages.Annex(std::move(state.messages()));
225 if (hadAnyTokenMatched) {
226 state.set_anyTokenMatched();
228 }
else if (state.anyTokenMatched()) {
229 emitMessage = state.messages().empty();
230 messages.Annex(std::move(state.messages()));
234 if (hadAnyTokenMatched) {
235 state.set_anyTokenMatched();
238 state.messages() = std::move(messages);
241 state.Say(start, text_);
254template <
typename PA>
263template <
typename PA,
typename PB>
class SequenceParser {
265 using resultType =
typename PB::resultType;
266 constexpr SequenceParser(
const SequenceParser &) =
default;
267 constexpr SequenceParser(PA pa, PB pb) : pa_{pa}, pb2_{pb} {}
268 std::optional<resultType> Parse(
ParseState &state)
const {
269 if (pa_.Parse(state)) {
270 return pb2_.Parse(state);
281template <
typename PA,
typename PB>
282inline constexpr auto operator>>(PA pa, PB pb) {
286template <
typename PA,
typename PB>
class FollowParser {
288 using resultType =
typename PA::resultType;
289 constexpr FollowParser(
const FollowParser &) =
default;
290 constexpr FollowParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
291 std::optional<resultType> Parse(
ParseState &state)
const {
292 if (std::optional<resultType> ax{pa_.Parse(state)}) {
293 if (pb_.Parse(state)) {
305template <
typename PA,
typename PB>
306inline constexpr auto operator/(PA pa, PB pb) {
310template <
typename PA,
typename... Ps>
class AlternativesParser {
312 using resultType =
typename PA::resultType;
313 constexpr AlternativesParser(PA pa, Ps... ps) : ps_{pa, ps...} {}
314 constexpr AlternativesParser(
const AlternativesParser &) =
default;
315 std::optional<resultType> Parse(
ParseState &state)
const {
316 Messages messages{std::move(state.messages())};
318 std::optional<resultType> result{std::get<0>(ps_).Parse(state)};
319 if constexpr (
sizeof...(Ps) > 0) {
321 ParseRest<1>(result, state, backtrack);
324 state.messages().Annex(std::move(messages));
330 void ParseRest(std::optional<resultType> &result,
ParseState &state,
334 result = std::get<J>(ps_).Parse(state);
336 state.CombineFailedParses(std::move(prevState));
337 if constexpr (J <
sizeof...(Ps)) {
338 ParseRest<J + 1>(result, state, backtrack);
343 const std::tuple<PA, Ps...> ps_;
346template <
typename... Ps>
inline constexpr auto first(Ps... ps) {
350template <
typename PA,
typename PB>
351inline constexpr auto operator||(PA pa, PB pb) {
352 return AlternativesParser<PA, PB>{pa, pb};
359template <
typename PA,
typename PB>
class RecoveryParser {
361 using resultType =
typename PA::resultType;
362 static_assert(std::is_same_v<resultType, typename PB::resultType>);
363 constexpr RecoveryParser(
const RecoveryParser &) =
default;
364 constexpr RecoveryParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
365 std::optional<resultType> Parse(
ParseState &state)
const {
366 bool originallyDeferred{state.deferMessages()};
368 if (!originallyDeferred && state.messages().empty() &&
369 !state.anyErrorRecovery()) {
373 state.set_deferMessages(
true);
374 if (std::optional<resultType> ax{pa_.Parse(state)}) {
375 if (!state.anyDeferredMessages() && !state.anyErrorRecovery()) {
376 state.set_deferMessages(
false);
382 Messages messages{std::move(state.messages())};
383 if (std::optional<resultType> ax{pa_.Parse(state)}) {
384 state.messages().Annex(std::move(messages));
387 messages.Annex(std::move(state.messages()));
388 bool hadDeferredMessages{state.anyDeferredMessages()};
389 bool anyTokenMatched{state.anyTokenMatched()};
390 state = std::move(backtrack);
391 state.set_deferMessages(
true);
392 std::optional<resultType> bx{pb_.Parse(state)};
393 state.messages() = std::move(messages);
394 state.set_deferMessages(originallyDeferred);
395 if (anyTokenMatched) {
396 state.set_anyTokenMatched();
398 if (hadDeferredMessages) {
399 state.set_anyDeferredMessages();
403 CHECK(hadDeferredMessages || state.messages().AnyFatalError());
404 state.set_anyErrorRecovery();
414template <
typename PA,
typename PB>
415inline constexpr auto recovery(PA pa, PB pb) {
422template <
typename PA>
class ManyParser {
423 using paType =
typename PA::resultType;
426 using resultType = std::list<paType>;
427 constexpr ManyParser(
const ManyParser &) =
default;
429 std::optional<resultType> Parse(
ParseState &state)
const {
431 auto at{state.GetLocation()};
432 while (std::optional<paType> x{parser_.Parse(state)}) {
433 result.emplace_back(std::move(*x));
434 if (state.GetLocation() <= at) {
437 at = state.GetLocation();
439 return {std::move(result)};
446template <
typename PA>
inline constexpr auto many(PA
parser) {
454template <
typename PA>
class SomeParser {
455 using paType =
typename PA::resultType;
458 using resultType = std::list<paType>;
459 constexpr SomeParser(
const SomeParser &) =
default;
461 std::optional<resultType> Parse(
ParseState &state)
const {
462 auto start{state.GetLocation()};
463 if (std::optional<paType> first{parser_.Parse(state)}) {
465 result.emplace_back(std::move(*first));
466 if (state.GetLocation() > start) {
467 result.splice(result.end(), many(parser_).Parse(state).value());
469 return {std::move(result)};
478template <
typename PA>
inline constexpr auto some(PA
parser) {
483template <
typename PA>
class SkipManyParser {
486 constexpr SkipManyParser(
const SkipManyParser &) =
default;
487 constexpr SkipManyParser(PA
parser) : parser_{
parser} {}
488 std::optional<Success> Parse(
ParseState &state)
const {
489 for (
auto at{state.GetLocation()};
490 parser_.Parse(state) && state.GetLocation() > at;
491 at = state.GetLocation()) {
500template <
typename PA>
inline constexpr auto skipMany(PA
parser) {
507template <
typename PA>
class SkipManyFastParser {
510 constexpr SkipManyFastParser(
const SkipManyFastParser &) =
default;
511 constexpr SkipManyFastParser(PA
parser) : parser_{
parser} {}
512 std::optional<Success> Parse(
ParseState &state)
const {
513 while (parser_.Parse(state)) {
522template <
typename PA>
inline constexpr auto skipManyFast(PA
parser) {
528template <
typename PA>
class MaybeParser {
529 using paType =
typename PA::resultType;
532 using resultType = std::optional<paType>;
533 constexpr MaybeParser(
const MaybeParser &) =
default;
535 std::optional<resultType> Parse(
ParseState &state)
const {
536 if (resultType result{parser_.Parse(state)}) {
538 return {std::move(result)};
547template <
typename PA>
inline constexpr auto maybe(PA
parser) {
554template <
typename PA>
class DefaultedParser {
556 using resultType =
typename PA::resultType;
557 constexpr DefaultedParser(
const DefaultedParser &) =
default;
558 constexpr DefaultedParser(PA p) : parser_{p} {}
559 std::optional<resultType> Parse(
ParseState &state)
const {
560 std::optional<std::optional<resultType>> ax{maybe(parser_).Parse(state)};
562 return std::move(*ax);
571template <
typename PA>
inline constexpr auto defaulted(PA p) {
596template <
typename... PARSER>
597using ApplyArgs = std::tuple<std::optional<typename PARSER::resultType>...>;
599template <
typename... PARSER, std::size_t... J>
600inline bool ApplyHelperArgs(
const std::tuple<PARSER...> &parsers,
601 ApplyArgs<PARSER...> &args, ParseState &state, std::index_sequence<J...>) {
603 (std::get<J>(args) = std::get<J>(parsers).Parse(state),
604 std::get<J>(args).has_value()));
608template <
typename RESULT,
typename... PARSER>
609using ApplicableFunctionPointer = RESULT (*)(
typename PARSER::resultType &&...);
610template <
typename RESULT,
typename... PARSER>
611using ApplicableFunctionObject =
612 const std::function<RESULT(
typename PARSER::resultType &&...)> &;
614template <
template <
typename...>
class FUNCTION,
typename RESULT,
615 typename... PARSER, std::size_t... J>
616inline RESULT ApplyHelperFunction(FUNCTION<RESULT, PARSER...> f,
617 ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) {
618 return f(std::move(*std::get<J>(args))...);
621template <
template <
typename...>
class FUNCTION,
typename RESULT,
624 using funcType = FUNCTION<RESULT, PARSER...>;
627 using resultType = RESULT;
628 constexpr ApplyFunction(
const ApplyFunction &) =
default;
629 constexpr ApplyFunction(funcType f, PARSER... p)
630 : function_{f}, parsers_{p...} {}
631 std::optional<resultType> Parse(
ParseState &state)
const {
632 ApplyArgs<PARSER...> results;
633 using Sequence = std::index_sequence_for<PARSER...>;
634 if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
635 return ApplyHelperFunction<FUNCTION, RESULT, PARSER...>(
636 function_, std::move(results), Sequence{});
643 const funcType function_;
644 const std::tuple<PARSER...> parsers_;
647template <
typename RESULT,
typename... PARSER>
648inline constexpr auto applyFunction(
649 ApplicableFunctionPointer<RESULT, PARSER...> f,
const PARSER &...
parser) {
650 return ApplyFunction<ApplicableFunctionPointer, RESULT, PARSER...>{
654template <
typename RESULT,
typename... PARSER>
655inline auto applyLambda(
656 ApplicableFunctionObject<RESULT, PARSER...> f,
const PARSER &...parser) {
657 return ApplyFunction<ApplicableFunctionObject, RESULT, PARSER...>{
662template <
typename MEMFUNC,
typename OBJPARSER,
typename... PARSER,
664inline auto ApplyHelperMember(MEMFUNC mfp,
665 ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) {
666 return ((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...);
669template <
typename MEMFUNC,
typename OBJPARSER,
typename... PARSER>
670class ApplyMemberFunction {
671 static_assert(std::is_member_function_pointer_v<MEMFUNC>);
672 using funcType = MEMFUNC;
676 std::invoke_result_t<MEMFUNC,
typename OBJPARSER::resultType, PARSER...>;
678 constexpr ApplyMemberFunction(
const ApplyMemberFunction &) =
default;
679 constexpr ApplyMemberFunction(MEMFUNC f, OBJPARSER o, PARSER... p)
680 : function_{f}, parsers_{o, p...} {}
681 std::optional<resultType> Parse(
ParseState &state)
const {
682 ApplyArgs<OBJPARSER, PARSER...> results;
683 using Sequence1 = std::index_sequence_for<OBJPARSER, PARSER...>;
684 using Sequence2 = std::index_sequence_for<PARSER...>;
685 if (ApplyHelperArgs(parsers_, results, state, Sequence1{})) {
686 return ApplyHelperMember<MEMFUNC, OBJPARSER, PARSER...>(
687 function_, std::move(results), Sequence2{});
694 const funcType function_;
695 const std::tuple<OBJPARSER, PARSER...> parsers_;
698template <
typename MEMFUNC,
typename OBJPARSER,
typename... PARSER>
699inline constexpr auto applyMem(
700 MEMFUNC memfn,
const OBJPARSER &objParser, PARSER...
parser) {
702 memfn, objParser,
parser...};
718template <
typename RESULT,
typename... PARSER, std::size_t... J>
719inline RESULT ApplyHelperConstructor(
720 ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) {
721 return RESULT{std::move(*std::get<J>(args))...};
724template <
typename RESULT,
typename... PARSER>
class ApplyConstructor {
726 using resultType = RESULT;
727 constexpr ApplyConstructor(
const ApplyConstructor &) =
default;
728 constexpr explicit ApplyConstructor(PARSER... p) : parsers_{p...} {}
729 std::optional<resultType> Parse(
ParseState &state)
const {
730 if constexpr (
sizeof...(PARSER) == 0) {
733 if constexpr (
sizeof...(PARSER) == 1) {
734 return ParseOne(state);
736 ApplyArgs<PARSER...> results;
737 using Sequence = std::index_sequence_for<PARSER...>;
738 if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
739 return ApplyHelperConstructor<RESULT, PARSER...>(
740 std::move(results), Sequence{});
748 std::optional<resultType> ParseOne(
ParseState &state)
const {
749 if constexpr (std::is_same_v<
Success,
typename PARSER::resultType...>) {
750 if (std::get<0>(parsers_).Parse(state)) {
753 }
else if (
auto arg{std::get<0>(parsers_).Parse(state)}) {
754 return RESULT{std::move(*arg)};
759 const std::tuple<PARSER...> parsers_;
762template <
typename RESULT,
typename... PARSER>
763inline constexpr auto construct(PARSER... p) {
769template <
typename PA>
inline constexpr auto indirect(PA p) {
770 return construct<common::Indirection<typename PA::resultType>>(p);
778common::IfNoLvalue<std::list<T>, T> prepend(T &&head, std::list<T> &&rest) {
779 rest.push_front(std::move(head));
780 return std::move(rest);
783template <
typename PA,
typename PB>
class NonemptySeparated {
785 using paType =
typename PA::resultType;
788 using resultType = std::list<paType>;
789 constexpr NonemptySeparated(
const NonemptySeparated &) =
default;
790 constexpr NonemptySeparated(PA p, PB sep) : parser_{p}, separator_{sep} {}
791 std::optional<resultType> Parse(
ParseState &state)
const {
792 return applyFunction<std::list<paType>>(
793 prepend<paType>, parser_, many(separator_ >> parser_))
802template <
typename PA,
typename PB>
803inline constexpr auto nonemptySeparated(PA p, PB sep) {
813 constexpr OkParser() {}
814 static constexpr std::optional<Success> Parse(
ParseState &) {
821template <
typename PA,
typename PB>
823 return recovery(withMessage(msg, pa), pb >> pure<typename PA::resultType>());
830 using resultType =
const char *;
831 constexpr NextCh() {}
832 std::optional<const char *> Parse(
ParseState &state)
const {
833 if (std::optional<const char *> result{state.GetNextChar()}) {
836 state.Say(MessageFixedText::endOfFileMessage);
846template <LanguageFeature LF,
typename PA>
class NonstandardParser {
848 using resultType =
typename PA::resultType;
849 constexpr NonstandardParser(
const NonstandardParser &) =
default;
851 : parser_{
parser}, message_{msg} {}
852 constexpr NonstandardParser(PA
parser) : parser_{
parser} {}
853 std::optional<resultType> Parse(
ParseState &state)
const {
854 if (
UserState * ustate{state.userState()}) {
855 if (!ustate->features().IsEnabled(LF)) {
859 auto at{state.GetLocation()};
860 auto result{parser_.Parse(state)};
861 if (result && !message_.empty()) {
863 CharBlock{at, std::max(state.GetLocation(), at + 1)}, LF, message_);
873template <LanguageFeature LF,
typename PA>
878template <LanguageFeature LF,
typename PA>
879inline constexpr auto extension(PA
parser) {
880 return NonstandardParser<LF, PA>(
parser);
886template <LanguageFeature LF,
typename PA>
class DeprecatedParser {
888 using resultType =
typename PA::resultType;
889 constexpr DeprecatedParser(
const DeprecatedParser &) =
default;
890 constexpr DeprecatedParser(PA
parser) : parser_{
parser} {}
891 std::optional<resultType> Parse(
ParseState &state)
const {
892 if (
UserState * ustate{state.userState()}) {
893 if (!ustate->features().IsEnabled(LF)) {
897 auto at{state.GetLocation()};
898 auto result{parser_.Parse(state)};
900 state.Nonstandard(
CharBlock{at, state.GetLocation()}, LF,
901 "deprecated usage"_port_en_US);
910template <LanguageFeature LF,
typename PA>
911inline constexpr auto deprecated(PA
parser) {
916template <
typename PA>
class SourcedParser {
918 using resultType =
typename PA::resultType;
919 constexpr SourcedParser(
const SourcedParser &) =
default;
921 std::optional<resultType> Parse(
ParseState &state)
const {
922 const char *start{state.GetLocation()};
923 auto result{parser_.Parse(state)};
925 const char *end{state.GetLocation()};
926 for (; start < end && start[0] ==
' '; ++start) {
928 for (; start < end && end[-1] ==
' '; --end) {
939template <
typename PA>
inline constexpr auto sourced(PA
parser) {
Definition basic-parsers.h:310
Definition basic-parsers.h:724
Definition basic-parsers.h:623
Definition basic-parsers.h:670
Definition basic-parsers.h:99
Definition char-block.h:26
Definition basic-parsers.h:554
Definition basic-parsers.h:886
Definition basic-parsers.h:47
Definition basic-parsers.h:286
Definition basic-parsers.h:152
Definition basic-parsers.h:422
Definition basic-parsers.h:528
Definition basic-parsers.h:176
Definition basic-parsers.h:127
Definition basic-parsers.h:783
Definition basic-parsers.h:846
Definition parse-state.h:31
Definition basic-parsers.h:85
Definition basic-parsers.h:70
Definition basic-parsers.h:359
Definition basic-parsers.h:263
Definition basic-parsers.h:507
Definition basic-parsers.h:483
Definition basic-parsers.h:454
Definition basic-parsers.h:916
Definition user-state.h:33
Definition user-state.h:35
Definition basic-parsers.h:202
Definition check-expression.h:19
Definition basic-parsers.h:829
Definition basic-parsers.h:811