FLANG

basic-parsers.h
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().Restore(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 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>
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;
257 constexpr SequenceParser(PA pa, PB pb) : pa_{pa}, pb2_{pb} {}
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;
280 constexpr FollowParser(PA pa, PB pb) : pa_{pa}, pb_{pb} {}
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;
303 constexpr AlternativesParser(PA pa, Ps... ps) : ps_{pa, ps...} {}
304 constexpr AlternativesParser(const AlternativesParser &) = default;
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().Restore(std::move(messages));
315 return result;
316 }
317
318 private:
319 template <int J>
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
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;
354 constexpr RecoveryParser(PA pa, PB pb) : pa_{pa}, pb3_{pb} {}
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().Restore(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>
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;
418 constexpr ManyParser(PA parser) : parser_{parser} {}
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
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;
450 constexpr SomeParser(PA parser) : parser_{parser} {}
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
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;
477 constexpr SkipManyParser(PA parser) : parser_{parser} {}
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
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;
501 constexpr SkipManyFastParser(PA parser) : parser_{parser} {}
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
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;
524 constexpr MaybeParser(PA parser) : parser_{parser} {}
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
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;
548 constexpr DefaultedParser(PA p) : parser_{p} {}
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
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>
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>
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;
619 constexpr ApplyFunction(funcType f, PARSER... p)
620 : function_{f}, parsers_{p...} {}
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>
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>
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;
677 constexpr ApplyMemberFunction(funcType f, OBJPARSER o, PARSER... p)
678 : function_{f}, parsers_{o, p...} {}
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>
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>
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;
726 constexpr explicit ApplyConstructor(PARSER... p) : parsers_{p...} {}
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 if constexpr (std::is_same_v<Success, typename PARSER::resultType...>) {
733 if (std::get<0>(parsers_).Parse(state)) {
734 return RESULT{};
735 }
736 } else if (auto arg{std::get<0>(parsers_).Parse(state)}) {
737 return RESULT{std::move(*arg)};
738 }
739 } else {
740 ApplyArgs<PARSER...> results;
741 using Sequence = std::index_sequence_for<PARSER...>;
742 if (ApplyHelperArgs(parsers_, results, state, Sequence{})) {
743 return ApplyHelperConstructor<RESULT, PARSER...>(
744 std::move(results), Sequence{});
745 }
746 }
747 return std::nullopt;
748 }
749 }
750
751 private:
752 const std::tuple<PARSER...> parsers_;
753 };
754
755 template <typename RESULT, typename... PARSER>
756 inline constexpr auto construct(PARSER... p) {
757 return ApplyConstructor<RESULT, PARSER...>{p...};
758 }
759
760 // For a parser p, indirect(p) returns a parser that builds an indirect
761 // reference to p's return type.
762 template <typename PA> inline constexpr auto indirect(PA p) {
763 return construct<common::Indirection<typename PA::resultType>>(p);
764 }
765
766 // If a and b are parsers, then nonemptySeparated(a, b) returns a parser
767 // that succeeds if a does. If a succeeds, it then applies many(b >> a).
768 // The result is the list of the values returned from all of the applications
769 // of a.
770 template <typename T>
771 common::IfNoLvalue<std::list<T>, T> prepend(T &&head, std::list<T> &&rest) {
772 rest.push_front(std::move(head));
773 return std::move(rest);
774 }
775
776 template <typename PA, typename PB> class NonemptySeparated {
777 private:
778 using paType = typename PA::resultType;
779
780 public:
781 using resultType = std::list<paType>;
782 constexpr NonemptySeparated(const NonemptySeparated &) = default;
783 constexpr NonemptySeparated(PA p, PB sep) : parser_{p}, separator_{sep} {}
784 std::optional<resultType> Parse(ParseState &state) const {
785 return applyFunction(prepend<paType>, parser_, many(separator_ >> parser_))
786 .Parse(state);
787 }
788
789 private:
790 const PA parser_;
791 const PB separator_;
792 };
793
794 template <typename PA, typename PB>
795 inline constexpr auto nonemptySeparated(PA p, PB sep) {
796 return NonemptySeparated<PA, PB>{p, sep};
797 }
798
799 // ok is a parser that always succeeds. It is useful when a parser
800 // must discard its result in order to be compatible in type with other
801 // parsers in an alternative, e.g. "x >> ok || y >> ok" is type-safe even
802 // when x and y have distinct result types.
803 constexpr struct OkParser {
804 using resultType = Success;
805 constexpr OkParser() {}
806 static constexpr std::optional<Success> Parse(ParseState &) {
807 return Success{};
808 }
809 } ok;
810
811 // A variant of recovery() above for convenience.
812 template <typename PA, typename PB>
813 inline constexpr auto localRecovery(MessageFixedText msg, PA pa, PB pb) {
814 return recovery(withMessage(msg, pa), pb >> pure<typename PA::resultType>());
815 }
816
817 // nextCh is a parser that succeeds if the parsing state is not
818 // at the end of its input, returning the next character location and
819 // advancing the parse when it does so.
820 struct NextCh {
821 using resultType = const char *;
822 constexpr NextCh() {}
823 std::optional<const char *> Parse(ParseState &state) const {
824 if (std::optional<const char *> result{state.GetNextChar()}) {
825 return result;
826 }
827 state.Say("end of file"_err_en_US);
828 return std::nullopt;
829 }
830 };
831
832 constexpr NextCh nextCh;
833
834 // If a is a parser for some nonstandard language feature LF, extension<LF>(a)
835 // is a parser that optionally enabled, sets a strict conformance violation
836 // flag, and may emit a warning message, if those are enabled.
837 template <LanguageFeature LF, typename PA> class NonstandardParser {
838 public:
839 using resultType = typename PA::resultType;
840 constexpr NonstandardParser(const NonstandardParser &) = default;
841 constexpr NonstandardParser(PA parser) : parser_{parser} {}
842 std::optional<resultType> Parse(ParseState &state) const {
843 if (UserState * ustate{state.userState()}) {
844 if (!ustate->features().IsEnabled(LF)) {
845 return std::nullopt;
846 }
847 }
848 auto at{state.GetLocation()};
849 auto result{parser_.Parse(state)};
850 if (result) {
851 state.Nonstandard(
852 CharBlock{at, state.GetLocation()}, LF, "nonstandard usage"_en_US);
853 }
854 return result;
855 }
856
857 private:
858 const PA parser_;
859 };
860
861 template <LanguageFeature LF, typename PA>
862 inline constexpr auto extension(PA parser) {
863 return NonstandardParser<LF, PA>(parser);
864 }
865
866 // If a is a parser for some deprecated or deleted language feature LF,
867 // deprecated<LF>(a) is a parser that is optionally enabled, sets a strict
868 // conformance violation flag, and may emit a warning message, if enabled.
869 template <LanguageFeature LF, typename PA> class DeprecatedParser {
870 public:
871 using resultType = typename PA::resultType;
872 constexpr DeprecatedParser(const DeprecatedParser &) = default;
873 constexpr DeprecatedParser(PA parser) : parser_{parser} {}
874 std::optional<resultType> Parse(ParseState &state) const {
875 if (UserState * ustate{state.userState()}) {
876 if (!ustate->features().IsEnabled(LF)) {
877 return std::nullopt;
878 }
879 }
880 auto at{state.GetLocation()};
881 auto result{parser_.Parse(state)};
882 if (result) {
883 state.Nonstandard(
884 CharBlock{at, state.GetLocation()}, LF, "deprecated usage"_en_US);
885 }
886 return result;
887 }
888
889 private:
890 const PA parser_;
891 };
892
893 template <LanguageFeature LF, typename PA>
894 inline constexpr auto deprecated(PA parser) {
895 return DeprecatedParser<LF, PA>(parser);
896 }
897
898 // Parsing objects with "source" members.
899 template <typename PA> class SourcedParser {
900 public:
901 using resultType = typename PA::resultType;
902 constexpr SourcedParser(const SourcedParser &) = default;
903 constexpr SourcedParser(PA parser) : parser_{parser} {}
904 std::optional<resultType> Parse(ParseState &state) const {
905 const char *start{state.GetLocation()};
906 auto result{parser_.Parse(state)};
907 if (result) {
908 const char *end{state.GetLocation()};
909 for (; start < end && start[0] == ' '; ++start) {
910 }
911 for (; start < end && end[-1] == ' '; --end) {
912 }
913 result->source = CharBlock{start, end};
914 }
915 return result;
916 }
917
918 private:
919 const PA parser_;
920 };
921
922 template <typename PA> inline constexpr auto sourced(PA parser) {
923 return SourcedParser<PA>{parser};
924 }
925 } // namespace Fortran::parser
926 #endif // FORTRAN_PARSER_BASIC_PARSERS_H_
Fortran::parser::BacktrackingParser
Definition: basic-parsers.h:101
Fortran::parser::Success
Definition: user-state.h:33
Fortran::parser::SkipManyFastParser
Definition: basic-parsers.h:497
Fortran::parser::LookAheadParser
Definition: basic-parsers.h:154
Fortran::parser::PureDefaultParser
Definition: basic-parsers.h:87
Fortran::parser::ApplyConstructor
Definition: basic-parsers.h:722
Fortran::parser::NonstandardParser
Definition: basic-parsers.h:837
Fortran::parser::NonemptySeparated
Definition: basic-parsers.h:776
Fortran::parser::Messages
Definition: message.h:213
Fortran::parser::NextCh
Definition: basic-parsers.h:820
Fortran::parser::MessageContextParser
Definition: basic-parsers.h:178
Fortran::parser::NegatedParser
Definition: basic-parsers.h:129
Fortran::parser::OkParser
Definition: basic-parsers.h:803
Fortran::parser::DefaultedParser
Definition: basic-parsers.h:544
Fortran::parser::FollowParser
Definition: basic-parsers.h:276
Fortran::parser::ApplyMemberFunction
Definition: basic-parsers.h:671
Fortran::parser::ManyParser
Definition: basic-parsers.h:412
Fortran::parser::SequenceParser
Definition: basic-parsers.h:253
Fortran::parser::MessageFixedText
Definition: message.h:33
Fortran::parser::FailParser
Definition: basic-parsers.h:49
Fortran::parser::ApplyFunction
Definition: basic-parsers.h:613
Fortran::parser::CharBlock
Definition: char-block.h:28
Fortran::parser::SourcedParser
Definition: basic-parsers.h:899
Fortran::parser::PureParser
Definition: basic-parsers.h:72
Fortran::parser::DeprecatedParser
Definition: basic-parsers.h:869
Fortran::parser::AlternativesParser
Definition: basic-parsers.h:300
Fortran::parser::ParseState
Definition: parse-state.h:35
Fortran::parser
Definition: check-expression.h:19
Fortran::parser::WithMessageParser
Definition: basic-parsers.h:204
Fortran::parser::SomeParser
Definition: basic-parsers.h:444
Fortran::parser::MaybeParser
Definition: basic-parsers.h:518
Fortran::parser::UserState
Definition: user-state.h:35
Fortran::parser::RecoveryParser
Definition: basic-parsers.h:349
Fortran::parser::SkipManyParser
Definition: basic-parsers.h:473
Fortran::parser::AMFPHelper
Definition: basic-parsers.h:652