• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
FailParser(MessageFixedText t)53   constexpr explicit FailParser(MessageFixedText t) : text_{t} {}
Parse(ParseState & state)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 
fail(MessageFixedText t)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;
PureParser(A && x)76   constexpr explicit PureParser(A &&x) : value_(std::move(x)) {}
Parse(ParseState &)77   std::optional<A> Parse(ParseState &) const { return value_; }
78 
79 private:
80   const A value_;
81 };
82 
pure(A x)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;
PureDefaultParser()91   constexpr PureDefaultParser() {}
Parse(ParseState &)92   std::optional<A> Parse(ParseState &) const { return std::make_optional<A>(); }
93 };
94 
pure()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;
BacktrackingParser(const A & parser)105   constexpr BacktrackingParser(const A &parser) : parser_{parser} {}
Parse(ParseState & state)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 
attempt(const A & parser)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;
NegatedParser(PA p)133   constexpr NegatedParser(PA p) : parser_{p} {}
Parse(ParseState & state)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;
LookAheadParser(PA p)158   constexpr LookAheadParser(PA p) : parser_{p} {}
Parse(ParseState & state)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 
lookAhead(PA p)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;
MessageContextParser(MessageFixedText t,PA p)182   constexpr MessageContextParser(MessageFixedText t, PA p)
183       : text_{t}, parser_{p} {}
Parse(ParseState & state)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>
inContext(MessageFixedText context,PA parser)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;
WithMessageParser(MessageFixedText t,PA p)208   constexpr WithMessageParser(MessageFixedText t, PA p)
209       : text_{t}, parser_{p} {}
Parse(ParseState & state)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>
withMessage(MessageFixedText msg,PA parser)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;
SequenceParser(PA pa,PB pb)257   constexpr SequenceParser(PA pa, PB pb) : pa_{pa}, pb2_{pb} {}
Parse(ParseState & state)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;
FollowParser(PA pa,PB pb)280   constexpr FollowParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
Parse(ParseState & state)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;
AlternativesParser(PA pa,Ps...ps)303   constexpr AlternativesParser(PA pa, Ps... ps) : ps_{pa, ps...} {}
304   constexpr AlternativesParser(const AlternativesParser &) = default;
Parse(ParseState & state)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>
ParseRest(std::optional<resultType> & result,ParseState & state,ParseState & backtrack)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 
first(Ps...ps)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;
RecoveryParser(PA pa,PB pb)354   constexpr RecoveryParser(PA pa, PB pb) : pa_{pa}, pb3_{pb} {}
Parse(ParseState & state)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>
recovery(PA pa,PB 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;
ManyParser(PA parser)418   constexpr ManyParser(PA parser) : parser_{parser} {}
Parse(ParseState & state)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 
many(PA parser)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;
SomeParser(PA parser)450   constexpr SomeParser(PA parser) : parser_{parser} {}
Parse(ParseState & state)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 
some(PA parser)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;
SkipManyParser(PA parser)477   constexpr SkipManyParser(PA parser) : parser_{parser} {}
Parse(ParseState & state)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 
skipMany(PA parser)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;
SkipManyFastParser(PA parser)501   constexpr SkipManyFastParser(PA parser) : parser_{parser} {}
Parse(ParseState & state)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 
skipManyFast(PA parser)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;
MaybeParser(PA parser)524   constexpr MaybeParser(PA parser) : parser_{parser} {}
Parse(ParseState & state)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 
maybe(PA parser)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;
DefaultedParser(PA p)548   constexpr DefaultedParser(PA p) : parser_{p} {}
Parse(ParseState & state)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 
defaulted(PA p)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>
ApplyHelperArgs(const std::tuple<PARSER...> & parsers,ApplyArgs<PARSER...> & args,ParseState & state,std::index_sequence<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>
ApplyHelperFunction(FUNCTION<RESULT,PARSER...> f,ApplyArgs<PARSER...> && args,std::index_sequence<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;
ApplyFunction(funcType f,PARSER...p)619   constexpr ApplyFunction(funcType f, PARSER... p)
620       : function_{f}, parsers_{p...} {}
Parse(ParseState & state)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>
applyFunction(ApplicableFunctionPointer<RESULT,PARSER...> f,const PARSER &...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>
applyLambda(ApplicableFunctionObject<RESULT,PARSER...> f,const PARSER &...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;
ApplyMemberFunction(funcType f,OBJPARSER o,PARSER...p)677   constexpr ApplyMemberFunction(funcType f, OBJPARSER o, PARSER... p)
678       : function_{f}, parsers_{o, p...} {}
Parse(ParseState & state)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>
applyMem(ApplicableMemberFunctionPointer<OBJPARSER,PARSER...> mfp,const OBJPARSER & objParser,PARSER...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>
ApplyHelperConstructor(ApplyArgs<PARSER...> && args,std::index_sequence<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;
ApplyConstructor(PARSER...p)726   constexpr explicit ApplyConstructor(PARSER... p) : parsers_{p...} {}
Parse(ParseState & state)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:
ParseOne(ParseState & state)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>
construct(PARSER...p)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.
indirect(PA p)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>
prepend(T && head,std::list<T> && rest)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;
NonemptySeparated(PA p,PB sep)788   constexpr NonemptySeparated(PA p, PB sep) : parser_{p}, separator_{sep} {}
Parse(ParseState & state)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>
nonemptySeparated(PA p,PB sep)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;
OkParserOkParser811   constexpr OkParser() {}
ParseOkParser812   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>
localRecovery(MessageFixedText msg,PA pa,PB 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 *;
NextChNextCh829   constexpr NextCh() {}
ParseNextCh830   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;
NonstandardParser(PA parser)848   constexpr NonstandardParser(PA parser) : parser_{parser} {}
Parse(ParseState & state)849   std::optional<resultType> Parse(ParseState &state) const {
850     if (UserState * ustate{state.userState()}) {
851       if (!ustate->features().IsEnabled(LF)) {
852         return std::nullopt;
853       }
854     }
855     auto at{state.GetLocation()};
856     auto result{parser_.Parse(state)};
857     if (result) {
858       state.Nonstandard(
859           CharBlock{at, state.GetLocation()}, LF, "nonstandard usage"_en_US);
860     }
861     return result;
862   }
863 
864 private:
865   const PA parser_;
866 };
867 
868 template <LanguageFeature LF, typename PA>
extension(PA parser)869 inline constexpr auto extension(PA parser) {
870   return NonstandardParser<LF, PA>(parser);
871 }
872 
873 // If a is a parser for some deprecated or deleted language feature LF,
874 // deprecated<LF>(a) is a parser that is optionally enabled, sets a strict
875 // conformance violation flag, and may emit a warning message, if enabled.
876 template <LanguageFeature LF, typename PA> class DeprecatedParser {
877 public:
878   using resultType = typename PA::resultType;
879   constexpr DeprecatedParser(const DeprecatedParser &) = default;
DeprecatedParser(PA parser)880   constexpr DeprecatedParser(PA parser) : parser_{parser} {}
Parse(ParseState & state)881   std::optional<resultType> Parse(ParseState &state) const {
882     if (UserState * ustate{state.userState()}) {
883       if (!ustate->features().IsEnabled(LF)) {
884         return std::nullopt;
885       }
886     }
887     auto at{state.GetLocation()};
888     auto result{parser_.Parse(state)};
889     if (result) {
890       state.Nonstandard(
891           CharBlock{at, state.GetLocation()}, LF, "deprecated usage"_en_US);
892     }
893     return result;
894   }
895 
896 private:
897   const PA parser_;
898 };
899 
900 template <LanguageFeature LF, typename PA>
deprecated(PA parser)901 inline constexpr auto deprecated(PA parser) {
902   return DeprecatedParser<LF, PA>(parser);
903 }
904 
905 // Parsing objects with "source" members.
906 template <typename PA> class SourcedParser {
907 public:
908   using resultType = typename PA::resultType;
909   constexpr SourcedParser(const SourcedParser &) = default;
SourcedParser(PA parser)910   constexpr SourcedParser(PA parser) : parser_{parser} {}
Parse(ParseState & state)911   std::optional<resultType> Parse(ParseState &state) const {
912     const char *start{state.GetLocation()};
913     auto result{parser_.Parse(state)};
914     if (result) {
915       const char *end{state.GetLocation()};
916       for (; start < end && start[0] == ' '; ++start) {
917       }
918       for (; start < end && end[-1] == ' '; --end) {
919       }
920       result->source = CharBlock{start, end};
921     }
922     return result;
923   }
924 
925 private:
926   const PA parser_;
927 };
928 
sourced(PA parser)929 template <typename PA> inline constexpr auto sourced(PA parser) {
930   return SourcedParser<PA>{parser};
931 }
932 } // namespace Fortran::parser
933 #endif // FORTRAN_PARSER_BASIC_PARSERS_H_
934