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