xref: /llvm-project/flang/lib/Parser/basic-parsers.h (revision 70e96dc3fb895e95dc659f87c2ed188507831801)
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     if (state.deferMessages()) { // fast path
212       std::optional<resultType> result{parser_.Parse(state)};
213       if (!result) {
214         state.set_anyDeferredMessages();
215       }
216       return result;
217     }
218     Messages messages{std::move(state.messages())};
219     bool hadAnyTokenMatched{state.anyTokenMatched()};
220     state.set_anyTokenMatched(false);
221     std::optional<resultType> result{parser_.Parse(state)};
222     bool emitMessage{false};
223     if (result) {
224       messages.Annex(std::move(state.messages()));
225       if (hadAnyTokenMatched) {
226         state.set_anyTokenMatched();
227       }
228     } else if (state.anyTokenMatched()) {
229       emitMessage = state.messages().empty();
230       messages.Annex(std::move(state.messages()));
231     } else {
232       emitMessage = true;
233       if (hadAnyTokenMatched) {
234         state.set_anyTokenMatched();
235       }
236     }
237     state.messages() = std::move(messages);
238     if (emitMessage) {
239       state.Say(text_);
240     }
241     return result;
242   }
243 
244 private:
245   const MessageFixedText text_;
246   const PA parser_;
247 };
248 
249 template <typename PA>
250 inline constexpr auto withMessage(MessageFixedText msg, PA parser) {
251   return WithMessageParser{msg, parser};
252 }
253 
254 // If a and b are parsers, then a >> b returns a parser that succeeds when
255 // b succeeds after a does so, but fails when either a or b does.  The
256 // result is taken from b.  Similarly, a / b also succeeds if both a and b
257 // do so, but the result is that returned by a.
258 template <typename PA, typename PB> class SequenceParser {
259 public:
260   using resultType = typename PB::resultType;
261   constexpr SequenceParser(const SequenceParser &) = default;
262   constexpr SequenceParser(PA pa, PB pb) : pa_{pa}, pb2_{pb} {}
263   std::optional<resultType> Parse(ParseState &state) const {
264     if (pa_.Parse(state)) {
265       return pb2_.Parse(state);
266     } else {
267       return std::nullopt;
268     }
269   }
270 
271 private:
272   const PA pa_;
273   const PB pb2_;
274 };
275 
276 template <typename PA, typename PB>
277 inline constexpr auto operator>>(PA pa, PB pb) {
278   return SequenceParser<PA, PB>{pa, pb};
279 }
280 
281 template <typename PA, typename PB> class FollowParser {
282 public:
283   using resultType = typename PA::resultType;
284   constexpr FollowParser(const FollowParser &) = default;
285   constexpr FollowParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
286   std::optional<resultType> Parse(ParseState &state) const {
287     if (std::optional<resultType> ax{pa_.Parse(state)}) {
288       if (pb_.Parse(state)) {
289         return ax;
290       }
291     }
292     return std::nullopt;
293   }
294 
295 private:
296   const PA pa_;
297   const PB pb_;
298 };
299 
300 template <typename PA, typename PB>
301 inline constexpr auto operator/(PA pa, PB pb) {
302   return FollowParser<PA, PB>{pa, pb};
303 }
304 
305 template <typename PA, typename... Ps> class AlternativesParser {
306 public:
307   using resultType = typename PA::resultType;
308   constexpr AlternativesParser(PA pa, Ps... ps) : ps_{pa, ps...} {}
309   constexpr AlternativesParser(const AlternativesParser &) = default;
310   std::optional<resultType> Parse(ParseState &state) const {
311     Messages messages{std::move(state.messages())};
312     ParseState backtrack{state};
313     std::optional<resultType> result{std::get<0>(ps_).Parse(state)};
314     if constexpr (sizeof...(Ps) > 0) {
315       if (!result) {
316         ParseRest<1>(result, state, backtrack);
317       }
318     }
319     state.messages().Annex(std::move(messages));
320     return result;
321   }
322 
323 private:
324   template <int J>
325   void ParseRest(std::optional<resultType> &result, ParseState &state,
326       ParseState &backtrack) const {
327     ParseState prevState{std::move(state)};
328     state = backtrack;
329     result = std::get<J>(ps_).Parse(state);
330     if (!result) {
331       state.CombineFailedParses(std::move(prevState));
332       if constexpr (J < sizeof...(Ps)) {
333         ParseRest<J + 1>(result, state, backtrack);
334       }
335     }
336   }
337 
338   const std::tuple<PA, Ps...> ps_;
339 };
340 
341 template <typename... Ps> inline constexpr auto first(Ps... ps) {
342   return AlternativesParser<Ps...>{ps...};
343 }
344 
345 template <typename PA, typename PB>
346 inline constexpr auto operator||(PA pa, PB pb) {
347   return AlternativesParser<PA, PB>{pa, pb};
348 }
349 
350 // If a and b are parsers, then recovery(a,b) returns a parser that succeeds if
351 // a does so, or if a fails and b succeeds.  If a succeeds, b is not attempted.
352 // All messages from the first parse are retained.
353 // The two parsers must return values of the same type.
354 template <typename PA, typename PB> class RecoveryParser {
355 public:
356   using resultType = typename PA::resultType;
357   static_assert(std::is_same_v<resultType, typename PB::resultType>);
358   constexpr RecoveryParser(const RecoveryParser &) = default;
359   constexpr RecoveryParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
360   std::optional<resultType> Parse(ParseState &state) const {
361     bool originallyDeferred{state.deferMessages()};
362     ParseState backtrack{state};
363     if (!originallyDeferred && state.messages().empty() &&
364         !state.anyErrorRecovery()) {
365       // Fast path.  There are no messages or recovered errors in the incoming
366       // state.  Attempt to parse with messages deferred, expecting that the
367       // parse will succeed silently.
368       state.set_deferMessages(true);
369       if (std::optional<resultType> ax{pa_.Parse(state)}) {
370         if (!state.anyDeferredMessages() && !state.anyErrorRecovery()) {
371           state.set_deferMessages(false);
372           return ax;
373         }
374       }
375       state = backtrack;
376     }
377     Messages messages{std::move(state.messages())};
378     if (std::optional<resultType> ax{pa_.Parse(state)}) {
379       state.messages().Annex(std::move(messages));
380       return ax;
381     }
382     messages.Annex(std::move(state.messages()));
383     bool hadDeferredMessages{state.anyDeferredMessages()};
384     bool anyTokenMatched{state.anyTokenMatched()};
385     state = std::move(backtrack);
386     state.set_deferMessages(true);
387     std::optional<resultType> bx{pb_.Parse(state)};
388     state.messages() = std::move(messages);
389     state.set_deferMessages(originallyDeferred);
390     if (anyTokenMatched) {
391       state.set_anyTokenMatched();
392     }
393     if (hadDeferredMessages) {
394       state.set_anyDeferredMessages();
395     }
396     if (bx) {
397       // Error recovery situations must also produce messages.
398       CHECK(state.anyDeferredMessages() || state.messages().AnyFatalError());
399       state.set_anyErrorRecovery();
400     }
401     return bx;
402   }
403 
404 private:
405   const PA pa_;
406   const PB pb_;
407 };
408 
409 template <typename PA, typename PB>
410 inline constexpr auto recovery(PA pa, PB pb) {
411   return RecoveryParser<PA, PB>{pa, pb};
412 }
413 
414 // If x is a parser, then many(x) returns a parser that always succeeds
415 // and whose value is a list, possibly empty, of the values returned from
416 // repeated application of x until it fails or does not advance the parse.
417 template <typename PA> class ManyParser {
418   using paType = typename PA::resultType;
419 
420 public:
421   using resultType = std::list<paType>;
422   constexpr ManyParser(const ManyParser &) = default;
423   constexpr ManyParser(PA parser) : parser_{parser} {}
424   std::optional<resultType> Parse(ParseState &state) const {
425     resultType result;
426     auto at{state.GetLocation()};
427     while (std::optional<paType> x{parser_.Parse(state)}) {
428       result.emplace_back(std::move(*x));
429       if (state.GetLocation() <= at) {
430         break; // no forward progress, don't loop
431       }
432       at = state.GetLocation();
433     }
434     return {std::move(result)};
435   }
436 
437 private:
438   const BacktrackingParser<PA> parser_;
439 };
440 
441 template <typename PA> inline constexpr auto many(PA parser) {
442   return ManyParser<PA>{parser};
443 }
444 
445 // If x is a parser, then some(x) returns a parser that succeeds if x does
446 // and whose value is a nonempty list of the values returned from repeated
447 // application of x until it fails or does not advance the parse.  In other
448 // words, some(x) is a variant of many(x) that has to succeed at least once.
449 template <typename PA> class SomeParser {
450   using paType = typename PA::resultType;
451 
452 public:
453   using resultType = std::list<paType>;
454   constexpr SomeParser(const SomeParser &) = default;
455   constexpr SomeParser(PA parser) : parser_{parser} {}
456   std::optional<resultType> Parse(ParseState &state) const {
457     auto start{state.GetLocation()};
458     if (std::optional<paType> first{parser_.Parse(state)}) {
459       resultType result;
460       result.emplace_back(std::move(*first));
461       if (state.GetLocation() > start) {
462         result.splice(result.end(), many(parser_).Parse(state).value());
463       }
464       return {std::move(result)};
465     }
466     return std::nullopt;
467   }
468 
469 private:
470   const PA parser_;
471 };
472 
473 template <typename PA> inline constexpr auto some(PA parser) {
474   return SomeParser<PA>{parser};
475 }
476 
477 // If x is a parser, skipMany(x) is equivalent to many(x) but with no result.
478 template <typename PA> class SkipManyParser {
479 public:
480   using resultType = Success;
481   constexpr SkipManyParser(const SkipManyParser &) = default;
482   constexpr SkipManyParser(PA parser) : parser_{parser} {}
483   std::optional<Success> Parse(ParseState &state) const {
484     for (auto at{state.GetLocation()};
485          parser_.Parse(state) && state.GetLocation() > at;
486          at = state.GetLocation()) {
487     }
488     return Success{};
489   }
490 
491 private:
492   const BacktrackingParser<PA> parser_;
493 };
494 
495 template <typename PA> inline constexpr auto skipMany(PA parser) {
496   return SkipManyParser<PA>{parser};
497 }
498 
499 // If x is a parser, skipManyFast(x) is equivalent to skipMany(x).
500 // The parser x must always advance on success and never invalidate the
501 // state on failure.
502 template <typename PA> class SkipManyFastParser {
503 public:
504   using resultType = Success;
505   constexpr SkipManyFastParser(const SkipManyFastParser &) = default;
506   constexpr SkipManyFastParser(PA parser) : parser_{parser} {}
507   std::optional<Success> Parse(ParseState &state) const {
508     while (parser_.Parse(state)) {
509     }
510     return Success{};
511   }
512 
513 private:
514   const PA parser_;
515 };
516 
517 template <typename PA> inline constexpr auto skipManyFast(PA parser) {
518   return SkipManyFastParser<PA>{parser};
519 }
520 
521 // If x is a parser returning some type A, then maybe(x) returns a
522 // parser that returns std::optional<A>, always succeeding.
523 template <typename PA> class MaybeParser {
524   using paType = typename PA::resultType;
525 
526 public:
527   using resultType = std::optional<paType>;
528   constexpr MaybeParser(const MaybeParser &) = default;
529   constexpr MaybeParser(PA parser) : parser_{parser} {}
530   std::optional<resultType> Parse(ParseState &state) const {
531     if (resultType result{parser_.Parse(state)}) {
532       // permit optional<optional<...>>
533       return {std::move(result)};
534     }
535     return resultType{};
536   }
537 
538 private:
539   const BacktrackingParser<PA> parser_;
540 };
541 
542 template <typename PA> inline constexpr auto maybe(PA parser) {
543   return MaybeParser<PA>{parser};
544 }
545 
546 // If x is a parser, then defaulted(x) returns a parser that always
547 // succeeds.  When x succeeds, its result is that of x; otherwise, its
548 // result is a default-constructed value of x's result type.
549 template <typename PA> class DefaultedParser {
550 public:
551   using resultType = typename PA::resultType;
552   constexpr DefaultedParser(const DefaultedParser &) = default;
553   constexpr DefaultedParser(PA p) : parser_{p} {}
554   std::optional<resultType> Parse(ParseState &state) const {
555     std::optional<std::optional<resultType>> ax{maybe(parser_).Parse(state)};
556     if (ax.value()) { // maybe() always succeeds
557       return std::move(*ax);
558     }
559     return resultType{};
560   }
561 
562 private:
563   const BacktrackingParser<PA> parser_;
564 };
565 
566 template <typename PA> inline constexpr auto defaulted(PA p) {
567   return DefaultedParser<PA>(p);
568 }
569 
570 // If a is a parser, and f is a function mapping an rvalue of a's result type
571 // to some other type T, then applyFunction(f, a) returns a parser that succeeds
572 // iff a does, and whose result value ax has been passed through the function;
573 // the final result is that returned by the call f(std::move(ax)).
574 //
575 // Function application is generalized to functions with more than one
576 // argument with applyFunction(f, a, b, ...) succeeding if all of the parsers
577 // a, b, &c. do so, and the result is the value of applying f to their
578 // results.
579 //
580 // applyLambda(f, ...) is the same concept extended to std::function<> functors.
581 // It is not constexpr.
582 //
583 // Member function application is supported by applyMem(&C::f, a).  If the
584 // parser a succeeds and returns some value ax of type C, the result is that
585 // returned by ax.f().  Additional parser arguments can be specified to supply
586 // their results to the member function call, so applyMem(&C::f, a, b) succeeds
587 // if both a and b do so and returns the result of calling ax.f(std::move(bx)).
588 
589 // Runs a sequence of parsers until one fails or all have succeeded.
590 // Collects their results in a std::tuple<std::optional<>...>.
591 template <typename... PARSER>
592 using ApplyArgs = std::tuple<std::optional<typename PARSER::resultType>...>;
593 
594 template <typename... PARSER, std::size_t... J>
595 inline bool ApplyHelperArgs(const std::tuple<PARSER...> &parsers,
596     ApplyArgs<PARSER...> &args, ParseState &state, std::index_sequence<J...>) {
597   return (... &&
598       (std::get<J>(args) = std::get<J>(parsers).Parse(state),
599           std::get<J>(args).has_value()));
600 }
601 
602 // Applies a function to the arguments collected by ApplyHelperArgs.
603 template <typename RESULT, typename... PARSER>
604 using ApplicableFunctionPointer = RESULT (*)(typename PARSER::resultType &&...);
605 template <typename RESULT, typename... PARSER>
606 using ApplicableFunctionObject =
607     const std::function<RESULT(typename PARSER::resultType &&...)> &;
608 
609 template <template <typename...> class FUNCTION, typename RESULT,
610     typename... PARSER, std::size_t... J>
611 inline RESULT ApplyHelperFunction(FUNCTION<RESULT, PARSER...> f,
612     ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) {
613   return f(std::move(*std::get<J>(args))...);
614 }
615 
616 template <template <typename...> class FUNCTION, typename RESULT,
617     typename... PARSER>
618 class ApplyFunction {
619   using funcType = FUNCTION<RESULT, PARSER...>;
620 
621 public:
622   using resultType = RESULT;
623   constexpr ApplyFunction(const ApplyFunction &) = default;
624   constexpr ApplyFunction(funcType f, PARSER... p)
625       : function_{f}, parsers_{p...} {}
626   std::optional<resultType> Parse(ParseState &state) const {
627     ApplyArgs<PARSER...> results;
628     using Sequence = std::index_sequence_for<PARSER...>;
629     if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
630       return ApplyHelperFunction<FUNCTION, RESULT, PARSER...>(
631           function_, std::move(results), Sequence{});
632     } else {
633       return std::nullopt;
634     }
635   }
636 
637 private:
638   const funcType function_;
639   const std::tuple<PARSER...> parsers_;
640 };
641 
642 template <typename RESULT, typename... PARSER>
643 inline constexpr auto applyFunction(
644     ApplicableFunctionPointer<RESULT, PARSER...> f, const PARSER &...parser) {
645   return ApplyFunction<ApplicableFunctionPointer, RESULT, PARSER...>{
646       f, parser...};
647 }
648 
649 template <typename RESULT, typename... PARSER>
650 inline /* not constexpr */ auto applyLambda(
651     ApplicableFunctionObject<RESULT, PARSER...> f, const PARSER &...parser) {
652   return ApplyFunction<ApplicableFunctionObject, RESULT, PARSER...>{
653       f, parser...};
654 }
655 
656 // Member function application
657 template <typename MEMFUNC, typename OBJPARSER, typename... PARSER,
658     std::size_t... J>
659 inline auto ApplyHelperMember(MEMFUNC mfp,
660     ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) {
661   return ((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...);
662 }
663 
664 template <typename MEMFUNC, typename OBJPARSER, typename... PARSER>
665 class ApplyMemberFunction {
666   static_assert(std::is_member_function_pointer_v<MEMFUNC>);
667   using funcType = MEMFUNC;
668 
669 public:
670   using resultType =
671       std::invoke_result_t<MEMFUNC, typename OBJPARSER::resultType, PARSER...>;
672 
673   constexpr ApplyMemberFunction(const ApplyMemberFunction &) = default;
674   constexpr ApplyMemberFunction(MEMFUNC f, OBJPARSER o, PARSER... p)
675       : function_{f}, parsers_{o, p...} {}
676   std::optional<resultType> Parse(ParseState &state) const {
677     ApplyArgs<OBJPARSER, PARSER...> results;
678     using Sequence1 = std::index_sequence_for<OBJPARSER, PARSER...>;
679     using Sequence2 = std::index_sequence_for<PARSER...>;
680     if (ApplyHelperArgs(parsers_, results, state, Sequence1{})) {
681       return ApplyHelperMember<MEMFUNC, OBJPARSER, PARSER...>(
682           function_, std::move(results), Sequence2{});
683     } else {
684       return std::nullopt;
685     }
686   }
687 
688 private:
689   const funcType function_;
690   const std::tuple<OBJPARSER, PARSER...> parsers_;
691 };
692 
693 template <typename MEMFUNC, typename OBJPARSER, typename... PARSER>
694 inline constexpr auto applyMem(
695     MEMFUNC memfn, const OBJPARSER &objParser, PARSER... parser) {
696   return ApplyMemberFunction<MEMFUNC, OBJPARSER, PARSER...>{
697       memfn, objParser, parser...};
698 }
699 
700 // As is done with function application via applyFunction() above, class
701 // instance construction can also be based upon the results of successful
702 // parses.  For some type T and zero or more parsers a, b, &c., the call
703 // construct<T>(a, b, ...) returns a parser that succeeds if all of
704 // its argument parsers do so in succession, and whose result is an
705 // instance of T constructed upon the values they returned.
706 // With a single argument that is a parser with no usable value,
707 // construct<T>(p) invokes T's default nullary constructor (T(){}).
708 // (This means that "construct<T>(Foo >> Bar >> ok)" is functionally
709 // equivalent to "Foo >> Bar >> construct<T>()", but I'd like to hold open
710 // the opportunity to make construct<> capture source provenance all of the
711 // time, and the first form will then lead to better error positioning.)
712 
713 template <typename RESULT, typename... PARSER, std::size_t... J>
714 inline RESULT ApplyHelperConstructor(
715     ApplyArgs<PARSER...> &&args, std::index_sequence<J...>) {
716   return RESULT{std::move(*std::get<J>(args))...};
717 }
718 
719 template <typename RESULT, typename... PARSER> class ApplyConstructor {
720 public:
721   using resultType = RESULT;
722   constexpr ApplyConstructor(const ApplyConstructor &) = default;
723   constexpr explicit ApplyConstructor(PARSER... p) : parsers_{p...} {}
724   std::optional<resultType> Parse(ParseState &state) const {
725     if constexpr (sizeof...(PARSER) == 0) {
726       return RESULT{};
727     } else {
728       if constexpr (sizeof...(PARSER) == 1) {
729         return ParseOne(state);
730       } else {
731         ApplyArgs<PARSER...> results;
732         using Sequence = std::index_sequence_for<PARSER...>;
733         if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
734           return ApplyHelperConstructor<RESULT, PARSER...>(
735               std::move(results), Sequence{});
736         }
737       }
738       return std::nullopt;
739     }
740   }
741 
742 private:
743   std::optional<resultType> ParseOne(ParseState &state) const {
744     if constexpr (std::is_same_v<Success, typename PARSER::resultType...>) {
745       if (std::get<0>(parsers_).Parse(state)) {
746         return RESULT{};
747       }
748     } else if (auto arg{std::get<0>(parsers_).Parse(state)}) {
749       return RESULT{std::move(*arg)};
750     }
751     return std::nullopt;
752   }
753 
754   const std::tuple<PARSER...> parsers_;
755 };
756 
757 template <typename RESULT, typename... PARSER>
758 inline constexpr auto construct(PARSER... p) {
759   return ApplyConstructor<RESULT, PARSER...>{p...};
760 }
761 
762 // For a parser p, indirect(p) returns a parser that builds an indirect
763 // reference to p's return type.
764 template <typename PA> inline constexpr auto indirect(PA p) {
765   return construct<common::Indirection<typename PA::resultType>>(p);
766 }
767 
768 // If a and b are parsers, then nonemptySeparated(a, b) returns a parser
769 // that succeeds if a does.  If a succeeds, it then applies many(b >> a).
770 // The result is the list of the values returned from all of the applications
771 // of a.
772 template <typename T>
773 common::IfNoLvalue<std::list<T>, T> prepend(T &&head, std::list<T> &&rest) {
774   rest.push_front(std::move(head));
775   return std::move(rest);
776 }
777 
778 template <typename PA, typename PB> class NonemptySeparated {
779 private:
780   using paType = typename PA::resultType;
781 
782 public:
783   using resultType = std::list<paType>;
784   constexpr NonemptySeparated(const NonemptySeparated &) = default;
785   constexpr NonemptySeparated(PA p, PB sep) : parser_{p}, separator_{sep} {}
786   std::optional<resultType> Parse(ParseState &state) const {
787     return applyFunction<std::list<paType>>(
788         prepend<paType>, parser_, many(separator_ >> parser_))
789         .Parse(state);
790   }
791 
792 private:
793   const PA parser_;
794   const PB separator_;
795 };
796 
797 template <typename PA, typename PB>
798 inline constexpr auto nonemptySeparated(PA p, PB sep) {
799   return NonemptySeparated<PA, PB>{p, sep};
800 }
801 
802 // ok is a parser that always succeeds.  It is useful when a parser
803 // must discard its result in order to be compatible in type with other
804 // parsers in an alternative, e.g. "x >> ok || y >> ok" is type-safe even
805 // when x and y have distinct result types.
806 struct OkParser {
807   using resultType = Success;
808   constexpr OkParser() {}
809   static constexpr std::optional<Success> Parse(ParseState &) {
810     return Success{};
811   }
812 };
813 constexpr OkParser ok;
814 
815 // A variant of recovery() above for convenience.
816 template <typename PA, typename PB>
817 inline constexpr auto localRecovery(MessageFixedText msg, PA pa, PB pb) {
818   return recovery(withMessage(msg, pa), pb >> pure<typename PA::resultType>());
819 }
820 
821 // nextCh is a parser that succeeds if the parsing state is not
822 // at the end of its input, returning the next character location and
823 // advancing the parse when it does so.
824 struct NextCh {
825   using resultType = const char *;
826   constexpr NextCh() {}
827   std::optional<const char *> Parse(ParseState &state) const {
828     if (std::optional<const char *> result{state.GetNextChar()}) {
829       return result;
830     }
831     state.Say("end of file"_err_en_US);
832     return std::nullopt;
833   }
834 };
835 
836 constexpr NextCh nextCh;
837 
838 // If a is a parser for some nonstandard language feature LF, extension<LF>(a)
839 // is a parser that optionally enabled, sets a strict conformance violation
840 // flag, and may emit a warning message, if those are enabled.
841 template <LanguageFeature LF, typename PA> class NonstandardParser {
842 public:
843   using resultType = typename PA::resultType;
844   constexpr NonstandardParser(const NonstandardParser &) = default;
845   constexpr NonstandardParser(PA parser, MessageFixedText msg)
846       : parser_{parser}, message_{msg} {}
847   constexpr NonstandardParser(PA parser) : parser_{parser} {}
848   std::optional<resultType> Parse(ParseState &state) const {
849     if (UserState * ustate{state.userState()}) {
850       if (!ustate->features().IsEnabled(LF)) {
851         return std::nullopt;
852       }
853     }
854     auto at{state.GetLocation()};
855     auto result{parser_.Parse(state)};
856     if (result && !message_.empty()) {
857       state.Nonstandard(
858           CharBlock{at, std::max(state.GetLocation(), at + 1)}, LF, message_);
859     }
860     return result;
861   }
862 
863 private:
864   const PA parser_;
865   const MessageFixedText message_;
866 };
867 
868 template <LanguageFeature LF, typename PA>
869 inline constexpr auto extension(MessageFixedText feature, PA parser) {
870   return NonstandardParser<LF, PA>(parser, feature);
871 }
872 
873 template <LanguageFeature LF, typename PA>
874 inline constexpr auto extension(PA parser) {
875   return NonstandardParser<LF, PA>(parser);
876 }
877 
878 // If a is a parser for some deprecated or deleted language feature LF,
879 // deprecated<LF>(a) is a parser that is optionally enabled, sets a strict
880 // conformance violation flag, and may emit a warning message, if enabled.
881 template <LanguageFeature LF, typename PA> class DeprecatedParser {
882 public:
883   using resultType = typename PA::resultType;
884   constexpr DeprecatedParser(const DeprecatedParser &) = default;
885   constexpr DeprecatedParser(PA parser) : parser_{parser} {}
886   std::optional<resultType> Parse(ParseState &state) const {
887     if (UserState * ustate{state.userState()}) {
888       if (!ustate->features().IsEnabled(LF)) {
889         return std::nullopt;
890       }
891     }
892     auto at{state.GetLocation()};
893     auto result{parser_.Parse(state)};
894     if (result) {
895       state.Nonstandard(CharBlock{at, state.GetLocation()}, LF,
896           "deprecated usage"_port_en_US);
897     }
898     return result;
899   }
900 
901 private:
902   const PA parser_;
903 };
904 
905 template <LanguageFeature LF, typename PA>
906 inline constexpr auto deprecated(PA parser) {
907   return DeprecatedParser<LF, PA>(parser);
908 }
909 
910 // Parsing objects with "source" members.
911 template <typename PA> class SourcedParser {
912 public:
913   using resultType = typename PA::resultType;
914   constexpr SourcedParser(const SourcedParser &) = default;
915   constexpr SourcedParser(PA parser) : parser_{parser} {}
916   std::optional<resultType> Parse(ParseState &state) const {
917     const char *start{state.GetLocation()};
918     auto result{parser_.Parse(state)};
919     if (result) {
920       const char *end{state.GetLocation()};
921       for (; start < end && start[0] == ' '; ++start) {
922       }
923       for (; start < end && end[-1] == ' '; --end) {
924       }
925       result->source = CharBlock{start, end};
926     }
927     return result;
928   }
929 
930 private:
931   const PA parser_;
932 };
933 
934 template <typename PA> inline constexpr auto sourced(PA parser) {
935   return SourcedParser<PA>{parser};
936 }
937 } // namespace Fortran::parser
938 #endif // FORTRAN_PARSER_BASIC_PARSERS_H_
939