Skip to content

Commit fa9b23d

Browse files
committed
[flang][Parser] Convert applyMem to invoke non-void members
Currently applyMem(f, a, ...) calls a.f(...), but still returns the result of parser a. This is in contrast to applyFunction(f, a, ...), which returns the result of calling f(a, ...). The use case for this is being able to parse quoted or unquoted strings, and store the result as std::string: ``` construct<IdentifierOrString>( (space >> charLiteralConstantWithoutKind) || applyMem(&Name::ToString, Parser<Name>{})) // Parser<Name>{}.ToString() ``` The applyMem combinator is currently unused.
1 parent afcb7d4 commit fa9b23d

File tree

2 files changed

+24
-32
lines changed

2 files changed

+24
-32
lines changed

flang/docs/ParserCombinators.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ collect the values that they return.
141141
* `applyLambda([](&&x){}, p1, p2, ...)` is the same thing, but for lambdas
142142
and other function objects.
143143
* `applyMem(mf, p1, p2, ...)` is the same thing, but invokes a member
144-
function of the result of the first parser for updates in place.
144+
function of the result of the first parser.
145145

146146
### Token Parsers
147147
Last, we have these basic parsers on which the actual grammar of the Fortran

flang/lib/Parser/basic-parsers.h

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -580,11 +580,11 @@ template <typename PA> inline constexpr auto defaulted(PA p) {
580580
// applyLambda(f, ...) is the same concept extended to std::function<> functors.
581581
// It is not constexpr.
582582
//
583-
// Member function application is supported by applyMem(f, a). If the
584-
// parser a succeeds and returns some value ax, the result is that returned
585-
// by ax.f(). Additional parser arguments can be specified to supply their
586-
// results to the member function call, so applyMem(f, a, b) succeeds if
587-
// both a and b do so and returns the result of calling ax.f(std::move(bx)).
583+
// Member function application is supported by applyMem(&C::f, a). If the
584+
// parser a succeeds and returns some value ax of type C, the result is that
585+
// returned by ax.f(). Additional parser arguments can be specified to supply
586+
// their results to the member function call, so applyMem(&C::f, a, b) succeeds
587+
// if both a and b do so and returns the result of calling ax.f(std::move(bx)).
588588

589589
// Runs a sequence of parsers until one fails or all have succeeded.
590590
// Collects their results in a std::tuple<std::optional<>...>.
@@ -654,39 +654,31 @@ inline /* not constexpr */ auto applyLambda(
654654
}
655655

656656
// Member function application
657-
template <typename OBJPARSER, typename... PARSER> class AMFPHelper {
658-
using resultType = typename OBJPARSER::resultType;
659-
660-
public:
661-
using type = void (resultType::*)(typename PARSER::resultType &&...);
662-
};
663-
template <typename OBJPARSER, typename... PARSER>
664-
using ApplicableMemberFunctionPointer =
665-
typename AMFPHelper<OBJPARSER, PARSER...>::type;
666-
667-
template <typename OBJPARSER, typename... PARSER, std::size_t... J>
668-
inline auto ApplyHelperMember(
669-
ApplicableMemberFunctionPointer<OBJPARSER, PARSER...> mfp,
670-
ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) ->
671-
typename OBJPARSER::resultType {
672-
((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...);
673-
return std::get<0>(std::move(args));
657+
template <typename MEMFUNC, typename OBJPARSER, typename... PARSER,
658+
std::size_t... J>
659+
inline auto ApplyHelperMember(MEMFUNC mfp,
660+
ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) {
661+
return ((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...);
674662
}
675663

676-
template <typename OBJPARSER, typename... PARSER> class ApplyMemberFunction {
677-
using funcType = ApplicableMemberFunctionPointer<OBJPARSER, PARSER...>;
664+
template <typename MEMFUNC, typename OBJPARSER, typename... PARSER>
665+
class ApplyMemberFunction {
666+
static_assert(std::is_member_function_pointer_v<MEMFUNC>);
667+
using funcType = MEMFUNC;
678668

679669
public:
680-
using resultType = typename OBJPARSER::resultType;
670+
using resultType =
671+
std::invoke_result_t<MEMFUNC, typename OBJPARSER::resultType, PARSER...>;
672+
681673
constexpr ApplyMemberFunction(const ApplyMemberFunction &) = default;
682-
constexpr ApplyMemberFunction(funcType f, OBJPARSER o, PARSER... p)
674+
constexpr ApplyMemberFunction(MEMFUNC f, OBJPARSER o, PARSER... p)
683675
: function_{f}, parsers_{o, p...} {}
684676
std::optional<resultType> Parse(ParseState &state) const {
685677
ApplyArgs<OBJPARSER, PARSER...> results;
686678
using Sequence1 = std::index_sequence_for<OBJPARSER, PARSER...>;
687679
using Sequence2 = std::index_sequence_for<PARSER...>;
688680
if (ApplyHelperArgs(parsers_, results, state, Sequence1{})) {
689-
return ApplyHelperMember<OBJPARSER, PARSER...>(
681+
return ApplyHelperMember<MEMFUNC, OBJPARSER, PARSER...>(
690682
function_, std::move(results), Sequence2{});
691683
} else {
692684
return std::nullopt;
@@ -698,11 +690,11 @@ template <typename OBJPARSER, typename... PARSER> class ApplyMemberFunction {
698690
const std::tuple<OBJPARSER, PARSER...> parsers_;
699691
};
700692

701-
template <typename OBJPARSER, typename... PARSER>
693+
template <typename MEMFUNC, typename OBJPARSER, typename... PARSER>
702694
inline constexpr auto applyMem(
703-
ApplicableMemberFunctionPointer<OBJPARSER, PARSER...> mfp,
704-
const OBJPARSER &objParser, PARSER... parser) {
705-
return ApplyMemberFunction<OBJPARSER, PARSER...>{mfp, objParser, parser...};
695+
MEMFUNC memfn, const OBJPARSER &objParser, PARSER... parser) {
696+
return ApplyMemberFunction<MEMFUNC, OBJPARSER, PARSER...>{
697+
memfn, objParser, parser...};
706698
}
707699

708700
// As is done with function application via applyFunction() above, class

0 commit comments

Comments
 (0)